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