• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "net/http/transport_security_state.h"
6 
7 #if defined(USE_OPENSSL)
8 #include <openssl/ecdsa.h>
9 #include <openssl/ssl.h>
10 #else  // !defined(USE_OPENSSL)
11 #include <cryptohi.h>
12 #include <hasht.h>
13 #include <keyhi.h>
14 #include <nspr.h>
15 #include <pk11pub.h>
16 #endif
17 
18 #include <algorithm>
19 
20 #include "base/base64.h"
21 #include "base/build_time.h"
22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram.h"
25 #include "base/sha1.h"
26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/time/time.h"
30 #include "base/values.h"
31 #include "crypto/sha2.h"
32 #include "net/base/dns_util.h"
33 #include "net/cert/x509_cert_types.h"
34 #include "net/cert/x509_certificate.h"
35 #include "net/http/http_security_headers.h"
36 #include "net/ssl/ssl_info.h"
37 #include "url/gurl.h"
38 
39 #if defined(USE_OPENSSL)
40 #include "crypto/openssl_util.h"
41 #endif
42 
43 namespace net {
44 
45 namespace {
46 
HashesToBase64String(const HashValueVector & hashes)47 std::string HashesToBase64String(const HashValueVector& hashes) {
48   std::string str;
49   for (size_t i = 0; i != hashes.size(); ++i) {
50     if (i != 0)
51       str += ",";
52     str += hashes[i].ToString();
53   }
54   return str;
55 }
56 
HashHost(const std::string & canonicalized_host)57 std::string HashHost(const std::string& canonicalized_host) {
58   char hashed[crypto::kSHA256Length];
59   crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
60   return std::string(hashed, sizeof(hashed));
61 }
62 
63 // Returns true if the intersection of |a| and |b| is not empty. If either
64 // |a| or |b| is empty, returns false.
HashesIntersect(const HashValueVector & a,const HashValueVector & b)65 bool HashesIntersect(const HashValueVector& a,
66                      const HashValueVector& b) {
67   for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
68     HashValueVector::const_iterator j =
69         std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
70     if (j != b.end())
71       return true;
72   }
73   return false;
74 }
75 
AddHash(const char * sha1_hash,HashValueVector * out)76 bool AddHash(const char* sha1_hash,
77              HashValueVector* out) {
78   HashValue hash(HASH_VALUE_SHA1);
79   memcpy(hash.data(), sha1_hash, hash.size());
80   out->push_back(hash);
81   return true;
82 }
83 
84 }  // namespace
85 
TransportSecurityState()86 TransportSecurityState::TransportSecurityState()
87   : delegate_(NULL) {
88   DCHECK(CalledOnValidThread());
89 }
90 
Iterator(const TransportSecurityState & state)91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
92     : iterator_(state.enabled_hosts_.begin()),
93       end_(state.enabled_hosts_.end()) {
94 }
95 
~Iterator()96 TransportSecurityState::Iterator::~Iterator() {}
97 
ShouldSSLErrorsBeFatal(const std::string & host,bool sni_enabled)98 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host,
99                                                     bool sni_enabled) {
100   DomainState state;
101   if (GetStaticDomainState(host, sni_enabled, &state))
102     return true;
103   return GetDynamicDomainState(host, &state);
104 }
105 
ShouldUpgradeToSSL(const std::string & host,bool sni_enabled)106 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host,
107                                                 bool sni_enabled) {
108   DomainState dynamic_state;
109   if (GetDynamicDomainState(host, &dynamic_state))
110     return dynamic_state.ShouldUpgradeToSSL();
111 
112   DomainState static_state;
113   if (GetStaticDomainState(host, sni_enabled, &static_state) &&
114       static_state.ShouldUpgradeToSSL()) {
115       return true;
116   }
117 
118   return false;
119 }
120 
CheckPublicKeyPins(const std::string & host,bool sni_enabled,const HashValueVector & hashes,std::string * failure_log)121 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host,
122                                                 bool sni_enabled,
123                                                 const HashValueVector& hashes,
124                                                 std::string* failure_log) {
125   DomainState dynamic_state;
126   if (GetDynamicDomainState(host, &dynamic_state))
127     return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
128 
129   DomainState static_state;
130   if (GetStaticDomainState(host, sni_enabled, &static_state) &&
131       static_state.CheckPublicKeyPins(hashes, failure_log)) {
132       return true;
133   }
134 
135   return false;
136 }
137 
HasPublicKeyPins(const std::string & host,bool sni_enabled)138 bool TransportSecurityState::HasPublicKeyPins(const std::string& host,
139                                               bool sni_enabled) {
140   DomainState dynamic_state;
141   if (GetDynamicDomainState(host, &dynamic_state))
142     return dynamic_state.HasPublicKeyPins();
143 
144   DomainState static_state;
145   if (GetStaticDomainState(host, sni_enabled, &static_state)) {
146     if (static_state.HasPublicKeyPins())
147       return true;
148   }
149 
150   return false;
151 }
152 
SetDelegate(TransportSecurityState::Delegate * delegate)153 void TransportSecurityState::SetDelegate(
154     TransportSecurityState::Delegate* delegate) {
155   DCHECK(CalledOnValidThread());
156   delegate_ = delegate;
157 }
158 
EnableHost(const std::string & host,const DomainState & state)159 void TransportSecurityState::EnableHost(const std::string& host,
160                                         const DomainState& state) {
161   DCHECK(CalledOnValidThread());
162 
163   const std::string canonicalized_host = CanonicalizeHost(host);
164   if (canonicalized_host.empty())
165     return;
166 
167   DomainState state_copy(state);
168   // No need to store this value since it is redundant. (|canonicalized_host|
169   // is the map key.)
170   state_copy.domain.clear();
171 
172   enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
173   DirtyNotify();
174 }
175 
DeleteDynamicDataForHost(const std::string & host)176 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
177   DCHECK(CalledOnValidThread());
178 
179   const std::string canonicalized_host = CanonicalizeHost(host);
180   if (canonicalized_host.empty())
181     return false;
182 
183   DomainStateMap::iterator i = enabled_hosts_.find(
184       HashHost(canonicalized_host));
185   if (i != enabled_hosts_.end()) {
186     enabled_hosts_.erase(i);
187     DirtyNotify();
188     return true;
189   }
190   return false;
191 }
192 
ClearDynamicData()193 void TransportSecurityState::ClearDynamicData() {
194   DCHECK(CalledOnValidThread());
195   enabled_hosts_.clear();
196 }
197 
DeleteAllDynamicDataSince(const base::Time & time)198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
199   DCHECK(CalledOnValidThread());
200 
201   bool dirtied = false;
202   DomainStateMap::iterator i = enabled_hosts_.begin();
203   while (i != enabled_hosts_.end()) {
204     if (i->second.sts.last_observed >= time &&
205         i->second.pkp.last_observed >= time) {
206       dirtied = true;
207       enabled_hosts_.erase(i++);
208       continue;
209     }
210 
211     if (i->second.sts.last_observed >= time) {
212       dirtied = true;
213       i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
214     } else if (i->second.pkp.last_observed >= time) {
215       dirtied = true;
216       i->second.pkp.spki_hashes.clear();
217       i->second.pkp.expiry = base::Time();
218     }
219     ++i;
220   }
221 
222   if (dirtied)
223     DirtyNotify();
224 }
225 
~TransportSecurityState()226 TransportSecurityState::~TransportSecurityState() {
227   DCHECK(CalledOnValidThread());
228 }
229 
DirtyNotify()230 void TransportSecurityState::DirtyNotify() {
231   DCHECK(CalledOnValidThread());
232 
233   if (delegate_)
234     delegate_->StateIsDirty(this);
235 }
236 
237 // static
CanonicalizeHost(const std::string & host)238 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
239   // We cannot perform the operations as detailed in the spec here as |host|
240   // has already undergone IDN processing before it reached us. Thus, we check
241   // that there are no invalid characters in the host and lowercase the result.
242 
243   std::string new_host;
244   if (!DNSDomainFromDot(host, &new_host)) {
245     // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
246     // name is >255 bytes. However, search terms can have those properties.
247     return std::string();
248   }
249 
250   for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
251     const unsigned label_length = static_cast<unsigned>(new_host[i]);
252     if (!label_length)
253       break;
254 
255     for (size_t j = 0; j < label_length; ++j) {
256       new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
257     }
258   }
259 
260   return new_host;
261 }
262 
263 // |ReportUMAOnPinFailure| uses these to report which domain was associated
264 // with the public key pinning failure.
265 //
266 // DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new
267 // domains at the END of the listing (but before DOMAIN_NUM_EVENTS).
268 enum SecondLevelDomainName {
269   DOMAIN_NOT_PINNED,
270 
271   DOMAIN_GOOGLE_COM,
272   DOMAIN_ANDROID_COM,
273   DOMAIN_GOOGLE_ANALYTICS_COM,
274   DOMAIN_GOOGLEPLEX_COM,
275   DOMAIN_YTIMG_COM,
276   DOMAIN_GOOGLEUSERCONTENT_COM,
277   DOMAIN_YOUTUBE_COM,
278   DOMAIN_GOOGLEAPIS_COM,
279   DOMAIN_GOOGLEADSERVICES_COM,
280   DOMAIN_GOOGLECODE_COM,
281   DOMAIN_APPSPOT_COM,
282   DOMAIN_GOOGLESYNDICATION_COM,
283   DOMAIN_DOUBLECLICK_NET,
284   DOMAIN_GSTATIC_COM,
285   DOMAIN_GMAIL_COM,
286   DOMAIN_GOOGLEMAIL_COM,
287   DOMAIN_GOOGLEGROUPS_COM,
288 
289   DOMAIN_TORPROJECT_ORG,
290 
291   DOMAIN_TWITTER_COM,
292   DOMAIN_TWIMG_COM,
293 
294   DOMAIN_AKAMAIHD_NET,
295 
296   DOMAIN_TOR2WEB_ORG,
297 
298   DOMAIN_YOUTU_BE,
299   DOMAIN_GOOGLECOMMERCE_COM,
300   DOMAIN_URCHIN_COM,
301   DOMAIN_GOO_GL,
302   DOMAIN_G_CO,
303   DOMAIN_GOOGLE_AC,
304   DOMAIN_GOOGLE_AD,
305   DOMAIN_GOOGLE_AE,
306   DOMAIN_GOOGLE_AF,
307   DOMAIN_GOOGLE_AG,
308   DOMAIN_GOOGLE_AM,
309   DOMAIN_GOOGLE_AS,
310   DOMAIN_GOOGLE_AT,
311   DOMAIN_GOOGLE_AZ,
312   DOMAIN_GOOGLE_BA,
313   DOMAIN_GOOGLE_BE,
314   DOMAIN_GOOGLE_BF,
315   DOMAIN_GOOGLE_BG,
316   DOMAIN_GOOGLE_BI,
317   DOMAIN_GOOGLE_BJ,
318   DOMAIN_GOOGLE_BS,
319   DOMAIN_GOOGLE_BY,
320   DOMAIN_GOOGLE_CA,
321   DOMAIN_GOOGLE_CAT,
322   DOMAIN_GOOGLE_CC,
323   DOMAIN_GOOGLE_CD,
324   DOMAIN_GOOGLE_CF,
325   DOMAIN_GOOGLE_CG,
326   DOMAIN_GOOGLE_CH,
327   DOMAIN_GOOGLE_CI,
328   DOMAIN_GOOGLE_CL,
329   DOMAIN_GOOGLE_CM,
330   DOMAIN_GOOGLE_CN,
331   DOMAIN_CO_AO,
332   DOMAIN_CO_BW,
333   DOMAIN_CO_CK,
334   DOMAIN_CO_CR,
335   DOMAIN_CO_HU,
336   DOMAIN_CO_ID,
337   DOMAIN_CO_IL,
338   DOMAIN_CO_IM,
339   DOMAIN_CO_IN,
340   DOMAIN_CO_JE,
341   DOMAIN_CO_JP,
342   DOMAIN_CO_KE,
343   DOMAIN_CO_KR,
344   DOMAIN_CO_LS,
345   DOMAIN_CO_MA,
346   DOMAIN_CO_MZ,
347   DOMAIN_CO_NZ,
348   DOMAIN_CO_TH,
349   DOMAIN_CO_TZ,
350   DOMAIN_CO_UG,
351   DOMAIN_CO_UK,
352   DOMAIN_CO_UZ,
353   DOMAIN_CO_VE,
354   DOMAIN_CO_VI,
355   DOMAIN_CO_ZA,
356   DOMAIN_CO_ZM,
357   DOMAIN_CO_ZW,
358   DOMAIN_COM_AF,
359   DOMAIN_COM_AG,
360   DOMAIN_COM_AI,
361   DOMAIN_COM_AR,
362   DOMAIN_COM_AU,
363   DOMAIN_COM_BD,
364   DOMAIN_COM_BH,
365   DOMAIN_COM_BN,
366   DOMAIN_COM_BO,
367   DOMAIN_COM_BR,
368   DOMAIN_COM_BY,
369   DOMAIN_COM_BZ,
370   DOMAIN_COM_CN,
371   DOMAIN_COM_CO,
372   DOMAIN_COM_CU,
373   DOMAIN_COM_CY,
374   DOMAIN_COM_DO,
375   DOMAIN_COM_EC,
376   DOMAIN_COM_EG,
377   DOMAIN_COM_ET,
378   DOMAIN_COM_FJ,
379   DOMAIN_COM_GE,
380   DOMAIN_COM_GH,
381   DOMAIN_COM_GI,
382   DOMAIN_COM_GR,
383   DOMAIN_COM_GT,
384   DOMAIN_COM_HK,
385   DOMAIN_COM_IQ,
386   DOMAIN_COM_JM,
387   DOMAIN_COM_JO,
388   DOMAIN_COM_KH,
389   DOMAIN_COM_KW,
390   DOMAIN_COM_LB,
391   DOMAIN_COM_LY,
392   DOMAIN_COM_MT,
393   DOMAIN_COM_MX,
394   DOMAIN_COM_MY,
395   DOMAIN_COM_NA,
396   DOMAIN_COM_NF,
397   DOMAIN_COM_NG,
398   DOMAIN_COM_NI,
399   DOMAIN_COM_NP,
400   DOMAIN_COM_NR,
401   DOMAIN_COM_OM,
402   DOMAIN_COM_PA,
403   DOMAIN_COM_PE,
404   DOMAIN_COM_PH,
405   DOMAIN_COM_PK,
406   DOMAIN_COM_PL,
407   DOMAIN_COM_PR,
408   DOMAIN_COM_PY,
409   DOMAIN_COM_QA,
410   DOMAIN_COM_RU,
411   DOMAIN_COM_SA,
412   DOMAIN_COM_SB,
413   DOMAIN_COM_SG,
414   DOMAIN_COM_SL,
415   DOMAIN_COM_SV,
416   DOMAIN_COM_TJ,
417   DOMAIN_COM_TN,
418   DOMAIN_COM_TR,
419   DOMAIN_COM_TW,
420   DOMAIN_COM_UA,
421   DOMAIN_COM_UY,
422   DOMAIN_COM_VC,
423   DOMAIN_COM_VE,
424   DOMAIN_COM_VN,
425   DOMAIN_GOOGLE_CV,
426   DOMAIN_GOOGLE_CZ,
427   DOMAIN_GOOGLE_DE,
428   DOMAIN_GOOGLE_DJ,
429   DOMAIN_GOOGLE_DK,
430   DOMAIN_GOOGLE_DM,
431   DOMAIN_GOOGLE_DZ,
432   DOMAIN_GOOGLE_EE,
433   DOMAIN_GOOGLE_ES,
434   DOMAIN_GOOGLE_FI,
435   DOMAIN_GOOGLE_FM,
436   DOMAIN_GOOGLE_FR,
437   DOMAIN_GOOGLE_GA,
438   DOMAIN_GOOGLE_GE,
439   DOMAIN_GOOGLE_GG,
440   DOMAIN_GOOGLE_GL,
441   DOMAIN_GOOGLE_GM,
442   DOMAIN_GOOGLE_GP,
443   DOMAIN_GOOGLE_GR,
444   DOMAIN_GOOGLE_GY,
445   DOMAIN_GOOGLE_HK,
446   DOMAIN_GOOGLE_HN,
447   DOMAIN_GOOGLE_HR,
448   DOMAIN_GOOGLE_HT,
449   DOMAIN_GOOGLE_HU,
450   DOMAIN_GOOGLE_IE,
451   DOMAIN_GOOGLE_IM,
452   DOMAIN_GOOGLE_INFO,
453   DOMAIN_GOOGLE_IQ,
454   DOMAIN_GOOGLE_IS,
455   DOMAIN_GOOGLE_IT,
456   DOMAIN_IT_AO,
457   DOMAIN_GOOGLE_JE,
458   DOMAIN_GOOGLE_JO,
459   DOMAIN_GOOGLE_JOBS,
460   DOMAIN_GOOGLE_JP,
461   DOMAIN_GOOGLE_KG,
462   DOMAIN_GOOGLE_KI,
463   DOMAIN_GOOGLE_KZ,
464   DOMAIN_GOOGLE_LA,
465   DOMAIN_GOOGLE_LI,
466   DOMAIN_GOOGLE_LK,
467   DOMAIN_GOOGLE_LT,
468   DOMAIN_GOOGLE_LU,
469   DOMAIN_GOOGLE_LV,
470   DOMAIN_GOOGLE_MD,
471   DOMAIN_GOOGLE_ME,
472   DOMAIN_GOOGLE_MG,
473   DOMAIN_GOOGLE_MK,
474   DOMAIN_GOOGLE_ML,
475   DOMAIN_GOOGLE_MN,
476   DOMAIN_GOOGLE_MS,
477   DOMAIN_GOOGLE_MU,
478   DOMAIN_GOOGLE_MV,
479   DOMAIN_GOOGLE_MW,
480   DOMAIN_GOOGLE_NE,
481   DOMAIN_NE_JP,
482   DOMAIN_GOOGLE_NET,
483   DOMAIN_GOOGLE_NL,
484   DOMAIN_GOOGLE_NO,
485   DOMAIN_GOOGLE_NR,
486   DOMAIN_GOOGLE_NU,
487   DOMAIN_OFF_AI,
488   DOMAIN_GOOGLE_PK,
489   DOMAIN_GOOGLE_PL,
490   DOMAIN_GOOGLE_PN,
491   DOMAIN_GOOGLE_PS,
492   DOMAIN_GOOGLE_PT,
493   DOMAIN_GOOGLE_RO,
494   DOMAIN_GOOGLE_RS,
495   DOMAIN_GOOGLE_RU,
496   DOMAIN_GOOGLE_RW,
497   DOMAIN_GOOGLE_SC,
498   DOMAIN_GOOGLE_SE,
499   DOMAIN_GOOGLE_SH,
500   DOMAIN_GOOGLE_SI,
501   DOMAIN_GOOGLE_SK,
502   DOMAIN_GOOGLE_SM,
503   DOMAIN_GOOGLE_SN,
504   DOMAIN_GOOGLE_SO,
505   DOMAIN_GOOGLE_ST,
506   DOMAIN_GOOGLE_TD,
507   DOMAIN_GOOGLE_TG,
508   DOMAIN_GOOGLE_TK,
509   DOMAIN_GOOGLE_TL,
510   DOMAIN_GOOGLE_TM,
511   DOMAIN_GOOGLE_TN,
512   DOMAIN_GOOGLE_TO,
513   DOMAIN_GOOGLE_TP,
514   DOMAIN_GOOGLE_TT,
515   DOMAIN_GOOGLE_US,
516   DOMAIN_GOOGLE_UZ,
517   DOMAIN_GOOGLE_VG,
518   DOMAIN_GOOGLE_VU,
519   DOMAIN_GOOGLE_WS,
520 
521   DOMAIN_CHROMIUM_ORG,
522 
523   DOMAIN_CRYPTO_CAT,
524   DOMAIN_LAVABIT_COM,
525 
526   DOMAIN_GOOGLETAGMANAGER_COM,
527   DOMAIN_GOOGLETAGSERVICES_COM,
528 
529   // Boundary value for UMA_HISTOGRAM_ENUMERATION:
530   DOMAIN_NUM_EVENTS
531 };
532 
533 // PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site.
534 // The validated certificate chain for the site must not include any of
535 // |excluded_hashes| and must include one or more of |required_hashes|.
536 struct PublicKeyPins {
537   const char* const* required_hashes;
538   const char* const* excluded_hashes;
539 };
540 
541 struct HSTSPreload {
542   uint8 length;
543   bool include_subdomains;
544   char dns_name[38];
545   bool https_required;
546   PublicKeyPins pins;
547   SecondLevelDomainName second_level_domain_name;
548 };
549 
HasPreload(const struct HSTSPreload * entries,size_t num_entries,const std::string & canonicalized_host,size_t i,TransportSecurityState::DomainState * out,bool * ret)550 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
551                        const std::string& canonicalized_host, size_t i,
552                        TransportSecurityState::DomainState* out, bool* ret) {
553   for (size_t j = 0; j < num_entries; j++) {
554     if (entries[j].length == canonicalized_host.size() - i &&
555         memcmp(entries[j].dns_name, &canonicalized_host[i],
556                entries[j].length) == 0) {
557       if (!entries[j].include_subdomains && i != 0) {
558         *ret = false;
559       } else {
560         out->sts.include_subdomains = entries[j].include_subdomains;
561         out->sts.last_observed = base::GetBuildTime();
562         out->pkp.include_subdomains = entries[j].include_subdomains;
563         out->pkp.last_observed = base::GetBuildTime();
564         *ret = true;
565         out->sts.upgrade_mode =
566             TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
567         if (!entries[j].https_required)
568           out->sts.upgrade_mode =
569               TransportSecurityState::DomainState::MODE_DEFAULT;
570         if (entries[j].pins.required_hashes) {
571           const char* const* sha1_hash = entries[j].pins.required_hashes;
572           while (*sha1_hash) {
573             AddHash(*sha1_hash, &out->pkp.spki_hashes);
574             sha1_hash++;
575           }
576         }
577         if (entries[j].pins.excluded_hashes) {
578           const char* const* sha1_hash = entries[j].pins.excluded_hashes;
579           while (*sha1_hash) {
580             AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
581             sha1_hash++;
582           }
583         }
584       }
585       return true;
586     }
587   }
588   return false;
589 }
590 
591 #include "net/http/transport_security_state_static.h"
592 
593 // Returns the HSTSPreload entry for the |canonicalized_host| in |entries|,
594 // or NULL if there is none. Prefers exact hostname matches to those that
595 // match only because HSTSPreload.include_subdomains is true.
596 //
597 // |canonicalized_host| should be the hostname as canonicalized by
598 // CanonicalizeHost.
GetHSTSPreload(const std::string & canonicalized_host,const struct HSTSPreload * entries,size_t num_entries)599 static const struct HSTSPreload* GetHSTSPreload(
600     const std::string& canonicalized_host,
601     const struct HSTSPreload* entries,
602     size_t num_entries) {
603   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
604     for (size_t j = 0; j < num_entries; j++) {
605       const struct HSTSPreload* entry = entries + j;
606 
607       if (i != 0 && !entry->include_subdomains)
608         continue;
609 
610       if (entry->length == canonicalized_host.size() - i &&
611           memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
612         return entry;
613       }
614     }
615   }
616 
617   return NULL;
618 }
619 
AddHSTSHeader(const std::string & host,const std::string & value)620 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
621                                            const std::string& value) {
622   DCHECK(CalledOnValidThread());
623 
624   base::Time now = base::Time::Now();
625   base::TimeDelta max_age;
626   TransportSecurityState::DomainState domain_state;
627   GetDynamicDomainState(host, &domain_state);
628   if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) {
629     // Handle max-age == 0.
630     if (max_age.InSeconds() == 0)
631       domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT;
632     else
633       domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
634     domain_state.sts.last_observed = now;
635     domain_state.sts.expiry = now + max_age;
636     EnableHost(host, domain_state);
637     return true;
638   }
639   return false;
640 }
641 
AddHPKPHeader(const std::string & host,const std::string & value,const SSLInfo & ssl_info)642 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
643                                            const std::string& value,
644                                            const SSLInfo& ssl_info) {
645   DCHECK(CalledOnValidThread());
646 
647   base::Time now = base::Time::Now();
648   base::TimeDelta max_age;
649   TransportSecurityState::DomainState domain_state;
650   GetDynamicDomainState(host, &domain_state);
651   if (ParseHPKPHeader(value,
652                       ssl_info.public_key_hashes,
653                       &max_age,
654                       &domain_state.pkp.include_subdomains,
655                       &domain_state.pkp.spki_hashes)) {
656     // Handle max-age == 0.
657     if (max_age.InSeconds() == 0)
658       domain_state.pkp.spki_hashes.clear();
659     domain_state.pkp.last_observed = now;
660     domain_state.pkp.expiry = now + max_age;
661     EnableHost(host, domain_state);
662     return true;
663   }
664   return false;
665 }
666 
AddHSTS(const std::string & host,const base::Time & expiry,bool include_subdomains)667 bool TransportSecurityState::AddHSTS(const std::string& host,
668                                      const base::Time& expiry,
669                                      bool include_subdomains) {
670   DCHECK(CalledOnValidThread());
671 
672   // Copy-and-modify the existing DomainState for this host (if any).
673   TransportSecurityState::DomainState domain_state;
674   const std::string canonicalized_host = CanonicalizeHost(host);
675   const std::string hashed_host = HashHost(canonicalized_host);
676   DomainStateMap::const_iterator i = enabled_hosts_.find(
677       hashed_host);
678   if (i != enabled_hosts_.end())
679     domain_state = i->second;
680 
681   domain_state.sts.last_observed = base::Time::Now();
682   domain_state.sts.include_subdomains = include_subdomains;
683   domain_state.sts.expiry = expiry;
684   domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
685   EnableHost(host, domain_state);
686   return true;
687 }
688 
AddHPKP(const std::string & host,const base::Time & expiry,bool include_subdomains,const HashValueVector & hashes)689 bool TransportSecurityState::AddHPKP(const std::string& host,
690                                      const base::Time& expiry,
691                                      bool include_subdomains,
692                                      const HashValueVector& hashes) {
693   DCHECK(CalledOnValidThread());
694 
695   // Copy-and-modify the existing DomainState for this host (if any).
696   TransportSecurityState::DomainState domain_state;
697   const std::string canonicalized_host = CanonicalizeHost(host);
698   const std::string hashed_host = HashHost(canonicalized_host);
699   DomainStateMap::const_iterator i = enabled_hosts_.find(
700       hashed_host);
701   if (i != enabled_hosts_.end())
702     domain_state = i->second;
703 
704   domain_state.pkp.last_observed = base::Time::Now();
705   domain_state.pkp.include_subdomains = include_subdomains;
706   domain_state.pkp.expiry = expiry;
707   domain_state.pkp.spki_hashes = hashes;
708   EnableHost(host, domain_state);
709   return true;
710 }
711 
712 // static
IsGooglePinnedProperty(const std::string & host,bool sni_enabled)713 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
714                                                     bool sni_enabled) {
715   std::string canonicalized_host = CanonicalizeHost(host);
716   const struct HSTSPreload* entry =
717       GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
718 
719   if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
720     return true;
721 
722   if (sni_enabled) {
723     entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
724                            kNumPreloadedSNISTS);
725     if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
726       return true;
727   }
728 
729   return false;
730 }
731 
732 // static
ReportUMAOnPinFailure(const std::string & host)733 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
734   std::string canonicalized_host = CanonicalizeHost(host);
735 
736   const struct HSTSPreload* entry =
737       GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
738 
739   if (!entry) {
740     entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
741                            kNumPreloadedSNISTS);
742   }
743 
744   if (!entry) {
745     // We don't care to report pin failures for dynamic pins.
746     return;
747   }
748 
749   DCHECK(entry);
750   DCHECK(entry->pins.required_hashes);
751   DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
752 
753   UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
754                             entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
755 }
756 
757 // static
IsBuildTimely()758 bool TransportSecurityState::IsBuildTimely() {
759   const base::Time build_time = base::GetBuildTime();
760   // We consider built-in information to be timely for 10 weeks.
761   return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
762 }
763 
GetStaticDomainState(const std::string & host,bool sni_enabled,DomainState * out) const764 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
765                                                   bool sni_enabled,
766                                                   DomainState* out) const {
767   DCHECK(CalledOnValidThread());
768 
769   const std::string canonicalized_host = CanonicalizeHost(host);
770 
771   out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
772   out->sts.include_subdomains = false;
773   out->pkp.include_subdomains = false;
774 
775   const bool is_build_timely = IsBuildTimely();
776 
777   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
778     std::string host_sub_chunk(&canonicalized_host[i],
779                                canonicalized_host.size() - i);
780     out->domain = DNSDomainToString(host_sub_chunk);
781     bool ret;
782     if (is_build_timely &&
783         HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
784                    &ret)) {
785       return ret;
786     }
787     if (sni_enabled &&
788         is_build_timely &&
789         HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i,
790                    out, &ret)) {
791       return ret;
792     }
793   }
794 
795   return false;
796 }
797 
GetDynamicDomainState(const std::string & host,DomainState * result)798 bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
799                                                    DomainState* result) {
800   DCHECK(CalledOnValidThread());
801 
802   DomainState state;
803   const std::string canonicalized_host = CanonicalizeHost(host);
804   if (canonicalized_host.empty())
805     return false;
806 
807   base::Time current_time(base::Time::Now());
808 
809   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
810     std::string host_sub_chunk(&canonicalized_host[i],
811                                canonicalized_host.size() - i);
812     DomainStateMap::iterator j =
813         enabled_hosts_.find(HashHost(host_sub_chunk));
814     if (j == enabled_hosts_.end())
815       continue;
816 
817     if (current_time > j->second.sts.expiry &&
818         current_time > j->second.pkp.expiry) {
819       enabled_hosts_.erase(j);
820       DirtyNotify();
821       continue;
822     }
823 
824     state = j->second;
825     state.domain = DNSDomainToString(host_sub_chunk);
826 
827     // Succeed if we matched the domain exactly or if subdomain matches are
828     // allowed.
829     if (i == 0 || j->second.sts.include_subdomains ||
830         j->second.pkp.include_subdomains) {
831       *result = state;
832       return true;
833     }
834 
835     return false;
836   }
837 
838   return false;
839 }
840 
AddOrUpdateEnabledHosts(const std::string & hashed_host,const DomainState & state)841 void TransportSecurityState::AddOrUpdateEnabledHosts(
842     const std::string& hashed_host, const DomainState& state) {
843   DCHECK(CalledOnValidThread());
844   enabled_hosts_[hashed_host] = state;
845 }
846 
DomainState()847 TransportSecurityState::DomainState::DomainState() {
848   sts.upgrade_mode = MODE_DEFAULT;
849   sts.include_subdomains = false;
850   pkp.include_subdomains = false;
851 }
852 
~DomainState()853 TransportSecurityState::DomainState::~DomainState() {
854 }
855 
CheckPublicKeyPins(const HashValueVector & hashes,std::string * failure_log) const856 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
857     const HashValueVector& hashes, std::string* failure_log) const {
858   // Validate that hashes is not empty. By the time this code is called (in
859   // production), that should never happen, but it's good to be defensive.
860   // And, hashes *can* be empty in some test scenarios.
861   if (hashes.empty()) {
862     failure_log->append(
863         "Rejecting empty public key chain for public-key-pinned domains: " +
864         domain);
865     return false;
866   }
867 
868   if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
869     failure_log->append("Rejecting public key chain for domain " + domain +
870                         ". Validated chain: " + HashesToBase64String(hashes) +
871                         ", matches one or more bad hashes: " +
872                         HashesToBase64String(pkp.bad_spki_hashes));
873     return false;
874   }
875 
876   // If there are no pins, then any valid chain is acceptable.
877   if (pkp.spki_hashes.empty())
878     return true;
879 
880   if (HashesIntersect(pkp.spki_hashes, hashes)) {
881     return true;
882   }
883 
884   failure_log->append("Rejecting public key chain for domain " + domain +
885                       ". Validated chain: " + HashesToBase64String(hashes) +
886                       ", expected: " + HashesToBase64String(pkp.spki_hashes));
887   return false;
888 }
889 
ShouldUpgradeToSSL() const890 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
891   return sts.upgrade_mode == MODE_FORCE_HTTPS;
892 }
893 
ShouldSSLErrorsBeFatal() const894 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
895   return true;
896 }
897 
HasPublicKeyPins() const898 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
899   return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
900 }
901 
PKPState()902 TransportSecurityState::DomainState::PKPState::PKPState() {
903 }
904 
~PKPState()905 TransportSecurityState::DomainState::PKPState::~PKPState() {
906 }
907 
908 }  // namespace
909