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
37namespace net {
38
39class TransportSecurityStateTest : public testing::Test {
40  virtual void SetUp() {
41#if defined(USE_OPENSSL)
42    crypto::EnsureOpenSSLInit();
43#else
44    crypto::EnsureNSSInit();
45#endif
46  }
47
48 protected:
49  std::string CanonicalizeHost(const std::string& host) {
50    return TransportSecurityState::CanonicalizeHost(host);
51  }
52
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
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
67TEST_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
79TEST_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
91TEST_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
103TEST_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
120TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) {
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  const base::Time older = current_time - base::TimeDelta::FromSeconds(1000);
126
127  EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
128  bool include_subdomains = false;
129  state.AddHSTS("yahoo.com", expiry, include_subdomains);
130
131  state.DeleteAllDynamicDataSince(expiry);
132  EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
133  state.DeleteAllDynamicDataSince(older);
134  EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
135}
136
137TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) {
138  TransportSecurityState state;
139  TransportSecurityState::DomainState domain_state;
140  const base::Time current_time(base::Time::Now());
141  const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
142  bool include_subdomains = false;
143  state.AddHSTS("yahoo.com", expiry, include_subdomains);
144
145  EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state));
146  EXPECT_FALSE(state.GetDomainState("example.com", true, &domain_state));
147  EXPECT_TRUE(state.DeleteDynamicDataForHost("yahoo.com"));
148  EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
149}
150
151TEST_F(TransportSecurityStateTest, IsPreloaded) {
152  const std::string paypal = CanonicalizeHost("paypal.com");
153  const std::string www_paypal = CanonicalizeHost("www.paypal.com");
154  const std::string foo_paypal = CanonicalizeHost("foo.paypal.com");
155  const std::string a_www_paypal = CanonicalizeHost("a.www.paypal.com");
156  const std::string abc_paypal = CanonicalizeHost("a.b.c.paypal.com");
157  const std::string example = CanonicalizeHost("example.com");
158  const std::string aypal = CanonicalizeHost("aypal.com");
159
160  TransportSecurityState state;
161  TransportSecurityState::DomainState domain_state;
162
163  EXPECT_TRUE(GetStaticDomainState(&state, paypal, true, &domain_state));
164  EXPECT_TRUE(GetStaticDomainState(&state, www_paypal, true, &domain_state));
165  EXPECT_FALSE(domain_state.sts_include_subdomains);
166  EXPECT_FALSE(domain_state.pkp_include_subdomains);
167  EXPECT_FALSE(GetStaticDomainState(&state, a_www_paypal, true, &domain_state));
168  EXPECT_FALSE(GetStaticDomainState(&state, abc_paypal, true, &domain_state));
169  EXPECT_FALSE(GetStaticDomainState(&state, example, true, &domain_state));
170  EXPECT_FALSE(GetStaticDomainState(&state, aypal, true, &domain_state));
171}
172
173TEST_F(TransportSecurityStateTest, PreloadedDomainSet) {
174  TransportSecurityState state;
175  TransportSecurityState::DomainState domain_state;
176
177  // The domain wasn't being set, leading to a blank string in the
178  // chrome://net-internals/#hsts UI. So test that.
179  EXPECT_TRUE(state.GetDomainState("market.android.com", true, &domain_state));
180  EXPECT_EQ(domain_state.domain, "market.android.com");
181  EXPECT_TRUE(state.GetDomainState("sub.market.android.com", true,
182                                   &domain_state));
183  EXPECT_EQ(domain_state.domain, "market.android.com");
184}
185
186static bool ShouldRedirect(const char* hostname) {
187  TransportSecurityState state;
188  TransportSecurityState::DomainState domain_state;
189  return state.GetDomainState(hostname, true /* SNI ok */, &domain_state) &&
190         domain_state.ShouldUpgradeToSSL();
191}
192
193static bool HasState(const char* hostname) {
194  TransportSecurityState state;
195  TransportSecurityState::DomainState domain_state;
196  return state.GetDomainState(hostname, true /* SNI ok */, &domain_state);
197}
198
199static bool HasPublicKeyPins(const char* hostname, bool sni_enabled) {
200  TransportSecurityState state;
201  TransportSecurityState::DomainState domain_state;
202  if (!state.GetDomainState(hostname, sni_enabled, &domain_state))
203    return false;
204
205  return domain_state.HasPublicKeyPins();
206}
207
208static bool HasPublicKeyPins(const char* hostname) {
209  return HasPublicKeyPins(hostname, true);
210}
211
212static bool OnlyPinning(const char *hostname) {
213  TransportSecurityState state;
214  TransportSecurityState::DomainState domain_state;
215  if (!state.GetDomainState(hostname, true /* SNI ok */, &domain_state))
216    return false;
217
218  return (domain_state.static_spki_hashes.size() > 0 ||
219          domain_state.bad_static_spki_hashes.size() > 0 ||
220          domain_state.dynamic_spki_hashes.size() > 0) &&
221         !domain_state.ShouldUpgradeToSSL();
222}
223
224TEST_F(TransportSecurityStateTest, Preloaded) {
225  TransportSecurityState state;
226  TransportSecurityState::DomainState domain_state;
227
228  // We do more extensive checks for the first domain.
229  EXPECT_TRUE(state.GetDomainState("www.paypal.com", true, &domain_state));
230  EXPECT_EQ(domain_state.upgrade_mode,
231            TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
232  EXPECT_FALSE(domain_state.sts_include_subdomains);
233  EXPECT_FALSE(domain_state.pkp_include_subdomains);
234
235  EXPECT_TRUE(HasState("paypal.com"));
236  EXPECT_FALSE(HasState("www2.paypal.com"));
237  EXPECT_FALSE(HasState("www2.paypal.com"));
238
239  // Google hosts:
240
241  EXPECT_TRUE(ShouldRedirect("chrome.google.com"));
242  EXPECT_TRUE(ShouldRedirect("checkout.google.com"));
243  EXPECT_TRUE(ShouldRedirect("health.google.com"));
244  EXPECT_TRUE(ShouldRedirect("docs.google.com"));
245  EXPECT_TRUE(ShouldRedirect("sites.google.com"));
246  EXPECT_TRUE(ShouldRedirect("drive.google.com"));
247  EXPECT_TRUE(ShouldRedirect("spreadsheets.google.com"));
248  EXPECT_TRUE(ShouldRedirect("appengine.google.com"));
249  EXPECT_TRUE(ShouldRedirect("market.android.com"));
250  EXPECT_TRUE(ShouldRedirect("encrypted.google.com"));
251  EXPECT_TRUE(ShouldRedirect("accounts.google.com"));
252  EXPECT_TRUE(ShouldRedirect("profiles.google.com"));
253  EXPECT_TRUE(ShouldRedirect("mail.google.com"));
254  EXPECT_TRUE(ShouldRedirect("chatenabled.mail.google.com"));
255  EXPECT_TRUE(ShouldRedirect("talkgadget.google.com"));
256  EXPECT_TRUE(ShouldRedirect("hostedtalkgadget.google.com"));
257  EXPECT_TRUE(ShouldRedirect("talk.google.com"));
258  EXPECT_TRUE(ShouldRedirect("plus.google.com"));
259  EXPECT_TRUE(ShouldRedirect("groups.google.com"));
260  EXPECT_TRUE(ShouldRedirect("apis.google.com"));
261  EXPECT_FALSE(ShouldRedirect("chart.apis.google.com"));
262  EXPECT_TRUE(ShouldRedirect("ssl.google-analytics.com"));
263  EXPECT_TRUE(ShouldRedirect("gmail.com"));
264  EXPECT_TRUE(ShouldRedirect("www.gmail.com"));
265  EXPECT_TRUE(ShouldRedirect("googlemail.com"));
266  EXPECT_TRUE(ShouldRedirect("www.googlemail.com"));
267  EXPECT_TRUE(ShouldRedirect("googleplex.com"));
268  EXPECT_TRUE(ShouldRedirect("www.googleplex.com"));
269  EXPECT_FALSE(HasState("m.gmail.com"));
270  EXPECT_FALSE(HasState("m.googlemail.com"));
271
272  EXPECT_TRUE(OnlyPinning("www.google.com"));
273  EXPECT_TRUE(OnlyPinning("foo.google.com"));
274  EXPECT_TRUE(OnlyPinning("google.com"));
275  EXPECT_TRUE(OnlyPinning("www.youtube.com"));
276  EXPECT_TRUE(OnlyPinning("youtube.com"));
277  EXPECT_TRUE(OnlyPinning("i.ytimg.com"));
278  EXPECT_TRUE(OnlyPinning("ytimg.com"));
279  EXPECT_TRUE(OnlyPinning("googleusercontent.com"));
280  EXPECT_TRUE(OnlyPinning("www.googleusercontent.com"));
281  EXPECT_TRUE(OnlyPinning("www.google-analytics.com"));
282  EXPECT_TRUE(OnlyPinning("googleapis.com"));
283  EXPECT_TRUE(OnlyPinning("googleadservices.com"));
284  EXPECT_TRUE(OnlyPinning("googlecode.com"));
285  EXPECT_TRUE(OnlyPinning("appspot.com"));
286  EXPECT_TRUE(OnlyPinning("googlesyndication.com"));
287  EXPECT_TRUE(OnlyPinning("doubleclick.net"));
288  EXPECT_TRUE(OnlyPinning("googlegroups.com"));
289
290  // Tests for domains that don't work without SNI.
291  EXPECT_FALSE(state.GetDomainState("gmail.com", false, &domain_state));
292  EXPECT_FALSE(state.GetDomainState("www.gmail.com", false, &domain_state));
293  EXPECT_FALSE(state.GetDomainState("m.gmail.com", false, &domain_state));
294  EXPECT_FALSE(state.GetDomainState("googlemail.com", false, &domain_state));
295  EXPECT_FALSE(state.GetDomainState("www.googlemail.com", false,
296                                    &domain_state));
297  EXPECT_FALSE(state.GetDomainState("m.googlemail.com", false, &domain_state));
298
299  // Other hosts:
300
301  EXPECT_TRUE(ShouldRedirect("aladdinschools.appspot.com"));
302
303  EXPECT_TRUE(ShouldRedirect("ottospora.nl"));
304  EXPECT_TRUE(ShouldRedirect("www.ottospora.nl"));
305
306  EXPECT_TRUE(ShouldRedirect("www.paycheckrecords.com"));
307
308  EXPECT_TRUE(ShouldRedirect("lastpass.com"));
309  EXPECT_TRUE(ShouldRedirect("www.lastpass.com"));
310  EXPECT_FALSE(HasState("blog.lastpass.com"));
311
312  EXPECT_TRUE(ShouldRedirect("keyerror.com"));
313  EXPECT_TRUE(ShouldRedirect("www.keyerror.com"));
314
315  EXPECT_TRUE(ShouldRedirect("entropia.de"));
316  EXPECT_TRUE(ShouldRedirect("www.entropia.de"));
317  EXPECT_FALSE(HasState("foo.entropia.de"));
318
319  EXPECT_TRUE(ShouldRedirect("www.elanex.biz"));
320  EXPECT_FALSE(HasState("elanex.biz"));
321  EXPECT_FALSE(HasState("foo.elanex.biz"));
322
323  EXPECT_TRUE(ShouldRedirect("sunshinepress.org"));
324  EXPECT_TRUE(ShouldRedirect("www.sunshinepress.org"));
325  EXPECT_TRUE(ShouldRedirect("a.b.sunshinepress.org"));
326
327  EXPECT_TRUE(ShouldRedirect("www.noisebridge.net"));
328  EXPECT_FALSE(HasState("noisebridge.net"));
329  EXPECT_FALSE(HasState("foo.noisebridge.net"));
330
331  EXPECT_TRUE(ShouldRedirect("neg9.org"));
332  EXPECT_FALSE(HasState("www.neg9.org"));
333
334  EXPECT_TRUE(ShouldRedirect("riseup.net"));
335  EXPECT_TRUE(ShouldRedirect("foo.riseup.net"));
336
337  EXPECT_TRUE(ShouldRedirect("factor.cc"));
338  EXPECT_FALSE(HasState("www.factor.cc"));
339
340  EXPECT_TRUE(ShouldRedirect("members.mayfirst.org"));
341  EXPECT_TRUE(ShouldRedirect("support.mayfirst.org"));
342  EXPECT_TRUE(ShouldRedirect("id.mayfirst.org"));
343  EXPECT_TRUE(ShouldRedirect("lists.mayfirst.org"));
344  EXPECT_FALSE(HasState("www.mayfirst.org"));
345
346  EXPECT_TRUE(ShouldRedirect("romab.com"));
347  EXPECT_TRUE(ShouldRedirect("www.romab.com"));
348  EXPECT_TRUE(ShouldRedirect("foo.romab.com"));
349
350  EXPECT_TRUE(ShouldRedirect("logentries.com"));
351  EXPECT_TRUE(ShouldRedirect("www.logentries.com"));
352  EXPECT_FALSE(HasState("foo.logentries.com"));
353
354  EXPECT_TRUE(ShouldRedirect("stripe.com"));
355  EXPECT_TRUE(ShouldRedirect("foo.stripe.com"));
356
357  EXPECT_TRUE(ShouldRedirect("cloudsecurityalliance.org"));
358  EXPECT_TRUE(ShouldRedirect("foo.cloudsecurityalliance.org"));
359
360  EXPECT_TRUE(ShouldRedirect("login.sapo.pt"));
361  EXPECT_TRUE(ShouldRedirect("foo.login.sapo.pt"));
362
363  EXPECT_TRUE(ShouldRedirect("mattmccutchen.net"));
364  EXPECT_TRUE(ShouldRedirect("foo.mattmccutchen.net"));
365
366  EXPECT_TRUE(ShouldRedirect("betnet.fr"));
367  EXPECT_TRUE(ShouldRedirect("foo.betnet.fr"));
368
369  EXPECT_TRUE(ShouldRedirect("uprotect.it"));
370  EXPECT_TRUE(ShouldRedirect("foo.uprotect.it"));
371
372  EXPECT_TRUE(ShouldRedirect("squareup.com"));
373  EXPECT_FALSE(HasState("foo.squareup.com"));
374
375  EXPECT_TRUE(ShouldRedirect("cert.se"));
376  EXPECT_TRUE(ShouldRedirect("foo.cert.se"));
377
378  EXPECT_TRUE(ShouldRedirect("crypto.is"));
379  EXPECT_TRUE(ShouldRedirect("foo.crypto.is"));
380
381  EXPECT_TRUE(ShouldRedirect("simon.butcher.name"));
382  EXPECT_TRUE(ShouldRedirect("foo.simon.butcher.name"));
383
384  EXPECT_TRUE(ShouldRedirect("linx.net"));
385  EXPECT_TRUE(ShouldRedirect("foo.linx.net"));
386
387  EXPECT_TRUE(ShouldRedirect("dropcam.com"));
388  EXPECT_TRUE(ShouldRedirect("www.dropcam.com"));
389  EXPECT_FALSE(HasState("foo.dropcam.com"));
390
391  EXPECT_TRUE(state.GetDomainState("torproject.org", false, &domain_state));
392  EXPECT_FALSE(domain_state.static_spki_hashes.empty());
393  EXPECT_TRUE(state.GetDomainState("www.torproject.org", false,
394                                   &domain_state));
395  EXPECT_FALSE(domain_state.static_spki_hashes.empty());
396  EXPECT_TRUE(state.GetDomainState("check.torproject.org", false,
397                                   &domain_state));
398  EXPECT_FALSE(domain_state.static_spki_hashes.empty());
399  EXPECT_TRUE(state.GetDomainState("blog.torproject.org", false,
400                                   &domain_state));
401  EXPECT_FALSE(domain_state.static_spki_hashes.empty());
402  EXPECT_TRUE(ShouldRedirect("ebanking.indovinabank.com.vn"));
403  EXPECT_TRUE(ShouldRedirect("foo.ebanking.indovinabank.com.vn"));
404
405  EXPECT_TRUE(ShouldRedirect("epoxate.com"));
406  EXPECT_FALSE(HasState("foo.epoxate.com"));
407
408  EXPECT_TRUE(HasPublicKeyPins("torproject.org"));
409  EXPECT_TRUE(HasPublicKeyPins("www.torproject.org"));
410  EXPECT_TRUE(HasPublicKeyPins("check.torproject.org"));
411  EXPECT_TRUE(HasPublicKeyPins("blog.torproject.org"));
412  EXPECT_FALSE(HasState("foo.torproject.org"));
413
414  EXPECT_TRUE(ShouldRedirect("www.moneybookers.com"));
415  EXPECT_FALSE(HasState("moneybookers.com"));
416
417  EXPECT_TRUE(ShouldRedirect("ledgerscope.net"));
418  EXPECT_TRUE(ShouldRedirect("www.ledgerscope.net"));
419  EXPECT_FALSE(HasState("status.ledgerscope.net"));
420
421  EXPECT_TRUE(ShouldRedirect("foo.app.recurly.com"));
422  EXPECT_TRUE(ShouldRedirect("foo.api.recurly.com"));
423
424  EXPECT_TRUE(ShouldRedirect("greplin.com"));
425  EXPECT_TRUE(ShouldRedirect("www.greplin.com"));
426  EXPECT_FALSE(HasState("foo.greplin.com"));
427
428  EXPECT_TRUE(ShouldRedirect("luneta.nearbuysystems.com"));
429  EXPECT_TRUE(ShouldRedirect("foo.luneta.nearbuysystems.com"));
430
431  EXPECT_TRUE(ShouldRedirect("ubertt.org"));
432  EXPECT_TRUE(ShouldRedirect("foo.ubertt.org"));
433
434  EXPECT_TRUE(ShouldRedirect("pixi.me"));
435  EXPECT_TRUE(ShouldRedirect("www.pixi.me"));
436
437  EXPECT_TRUE(ShouldRedirect("grepular.com"));
438  EXPECT_TRUE(ShouldRedirect("www.grepular.com"));
439
440  EXPECT_TRUE(ShouldRedirect("mydigipass.com"));
441  EXPECT_FALSE(ShouldRedirect("foo.mydigipass.com"));
442  EXPECT_TRUE(ShouldRedirect("www.mydigipass.com"));
443  EXPECT_FALSE(ShouldRedirect("foo.www.mydigipass.com"));
444  EXPECT_TRUE(ShouldRedirect("developer.mydigipass.com"));
445  EXPECT_FALSE(ShouldRedirect("foo.developer.mydigipass.com"));
446  EXPECT_TRUE(ShouldRedirect("www.developer.mydigipass.com"));
447  EXPECT_FALSE(ShouldRedirect("foo.www.developer.mydigipass.com"));
448  EXPECT_TRUE(ShouldRedirect("sandbox.mydigipass.com"));
449  EXPECT_FALSE(ShouldRedirect("foo.sandbox.mydigipass.com"));
450  EXPECT_TRUE(ShouldRedirect("www.sandbox.mydigipass.com"));
451  EXPECT_FALSE(ShouldRedirect("foo.www.sandbox.mydigipass.com"));
452
453  EXPECT_TRUE(ShouldRedirect("crypto.cat"));
454  EXPECT_FALSE(ShouldRedirect("foo.crypto.cat"));
455
456  EXPECT_TRUE(ShouldRedirect("bigshinylock.minazo.net"));
457  EXPECT_TRUE(ShouldRedirect("foo.bigshinylock.minazo.net"));
458
459  EXPECT_TRUE(ShouldRedirect("crate.io"));
460  EXPECT_TRUE(ShouldRedirect("foo.crate.io"));
461
462  EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
463}
464
465TEST_F(TransportSecurityStateTest, LongNames) {
466  TransportSecurityState state;
467  const char kLongName[] =
468      "lookupByWaveIdHashAndWaveIdIdAndWaveIdDomainAndWaveletIdIdAnd"
469      "WaveletIdDomainAndBlipBlipid";
470  TransportSecurityState::DomainState domain_state;
471  // Just checks that we don't hit a NOTREACHED.
472  EXPECT_FALSE(state.GetDomainState(kLongName, true, &domain_state));
473}
474
475TEST_F(TransportSecurityStateTest, BuiltinCertPins) {
476  TransportSecurityState state;
477  TransportSecurityState::DomainState domain_state;
478
479  EXPECT_TRUE(state.GetDomainState("chrome.google.com", true, &domain_state));
480  EXPECT_TRUE(HasPublicKeyPins("chrome.google.com"));
481
482  HashValueVector hashes;
483  // Checks that a built-in list does exist.
484  EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
485  EXPECT_FALSE(HasPublicKeyPins("www.paypal.com"));
486
487  EXPECT_TRUE(HasPublicKeyPins("docs.google.com"));
488  EXPECT_TRUE(HasPublicKeyPins("1.docs.google.com"));
489  EXPECT_TRUE(HasPublicKeyPins("sites.google.com"));
490  EXPECT_TRUE(HasPublicKeyPins("drive.google.com"));
491  EXPECT_TRUE(HasPublicKeyPins("spreadsheets.google.com"));
492  EXPECT_TRUE(HasPublicKeyPins("health.google.com"));
493  EXPECT_TRUE(HasPublicKeyPins("checkout.google.com"));
494  EXPECT_TRUE(HasPublicKeyPins("appengine.google.com"));
495  EXPECT_TRUE(HasPublicKeyPins("market.android.com"));
496  EXPECT_TRUE(HasPublicKeyPins("encrypted.google.com"));
497  EXPECT_TRUE(HasPublicKeyPins("accounts.google.com"));
498  EXPECT_TRUE(HasPublicKeyPins("profiles.google.com"));
499  EXPECT_TRUE(HasPublicKeyPins("mail.google.com"));
500  EXPECT_TRUE(HasPublicKeyPins("chatenabled.mail.google.com"));
501  EXPECT_TRUE(HasPublicKeyPins("talkgadget.google.com"));
502  EXPECT_TRUE(HasPublicKeyPins("hostedtalkgadget.google.com"));
503  EXPECT_TRUE(HasPublicKeyPins("talk.google.com"));
504  EXPECT_TRUE(HasPublicKeyPins("plus.google.com"));
505  EXPECT_TRUE(HasPublicKeyPins("groups.google.com"));
506  EXPECT_TRUE(HasPublicKeyPins("apis.google.com"));
507
508  EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com"));
509  EXPECT_FALSE(HasPublicKeyPins("www.gstatic.com"));
510  EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com"));
511  EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com"));
512
513  // Disabled in order to help track down pinning failures --agl
514  EXPECT_TRUE(HasPublicKeyPins("twitter.com"));
515  EXPECT_FALSE(HasPublicKeyPins("foo.twitter.com"));
516  EXPECT_TRUE(HasPublicKeyPins("www.twitter.com"));
517  EXPECT_TRUE(HasPublicKeyPins("api.twitter.com"));
518  EXPECT_TRUE(HasPublicKeyPins("oauth.twitter.com"));
519  EXPECT_TRUE(HasPublicKeyPins("mobile.twitter.com"));
520  EXPECT_TRUE(HasPublicKeyPins("dev.twitter.com"));
521  EXPECT_TRUE(HasPublicKeyPins("business.twitter.com"));
522  EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com"));
523  EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com"));
524  EXPECT_TRUE(HasPublicKeyPins("twimg0-a.akamaihd.net"));
525}
526
527static bool AddHash(const std::string& type_and_base64,
528                    HashValueVector* out) {
529  HashValue hash;
530  if (!hash.FromString(type_and_base64))
531    return false;
532
533  out->push_back(hash);
534  return true;
535}
536
537TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) {
538  // kGoodPath is plus.google.com via Google Internet Authority.
539  static const char* kGoodPath[] = {
540    "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
541    "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=",
542    "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
543    NULL,
544  };
545
546  // kBadPath is plus.google.com via Trustcenter, which contains a required
547  // certificate (Equifax root), but also an excluded certificate
548  // (Trustcenter).
549  static const char* kBadPath[] = {
550    "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
551    "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=",
552    "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
553    NULL,
554  };
555
556  HashValueVector good_hashes, bad_hashes;
557
558  for (size_t i = 0; kGoodPath[i]; i++) {
559    EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes));
560  }
561  for (size_t i = 0; kBadPath[i]; i++) {
562    EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
563  }
564
565  TransportSecurityState state;
566  TransportSecurityState::DomainState domain_state;
567  EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state));
568  EXPECT_TRUE(domain_state.HasPublicKeyPins());
569
570  EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes));
571  EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
572}
573
574TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) {
575  // kGoodPath is blog.torproject.org.
576  static const char* kGoodPath[] = {
577    "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=",
578    "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=",
579    "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=",
580    NULL,
581  };
582
583  // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for
584  // torproject.org.
585  static const char* kBadPath[] = {
586    "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
587    "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=",
588    "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
589    NULL,
590  };
591
592  HashValueVector good_hashes, bad_hashes;
593
594  for (size_t i = 0; kGoodPath[i]; i++) {
595    EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes));
596  }
597  for (size_t i = 0; kBadPath[i]; i++) {
598    EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
599  }
600
601  TransportSecurityState state;
602  TransportSecurityState::DomainState domain_state;
603  EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state));
604  EXPECT_TRUE(domain_state.HasPublicKeyPins());
605
606  EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes));
607  EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
608}
609
610TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCertsMixedHashes) {
611  static const char* ee_sha1 = "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=";
612  static const char* ee_sha256 =
613      "sha256/sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I=";
614  static const char* google_1024_sha1 = "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=";
615  static const char* google_1024_sha256 =
616      "sha256/trlUMquuV/4CDLK3T0+fkXPIxwivyecyrOIyeQR8bQU=";
617  static const char* equifax_sha1 = "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=";
618  static const char* equifax_sha256 =
619      "sha256//1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY=";
620  static const char* trustcenter_sha1 = "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=";
621  static const char* trustcenter_sha256 =
622      "sha256/Dq58KIA4NMLsboWMLU8/aTREzaAGEFW+EtUule8dd/M=";
623
624  // Good chains for plus.google.com chain up through google_1024_sha{1,256}
625  // to equifax_sha{1,256}. Bad chains chain up to Equifax through
626  // trustcenter_sha{1,256}, which is a blacklisted key. Even though Equifax
627  // and Google1024 are known-good, the blacklistedness of Trustcenter
628  // should override and cause pin validation failure.
629
630  TransportSecurityState state;
631  TransportSecurityState::DomainState domain_state;
632  EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state));
633  EXPECT_TRUE(domain_state.HasPublicKeyPins());
634
635  // The statically-defined pins are all SHA-1, so we add some SHA-256 pins
636  // manually:
637  EXPECT_TRUE(AddHash(google_1024_sha256, &domain_state.static_spki_hashes));
638  EXPECT_TRUE(AddHash(trustcenter_sha256,
639                      &domain_state.bad_static_spki_hashes));
640
641  // Try an all-good SHA1 chain.
642  HashValueVector validated_chain;
643  EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
644  EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
645  EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
646  EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
647
648  // Try an all-bad SHA1 chain.
649  validated_chain.clear();
650  EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
651  EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain));
652  EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
653  EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
654
655  // Try an all-good SHA-256 chain.
656  validated_chain.clear();
657  EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
658  EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain));
659  EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
660  EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
661
662  // Try an all-bad SHA-256 chain.
663  validated_chain.clear();
664  EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
665  EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
666  EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
667  EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
668
669  // Try a mixed-hash good chain.
670  validated_chain.clear();
671  EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
672  EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
673  EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
674  EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
675
676  // Try a mixed-hash bad chain.
677  validated_chain.clear();
678  EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
679  EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
680  EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
681  EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
682
683  // Try a chain with all good hashes.
684  validated_chain.clear();
685  EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
686  EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
687  EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
688  EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
689  EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain));
690  EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
691  EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
692
693  // Try a chain with all bad hashes.
694  validated_chain.clear();
695  EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
696  EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain));
697  EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
698  EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
699  EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
700  EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
701  EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
702}
703
704TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) {
705  TransportSecurityState state;
706  TransportSecurityState::DomainState domain_state;
707
708  EXPECT_FALSE(ShouldRedirect("www.google-analytics.com"));
709
710  EXPECT_FALSE(HasPublicKeyPins("www.google-analytics.com", false));
711  EXPECT_TRUE(HasPublicKeyPins("www.google-analytics.com"));
712  EXPECT_TRUE(HasPublicKeyPins("google.com"));
713  EXPECT_TRUE(HasPublicKeyPins("www.google.com"));
714  EXPECT_TRUE(HasPublicKeyPins("mail-attachment.googleusercontent.com"));
715  EXPECT_TRUE(HasPublicKeyPins("www.youtube.com"));
716  EXPECT_TRUE(HasPublicKeyPins("i.ytimg.com"));
717  EXPECT_TRUE(HasPublicKeyPins("googleapis.com"));
718  EXPECT_TRUE(HasPublicKeyPins("ajax.googleapis.com"));
719  EXPECT_TRUE(HasPublicKeyPins("googleadservices.com"));
720  EXPECT_TRUE(HasPublicKeyPins("pagead2.googleadservices.com"));
721  EXPECT_TRUE(HasPublicKeyPins("googlecode.com"));
722  EXPECT_TRUE(HasPublicKeyPins("kibbles.googlecode.com"));
723  EXPECT_TRUE(HasPublicKeyPins("appspot.com"));
724  EXPECT_TRUE(HasPublicKeyPins("googlesyndication.com"));
725  EXPECT_TRUE(HasPublicKeyPins("doubleclick.net"));
726  EXPECT_TRUE(HasPublicKeyPins("ad.doubleclick.net"));
727  EXPECT_FALSE(HasPublicKeyPins("learn.doubleclick.net"));
728  EXPECT_TRUE(HasPublicKeyPins("a.googlegroups.com"));
729  EXPECT_FALSE(HasPublicKeyPins("a.googlegroups.com", false));
730}
731
732TEST_F(TransportSecurityStateTest, OverrideBuiltins) {
733  EXPECT_TRUE(HasPublicKeyPins("google.com"));
734  EXPECT_FALSE(ShouldRedirect("google.com"));
735  EXPECT_FALSE(ShouldRedirect("www.google.com"));
736
737  TransportSecurityState state;
738  TransportSecurityState::DomainState domain_state;
739  const base::Time current_time(base::Time::Now());
740  const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
741  domain_state.upgrade_expiry = expiry;
742  EnableHost(&state, "www.google.com", domain_state);
743
744  EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state));
745}
746
747static const uint8 kSidePinLeafSPKI[] = {
748  0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
749  0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xe4,
750  0x1d, 0xcc, 0xf2, 0x92, 0xe7, 0x7a, 0xc6, 0x36, 0xf7, 0x1a, 0x62, 0x31, 0x7d,
751  0x37, 0xea, 0x0d, 0xa2, 0xa8, 0x12, 0x2b, 0xc2, 0x1c, 0x82, 0x3e, 0xa5, 0x70,
752  0x4a, 0x83, 0x5d, 0x9b, 0x84, 0x82, 0x70, 0xa4, 0x88, 0x98, 0x98, 0x41, 0x29,
753  0x31, 0xcb, 0x6e, 0x2a, 0x54, 0x65, 0x14, 0x60, 0xcc, 0x00, 0xe8, 0x10, 0x30,
754  0x0a, 0x4a, 0xd1, 0xa7, 0x52, 0xfe, 0x2d, 0x31, 0x2a, 0x1d, 0x0d, 0x02, 0x03,
755  0x01, 0x00, 0x01,
756};
757
758static const uint8 kSidePinInfo[] = {
759  0x01, 0x00, 0x53, 0x50, 0x49, 0x4e, 0xa0, 0x00, 0x03, 0x00, 0x53, 0x49, 0x47,
760  0x00, 0x50, 0x55, 0x42, 0x4b, 0x41, 0x4c, 0x47, 0x4f, 0x47, 0x00, 0x41, 0x00,
761  0x04, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfb, 0x26, 0xd5, 0xe8, 0x76, 0x35,
762  0x96, 0x6d, 0x91, 0x9b, 0x5b, 0x27, 0xe6, 0x09, 0x1c, 0x7b, 0x6c, 0xcd, 0xc8,
763  0x10, 0x25, 0x95, 0xc0, 0xa5, 0xf6, 0x6c, 0x6f, 0xfb, 0x59, 0x1e, 0x2d, 0xf4,
764  0x02, 0x20, 0x33, 0x0a, 0xf8, 0x8b, 0x3e, 0xc4, 0xca, 0x75, 0x28, 0xdf, 0x5f,
765  0xab, 0xe4, 0x46, 0xa0, 0xdd, 0x2d, 0xe5, 0xad, 0xc3, 0x81, 0x44, 0x70, 0xb2,
766  0x10, 0x87, 0xe8, 0xc3, 0xd6, 0x6e, 0x12, 0x5d, 0x04, 0x67, 0x0b, 0x7d, 0xf2,
767  0x99, 0x75, 0x57, 0x99, 0x3a, 0x98, 0xf8, 0xe4, 0xdf, 0x79, 0xdf, 0x8e, 0x02,
768  0x2c, 0xbe, 0xd8, 0xfd, 0x75, 0x80, 0x18, 0xb1, 0x6f, 0x43, 0xd9, 0x8a, 0x79,
769  0xc3, 0x6e, 0x18, 0xdf, 0x79, 0xc0, 0x59, 0xab, 0xd6, 0x77, 0x37, 0x6a, 0x94,
770  0x5a, 0x7e, 0xfb, 0xa9, 0xc5, 0x54, 0x14, 0x3a, 0x7b, 0x97, 0x17, 0x2a, 0xb6,
771  0x1e, 0x59, 0x4f, 0x2f, 0xb1, 0x15, 0x1a, 0x34, 0x50, 0x32, 0x35, 0x36,
772};
773
774static const uint8 kSidePinExpectedHash[20] = {
775  0xb5, 0x91, 0x66, 0x47, 0x43, 0x16, 0x62, 0x86, 0xd4, 0x1e, 0x5d, 0x36, 0xe1,
776  0xc4, 0x09, 0x3d, 0x2d, 0x1d, 0xea, 0x1e,
777};
778
779TEST_F(TransportSecurityStateTest, GooglePinnedProperties) {
780  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
781      "www.example.com", true));
782  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
783      "www.paypal.com", true));
784  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
785      "mail.twitter.com", true));
786  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
787      "www.google.com.int", true));
788  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
789      "jottit.com", true));
790  // learn.doubleclick.net has a more specific match than
791  // *.doubleclick.com, and has 0 or NULL for its required certs.
792  // This test ensures that the exact-match-preferred behavior
793  // works.
794  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
795      "learn.doubleclick.net", true));
796
797  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
798      "encrypted.google.com", true));
799  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
800      "mail.google.com", true));
801  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
802      "accounts.google.com", true));
803  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
804      "doubleclick.net", true));
805  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
806      "ad.doubleclick.net", true));
807  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
808      "youtube.com", true));
809  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
810      "www.profiles.google.com", true));
811  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
812      "checkout.google.com", true));
813  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
814      "googleadservices.com", true));
815
816  // Test with sni_enabled false:
817  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
818      "www.example.com", false));
819  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
820      "www.paypal.com", false));
821  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
822      "checkout.google.com", false));
823  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
824      "googleadservices.com", false));
825
826  // Test some SNI hosts:
827  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
828      "gmail.com", true));
829  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
830      "googlegroups.com", true));
831  EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
832      "www.googlegroups.com", true));
833  // Expect to fail for SNI hosts when not searching the SNI list:
834  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
835      "gmail.com", false));
836  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
837      "googlegroups.com", false));
838  EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
839      "www.googlegroups.com", false));
840}
841
842}  // namespace net
843