• 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 #include <algorithm>
8 #include <string>
9 #include <vector>
10 
11 #include "base/base64.h"
12 #include "base/files/file_path.h"
13 #include "base/sha1.h"
14 #include "base/strings/string_piece.h"
15 #include "crypto/sha2.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_log.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/base/test_data_directory.h"
20 #include "net/cert/asn1_util.h"
21 #include "net/cert/cert_verifier.h"
22 #include "net/cert/cert_verify_result.h"
23 #include "net/cert/test_root_certs.h"
24 #include "net/cert/x509_cert_types.h"
25 #include "net/cert/x509_certificate.h"
26 #include "net/http/http_util.h"
27 #include "net/ssl/ssl_info.h"
28 #include "net/test/cert_test_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 
31 #if defined(USE_OPENSSL)
32 #include "crypto/openssl_util.h"
33 #else
34 #include "crypto/nss_util.h"
35 #endif
36 
37 namespace net {
38 
39 class TransportSecurityStateTest : public testing::Test {
SetUp()40   virtual void SetUp() {
41 #if defined(USE_OPENSSL)
42     crypto::EnsureOpenSSLInit();
43 #else
44     crypto::EnsureNSSInit();
45 #endif
46   }
47 
48  protected:
CanonicalizeHost(const std::string & host)49   std::string CanonicalizeHost(const std::string& host) {
50     return TransportSecurityState::CanonicalizeHost(host);
51   }
52 
GetStaticDomainState(TransportSecurityState * state,const std::string & host,bool sni_enabled,TransportSecurityState::DomainState * result)53   bool GetStaticDomainState(TransportSecurityState* state,
54                             const std::string& host,
55                             bool sni_enabled,
56                             TransportSecurityState::DomainState* result) {
57     return state->GetStaticDomainState(host, sni_enabled, result);
58   }
59 
EnableHost(TransportSecurityState * state,const std::string & host,const TransportSecurityState::DomainState & domain_state)60   void EnableHost(TransportSecurityState* state,
61                   const std::string& host,
62                   const TransportSecurityState::DomainState& domain_state) {
63     return state->EnableHost(host, domain_state);
64   }
65 };
66 
TEST_F(TransportSecurityStateTest,SimpleMatches)67 TEST_F(TransportSecurityStateTest, SimpleMatches) {
68   TransportSecurityState state;
69   TransportSecurityState::DomainState domain_state;
70   const base::Time current_time(base::Time::Now());
71   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
72 
73   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
74   bool include_subdomains = false;
75   state.AddHSTS("yahoo.com", expiry, include_subdomains);
76   EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
77 }
78 
TEST_F(TransportSecurityStateTest,MatchesCase1)79 TEST_F(TransportSecurityStateTest, MatchesCase1) {
80   TransportSecurityState state;
81   TransportSecurityState::DomainState domain_state;
82   const base::Time current_time(base::Time::Now());
83   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
84 
85   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
86   bool include_subdomains = false;
87   state.AddHSTS("YAhoo.coM", expiry, include_subdomains);
88   EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
89 }
90 
TEST_F(TransportSecurityStateTest,MatchesCase2)91 TEST_F(TransportSecurityStateTest, MatchesCase2) {
92   TransportSecurityState state;
93   TransportSecurityState::DomainState domain_state;
94   const base::Time current_time(base::Time::Now());
95   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
96 
97   EXPECT_FALSE(state.GetDomainState("YAhoo.coM", true, &domain_state));
98   bool include_subdomains = false;
99   state.AddHSTS("yahoo.com", expiry, include_subdomains);
100   EXPECT_TRUE(state.GetDomainState("YAhoo.coM", true, &domain_state));
101 }
102 
TEST_F(TransportSecurityStateTest,SubdomainMatches)103 TEST_F(TransportSecurityStateTest, SubdomainMatches) {
104   TransportSecurityState state;
105   TransportSecurityState::DomainState domain_state;
106   const base::Time current_time(base::Time::Now());
107   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
108 
109   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
110   bool include_subdomains = true;
111   state.AddHSTS("yahoo.com", expiry, include_subdomains);
112   EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
113   EXPECT_TRUE(state.GetDomainState("foo.yahoo.com", true, &domain_state));
114   EXPECT_TRUE(state.GetDomainState("foo.bar.yahoo.com", true, &domain_state));
115   EXPECT_TRUE(state.GetDomainState("foo.bar.baz.yahoo.com", true,
116                                    &domain_state));
117   EXPECT_FALSE(state.GetDomainState("com", true, &domain_state));
118 }
119 
TEST_F(TransportSecurityStateTest,InvalidDomains)120 TEST_F(TransportSecurityStateTest, InvalidDomains) {
121   TransportSecurityState state;
122   TransportSecurityState::DomainState domain_state;
123   const base::Time current_time(base::Time::Now());
124   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
125 
126   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
127   bool include_subdomains = true;
128   state.AddHSTS("yahoo.com", expiry, include_subdomains);
129   EXPECT_TRUE(state.GetDomainState("www-.foo.yahoo.com", true, &domain_state));
130   EXPECT_TRUE(state.GetDomainState("2\x01.foo.yahoo.com", true, &domain_state));
131 }
132 
TEST_F(TransportSecurityStateTest,DeleteAllDynamicDataSince)133 TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) {
134   TransportSecurityState state;
135   TransportSecurityState::DomainState domain_state;
136   const base::Time current_time(base::Time::Now());
137   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
138   const base::Time older = current_time - base::TimeDelta::FromSeconds(1000);
139 
140   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
141   bool include_subdomains = false;
142   state.AddHSTS("yahoo.com", expiry, include_subdomains);
143 
144   state.DeleteAllDynamicDataSince(expiry);
145   EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
146   state.DeleteAllDynamicDataSince(older);
147   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
148 }
149 
TEST_F(TransportSecurityStateTest,DeleteDynamicDataForHost)150 TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) {
151   TransportSecurityState state;
152   TransportSecurityState::DomainState domain_state;
153   const base::Time current_time(base::Time::Now());
154   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
155   bool include_subdomains = false;
156   state.AddHSTS("yahoo.com", expiry, include_subdomains);
157 
158   EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
159   EXPECT_FALSE(state.GetDomainState("example.com", true, &domain_state));
160   EXPECT_TRUE(state.DeleteDynamicDataForHost("yahoo.com"));
161   EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
162 }
163 
TEST_F(TransportSecurityStateTest,IsPreloaded)164 TEST_F(TransportSecurityStateTest, IsPreloaded) {
165   const std::string paypal = CanonicalizeHost("paypal.com");
166   const std::string www_paypal = CanonicalizeHost("www.paypal.com");
167   const std::string foo_paypal = CanonicalizeHost("foo.paypal.com");
168   const std::string a_www_paypal = CanonicalizeHost("a.www.paypal.com");
169   const std::string abc_paypal = CanonicalizeHost("a.b.c.paypal.com");
170   const std::string example = CanonicalizeHost("example.com");
171   const std::string aypal = CanonicalizeHost("aypal.com");
172 
173   TransportSecurityState state;
174   TransportSecurityState::DomainState domain_state;
175 
176   EXPECT_TRUE(GetStaticDomainState(&state, paypal, true, &domain_state));
177   EXPECT_TRUE(GetStaticDomainState(&state, www_paypal, true, &domain_state));
178   EXPECT_FALSE(domain_state.sts_include_subdomains);
179   EXPECT_FALSE(domain_state.pkp_include_subdomains);
180   EXPECT_FALSE(GetStaticDomainState(&state, a_www_paypal, true, &domain_state));
181   EXPECT_FALSE(GetStaticDomainState(&state, abc_paypal, true, &domain_state));
182   EXPECT_FALSE(GetStaticDomainState(&state, example, true, &domain_state));
183   EXPECT_FALSE(GetStaticDomainState(&state, aypal, true, &domain_state));
184 }
185 
TEST_F(TransportSecurityStateTest,PreloadedDomainSet)186 TEST_F(TransportSecurityStateTest, PreloadedDomainSet) {
187   TransportSecurityState state;
188   TransportSecurityState::DomainState domain_state;
189 
190   // The domain wasn't being set, leading to a blank string in the
191   // chrome://net-internals/#hsts UI. So test that.
192   EXPECT_TRUE(state.GetDomainState("market.android.com", true, &domain_state));
193   EXPECT_EQ(domain_state.domain, "market.android.com");
194   EXPECT_TRUE(state.GetDomainState("sub.market.android.com", true,
195                                    &domain_state));
196   EXPECT_EQ(domain_state.domain, "market.android.com");
197 }
198 
ShouldRedirect(const char * hostname)199 static bool ShouldRedirect(const char* hostname) {
200   TransportSecurityState state;
201   TransportSecurityState::DomainState domain_state;
202   return state.GetDomainState(hostname, true /* SNI ok */, &domain_state) &&
203          domain_state.ShouldUpgradeToSSL();
204 }
205 
HasState(const char * hostname)206 static bool HasState(const char* hostname) {
207   TransportSecurityState state;
208   TransportSecurityState::DomainState domain_state;
209   return state.GetDomainState(hostname, true /* SNI ok */, &domain_state);
210 }
211 
HasPublicKeyPins(const char * hostname,bool sni_enabled)212 static bool HasPublicKeyPins(const char* hostname, bool sni_enabled) {
213   TransportSecurityState state;
214   TransportSecurityState::DomainState domain_state;
215   if (!state.GetDomainState(hostname, sni_enabled, &domain_state))
216     return false;
217 
218   return domain_state.HasPublicKeyPins();
219 }
220 
HasPublicKeyPins(const char * hostname)221 static bool HasPublicKeyPins(const char* hostname) {
222   return HasPublicKeyPins(hostname, true);
223 }
224 
OnlyPinning(const char * hostname)225 static bool OnlyPinning(const char *hostname) {
226   TransportSecurityState state;
227   TransportSecurityState::DomainState domain_state;
228   if (!state.GetDomainState(hostname, true /* SNI ok */, &domain_state))
229     return false;
230 
231   return (domain_state.static_spki_hashes.size() > 0 ||
232           domain_state.bad_static_spki_hashes.size() > 0 ||
233           domain_state.dynamic_spki_hashes.size() > 0) &&
234          !domain_state.ShouldUpgradeToSSL();
235 }
236 
TEST_F(TransportSecurityStateTest,Preloaded)237 TEST_F(TransportSecurityStateTest, Preloaded) {
238   TransportSecurityState state;
239   TransportSecurityState::DomainState domain_state;
240 
241   // We do more extensive checks for the first domain.
242   EXPECT_TRUE(state.GetDomainState("www.paypal.com", true, &domain_state));
243   EXPECT_EQ(domain_state.upgrade_mode,
244             TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
245   EXPECT_FALSE(domain_state.sts_include_subdomains);
246   EXPECT_FALSE(domain_state.pkp_include_subdomains);
247 
248   EXPECT_TRUE(HasState("paypal.com"));
249   EXPECT_FALSE(HasState("www2.paypal.com"));
250   EXPECT_FALSE(HasState("www2.paypal.com"));
251 
252   // Google hosts:
253 
254   EXPECT_TRUE(ShouldRedirect("chrome.google.com"));
255   EXPECT_TRUE(ShouldRedirect("checkout.google.com"));
256   EXPECT_TRUE(ShouldRedirect("wallet.google.com"));
257   EXPECT_TRUE(ShouldRedirect("docs.google.com"));
258   EXPECT_TRUE(ShouldRedirect("sites.google.com"));
259   EXPECT_TRUE(ShouldRedirect("drive.google.com"));
260   EXPECT_TRUE(ShouldRedirect("spreadsheets.google.com"));
261   EXPECT_TRUE(ShouldRedirect("appengine.google.com"));
262   EXPECT_TRUE(ShouldRedirect("market.android.com"));
263   EXPECT_TRUE(ShouldRedirect("encrypted.google.com"));
264   EXPECT_TRUE(ShouldRedirect("accounts.google.com"));
265   EXPECT_TRUE(ShouldRedirect("profiles.google.com"));
266   EXPECT_TRUE(ShouldRedirect("mail.google.com"));
267   EXPECT_TRUE(ShouldRedirect("chatenabled.mail.google.com"));
268   EXPECT_TRUE(ShouldRedirect("talkgadget.google.com"));
269   EXPECT_TRUE(ShouldRedirect("hostedtalkgadget.google.com"));
270   EXPECT_TRUE(ShouldRedirect("talk.google.com"));
271   EXPECT_TRUE(ShouldRedirect("plus.google.com"));
272   EXPECT_TRUE(ShouldRedirect("groups.google.com"));
273   EXPECT_TRUE(ShouldRedirect("apis.google.com"));
274   EXPECT_FALSE(ShouldRedirect("chart.apis.google.com"));
275   EXPECT_TRUE(ShouldRedirect("ssl.google-analytics.com"));
276   EXPECT_TRUE(ShouldRedirect("gmail.com"));
277   EXPECT_TRUE(ShouldRedirect("www.gmail.com"));
278   EXPECT_TRUE(ShouldRedirect("googlemail.com"));
279   EXPECT_TRUE(ShouldRedirect("www.googlemail.com"));
280   EXPECT_TRUE(ShouldRedirect("googleplex.com"));
281   EXPECT_TRUE(ShouldRedirect("www.googleplex.com"));
282   EXPECT_FALSE(HasState("m.gmail.com"));
283   EXPECT_FALSE(HasState("m.googlemail.com"));
284 
285   EXPECT_TRUE(OnlyPinning("www.google.com"));
286   EXPECT_TRUE(OnlyPinning("foo.google.com"));
287   EXPECT_TRUE(OnlyPinning("google.com"));
288   EXPECT_TRUE(OnlyPinning("www.youtube.com"));
289   EXPECT_TRUE(OnlyPinning("youtube.com"));
290   EXPECT_TRUE(OnlyPinning("i.ytimg.com"));
291   EXPECT_TRUE(OnlyPinning("ytimg.com"));
292   EXPECT_TRUE(OnlyPinning("googleusercontent.com"));
293   EXPECT_TRUE(OnlyPinning("www.googleusercontent.com"));
294   EXPECT_TRUE(OnlyPinning("www.google-analytics.com"));
295   EXPECT_TRUE(OnlyPinning("googleapis.com"));
296   EXPECT_TRUE(OnlyPinning("googleadservices.com"));
297   EXPECT_TRUE(OnlyPinning("googlecode.com"));
298   EXPECT_TRUE(OnlyPinning("appspot.com"));
299   EXPECT_TRUE(OnlyPinning("googlesyndication.com"));
300   EXPECT_TRUE(OnlyPinning("doubleclick.net"));
301   EXPECT_TRUE(OnlyPinning("googlegroups.com"));
302 
303   // Tests for domains that don't work without SNI.
304   EXPECT_FALSE(state.GetDomainState("gmail.com", false, &domain_state));
305   EXPECT_FALSE(state.GetDomainState("www.gmail.com", false, &domain_state));
306   EXPECT_FALSE(state.GetDomainState("m.gmail.com", false, &domain_state));
307   EXPECT_FALSE(state.GetDomainState("googlemail.com", false, &domain_state));
308   EXPECT_FALSE(state.GetDomainState("www.googlemail.com", false,
309                                     &domain_state));
310   EXPECT_FALSE(state.GetDomainState("m.googlemail.com", false, &domain_state));
311 
312   // Other hosts:
313 
314   EXPECT_TRUE(ShouldRedirect("aladdinschools.appspot.com"));
315 
316   EXPECT_TRUE(ShouldRedirect("ottospora.nl"));
317   EXPECT_TRUE(ShouldRedirect("www.ottospora.nl"));
318 
319   EXPECT_TRUE(ShouldRedirect("www.paycheckrecords.com"));
320 
321   EXPECT_TRUE(ShouldRedirect("lastpass.com"));
322   EXPECT_TRUE(ShouldRedirect("www.lastpass.com"));
323   EXPECT_FALSE(HasState("blog.lastpass.com"));
324 
325   EXPECT_TRUE(ShouldRedirect("keyerror.com"));
326   EXPECT_TRUE(ShouldRedirect("www.keyerror.com"));
327 
328   EXPECT_TRUE(ShouldRedirect("entropia.de"));
329   EXPECT_TRUE(ShouldRedirect("www.entropia.de"));
330   EXPECT_FALSE(HasState("foo.entropia.de"));
331 
332   EXPECT_TRUE(ShouldRedirect("www.elanex.biz"));
333   EXPECT_FALSE(HasState("elanex.biz"));
334   EXPECT_FALSE(HasState("foo.elanex.biz"));
335 
336   EXPECT_TRUE(ShouldRedirect("sunshinepress.org"));
337   EXPECT_TRUE(ShouldRedirect("www.sunshinepress.org"));
338   EXPECT_TRUE(ShouldRedirect("a.b.sunshinepress.org"));
339 
340   EXPECT_TRUE(ShouldRedirect("www.noisebridge.net"));
341   EXPECT_FALSE(HasState("noisebridge.net"));
342   EXPECT_FALSE(HasState("foo.noisebridge.net"));
343 
344   EXPECT_TRUE(ShouldRedirect("neg9.org"));
345   EXPECT_FALSE(HasState("www.neg9.org"));
346 
347   EXPECT_TRUE(ShouldRedirect("riseup.net"));
348   EXPECT_TRUE(ShouldRedirect("foo.riseup.net"));
349 
350   EXPECT_TRUE(ShouldRedirect("factor.cc"));
351   EXPECT_FALSE(HasState("www.factor.cc"));
352 
353   EXPECT_TRUE(ShouldRedirect("members.mayfirst.org"));
354   EXPECT_TRUE(ShouldRedirect("support.mayfirst.org"));
355   EXPECT_TRUE(ShouldRedirect("id.mayfirst.org"));
356   EXPECT_TRUE(ShouldRedirect("lists.mayfirst.org"));
357   EXPECT_FALSE(HasState("www.mayfirst.org"));
358 
359   EXPECT_TRUE(ShouldRedirect("romab.com"));
360   EXPECT_TRUE(ShouldRedirect("www.romab.com"));
361   EXPECT_TRUE(ShouldRedirect("foo.romab.com"));
362 
363   EXPECT_TRUE(ShouldRedirect("logentries.com"));
364   EXPECT_TRUE(ShouldRedirect("www.logentries.com"));
365   EXPECT_FALSE(HasState("foo.logentries.com"));
366 
367   EXPECT_TRUE(ShouldRedirect("stripe.com"));
368   EXPECT_TRUE(ShouldRedirect("foo.stripe.com"));
369 
370   EXPECT_TRUE(ShouldRedirect("cloudsecurityalliance.org"));
371   EXPECT_TRUE(ShouldRedirect("foo.cloudsecurityalliance.org"));
372 
373   EXPECT_TRUE(ShouldRedirect("login.sapo.pt"));
374   EXPECT_TRUE(ShouldRedirect("foo.login.sapo.pt"));
375 
376   EXPECT_TRUE(ShouldRedirect("mattmccutchen.net"));
377   EXPECT_TRUE(ShouldRedirect("foo.mattmccutchen.net"));
378 
379   EXPECT_TRUE(ShouldRedirect("betnet.fr"));
380   EXPECT_TRUE(ShouldRedirect("foo.betnet.fr"));
381 
382   EXPECT_TRUE(ShouldRedirect("uprotect.it"));
383   EXPECT_TRUE(ShouldRedirect("foo.uprotect.it"));
384 
385   EXPECT_TRUE(ShouldRedirect("squareup.com"));
386   EXPECT_FALSE(HasState("foo.squareup.com"));
387 
388   EXPECT_TRUE(ShouldRedirect("cert.se"));
389   EXPECT_TRUE(ShouldRedirect("foo.cert.se"));
390 
391   EXPECT_TRUE(ShouldRedirect("crypto.is"));
392   EXPECT_TRUE(ShouldRedirect("foo.crypto.is"));
393 
394   EXPECT_TRUE(ShouldRedirect("simon.butcher.name"));
395   EXPECT_TRUE(ShouldRedirect("foo.simon.butcher.name"));
396 
397   EXPECT_TRUE(ShouldRedirect("linx.net"));
398   EXPECT_TRUE(ShouldRedirect("foo.linx.net"));
399 
400   EXPECT_TRUE(ShouldRedirect("dropcam.com"));
401   EXPECT_TRUE(ShouldRedirect("www.dropcam.com"));
402   EXPECT_FALSE(HasState("foo.dropcam.com"));
403 
404   EXPECT_TRUE(state.GetDomainState("torproject.org", false, &domain_state));
405   EXPECT_FALSE(domain_state.static_spki_hashes.empty());
406   EXPECT_TRUE(state.GetDomainState("www.torproject.org", false,
407                                    &domain_state));
408   EXPECT_FALSE(domain_state.static_spki_hashes.empty());
409   EXPECT_TRUE(state.GetDomainState("check.torproject.org", false,
410                                    &domain_state));
411   EXPECT_FALSE(domain_state.static_spki_hashes.empty());
412   EXPECT_TRUE(state.GetDomainState("blog.torproject.org", false,
413                                    &domain_state));
414   EXPECT_FALSE(domain_state.static_spki_hashes.empty());
415   EXPECT_TRUE(ShouldRedirect("ebanking.indovinabank.com.vn"));
416   EXPECT_TRUE(ShouldRedirect("foo.ebanking.indovinabank.com.vn"));
417 
418   EXPECT_TRUE(ShouldRedirect("epoxate.com"));
419   EXPECT_FALSE(HasState("foo.epoxate.com"));
420 
421   EXPECT_TRUE(HasPublicKeyPins("torproject.org"));
422   EXPECT_TRUE(HasPublicKeyPins("www.torproject.org"));
423   EXPECT_TRUE(HasPublicKeyPins("check.torproject.org"));
424   EXPECT_TRUE(HasPublicKeyPins("blog.torproject.org"));
425   EXPECT_FALSE(HasState("foo.torproject.org"));
426 
427   EXPECT_TRUE(ShouldRedirect("www.moneybookers.com"));
428   EXPECT_FALSE(HasState("moneybookers.com"));
429 
430   EXPECT_TRUE(ShouldRedirect("ledgerscope.net"));
431   EXPECT_TRUE(ShouldRedirect("www.ledgerscope.net"));
432   EXPECT_FALSE(HasState("status.ledgerscope.net"));
433 
434   EXPECT_TRUE(ShouldRedirect("foo.app.recurly.com"));
435   EXPECT_TRUE(ShouldRedirect("foo.api.recurly.com"));
436 
437   EXPECT_TRUE(ShouldRedirect("greplin.com"));
438   EXPECT_TRUE(ShouldRedirect("www.greplin.com"));
439   EXPECT_FALSE(HasState("foo.greplin.com"));
440 
441   EXPECT_TRUE(ShouldRedirect("luneta.nearbuysystems.com"));
442   EXPECT_TRUE(ShouldRedirect("foo.luneta.nearbuysystems.com"));
443 
444   EXPECT_TRUE(ShouldRedirect("ubertt.org"));
445   EXPECT_TRUE(ShouldRedirect("foo.ubertt.org"));
446 
447   EXPECT_TRUE(ShouldRedirect("pixi.me"));
448   EXPECT_TRUE(ShouldRedirect("www.pixi.me"));
449 
450   EXPECT_TRUE(ShouldRedirect("grepular.com"));
451   EXPECT_TRUE(ShouldRedirect("www.grepular.com"));
452 
453   EXPECT_TRUE(ShouldRedirect("mydigipass.com"));
454   EXPECT_FALSE(ShouldRedirect("foo.mydigipass.com"));
455   EXPECT_TRUE(ShouldRedirect("www.mydigipass.com"));
456   EXPECT_FALSE(ShouldRedirect("foo.www.mydigipass.com"));
457   EXPECT_TRUE(ShouldRedirect("developer.mydigipass.com"));
458   EXPECT_FALSE(ShouldRedirect("foo.developer.mydigipass.com"));
459   EXPECT_TRUE(ShouldRedirect("www.developer.mydigipass.com"));
460   EXPECT_FALSE(ShouldRedirect("foo.www.developer.mydigipass.com"));
461   EXPECT_TRUE(ShouldRedirect("sandbox.mydigipass.com"));
462   EXPECT_FALSE(ShouldRedirect("foo.sandbox.mydigipass.com"));
463   EXPECT_TRUE(ShouldRedirect("www.sandbox.mydigipass.com"));
464   EXPECT_FALSE(ShouldRedirect("foo.www.sandbox.mydigipass.com"));
465 
466   EXPECT_TRUE(ShouldRedirect("crypto.cat"));
467   EXPECT_FALSE(ShouldRedirect("foo.crypto.cat"));
468 
469   EXPECT_TRUE(ShouldRedirect("bigshinylock.minazo.net"));
470   EXPECT_TRUE(ShouldRedirect("foo.bigshinylock.minazo.net"));
471 
472   EXPECT_TRUE(ShouldRedirect("crate.io"));
473   EXPECT_TRUE(ShouldRedirect("foo.crate.io"));
474 
475   EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
476 }
477 
TEST_F(TransportSecurityStateTest,LongNames)478 TEST_F(TransportSecurityStateTest, LongNames) {
479   TransportSecurityState state;
480   const char kLongName[] =
481       "lookupByWaveIdHashAndWaveIdIdAndWaveIdDomainAndWaveletIdIdAnd"
482       "WaveletIdDomainAndBlipBlipid";
483   TransportSecurityState::DomainState domain_state;
484   // Just checks that we don't hit a NOTREACHED.
485   EXPECT_FALSE(state.GetDomainState(kLongName, true, &domain_state));
486 }
487 
TEST_F(TransportSecurityStateTest,BuiltinCertPins)488 TEST_F(TransportSecurityStateTest, BuiltinCertPins) {
489   TransportSecurityState state;
490   TransportSecurityState::DomainState domain_state;
491 
492   EXPECT_TRUE(state.GetDomainState("chrome.google.com", true, &domain_state));
493   EXPECT_TRUE(HasPublicKeyPins("chrome.google.com"));
494 
495   HashValueVector hashes;
496   // Checks that a built-in list does exist.
497   EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
498   EXPECT_FALSE(HasPublicKeyPins("www.paypal.com"));
499 
500   EXPECT_TRUE(HasPublicKeyPins("docs.google.com"));
501   EXPECT_TRUE(HasPublicKeyPins("1.docs.google.com"));
502   EXPECT_TRUE(HasPublicKeyPins("sites.google.com"));
503   EXPECT_TRUE(HasPublicKeyPins("drive.google.com"));
504   EXPECT_TRUE(HasPublicKeyPins("spreadsheets.google.com"));
505   EXPECT_TRUE(HasPublicKeyPins("wallet.google.com"));
506   EXPECT_TRUE(HasPublicKeyPins("checkout.google.com"));
507   EXPECT_TRUE(HasPublicKeyPins("appengine.google.com"));
508   EXPECT_TRUE(HasPublicKeyPins("market.android.com"));
509   EXPECT_TRUE(HasPublicKeyPins("encrypted.google.com"));
510   EXPECT_TRUE(HasPublicKeyPins("accounts.google.com"));
511   EXPECT_TRUE(HasPublicKeyPins("profiles.google.com"));
512   EXPECT_TRUE(HasPublicKeyPins("mail.google.com"));
513   EXPECT_TRUE(HasPublicKeyPins("chatenabled.mail.google.com"));
514   EXPECT_TRUE(HasPublicKeyPins("talkgadget.google.com"));
515   EXPECT_TRUE(HasPublicKeyPins("hostedtalkgadget.google.com"));
516   EXPECT_TRUE(HasPublicKeyPins("talk.google.com"));
517   EXPECT_TRUE(HasPublicKeyPins("plus.google.com"));
518   EXPECT_TRUE(HasPublicKeyPins("groups.google.com"));
519   EXPECT_TRUE(HasPublicKeyPins("apis.google.com"));
520 
521   EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com"));
522   EXPECT_TRUE(HasPublicKeyPins("gstatic.com"));
523   EXPECT_TRUE(HasPublicKeyPins("www.gstatic.com"));
524   EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com"));
525   EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com"));
526 
527   // Disabled in order to help track down pinning failures --agl
528   EXPECT_TRUE(HasPublicKeyPins("twitter.com"));
529   EXPECT_FALSE(HasPublicKeyPins("foo.twitter.com"));
530   EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
531   EXPECT_TRUE(HasPublicKeyPins("api.twitter.com"));
532   EXPECT_TRUE(HasPublicKeyPins("oauth.twitter.com"));
533   EXPECT_TRUE(HasPublicKeyPins("mobile.twitter.com"));
534   EXPECT_TRUE(HasPublicKeyPins("dev.twitter.com"));
535   EXPECT_TRUE(HasPublicKeyPins("business.twitter.com"));
536   EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com"));
537   EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com"));
538 }
539 
AddHash(const std::string & type_and_base64,HashValueVector * out)540 static bool AddHash(const std::string& type_and_base64,
541                     HashValueVector* out) {
542   HashValue hash;
543   if (!hash.FromString(type_and_base64))
544     return false;
545 
546   out->push_back(hash);
547   return true;
548 }
549 
TEST_F(TransportSecurityStateTest,PinValidationWithoutRejectedCerts)550 TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) {
551   // kGoodPath is blog.torproject.org.
552   static const char* kGoodPath[] = {
553     "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=",
554     "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=",
555     "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=",
556     NULL,
557   };
558 
559   // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for
560   // torproject.org.
561   static const char* kBadPath[] = {
562     "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
563     "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=",
564     "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
565     NULL,
566   };
567 
568   HashValueVector good_hashes, bad_hashes;
569 
570   for (size_t i = 0; kGoodPath[i]; i++) {
571     EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes));
572   }
573   for (size_t i = 0; kBadPath[i]; i++) {
574     EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
575   }
576 
577   TransportSecurityState state;
578   TransportSecurityState::DomainState domain_state;
579   EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state));
580   EXPECT_TRUE(domain_state.HasPublicKeyPins());
581 
582   EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes));
583   EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
584 }
585 
TEST_F(TransportSecurityStateTest,OptionalHSTSCertPins)586 TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) {
587   TransportSecurityState state;
588   TransportSecurityState::DomainState domain_state;
589 
590   EXPECT_FALSE(ShouldRedirect("www.google-analytics.com"));
591 
592   EXPECT_FALSE(HasPublicKeyPins("www.google-analytics.com", false));
593   EXPECT_TRUE(HasPublicKeyPins("www.google-analytics.com"));
594   EXPECT_TRUE(HasPublicKeyPins("google.com"));
595   EXPECT_TRUE(HasPublicKeyPins("www.google.com"));
596   EXPECT_TRUE(HasPublicKeyPins("mail-attachment.googleusercontent.com"));
597   EXPECT_TRUE(HasPublicKeyPins("www.youtube.com"));
598   EXPECT_TRUE(HasPublicKeyPins("i.ytimg.com"));
599   EXPECT_TRUE(HasPublicKeyPins("googleapis.com"));
600   EXPECT_TRUE(HasPublicKeyPins("ajax.googleapis.com"));
601   EXPECT_TRUE(HasPublicKeyPins("googleadservices.com"));
602   EXPECT_TRUE(HasPublicKeyPins("pagead2.googleadservices.com"));
603   EXPECT_TRUE(HasPublicKeyPins("googlecode.com"));
604   EXPECT_TRUE(HasPublicKeyPins("kibbles.googlecode.com"));
605   EXPECT_TRUE(HasPublicKeyPins("appspot.com"));
606   EXPECT_TRUE(HasPublicKeyPins("googlesyndication.com"));
607   EXPECT_TRUE(HasPublicKeyPins("doubleclick.net"));
608   EXPECT_TRUE(HasPublicKeyPins("ad.doubleclick.net"));
609   EXPECT_FALSE(HasPublicKeyPins("learn.doubleclick.net"));
610   EXPECT_TRUE(HasPublicKeyPins("a.googlegroups.com"));
611   EXPECT_FALSE(HasPublicKeyPins("a.googlegroups.com", false));
612 }
613 
TEST_F(TransportSecurityStateTest,OverrideBuiltins)614 TEST_F(TransportSecurityStateTest, OverrideBuiltins) {
615   EXPECT_TRUE(HasPublicKeyPins("google.com"));
616   EXPECT_FALSE(ShouldRedirect("google.com"));
617   EXPECT_FALSE(ShouldRedirect("www.google.com"));
618 
619   TransportSecurityState state;
620   TransportSecurityState::DomainState domain_state;
621   const base::Time current_time(base::Time::Now());
622   const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
623   domain_state.upgrade_expiry = expiry;
624   EnableHost(&state, "www.google.com", domain_state);
625 
626   EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state));
627 }
628 
TEST_F(TransportSecurityStateTest,GooglePinnedProperties)629 TEST_F(TransportSecurityStateTest, GooglePinnedProperties) {
630   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
631       "www.example.com", true));
632   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
633       "www.paypal.com", true));
634   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
635       "mail.twitter.com", true));
636   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
637       "www.google.com.int", true));
638   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
639       "jottit.com", true));
640   // learn.doubleclick.net has a more specific match than
641   // *.doubleclick.com, and has 0 or NULL for its required certs.
642   // This test ensures that the exact-match-preferred behavior
643   // works.
644   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
645       "learn.doubleclick.net", true));
646 
647   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
648       "encrypted.google.com", true));
649   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
650       "mail.google.com", true));
651   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
652       "accounts.google.com", true));
653   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
654       "doubleclick.net", true));
655   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
656       "ad.doubleclick.net", true));
657   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
658       "youtube.com", true));
659   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
660       "www.profiles.google.com", true));
661   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
662       "checkout.google.com", true));
663   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
664       "googleadservices.com", true));
665 
666   // Test with sni_enabled false:
667   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
668       "www.example.com", false));
669   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
670       "www.paypal.com", false));
671   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
672       "checkout.google.com", false));
673   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
674       "googleadservices.com", false));
675 
676   // Test some SNI hosts:
677   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
678       "gmail.com", true));
679   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
680       "googlegroups.com", true));
681   EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
682       "www.googlegroups.com", true));
683   // Expect to fail for SNI hosts when not searching the SNI list:
684   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
685       "gmail.com", false));
686   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
687       "googlegroups.com", false));
688   EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
689       "www.googlegroups.com", false));
690 }
691 
692 }  // namespace net
693