| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/cert_verify_proc.h" | 5 #include "net/cert/cert_verify_proc.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/sha1.h" | 9 #include "base/sha1.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 if (j->tag == HASH_VALUE_SHA1 && | 449 if (j->tag == HASH_VALUE_SHA1 && |
| 450 memcmp(j->data(), kHashes[i], base::kSHA1Length) == 0) { | 450 memcmp(j->data(), kHashes[i], base::kSHA1Length) == 0) { |
| 451 return true; | 451 return true; |
| 452 } | 452 } |
| 453 } | 453 } |
| 454 } | 454 } |
| 455 | 455 |
| 456 return false; | 456 return false; |
| 457 } | 457 } |
| 458 | 458 |
| 459 static const size_t kMaxTLDLength = 4; | 459 static const size_t kMaxDomainLength = 18; |
| 460 | 460 |
| 461 // CheckNameConstraints verifies that every name in |dns_names| is in one of | 461 // CheckNameConstraints verifies that every name in |dns_names| is in one of |
| 462 // the domains specified by |tlds|. The |tlds| array is terminated by an empty | 462 // the domains specified by |domains|. The |domains| array is terminated by an |
| 463 // string. | 463 // empty string. |
| 464 static bool CheckNameConstraints(const std::vector<std::string>& dns_names, | 464 static bool CheckNameConstraints(const std::vector<std::string>& dns_names, |
| 465 const char tlds[][kMaxTLDLength]) { | 465 const char domains[][kMaxDomainLength]) { |
| 466 for (std::vector<std::string>::const_iterator i = dns_names.begin(); | 466 for (std::vector<std::string>::const_iterator i = dns_names.begin(); |
| 467 i != dns_names.end(); ++i) { | 467 i != dns_names.end(); ++i) { |
| 468 bool ok = false; | 468 bool ok = false; |
| 469 url::CanonHostInfo host_info; | 469 url::CanonHostInfo host_info; |
| 470 const std::string dns_name = CanonicalizeHost(*i, &host_info); | 470 const std::string dns_name = CanonicalizeHost(*i, &host_info); |
| 471 if (host_info.IsIPAddress()) | 471 if (host_info.IsIPAddress()) |
| 472 continue; | 472 continue; |
| 473 | 473 |
| 474 const size_t registry_len = registry_controlled_domains::GetRegistryLength( | 474 const size_t registry_len = registry_controlled_domains::GetRegistryLength( |
| 475 dns_name, | 475 dns_name, |
| 476 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | 476 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, |
| 477 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | 477 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); |
| 478 // If the name is not in a known TLD, ignore it. This permits internal | 478 // If the name is not in a known TLD, ignore it. This permits internal |
| 479 // names. | 479 // names. |
| 480 if (registry_len == 0) | 480 if (registry_len == 0) |
| 481 continue; | 481 continue; |
| 482 | 482 |
| 483 for (size_t j = 0; tlds[j][0]; ++j) { | 483 for (size_t j = 0; domains[j][0]; ++j) { |
| 484 const size_t tld_length = strlen(tlds[j]); | 484 const size_t domain_length = strlen(domains[j]); |
| 485 // The DNS name must have "." + tlds[j] as a suffix. | 485 // The DNS name must have "." + domains[j] as a suffix. |
| 486 if (i->size() <= (1 /* period before TLD */ + tld_length)) | 486 if (i->size() <= (1 /* period before domain */ + domain_length)) |
| 487 continue; | 487 continue; |
| 488 | 488 |
| 489 const char* suffix = &dns_name[i->size() - tld_length - 1]; | 489 const char* suffix = &dns_name[i->size() - domain_length - 1]; |
| 490 if (suffix[0] != '.') | 490 if (suffix[0] != '.') |
| 491 continue; | 491 continue; |
| 492 if (memcmp(&suffix[1], tlds[j], tld_length) != 0) | 492 if (memcmp(&suffix[1], domains[j], domain_length) != 0) |
| 493 continue; | 493 continue; |
| 494 ok = true; | 494 ok = true; |
| 495 break; | 495 break; |
| 496 } | 496 } |
| 497 | 497 |
| 498 if (!ok) | 498 if (!ok) |
| 499 return false; | 499 return false; |
| 500 } | 500 } |
| 501 | 501 |
| 502 return true; | 502 return true; |
| 503 } | 503 } |
| 504 | 504 |
| 505 // PublicKeyTLDLimitation contains a SHA1, SPKI hash and a pointer to an array | 505 // PublicKeyDomainLimitation contains a SHA1, SPKI hash and a pointer to an |
| 506 // of fixed-length strings that contain the TLDs that the SPKI is allowed to | 506 // array of fixed-length strings that contain the domains that the SPKI is |
| 507 // issue for. | 507 // allowed to issue for. |
| 508 struct PublicKeyTLDLimitation { | 508 struct PublicKeyDomainLimitation { |
| 509 uint8 public_key[base::kSHA1Length]; | 509 uint8 public_key[base::kSHA1Length]; |
| 510 const char (*tlds)[kMaxTLDLength]; | 510 const char (*domains)[kMaxDomainLength]; |
| 511 }; | 511 }; |
| 512 | 512 |
| 513 // static | 513 // static |
| 514 bool CertVerifyProc::HasNameConstraintsViolation( | 514 bool CertVerifyProc::HasNameConstraintsViolation( |
| 515 const HashValueVector& public_key_hashes, | 515 const HashValueVector& public_key_hashes, |
| 516 const std::string& common_name, | 516 const std::string& common_name, |
| 517 const std::vector<std::string>& dns_names, | 517 const std::vector<std::string>& dns_names, |
| 518 const std::vector<std::string>& ip_addrs) { | 518 const std::vector<std::string>& ip_addrs) { |
| 519 static const char kTLDsANSSI[][kMaxTLDLength] = { | 519 static const char kDomainsANSSI[][kMaxDomainLength] = { |
| 520 "fr", // France | 520 "fr", // France |
| 521 "gp", // Guadeloupe | 521 "gp", // Guadeloupe |
| 522 "gf", // Guyane | 522 "gf", // Guyane |
| 523 "mq", // Martinique | 523 "mq", // Martinique |
| 524 "re", // Réunion | 524 "re", // Réunion |
| 525 "yt", // Mayotte | 525 "yt", // Mayotte |
| 526 "pm", // Saint-Pierre et Miquelon | 526 "pm", // Saint-Pierre et Miquelon |
| 527 "bl", // Saint Barthélemy | 527 "bl", // Saint Barthélemy |
| 528 "mf", // Saint Martin | 528 "mf", // Saint Martin |
| 529 "wf", // Wallis et Futuna | 529 "wf", // Wallis et Futuna |
| 530 "pf", // Polynésie française | 530 "pf", // Polynésie française |
| 531 "nc", // Nouvelle Calédonie | 531 "nc", // Nouvelle Calédonie |
| 532 "tf", // Terres australes et antarctiques françaises | 532 "tf", // Terres australes et antarctiques françaises |
| 533 "", | 533 "", |
| 534 }; | 534 }; |
| 535 | 535 |
| 536 static const char kTLDsTest[][kMaxTLDLength] = { | 536 static const char kDomainsIndiaCCA[][kMaxDomainLength] = { |
| 537 "com", | 537 "gov.in", |
| 538 "nic.in", |
| 539 "ac.in", |
| 540 "rbi.org.in", |
| 541 "bankofindia.co.in", |
| 542 "ncode.in", |
| 543 "tcs.co.in", |
| 538 "", | 544 "", |
| 539 }; | 545 }; |
| 540 | 546 |
| 541 static const PublicKeyTLDLimitation kLimits[] = { | 547 static const char kDomainsTest[][kMaxDomainLength] = { |
| 548 "example.com", |
| 549 "", |
| 550 }; |
| 551 |
| 552 static const PublicKeyDomainLimitation kLimits[] = { |
| 542 // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, | 553 // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, |
| 543 // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr | 554 // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr |
| 544 { | 555 { |
| 545 {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad, | 556 {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad, |
| 546 0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73}, | 557 0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73}, |
| 547 kTLDsANSSI, | 558 kDomainsANSSI, |
| 559 }, |
| 560 // C=IN, O=India PKI, CN=CCA India 2007 |
| 561 // Expires: July 4th 2015. |
| 562 { |
| 563 {0xfe, 0xe3, 0x95, 0x21, 0x2d, 0x5f, 0xea, 0xfc, 0x7e, 0xdc, |
| 564 0xcf, 0x88, 0x3f, 0x1e, 0xc0, 0x58, 0x27, 0xd8, 0xb8, 0xe4}, |
| 565 kDomainsIndiaCCA, |
| 566 }, |
| 567 // C=IN, O=India PKI, CN=CCA India 2011 |
| 568 // Expires: March 11 2016. |
| 569 { |
| 570 {0xf1, 0x42, 0xf6, 0xa2, 0x7d, 0x29, 0x3e, 0xa8, 0xf9, 0x64, |
| 571 0x52, 0x56, 0xed, 0x07, 0xa8, 0x63, 0xf2, 0xdb, 0x1c, 0xdf}, |
| 572 kDomainsIndiaCCA, |
| 573 }, |
| 574 // C=IN, O=India PKI, CN=CCA India 2014 |
| 575 // Expires: March 5 2024. |
| 576 { |
| 577 {0x36, 0x8c, 0x4a, 0x1e, 0x2d, 0xb7, 0x81, 0xe8, 0x6b, 0xed, |
| 578 0x5a, 0x0a, 0x42, 0xb8, 0xc5, 0xcf, 0x6d, 0xb3, 0x57, 0xe1}, |
| 579 kDomainsIndiaCCA, |
| 548 }, | 580 }, |
| 549 // Not a real certificate - just for testing. This is the SPKI hash of | 581 // Not a real certificate - just for testing. This is the SPKI hash of |
| 550 // the keys used in net/data/ssl/certificates/name_constraint_*.crt. | 582 // the keys used in net/data/ssl/certificates/name_constraint_*.crt. |
| 551 { | 583 { |
| 552 {0x15, 0x45, 0xd7, 0x3b, 0x58, 0x6b, 0x47, 0xcf, 0xc1, 0x44, | 584 {0x15, 0x45, 0xd7, 0x3b, 0x58, 0x6b, 0x47, 0xcf, 0xc1, 0x44, |
| 553 0xa2, 0xc9, 0xaa, 0xab, 0x98, 0x3d, 0x21, 0xcc, 0x42, 0xde}, | 585 0xa2, 0xc9, 0xaa, 0xab, 0x98, 0x3d, 0x21, 0xcc, 0x42, 0xde}, |
| 554 kTLDsTest, | 586 kDomainsTest, |
| 555 }, | 587 }, |
| 556 }; | 588 }; |
| 557 | 589 |
| 558 for (unsigned i = 0; i < arraysize(kLimits); ++i) { | 590 for (unsigned i = 0; i < arraysize(kLimits); ++i) { |
| 559 for (HashValueVector::const_iterator j = public_key_hashes.begin(); | 591 for (HashValueVector::const_iterator j = public_key_hashes.begin(); |
| 560 j != public_key_hashes.end(); ++j) { | 592 j != public_key_hashes.end(); ++j) { |
| 561 if (j->tag == HASH_VALUE_SHA1 && | 593 if (j->tag == HASH_VALUE_SHA1 && |
| 562 memcmp(j->data(), kLimits[i].public_key, base::kSHA1Length) == 0) { | 594 memcmp(j->data(), kLimits[i].public_key, base::kSHA1Length) == 0) { |
| 563 if (dns_names.empty() && ip_addrs.empty()) { | 595 if (dns_names.empty() && ip_addrs.empty()) { |
| 564 std::vector<std::string> dns_names; | 596 std::vector<std::string> dns_names; |
| 565 dns_names.push_back(common_name); | 597 dns_names.push_back(common_name); |
| 566 if (!CheckNameConstraints(dns_names, kLimits[i].tlds)) | 598 if (!CheckNameConstraints(dns_names, kLimits[i].domains)) |
| 567 return true; | 599 return true; |
| 568 } else { | 600 } else { |
| 569 if (!CheckNameConstraints(dns_names, kLimits[i].tlds)) | 601 if (!CheckNameConstraints(dns_names, kLimits[i].domains)) |
| 570 return true; | 602 return true; |
| 571 } | 603 } |
| 572 } | 604 } |
| 573 } | 605 } |
| 574 } | 606 } |
| 575 | 607 |
| 576 return false; | 608 return false; |
| 577 } | 609 } |
| 578 | 610 |
| 579 } // namespace net | 611 } // namespace net |
| OLD | NEW |