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