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/transport_security_state.h" | 5 #include "net/base/transport_security_state.h" |
6 | 6 |
7 #if defined(USE_OPENSSL) | 7 #if defined(USE_OPENSSL) |
8 #include <openssl/ecdsa.h> | 8 #include <openssl/ecdsa.h> |
9 #include <openssl/ssl.h> | 9 #include <openssl/ssl.h> |
10 #else // !defined(USE_OPENSSL) | 10 #else // !defined(USE_OPENSSL) |
11 #include <nspr.h> | 11 #include <nspr.h> |
12 | 12 |
13 #include <cryptohi.h> | 13 #include <cryptohi.h> |
14 #include <hasht.h> | 14 #include <hasht.h> |
15 #include <keyhi.h> | 15 #include <keyhi.h> |
16 #include <pk11pub.h> | 16 #include <pk11pub.h> |
17 #endif | 17 #endif |
18 | 18 |
19 #include "base/base64.h" | 19 #include "base/base64.h" |
20 #include "base/json/json_reader.h" | 20 #include "base/json/json_reader.h" |
21 #include "base/json/json_writer.h" | 21 #include "base/json/json_writer.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/memory/scoped_ptr.h" | 23 #include "base/memory/scoped_ptr.h" |
24 #include "base/metrics/histogram.h" | |
24 #include "base/sha1.h" | 25 #include "base/sha1.h" |
25 #include "base/string_number_conversions.h" | 26 #include "base/string_number_conversions.h" |
26 #include "base/string_tokenizer.h" | 27 #include "base/string_tokenizer.h" |
27 #include "base/string_util.h" | 28 #include "base/string_util.h" |
28 #include "base/utf_string_conversions.h" | 29 #include "base/utf_string_conversions.h" |
29 #include "base/values.h" | 30 #include "base/values.h" |
30 #include "crypto/sha2.h" | 31 #include "crypto/sha2.h" |
31 #include "googleurl/src/gurl.h" | 32 #include "googleurl/src/gurl.h" |
32 #include "net/base/dns_util.h" | 33 #include "net/base/dns_util.h" |
33 | 34 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 if (!LowerCaseEqualsASCII(tokenizer.token(), "max-age")) | 242 if (!LowerCaseEqualsASCII(tokenizer.token(), "max-age")) |
242 return false; | 243 return false; |
243 state = AFTER_MAX_AGE_LABEL; | 244 state = AFTER_MAX_AGE_LABEL; |
244 break; | 245 break; |
245 | 246 |
246 case AFTER_MAX_AGE_LABEL: | 247 case AFTER_MAX_AGE_LABEL: |
247 if (IsAsciiWhitespace(*tokenizer.token_begin())) | 248 if (IsAsciiWhitespace(*tokenizer.token_begin())) |
248 continue; | 249 continue; |
249 if (*tokenizer.token_begin() != '=') | 250 if (*tokenizer.token_begin() != '=') |
250 return false; | 251 return false; |
251 DCHECK(tokenizer.token().length() == 1); | 252 DCHECK_EQ(tokenizer.token().length(), 1U); |
252 state = AFTER_MAX_AGE_EQUALS; | 253 state = AFTER_MAX_AGE_EQUALS; |
253 break; | 254 break; |
254 | 255 |
255 case AFTER_MAX_AGE_EQUALS: | 256 case AFTER_MAX_AGE_EQUALS: |
256 if (IsAsciiWhitespace(*tokenizer.token_begin())) | 257 if (IsAsciiWhitespace(*tokenizer.token_begin())) |
257 continue; | 258 continue; |
258 if (!MaxAgeToInt(tokenizer.token_begin(), | 259 if (!MaxAgeToInt(tokenizer.token_begin(), |
259 tokenizer.token_end(), | 260 tokenizer.token_end(), |
260 &max_age_candidate)) | 261 &max_age_candidate)) |
261 return false; | 262 return false; |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
800 // step 3(b) | 801 // step 3(b) |
801 if (new_host[i + 1] == '-' || | 802 if (new_host[i + 1] == '-' || |
802 new_host[i + label_length] == '-') { | 803 new_host[i + label_length] == '-') { |
803 return std::string(); | 804 return std::string(); |
804 } | 805 } |
805 } | 806 } |
806 | 807 |
807 return new_host; | 808 return new_host; |
808 } | 809 } |
809 | 810 |
811 // |ReportUMAOnPinFailure| uses these to report which domain was associated | |
812 // with the public key pinning failure. | |
813 // | |
814 // DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new | |
815 // domains at the END of the listing (but before DOMAIN_NUM_EVENTS). | |
816 enum LowResolutionDomainName { | |
wtc
2011/10/27 22:21:42
What does "low resolution" mean here? Perhaps you
palmer
2011/10/28 00:24:39
Done.
| |
817 DOMAIN_NOT_PINNED, | |
818 | |
819 DOMAIN_GOOGLE_COM, | |
820 DOMAIN_ANDROID_COM, | |
821 DOMAIN_GOOGLE_ANALYTICS_COM, | |
822 DOMAIN_GOOGLEPLEX_COM, | |
823 DOMAIN_YTIMG_COM, | |
824 DOMAIN_GOOGLEUSERCONTENT_COM, | |
825 DOMAIN_YOUTUBE_COM, | |
826 DOMAIN_GOOGLEAPIS_COM, | |
827 DOMAIN_GOOGLEADSERVICES_COM, | |
828 DOMAIN_GOOGLECODE_COM, | |
829 DOMAIN_APPSPOT_COM, | |
830 DOMAIN_GOOGLESYNDICATION_COM, | |
831 DOMAIN_DOUBLECLICK_NET, | |
832 DOMAIN_GSTATIC_COM, | |
833 DOMAIN_GMAIL_COM, | |
834 DOMAIN_GOOGLEMAIL_COM, | |
835 DOMAIN_GOOGLEGROUPS_COM, | |
836 | |
837 DOMAIN_TORPROJECT_ORG, | |
838 | |
839 DOMAIN_TWITTER_COM, | |
840 DOMAIN_TWIMG_COM, | |
841 DOMAIN_AKAMAIHD_NET, | |
wtc
2011/10/27 22:21:42
You seem to group the enum constants by company af
palmer
2011/10/28 00:24:39
Done.
| |
842 | |
843 // Boundary value for UMA_HISTOGRAM_ENUMERATION: | |
844 DOMAIN_NUM_EVENTS | |
845 }; | |
846 | |
810 struct HSTSPreload { | 847 struct HSTSPreload { |
811 uint8 length; | 848 uint8 length; |
812 bool include_subdomains; | 849 bool include_subdomains; |
813 char dns_name[30]; | 850 char dns_name[30]; |
814 bool https_required; | 851 bool https_required; |
815 const char* const* required_hashes; | 852 const char* const* required_hashes; |
853 LowResolutionDomainName low_res_name; | |
816 }; | 854 }; |
817 | 855 |
818 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, | 856 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, |
819 const std::string& canonicalized_host, size_t i, | 857 const std::string& canonicalized_host, size_t i, |
820 TransportSecurityState::DomainState* out, bool* ret) { | 858 TransportSecurityState::DomainState* out, bool* ret) { |
821 for (size_t j = 0; j < num_entries; j++) { | 859 for (size_t j = 0; j < num_entries; j++) { |
822 if (entries[j].length == canonicalized_host.size() - i && | 860 if (entries[j].length == canonicalized_host.size() - i && |
823 memcmp(entries[j].dns_name, &canonicalized_host[i], | 861 memcmp(entries[j].dns_name, &canonicalized_host[i], |
824 entries[j].length) == 0) { | 862 entries[j].length) == 0) { |
825 if (!entries[j].include_subdomains && i != 0) { | 863 if (!entries[j].include_subdomains && i != 0) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
956 #if defined(OS_CHROMEOS) | 994 #if defined(OS_CHROMEOS) |
957 static const bool kTwitterHSTS = true; | 995 static const bool kTwitterHSTS = true; |
958 #else | 996 #else |
959 static const bool kTwitterHSTS = false; | 997 static const bool kTwitterHSTS = false; |
960 #endif | 998 #endif |
961 | 999 |
962 // In the medium term this list is likely to just be hardcoded here. This | 1000 // In the medium term this list is likely to just be hardcoded here. This |
963 // slightly odd form removes the need for additional relocations records. | 1001 // slightly odd form removes the need for additional relocations records. |
964 static const struct HSTSPreload kPreloadedSTS[] = { | 1002 static const struct HSTSPreload kPreloadedSTS[] = { |
965 // (*.)google.com, iff using SSL must use an acceptable certificate. | 1003 // (*.)google.com, iff using SSL must use an acceptable certificate. |
966 {12, true, "\006google\003com", false, kGoogleAcceptableCerts }, | 1004 {12, true, "\006google\003com", false, kGoogleAcceptableCerts, |
1005 DOMAIN_GOOGLE_COM }, | |
967 {25, true, "\013pinningtest\007appspot\003com", false, | 1006 {25, true, "\013pinningtest\007appspot\003com", false, |
968 kTestAcceptableCerts }, | 1007 kTestAcceptableCerts, DOMAIN_APPSPOT_COM }, |
969 // Now we force HTTPS for subtrees of google.com. | 1008 // Now we force HTTPS for subtrees of google.com. |
970 {19, true, "\006health\006google\003com", true, kGoogleAcceptableCerts }, | 1009 {19, true, "\006health\006google\003com", true, kGoogleAcceptableCerts, |
971 {21, true, "\010checkout\006google\003com", true, kGoogleAcceptableCerts }, | 1010 DOMAIN_GOOGLE_COM }, |
972 {19, true, "\006chrome\006google\003com", true, kGoogleAcceptableCerts }, | 1011 {21, true, "\010checkout\006google\003com", true, kGoogleAcceptableCerts, |
973 {17, true, "\004docs\006google\003com", true, kGoogleAcceptableCerts }, | 1012 DOMAIN_GOOGLE_COM }, |
974 {18, true, "\005sites\006google\003com", true, kGoogleAcceptableCerts }, | 1013 {19, true, "\006chrome\006google\003com", true, kGoogleAcceptableCerts, |
1014 DOMAIN_GOOGLE_COM }, | |
1015 {17, true, "\004docs\006google\003com", true, kGoogleAcceptableCerts, | |
1016 DOMAIN_GOOGLE_COM }, | |
1017 {18, true, "\005sites\006google\003com", true, kGoogleAcceptableCerts, | |
1018 DOMAIN_GOOGLE_COM }, | |
975 {25, true, "\014spreadsheets\006google\003com", true, | 1019 {25, true, "\014spreadsheets\006google\003com", true, |
976 kGoogleAcceptableCerts }, | 1020 kGoogleAcceptableCerts, DOMAIN_GOOGLE_COM }, |
977 {22, false, "\011appengine\006google\003com", true, | 1021 {22, false, "\011appengine\006google\003com", true, |
978 kGoogleAcceptableCerts }, | 1022 kGoogleAcceptableCerts, DOMAIN_GOOGLE_COM }, |
979 {22, true, "\011encrypted\006google\003com", true, kGoogleAcceptableCerts }, | 1023 {22, true, "\011encrypted\006google\003com", true, kGoogleAcceptableCerts, |
980 {21, true, "\010accounts\006google\003com", true, kGoogleAcceptableCerts }, | 1024 DOMAIN_GOOGLE_COM }, |
981 {21, true, "\010profiles\006google\003com", true, kGoogleAcceptableCerts }, | 1025 {21, true, "\010accounts\006google\003com", true, kGoogleAcceptableCerts, |
982 {17, true, "\004mail\006google\003com", true, kGoogleAcceptableCerts }, | 1026 DOMAIN_GOOGLE_COM }, |
1027 {21, true, "\010profiles\006google\003com", true, kGoogleAcceptableCerts, | |
1028 DOMAIN_GOOGLE_COM }, | |
1029 {17, true, "\004mail\006google\003com", true, kGoogleAcceptableCerts, | |
1030 DOMAIN_GOOGLE_COM }, | |
983 {23, true, "\012talkgadget\006google\003com", true, | 1031 {23, true, "\012talkgadget\006google\003com", true, |
984 kGoogleAcceptableCerts }, | 1032 kGoogleAcceptableCerts, DOMAIN_GOOGLE_COM }, |
985 {17, true, "\004talk\006google\003com", true, kGoogleAcceptableCerts }, | 1033 {17, true, "\004talk\006google\003com", true, kGoogleAcceptableCerts, |
1034 DOMAIN_GOOGLE_COM }, | |
986 {29, true, "\020hostedtalkgadget\006google\003com", true, | 1035 {29, true, "\020hostedtalkgadget\006google\003com", true, |
987 kGoogleAcceptableCerts }, | 1036 kGoogleAcceptableCerts, DOMAIN_GOOGLE_COM }, |
988 {17, true, "\004plus\006google\003com", true, kGoogleAcceptableCerts }, | 1037 {17, true, "\004plus\006google\003com", true, kGoogleAcceptableCerts, |
1038 DOMAIN_GOOGLE_COM }, | |
989 // Other Google-related domains that must use HTTPS. | 1039 // Other Google-related domains that must use HTTPS. |
990 {20, true, "\006market\007android\003com", true, kGoogleAcceptableCerts }, | 1040 {20, true, "\006market\007android\003com", true, kGoogleAcceptableCerts, |
1041 DOMAIN_ANDROID_COM }, | |
991 {26, true, "\003ssl\020google-analytics\003com", true, | 1042 {26, true, "\003ssl\020google-analytics\003com", true, |
992 kGoogleAcceptableCerts }, | 1043 kGoogleAcceptableCerts, DOMAIN_GOOGLE_ANALYTICS_COM }, |
993 {18, true, "\005drive\006google\003com", true, kGoogleAcceptableCerts }, | 1044 {18, true, "\005drive\006google\003com", true, kGoogleAcceptableCerts, |
994 {16, true, "\012googleplex\003com", true, kGoogleAcceptableCerts }, | 1045 DOMAIN_GOOGLE_COM }, |
995 {19, true, "\006groups\006google\003com", true, kGoogleAcceptableCerts }, | 1046 {16, true, "\012googleplex\003com", true, kGoogleAcceptableCerts, |
1047 DOMAIN_GOOGLEPLEX_COM }, | |
1048 {19, true, "\006groups\006google\003com", true, kGoogleAcceptableCerts, | |
1049 DOMAIN_GOOGLE_COM }, | |
996 // Other Google-related domains that must use an acceptable certificate | 1050 // Other Google-related domains that must use an acceptable certificate |
997 // iff using SSL. | 1051 // iff using SSL. |
998 {11, true, "\005ytimg\003com", false, kGoogleAcceptableCerts }, | 1052 {11, true, "\005ytimg\003com", false, kGoogleAcceptableCerts, |
999 {23, true, "\021googleusercontent\003com", false, kGoogleAcceptableCerts }, | 1053 DOMAIN_YTIMG_COM }, |
1000 {13, true, "\007youtube\003com", false, kGoogleAcceptableCerts }, | 1054 {23, true, "\021googleusercontent\003com", false, kGoogleAcceptableCerts, |
1001 {16, true, "\012googleapis\003com", false, kGoogleAcceptableCerts }, | 1055 DOMAIN_GOOGLEUSERCONTENT_COM }, |
1002 {22, true, "\020googleadservices\003com", false, kGoogleAcceptableCerts }, | 1056 {13, true, "\007youtube\003com", false, kGoogleAcceptableCerts, |
1003 {16, true, "\012googlecode\003com", false, kGoogleAcceptableCerts }, | 1057 DOMAIN_YOUTUBE_COM }, |
1004 {13, true, "\007appspot\003com", false, kGoogleAcceptableCerts }, | 1058 {16, true, "\012googleapis\003com", false, kGoogleAcceptableCerts, |
1005 {23, true, "\021googlesyndication\003com", false, kGoogleAcceptableCerts }, | 1059 DOMAIN_GOOGLEAPIS_COM }, |
1006 {17, true, "\013doubleclick\003net", false, kGoogleAcceptableCerts }, | 1060 {22, true, "\020googleadservices\003com", false, kGoogleAcceptableCerts, |
1007 {17, true, "\003ssl\007gstatic\003com", false, kGoogleAcceptableCerts }, | 1061 DOMAIN_GOOGLEADSERVICES_COM }, |
1062 {16, true, "\012googlecode\003com", false, kGoogleAcceptableCerts, | |
1063 DOMAIN_GOOGLECODE_COM }, | |
1064 {13, true, "\007appspot\003com", false, kGoogleAcceptableCerts, | |
1065 DOMAIN_APPSPOT_COM }, | |
1066 {23, true, "\021googlesyndication\003com", false, kGoogleAcceptableCerts, | |
1067 DOMAIN_GOOGLESYNDICATION_COM }, | |
1068 {17, true, "\013doubleclick\003net", false, kGoogleAcceptableCerts, | |
1069 DOMAIN_DOUBLECLICK_NET }, | |
1070 {17, true, "\003ssl\007gstatic\003com", false, kGoogleAcceptableCerts, | |
1071 DOMAIN_GSTATIC_COM }, | |
1008 // Exclude the learn.doubleclick.net subdomain because it uses a different | 1072 // Exclude the learn.doubleclick.net subdomain because it uses a different |
1009 // CA. | 1073 // CA. |
1010 {23, true, "\005learn\013doubleclick\003net", false, 0 }, | 1074 {23, true, "\005learn\013doubleclick\003net", false, 0, |
1075 DOMAIN_DOUBLECLICK_NET }, | |
wtc
2011/10/27 22:21:42
This should be DOMAIN_NOT_PINNED because its requi
palmer
2011/10/28 00:24:39
Done.
| |
1011 // Now we force HTTPS for other sites that have requested it. | 1076 // Now we force HTTPS for other sites that have requested it. |
1012 {16, false, "\003www\006paypal\003com", true, 0 }, | 1077 {16, false, "\003www\006paypal\003com", true, 0, DOMAIN_NOT_PINNED }, |
1013 {16, false, "\003www\006elanex\003biz", true, 0 }, | 1078 {16, false, "\003www\006elanex\003biz", true, 0, DOMAIN_NOT_PINNED }, |
1014 {12, true, "\006jottit\003com", true, 0 }, | 1079 {12, true, "\006jottit\003com", true, 0, DOMAIN_NOT_PINNED }, |
1015 {19, true, "\015sunshinepress\003org", true, 0 }, | 1080 {19, true, "\015sunshinepress\003org", true, 0, DOMAIN_NOT_PINNED }, |
1016 {21, false, "\003www\013noisebridge\003net", true, 0 }, | 1081 {21, false, "\003www\013noisebridge\003net", true, 0, |
1017 {10, false, "\004neg9\003org", true, 0 }, | 1082 DOMAIN_NOT_PINNED }, |
1018 {12, true, "\006riseup\003net", true, 0 }, | 1083 {10, false, "\004neg9\003org", true, 0, DOMAIN_NOT_PINNED }, |
1019 {11, false, "\006factor\002cc", true, 0 }, | 1084 {12, true, "\006riseup\003net", true, 0, DOMAIN_NOT_PINNED }, |
1020 {22, false, "\007members\010mayfirst\003org", true, 0 }, | 1085 {11, false, "\006factor\002cc", true, 0, DOMAIN_NOT_PINNED }, |
1021 {22, false, "\007support\010mayfirst\003org", true, 0 }, | 1086 {22, false, "\007members\010mayfirst\003org", true, 0, DOMAIN_NOT_PINNED }, |
1022 {17, false, "\002id\010mayfirst\003org", true, 0 }, | 1087 {22, false, "\007support\010mayfirst\003org", true, 0, DOMAIN_NOT_PINNED }, |
1023 {20, false, "\005lists\010mayfirst\003org", true, 0 }, | 1088 {17, false, "\002id\010mayfirst\003org", true, 0, DOMAIN_NOT_PINNED }, |
1024 {19, true, "\015splendidbacon\003com", true, 0 }, | 1089 {20, false, "\005lists\010mayfirst\003org", true, 0, DOMAIN_NOT_PINNED }, |
1025 {28, false, "\016aladdinschools\007appspot\003com", true, 0 }, | 1090 {19, true, "\015splendidbacon\003com", true, 0, DOMAIN_NOT_PINNED }, |
1026 {14, true, "\011ottospora\002nl", true, 0 }, | 1091 {28, false, "\016aladdinschools\007appspot\003com", true, 0, |
1027 {25, false, "\003www\017paycheckrecords\003com", true, 0 }, | 1092 DOMAIN_APPSPOT_COM }, |
wtc
2011/10/27 22:21:42
This should be DOMAIN_NOT_PINNED for the same reas
palmer
2011/10/28 00:24:39
Done.
| |
1028 {14, false, "\010lastpass\003com", true, 0 }, | 1093 {14, true, "\011ottospora\002nl", true, 0, DOMAIN_NOT_PINNED }, |
1029 {18, false, "\003www\010lastpass\003com", true, 0 }, | 1094 {25, false, "\003www\017paycheckrecords\003com", true, 0, |
1030 {14, true, "\010keyerror\003com", true, 0 }, | 1095 DOMAIN_NOT_PINNED }, |
1031 {13, false, "\010entropia\002de", true, 0 }, | 1096 {14, false, "\010lastpass\003com", true, 0, DOMAIN_NOT_PINNED }, |
1032 {17, false, "\003www\010entropia\002de", true, 0 }, | 1097 {18, false, "\003www\010lastpass\003com", true, 0, DOMAIN_NOT_PINNED }, |
1033 {11, true, "\005romab\003com", true, 0 }, | 1098 {14, true, "\010keyerror\003com", true, 0, DOMAIN_NOT_PINNED }, |
1034 {16, false, "\012logentries\003com", true, 0 }, | 1099 {13, false, "\010entropia\002de", true, 0, DOMAIN_NOT_PINNED }, |
1035 {20, false, "\003www\012logentries\003com", true, 0 }, | 1100 {17, false, "\003www\010entropia\002de", true, 0, DOMAIN_NOT_PINNED }, |
1036 {12, true, "\006stripe\003com", true, 0 }, | 1101 {11, true, "\005romab\003com", true, 0, DOMAIN_NOT_PINNED }, |
1037 {27, true, "\025cloudsecurityalliance\003org", true, 0 }, | 1102 {16, false, "\012logentries\003com", true, 0, DOMAIN_NOT_PINNED }, |
1038 {15, true, "\005login\004sapo\002pt", true, 0 }, | 1103 {20, false, "\003www\012logentries\003com", true, 0, DOMAIN_NOT_PINNED }, |
1039 {19, true, "\015mattmccutchen\003net", true, 0 }, | 1104 {12, true, "\006stripe\003com", true, 0, DOMAIN_NOT_PINNED }, |
1040 {11, true, "\006betnet\002fr", true, 0 }, | 1105 {27, true, "\025cloudsecurityalliance\003org", true, 0, |
1041 {13, true, "\010uprotect\002it", true, 0 }, | 1106 DOMAIN_NOT_PINNED }, |
1042 {14, false, "\010squareup\003com", true, 0 }, | 1107 {15, true, "\005login\004sapo\002pt", true, 0, DOMAIN_NOT_PINNED }, |
1043 {9, true, "\004cert\002se", true, 0 }, | 1108 {19, true, "\015mattmccutchen\003net", true, 0, DOMAIN_NOT_PINNED }, |
1044 {11, true, "\006crypto\002is", true, 0 }, | 1109 {11, true, "\006betnet\002fr", true, 0, DOMAIN_NOT_PINNED }, |
1045 {20, true, "\005simon\007butcher\004name", true, 0 }, | 1110 {13, true, "\010uprotect\002it", true, 0, DOMAIN_NOT_PINNED }, |
1046 {10, true, "\004linx\003net", true, 0 }, | 1111 {14, false, "\010squareup\003com", true, 0, DOMAIN_NOT_PINNED }, |
1047 {13, false, "\007dropcam\003com", true, 0 }, | 1112 {9, true, "\004cert\002se", true, 0, DOMAIN_NOT_PINNED }, |
1048 {17, false, "\003www\007dropcam\003com", true, 0 }, | 1113 {11, true, "\006crypto\002is", true, 0, DOMAIN_NOT_PINNED }, |
1049 {30, true, "\010ebanking\014indovinabank\003com\002vn", true, 0 }, | 1114 {20, true, "\005simon\007butcher\004name", true, 0, DOMAIN_NOT_PINNED }, |
1050 {13, false, "\007epoxate\003com", true, 0 }, | 1115 {10, true, "\004linx\003net", true, 0, DOMAIN_NOT_PINNED }, |
1051 {16, false, "\012torproject\003org", true, kTorAcceptableCerts }, | 1116 {13, false, "\007dropcam\003com", true, 0, DOMAIN_NOT_PINNED }, |
1052 {21, true, "\004blog\012torproject\003org", true, kTorAcceptableCerts }, | 1117 {17, false, "\003www\007dropcam\003com", true, 0, DOMAIN_NOT_PINNED }, |
1053 {22, true, "\005check\012torproject\003org", true, kTorAcceptableCerts }, | 1118 {30, true, "\010ebanking\014indovinabank\003com\002vn", true, 0, |
1054 {20, true, "\003www\012torproject\003org", true, kTorAcceptableCerts }, | 1119 DOMAIN_NOT_PINNED }, |
1055 {22, true, "\003www\014moneybookers\003com", true, 0 }, | 1120 {13, false, "\007epoxate\003com", true, 0, DOMAIN_NOT_PINNED }, |
1056 {17, false, "\013ledgerscope\003net", true, 0 }, | 1121 {16, false, "\012torproject\003org", true, kTorAcceptableCerts, |
1057 {21, false, "\003www\013ledgerscope\003net", true, 0 }, | 1122 DOMAIN_TORPROJECT_ORG }, |
1058 {10, false, "\004kyps\003net", true, 0 }, | 1123 {21, true, "\004blog\012torproject\003org", true, kTorAcceptableCerts, |
1059 {14, false, "\003www\004kyps\003net", true, 0 }, | 1124 DOMAIN_TORPROJECT_ORG }, |
1060 {17, true, "\003app\007recurly\003com", true, 0 }, | 1125 {22, true, "\005check\012torproject\003org", true, kTorAcceptableCerts, |
1061 {17, true, "\003api\007recurly\003com", true, 0 }, | 1126 DOMAIN_TORPROJECT_ORG }, |
1062 {13, false, "\007greplin\003com", true, 0 }, | 1127 {20, true, "\003www\012torproject\003org", true, kTorAcceptableCerts, |
1063 {17, false, "\003www\007greplin\003com", true, 0 }, | 1128 DOMAIN_TORPROJECT_ORG }, |
1064 {27, true, "\006luneta\016nearbuysystems\003com", true, 0 }, | 1129 {22, true, "\003www\014moneybookers\003com", true, 0, |
1065 {12, true, "\006ubertt\003org", true, 0 }, | 1130 DOMAIN_NOT_PINNED }, |
1066 | 1131 {17, false, "\013ledgerscope\003net", true, 0, DOMAIN_NOT_PINNED }, |
1067 {13, false, "\007twitter\003com", kTwitterHSTS, kTwitterComAcceptableCerts }, | 1132 {21, false, "\003www\013ledgerscope\003net", true, 0, |
1068 {17, true, "\003www\007twitter\003com", kTwitterHSTS, kTwitterComAcceptableCer ts }, | 1133 DOMAIN_NOT_PINNED }, |
1069 {17, true, "\003api\007twitter\003com", kTwitterHSTS, kTwitterComAcceptableCer ts }, | 1134 {10, false, "\004kyps\003net", true, 0, DOMAIN_NOT_PINNED }, |
1070 {19, true, "\005oauth\007twitter\003com", kTwitterHSTS, kTwitterComAcceptableC erts }, | 1135 {14, false, "\003www\004kyps\003net", true, 0, DOMAIN_NOT_PINNED }, |
1071 {20, true, "\006mobile\007twitter\003com", kTwitterHSTS, kTwitterComAcceptable Certs }, | 1136 {17, true, "\003app\007recurly\003com", true, 0, DOMAIN_NOT_PINNED }, |
1072 {17, true, "\003dev\007twitter\003com", kTwitterHSTS, kTwitterComAcceptableCer ts }, | 1137 {17, true, "\003api\007recurly\003com", true, 0, DOMAIN_NOT_PINNED }, |
1073 {22, true, "\010business\007twitter\003com", kTwitterHSTS, kTwitterComAcceptab leCerts }, | 1138 {13, false, "\007greplin\003com", true, 0, DOMAIN_NOT_PINNED }, |
1139 {17, false, "\003www\007greplin\003com", true, 0, DOMAIN_NOT_PINNED }, | |
1140 {27, true, "\006luneta\016nearbuysystems\003com", true, 0, | |
1141 DOMAIN_NOT_PINNED }, | |
1142 {12, true, "\006ubertt\003org", true, 0, DOMAIN_NOT_PINNED }, | |
1143 | |
1144 {13, false, "\007twitter\003com", kTwitterHSTS, | |
1145 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1146 {17, true, "\003www\007twitter\003com", kTwitterHSTS, | |
1147 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1148 {17, true, "\003api\007twitter\003com", kTwitterHSTS, | |
1149 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1150 {19, true, "\005oauth\007twitter\003com", kTwitterHSTS, | |
1151 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1152 {20, true, "\006mobile\007twitter\003com", kTwitterHSTS, | |
1153 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1154 {17, true, "\003dev\007twitter\003com", kTwitterHSTS, | |
1155 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1156 {22, true, "\010business\007twitter\003com", kTwitterHSTS, | |
1157 kTwitterComAcceptableCerts, DOMAIN_TWITTER_COM }, | |
1074 | 1158 |
1075 #if 0 | 1159 #if 0 |
1076 // Twitter CDN pins disabled in order to track down pinning failures --agl | 1160 // Twitter CDN pins disabled in order to track down pinning failures --agl |
1077 {22, true, "\010platform\007twitter\003com", false, kTwitterCDNAcceptableCerts }, | 1161 {22, true, "\010platform\007twitter\003com", false, |
1078 {15, true, "\003si0\005twimg\003com", false, kTwitterCDNAcceptableCerts }, | 1162 kTwitterCDNAcceptableCerts, DOMAIN_TWITTER_COM }, |
1079 {23, true, "\010twimg0-a\010akamaihd\003net", false, kTwitterCDNAcceptableCert s }, | 1163 {15, true, "\003si0\005twimg\003com", false, kTwitterCDNAcceptableCerts, |
1164 DOMAIN_TWIMG_COM }, | |
1165 {23, true, "\010twimg0-a\010akamaihd\003net", false, | |
1166 kTwitterCDNAcceptableCerts, DOMAIN_AKAMAIHD_NET }, | |
1080 #endif | 1167 #endif |
1081 }; | 1168 }; |
1082 static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS); | 1169 static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS); |
1083 | 1170 |
1084 static const struct HSTSPreload kPreloadedSNISTS[] = { | 1171 static const struct HSTSPreload kPreloadedSNISTS[] = { |
1085 // These SNI-only domains must always use HTTPS. | 1172 // These SNI-only domains must always use HTTPS. |
1086 {11, false, "\005gmail\003com", true, kGoogleAcceptableCerts }, | 1173 {11, false, "\005gmail\003com", true, kGoogleAcceptableCerts, |
1087 {16, false, "\012googlemail\003com", true, kGoogleAcceptableCerts }, | 1174 DOMAIN_GMAIL_COM }, |
1088 {15, false, "\003www\005gmail\003com", true, kGoogleAcceptableCerts }, | 1175 {16, false, "\012googlemail\003com", true, kGoogleAcceptableCerts, |
1089 {20, false, "\003www\012googlemail\003com", true, kGoogleAcceptableCerts }, | 1176 DOMAIN_GOOGLEMAIL_COM }, |
1177 {15, false, "\003www\005gmail\003com", true, kGoogleAcceptableCerts, | |
1178 DOMAIN_GMAIL_COM }, | |
1179 {20, false, "\003www\012googlemail\003com", true, kGoogleAcceptableCerts, | |
1180 DOMAIN_GOOGLEMAIL_COM }, | |
1090 // These SNI-only domains must use an acceptable certificate iff using | 1181 // These SNI-only domains must use an acceptable certificate iff using |
1091 // HTTPS. | 1182 // HTTPS. |
1092 {22, true, "\020google-analytics\003com", false, kGoogleAcceptableCerts }, | 1183 {22, true, "\020google-analytics\003com", false, kGoogleAcceptableCerts, |
1184 DOMAIN_GOOGLE_ANALYTICS_COM }, | |
1093 // www. requires SNI. | 1185 // www. requires SNI. |
1094 {18, true, "\014googlegroups\003com", false, kGoogleAcceptableCerts }, | 1186 {18, true, "\014googlegroups\003com", false, kGoogleAcceptableCerts, |
1187 DOMAIN_GOOGLEGROUPS_COM }, | |
1095 }; | 1188 }; |
1096 static const size_t kNumPreloadedSNISTS = ARRAYSIZE_UNSAFE(kPreloadedSNISTS); | 1189 static const size_t kNumPreloadedSNISTS = ARRAYSIZE_UNSAFE(kPreloadedSNISTS); |
1097 | 1190 |
1098 // Returns true if there is an HSTSPreload entry for the host in |entries|, and | 1191 // Returns the HSTSPreload entry for the |canonicalized_host| in |entries|, |
1099 // if its |required_hashes| member is identical (by address) to |certs|. | 1192 // or NULL if there is none. Prefers exact hostname matches to those that |
1100 static bool ScanForHostAndCerts( | 1193 // match only because HSTSPreload.include_subdomains is true. |
1194 // | |
1195 // |canonicalized_host| should be the hostname as canonicalized by | |
1196 // CanonicalizeHost. | |
1197 static const struct HSTSPreload* GetHSTSPreload( | |
1101 const std::string& canonicalized_host, | 1198 const std::string& canonicalized_host, |
1102 const struct HSTSPreload* entries, | 1199 const struct HSTSPreload* entries, |
1103 size_t num_entries, | 1200 size_t num_entries) { |
1104 const char* const certs[]) { | 1201 const struct HSTSPreload* hit = NULL; |
1105 bool hit = false; | |
1106 | 1202 |
1107 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 1203 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
1108 for (size_t j = 0; j < num_entries; j++) { | 1204 for (size_t j = 0; j < num_entries; j++) { |
1109 const struct HSTSPreload& entry = entries[j]; | 1205 const struct HSTSPreload* entry = entries + j; |
1110 | 1206 |
1111 if (i != 0 && !entry.include_subdomains) | 1207 if (i != 0 && !entry->include_subdomains) |
1112 continue; | 1208 continue; |
1113 | 1209 |
1114 if (entry.length == canonicalized_host.size() - i && | 1210 if (entry->length == canonicalized_host.size() - i && |
1115 memcmp(entry.dns_name, &canonicalized_host[i], entry.length) == 0) { | 1211 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) { |
1116 hit = entry.required_hashes == certs; | 1212 // Return immediately upon exact match. |
1117 // Return immediately upon exact match: | |
1118 if (i == 0) | 1213 if (i == 0) |
1119 return hit; | 1214 return entry; |
1215 hit = entry; | |
wtc
2011/10/27 22:21:42
It seems that we should always return entry here,
palmer
2011/10/28 00:24:39
Yep, you are right! Thanks. Tests all still pass,
| |
1120 } | 1216 } |
1121 } | 1217 } |
1122 } | 1218 } |
1123 | 1219 |
1124 return hit; | 1220 return hit; |
1125 } | 1221 } |
1126 | 1222 |
1127 // static | 1223 // static |
1128 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, | 1224 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, |
1129 bool sni_available) { | 1225 bool sni_available) { |
1130 std::string canonicalized_host = CanonicalizeHost(host); | 1226 std::string canonicalized_host = CanonicalizeHost(host); |
1227 const struct HSTSPreload* entry = | |
1228 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | |
1131 | 1229 |
1132 if (ScanForHostAndCerts(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS, | 1230 if (entry && entry->required_hashes == kGoogleAcceptableCerts) |
1133 kGoogleAcceptableCerts)) { | |
1134 return true; | 1231 return true; |
1135 } | |
1136 | 1232 |
1137 if (sni_available) { | 1233 if (sni_available) { |
1138 if (ScanForHostAndCerts(canonicalized_host, kPreloadedSNISTS, kNumPreloadedS NISTS, | 1234 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, |
1139 kGoogleAcceptableCerts)) { | 1235 kNumPreloadedSNISTS); |
1236 if (entry && entry->required_hashes == kGoogleAcceptableCerts) | |
1140 return true; | 1237 return true; |
1141 } | |
1142 } | 1238 } |
1143 | 1239 |
1144 return false; | 1240 return false; |
1145 } | 1241 } |
1146 | 1242 |
1243 // static | |
1244 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { | |
1245 std::string canonicalized_host = CanonicalizeHost(host); | |
1246 | |
1247 const struct HSTSPreload* entry = | |
1248 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | |
1249 | |
1250 if (!entry) { | |
1251 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, | |
1252 kNumPreloadedSNISTS); | |
1253 } | |
1254 | |
1255 DCHECK_NE(static_cast<const struct HSTSPreload*>(NULL), entry); | |
wtc
2011/10/27 22:21:42
You may want to assert these two:
DCHECK(entry->
palmer
2011/10/28 00:24:39
Done.
| |
1256 | |
1257 UMA_HISTOGRAM_ENUMERATION("SSL.PublicKeyPinFailure", entry->low_res_name, | |
1258 DOMAIN_NUM_EVENTS); | |
1259 } | |
1147 | 1260 |
1148 // IsPreloadedSTS returns true if the canonicalized hostname should always be | 1261 // IsPreloadedSTS returns true if the canonicalized hostname should always be |
1149 // considered to have STS enabled. | 1262 // considered to have STS enabled. |
1150 bool TransportSecurityState::IsPreloadedSTS( | 1263 bool TransportSecurityState::IsPreloadedSTS( |
1151 const std::string& canonicalized_host, | 1264 const std::string& canonicalized_host, |
1152 bool sni_available, | 1265 bool sni_available, |
1153 DomainState* out) { | 1266 DomainState* out) { |
1154 DCHECK(CalledOnValidThread()); | 1267 DCHECK(CalledOnValidThread()); |
1155 | 1268 |
1156 out->preloaded = true; | 1269 out->preloaded = true; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1223 } | 1336 } |
1224 | 1337 |
1225 LOG(ERROR) << "Rejecting public key chain for domain " << domain | 1338 LOG(ERROR) << "Rejecting public key chain for domain " << domain |
1226 << ". Validated chain: " << HashesToBase64String(hashes) | 1339 << ". Validated chain: " << HashesToBase64String(hashes) |
1227 << ", expected: " << HashesToBase64String(public_key_hashes); | 1340 << ", expected: " << HashesToBase64String(public_key_hashes); |
1228 | 1341 |
1229 return false; | 1342 return false; |
1230 } | 1343 } |
1231 | 1344 |
1232 } // namespace | 1345 } // namespace |
OLD | NEW |