Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base/dnssec_chain_verifier.h" | 5 #include "net/base/dnssec_chain_verifier.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/sha1.h" | 9 #include "base/sha1.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 // Add all the keys as trusted. | 536 // Add all the keys as trusted. |
| 537 for (unsigned i = 0; i < dnskeys.size(); i++) { | 537 for (unsigned i = 0; i < dnskeys.size(); i++) { |
| 538 if (i == entry_key) | 538 if (i == entry_key) |
| 539 continue; | 539 continue; |
| 540 current_zone_->trusted_keys.AddKey(dnskeys[i]); | 540 current_zone_->trusted_keys.AddKey(dnskeys[i]); |
| 541 } | 541 } |
| 542 | 542 |
| 543 return OK; | 543 return OK; |
| 544 } | 544 } |
| 545 | 545 |
| 546 // IsValidTerminalRRType returns true if the given RR type is one that we | |
| 547 // accept as the terminal record in a DNSSEC chain. | |
| 548 bool DNSSECChainVerifier::IsValidTerminalRRType(uint16 rrtype) { | |
| 549 switch (rrtype) { | |
| 550 case kDNS_CAA: | |
| 551 case kDNS_CERT: | |
| 552 case kDNS_TLSA: | |
| 553 case kDNS_TXT: | |
| 554 return true; | |
| 555 } | |
| 556 | |
| 557 return false; | |
| 558 } | |
| 559 | |
| 546 // LeaveZone transitions out of the current zone, either by following DS | 560 // LeaveZone transitions out of the current zone, either by following DS |
| 547 // records to validate the entry key of the next zone, or because the final | 561 // records to validate the entry key of the next zone, or because the final |
| 548 // resource records are given. | 562 // resource records are given. |
| 549 DNSSECChainVerifier::Error DNSSECChainVerifier::LeaveZone( | 563 DNSSECChainVerifier::Error DNSSECChainVerifier::LeaveZone( |
| 550 base::StringPiece* next_name) { | 564 base::StringPiece* next_name) { |
| 551 base::StringPiece sig; | 565 base::StringPiece sig; |
| 552 uint16 rrtype; | 566 uint16 rrtype; |
| 553 Error err; | 567 Error err; |
| 554 | 568 |
| 555 if (!ReadName(next_name) || | 569 if (!ReadName(next_name) || |
| 556 !U16(&rrtype) || | 570 !U16(&rrtype) || |
| 557 !VariableLength16(&sig)) { | 571 !VariableLength16(&sig)) { |
| 558 return BAD_DATA; | 572 return BAD_DATA; |
| 559 } | 573 } |
| 560 | 574 |
| 561 std::vector<base::StringPiece> rrdatas; | 575 std::vector<base::StringPiece> rrdatas; |
| 562 | 576 |
| 563 if (rrtype == kDNS_DS) { | 577 if (rrtype == kDNS_DS) { |
| 564 err = ReadDSSet(&rrdatas, *next_name); | 578 err = ReadDSSet(&rrdatas, *next_name); |
| 565 } else if (rrtype == kDNS_CERT || rrtype == kDNS_TXT || rrtype == kDNS_CAA) { | 579 } else if (IsValidTerminalRRType(rrtype)) { |
| 566 err = ReadGenericRRs(&rrdatas); | 580 err = ReadGenericRRs(&rrdatas); |
| 567 } else if (rrtype == kDNS_CNAME) { | 581 } else if (rrtype == kDNS_CNAME) { |
| 568 err = ReadCNAME(&rrdatas); | 582 err = ReadCNAME(&rrdatas); |
| 569 } else { | 583 } else { |
| 570 return UNKNOWN_TERMINAL_RRTYPE; | 584 return UNKNOWN_TERMINAL_RRTYPE; |
| 571 } | 585 } |
| 572 if (err != OK) | 586 if (err != OK) |
| 573 return err; | 587 return err; |
| 574 | 588 |
| 575 if (!current_zone_->trusted_keys.CheckSignature( | 589 if (!current_zone_->trusted_keys.CheckSignature( |
| 576 *next_name, current_zone_->name, sig, rrtype, rrdatas)) { | 590 *next_name, current_zone_->name, sig, rrtype, rrdatas)) { |
| 577 return BAD_SIGNATURE; | 591 return BAD_SIGNATURE; |
| 578 } | 592 } |
| 579 | 593 |
| 580 if (rrtype == kDNS_DS) { | 594 if (rrtype == kDNS_DS) { |
| 581 // If we are transitioning to another zone then the next zone must be | 595 // If we are transitioning to another zone then the next zone must be |
| 582 // 'closer' to the target than the current zone. | 596 // 'closer' to the target than the current zone. |
| 583 if (MatchingLabels(target_, *next_name) <= current_zone_->matching_labels) | 597 if (MatchingLabels(target_, *next_name) <= current_zone_->matching_labels) |
| 584 return OFF_COURSE; | 598 return OFF_COURSE; |
| 585 } else if (rrtype == kDNS_CERT || rrtype == kDNS_TXT || rrtype == kDNS_CAA) { | 599 } else if (IsValidTerminalRRType(rrtype)) { |
| 586 // If this is the final entry in the chain then the name must match target_ | 600 // If this is the final entry in the chain then the name must match target_ |
| 587 if (next_name->size() != target_.size() || | 601 if (next_name->size() != target_.size() || |
| 588 memcmp(next_name->data(), target_.data(), target_.size())) { | 602 memcmp(next_name->data(), target_.data(), target_.size())) { |
| 589 return BAD_TARGET; | 603 return BAD_TARGET; |
| 590 } | 604 } |
| 591 rrdatas_ = rrdatas; | 605 rrdatas_ = rrdatas; |
| 592 valid_ = true; | 606 valid_ = true; |
| 593 rrtype_ = rrtype; | 607 rrtype_ = rrtype; |
| 594 } else if (rrtype == kDNS_CNAME) { | 608 } else if (rrtype == kDNS_CNAME) { |
| 595 // A CNAME must match the current target. Then we update the current target | 609 // A CNAME must match the current target. Then we update the current target |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 737 | 751 |
| 738 struct CAAHashFunctionOID { | 752 struct CAAHashFunctionOID { |
| 739 uint8 length; | 753 uint8 length; |
| 740 uint8 bytes[12]; | 754 uint8 bytes[12]; |
| 741 int value; | 755 int value; |
| 742 }; | 756 }; |
| 743 | 757 |
| 744 // The values here are taken from NSS's freebl/hasht.h. Sadly, we cannot | 758 // The values here are taken from NSS's freebl/hasht.h. Sadly, we cannot |
| 745 // include it because it pulls in #defines that conflict with Chromium headers. | 759 // include it because it pulls in #defines that conflict with Chromium headers. |
| 746 // However, these values are part of NSS's public API and so are stable. | 760 // However, these values are part of NSS's public API and so are stable. |
| 761 static const int kHashNone = 0; | |
| 747 static const int kHashSHA256 = 4; | 762 static const int kHashSHA256 = 4; |
| 748 static const int kHashSHA384 = 5; | 763 static const int kHashSHA384 = 5; |
| 749 static const int kHashSHA512 = 6; | 764 static const int kHashSHA512 = 6; |
| 750 | 765 |
| 751 // kCAAHashFunctions maps from the DER encoding of hash function OIDs to NSS's | 766 // kCAAHashFunctions maps from the DER encoding of hash function OIDs to NSS's |
| 752 // hash function enumeration. | 767 // hash function enumeration. |
| 753 static CAAHashFunctionOID kCAAHashFunctions[] = { | 768 static CAAHashFunctionOID kCAAHashFunctions[] = { |
| 754 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01", kHashSHA256 }, | 769 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01", kHashSHA256 }, |
| 755 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02", kHashSHA384 }, | 770 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02", kHashSHA384 }, |
| 756 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03", kHashSHA512 }, | 771 { 11, "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03", kHashSHA512 }, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 909 return UNKNOWN_CRITICAL; | 924 return UNKNOWN_CRITICAL; |
| 910 } | 925 } |
| 911 } | 926 } |
| 912 | 927 |
| 913 if (output->authorized_hashes.empty()) | 928 if (output->authorized_hashes.empty()) |
| 914 return DISCARD; | 929 return DISCARD; |
| 915 | 930 |
| 916 return SUCCESS; | 931 return SUCCESS; |
| 917 } | 932 } |
| 918 | 933 |
| 934 void DnsTLSARecord::Parse( | |
| 935 const std::vector<base::StringPiece>& rrdatas, | |
| 936 std::vector<DnsTLSARecord::Match>* output) { | |
| 937 // see https://tools.ietf.org/html/rfc6698#section-2.1 | |
| 938 output->clear(); | |
| 939 | |
| 940 for (std::vector<base::StringPiece>::const_iterator | |
| 941 ii = rrdatas.begin(); ii != rrdatas.end(); ++ii) { | |
| 942 base::StringPiece i = *ii; | |
| 943 | |
| 944 if (i.size() < 3) | |
| 945 continue; | |
| 946 | |
| 947 const uint8 cert_usage = i[0]; | |
| 948 const uint8 selector = i[1]; | |
| 949 const uint8 match_type = i[2]; | |
| 950 i.remove_prefix(3); | |
| 951 | |
| 952 if (cert_usage != 3) { | |
| 953 // Type 3 is a "domain issued certificate" - i.e. a certificate (or | |
| 954 // public key) which is granted authority by the TLSA record. | |
| 955 continue; | |
| 956 } | |
| 957 | |
| 958 Match match; | |
| 959 | |
| 960 switch (selector) { | |
| 961 case 0: | |
| 962 match.target = Match::CERTIFICATE; | |
| 963 break; | |
| 964 case 1: | |
| 965 match.target = Match::SUBJECT_PUBLIC_KEY_INFO; | |
| 966 break; | |
| 967 default: | |
| 968 continue; | |
| 969 } | |
|
Ryan Sleevi
2012/10/18 23:21:13
style nit: indent 'case' to two spaces, inner bloc
agl
2012/10/29 15:41:56
Done.
| |
| 970 | |
| 971 switch (match_type) { | |
| 972 case 0: | |
| 973 match.algorithm = kHashNone; | |
| 974 break; | |
| 975 case 1: | |
| 976 match.algorithm = kHashSHA256; | |
| 977 break; | |
| 978 case 2: | |
| 979 match.algorithm = kHashSHA512; | |
| 980 break; | |
| 981 default: | |
| 982 continue; | |
| 983 } | |
| 984 | |
| 985 if (match.algorithm != kHashNone && | |
| 986 i.size() != DigestLength(match.algorithm)) { | |
| 987 continue; | |
| 988 } | |
| 989 | |
| 990 match.data = i.as_string(); | |
| 991 output->push_back(match); | |
| 992 } | |
| 993 } | |
| 994 | |
| 919 } // namespace net | 995 } // namespace net |
| OLD | NEW |