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 |