Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: chrome/browser/ssl/chrome_ssl_host_state_decisions_test.cc

Issue 369703002: Remember user decisions on invalid certificates behind a flag (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More fixes from sleevi plus a rebase on ToT Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 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 "base/command_line.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/test/simple_test_clock.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ssl/chrome_ssl_host_state_decisions.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/in_process_browser_test.h"
14 #include "content/public/browser/ssl_host_state_decisions.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/test/browser_test_utils.h"
17 #include "net/test/test_certificate_data.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
20
21 namespace {
22
23 GURL www_google_url("https://www.google.com");
24 GURL google_url("https://google.com");
25 GURL example_url("https://example.com");
Ryan Sleevi 2014/07/17 23:19:36 Don't use static variables in tests. You're invoki
jww 2014/07/21 23:39:33 Done.
26
27 const uint64 kDeltaOneDayInSeconds = 86400;
Ryan Sleevi 2014/07/17 23:19:36 TYPES: uint64_t ? COMPILE: UINT64_C(86400) (ensure
jww 2014/07/21 23:39:33 Done.
28
29 } // namespace
30
31 class ChromeSSLHostStateDecisionsTest : public InProcessBrowserTest {};
32
33 // These tests basic unit test functionality of the SSLHostStateDecisions class.
34 // For example, tests that if a certificate is accepted, then it is added to
35 // queryable, and if it is revoked, it is not queryable. Even though it is
36 // effectively a unit test, in needs to be an InProcessBrowserTest because the
37 // actual functionality is provided by ChromeSSLHostStateDecisions which is
38 // provided per-profile.
Ryan Sleevi 2014/07/17 23:19:36 Line break, then document what *this* test does.
jww 2014/07/21 23:39:33 Done.
39 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDecisionsTest, QueryPolicy) {
40 scoped_refptr<net::X509Certificate> google_cert(
41 net::X509Certificate::CreateFromBytes(
42 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
43 content::WebContents* tab =
44 browser()->tab_strip_model()->GetActiveWebContents();
45 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
46 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
47
48 // Verifying that all three of the certs we will be looking at are unknown
49 // before any action has been taken.
50 EXPECT_EQ(
51 net::CertPolicy::UNKNOWN,
52 state->QueryPolicy(
53 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
54 EXPECT_EQ(net::CertPolicy::UNKNOWN,
55 state->QueryPolicy(
56 google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
57 EXPECT_EQ(net::CertPolicy::UNKNOWN,
58 state->QueryPolicy(
59 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
60
61 // Simulate a user decision to allow an invalid certificate exception for
62 // www_google_url.
63 state->AllowCert(
64 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
65
66 // Verify that only www_google_url is allowed and that the other two certs
67 // being tested still have no decision associated with them.
68 EXPECT_EQ(
69 net::CertPolicy::ALLOWED,
70 state->QueryPolicy(
71 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
72 EXPECT_EQ(net::CertPolicy::UNKNOWN,
73 state->QueryPolicy(
74 google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
75 EXPECT_EQ(net::CertPolicy::UNKNOWN,
76 state->QueryPolicy(
77 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
78
79 // Simulate a user decision to allow an invalid certificate exception for
80 // example_url.
81 state->AllowCert(
82 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
83
84 // Verify that both www_google_url and example_url have allow exceptions while
85 // google_url still has no associated decision.
86 EXPECT_EQ(
87 net::CertPolicy::ALLOWED,
88 state->QueryPolicy(
89 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
90 EXPECT_EQ(net::CertPolicy::UNKNOWN,
91 state->QueryPolicy(
92 google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
93 EXPECT_EQ(net::CertPolicy::ALLOWED,
94 state->QueryPolicy(
95 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
96
97 // Simulate a user decision to deny an invalid certificate for example_url.
98 state->DenyCert(
99 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
100
101 // Verify that www_google_url is allowed and example_url is denied while
102 // google_url still has no associated decision.
103 EXPECT_EQ(
104 net::CertPolicy::ALLOWED,
105 state->QueryPolicy(
106 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
107 EXPECT_EQ(net::CertPolicy::UNKNOWN,
108 state->QueryPolicy(
109 google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
110 EXPECT_EQ(net::CertPolicy::DENIED,
111 state->QueryPolicy(
112 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
113 }
114
115 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDecisionsTest, HasPolicyAndRevoke) {
116 scoped_refptr<net::X509Certificate> google_cert(
117 net::X509Certificate::CreateFromBytes(
118 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
119 content::WebContents* tab =
120 browser()->tab_strip_model()->GetActiveWebContents();
121 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
122 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
123
124 // Simulate a user decision to allow an invalid certificate exception for
125 // www_google_url and for example_url.
126 state->AllowCert(
127 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
128 state->AllowCert(
129 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
130
131 // Verify that HasAllowedOrDeniedCert correctly acknowledges that a user
132 // decision has been made about www_google_url. Then verify that
133 // HasAllowedOrDeniedCert correctly identifies that the decision has been
134 // revoked.
135 EXPECT_TRUE(state->HasAllowedOrDeniedCert(www_google_url));
136 state->RevokeAllowAndDenyPreferences(www_google_url);
137 EXPECT_FALSE(state->HasAllowedOrDeniedCert(www_google_url));
138 EXPECT_EQ(
139 net::CertPolicy::UNKNOWN,
140 state->QueryPolicy(
141 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
142
143 // Verify that the revocation of the www_google_url decision does not affect
144 // the Allow for example_url.
145 EXPECT_TRUE(state->HasAllowedOrDeniedCert(example_url));
146
147 // Verify the rovaction of the www_google_url decision does not affect the
148 // non-decision for google_url. Then verify that a revocation of a URL with no
149 // decision has no effect.
150 EXPECT_FALSE(state->HasAllowedOrDeniedCert(google_url));
151 state->RevokeAllowAndDenyPreferences(google_url);
152 EXPECT_FALSE(state->HasAllowedOrDeniedCert(google_url));
153 }
154
155 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDecisionsTest, Clear) {
156 scoped_refptr<net::X509Certificate> google_cert(
157 net::X509Certificate::CreateFromBytes(
158 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
159 content::WebContents* tab =
160 browser()->tab_strip_model()->GetActiveWebContents();
161 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
162 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
163
164 // Simulate a user decision to allow an invalid certificate exception for
165 // www_google_url and for example_url.
166 state->AllowCert(
167 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
168
169 // Do a full clear, then make sure that both www_google_url, which had a
170 // decision made, and example_url, which was untouched, are now in a
171 // non-decision state.
172 state->Clear();
173 EXPECT_FALSE(state->HasAllowedOrDeniedCert(www_google_url));
174 EXPECT_EQ(
175 net::CertPolicy::UNKNOWN,
176 state->QueryPolicy(
177 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
178 EXPECT_FALSE(state->HasAllowedOrDeniedCert(example_url));
179 EXPECT_EQ(net::CertPolicy::UNKNOWN,
180 state->QueryPolicy(
181 example_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
182 }
183
184 // Tests the basic behavior of cert memory in incognito
185 class IncognitoSSLHostStateDecisionsTest
186 : public ChromeSSLHostStateDecisionsTest {
187 protected:
188 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
189 ChromeSSLHostStateDecisionsTest::SetUpCommandLine(command_line);
190 command_line->AppendSwitch(switches::kRememberCertErrorDecisionsOneDay);
191 }
192 };
193
194 IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDecisionsTest, PRE_AfterRestart) {
195 scoped_refptr<net::X509Certificate> google_cert(
196 net::X509Certificate::CreateFromBytes(
197 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
198 content::WebContents* tab =
199 browser()->tab_strip_model()->GetActiveWebContents();
200 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
201 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
202
203 // Add a cert exception to the profile and then verify that it still exists
204 // in the incognito profile.
205 state->AllowCert(
206 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
207
208 scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
209 content::SSLHostStateDecisions* incognito_state =
210 incognito->GetSSLHostStateDecisions();
211
212 EXPECT_EQ(
213 net::CertPolicy::ALLOWED,
214 incognito_state->QueryPolicy(
215 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
216
217 // Add a cert exception to the incognito profile. It will be checked after
218 // restart that this exception does not exist. Note the different cert URL and
219 // error than above thus mapping to a second exception. Also validate that it
220 // was not added as an exception to the regular profile.
221 incognito_state->AllowCert(
222 google_url, google_cert.get(), net::CERT_STATUS_COMMON_NAME_INVALID);
223
224 EXPECT_EQ(
225 net::CertPolicy::UNKNOWN,
226 state->QueryPolicy(
227 google_url, google_cert.get(), net::CERT_STATUS_COMMON_NAME_INVALID));
228 }
229
230 IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDecisionsTest, AfterRestart) {
Ryan Sleevi 2014/07/17 23:19:36 Document a bit of the test // Decisions made in a
jww 2014/07/21 23:39:33 Done.
231 scoped_refptr<net::X509Certificate> google_cert(
232 net::X509Certificate::CreateFromBytes(
233 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
234 content::WebContents* tab =
235 browser()->tab_strip_model()->GetActiveWebContents();
236 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
237 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
238
239 // Verify that the exception added before restart to the regular
240 // (non-incognito) profile still exists and was not cleared after the
241 // incognito session ended.
242 EXPECT_EQ(
243 net::CertPolicy::ALLOWED,
244 state->QueryPolicy(
245 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
246
247 scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
248 content::SSLHostStateDecisions* incognito_state =
249 incognito->GetSSLHostStateDecisions();
250
251 // Verify that the exception added before restart to the incognito profile was
252 // cleared when the incognito session ended.
253 EXPECT_EQ(
254 net::CertPolicy::UNKNOWN,
255 incognito_state->QueryPolicy(
256 google_url, google_cert.get(), net::CERT_STATUS_COMMON_NAME_INVALID));
257 }
258
259 // Tests to make sure that if the remember value is set to -1, any decisions
260 // won't be remembered over a restart.
261 class ForgetSSLHostStateDecisionsTest : public ChromeSSLHostStateDecisionsTest {
262 protected:
263 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
264 ChromeSSLHostStateDecisionsTest::SetUpCommandLine(command_line);
265 command_line->AppendSwitch(switches::kRememberCertErrorDecisionsDisable);
266 }
267 };
268
269 IN_PROC_BROWSER_TEST_F(ForgetSSLHostStateDecisionsTest, PRE_AfterRestart) {
270 scoped_refptr<net::X509Certificate> google_cert(
271 net::X509Certificate::CreateFromBytes(
272 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
273 content::WebContents* tab =
274 browser()->tab_strip_model()->GetActiveWebContents();
275 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
276 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
277
278 state->AllowCert(
279 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
280 EXPECT_EQ(
281 net::CertPolicy::ALLOWED,
282 state->QueryPolicy(
283 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
284 }
285
286 IN_PROC_BROWSER_TEST_F(ForgetSSLHostStateDecisionsTest, AfterRestart) {
287 scoped_refptr<net::X509Certificate> google_cert(
288 net::X509Certificate::CreateFromBytes(
289 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
290 content::WebContents* tab =
291 browser()->tab_strip_model()->GetActiveWebContents();
292 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
293 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
294
295 // The cert should now be |UNKONWN| because the profile is set to forget cert
296 // exceptions after session end.
297 EXPECT_EQ(
298 net::CertPolicy::UNKNOWN,
299 state->QueryPolicy(
300 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
301 }
302
303 // Tests to make sure that if the remember value is set to 0, any decisions made
304 // will be forgetten immediately.
305 class ForgetInstantlySSLHostStateDecisionsTest
306 : public ChromeSSLHostStateDecisionsTest {
307 protected:
308 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
309 ChromeSSLHostStateDecisionsTest::SetUpCommandLine(command_line);
310 command_line->AppendSwitch(switches::kRememberCertErrorDecisionsNone);
311 }
312 };
313
314 IN_PROC_BROWSER_TEST_F(ForgetInstantlySSLHostStateDecisionsTest,
315 MakeAndForgetException) {
316 scoped_refptr<net::X509Certificate> google_cert(
317 net::X509Certificate::CreateFromBytes(
318 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
319 content::WebContents* tab =
320 browser()->tab_strip_model()->GetActiveWebContents();
321 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
322 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
323
324 // chrome_state takes ownership of this clock
325 base::SimpleTestClock* clock = new base::SimpleTestClock();
326 ChromeSSLHostStateDecisions* chrome_state =
327 static_cast<ChromeSSLHostStateDecisions*>(state);
328 chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
329
330 // Start the clock at standard system time but do not advance at all to
331 // emphasize that instant forget works.
332 clock->SetNow(base::Time::NowFromSystemTime());
333
334 state->AllowCert(
335 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
336 EXPECT_EQ(
337 net::CertPolicy::UNKNOWN,
338 state->QueryPolicy(
339 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
340 }
341
342 // Tests to make sure that if the remember value is set to a non-zero value0,
343 // any decisions will be remembered over a restart, but only for the length
344 // specified.
345 class RememberSSLHostStateDecisionsTest
346 : public ChromeSSLHostStateDecisionsTest {
347 protected:
348 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
349 ChromeSSLHostStateDecisionsTest::SetUpCommandLine(command_line);
350 command_line->AppendSwitch(switches::kRememberCertErrorDecisionsOneDay);
351 }
352 };
353
354 IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDecisionsTest, PRE_AfterRestart) {
355 scoped_refptr<net::X509Certificate> google_cert(
356 net::X509Certificate::CreateFromBytes(
357 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
358 content::WebContents* tab =
359 browser()->tab_strip_model()->GetActiveWebContents();
360 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
361 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
362
363 state->AllowCert(
364 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID);
365 EXPECT_EQ(
366 net::CertPolicy::ALLOWED,
367 state->QueryPolicy(
368 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
369 }
370
371 IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDecisionsTest, AfterRestart) {
372 scoped_refptr<net::X509Certificate> google_cert(
373 net::X509Certificate::CreateFromBytes(
374 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
375 content::WebContents* tab =
376 browser()->tab_strip_model()->GetActiveWebContents();
377 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
378 content::SSLHostStateDecisions* state = profile->GetSSLHostStateDecisions();
379
380 // chrome_state takes ownership of this clock
381 base::SimpleTestClock* clock = new base::SimpleTestClock();
382 ChromeSSLHostStateDecisions* chrome_state =
383 static_cast<ChromeSSLHostStateDecisions*>(state);
384 chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
385
386 // Start the clock at standard system time.
387 clock->SetNow(base::Time::NowFromSystemTime());
388
389 // This should only pass if the cert was allowed before the test was restart
390 // and thus has now been rememebered across browser restarts.
391 EXPECT_EQ(
392 net::CertPolicy::ALLOWED,
393 state->QueryPolicy(
394 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
395
396 // Simulate the clock advancing by the specified delta.
397 clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
398
399 // The cert should now be |UNKONWN| because the specified delta has passed.
400 EXPECT_EQ(
401 net::CertPolicy::UNKNOWN,
402 state->QueryPolicy(
403 www_google_url, google_cert.get(), net::CERT_STATUS_DATE_INVALID));
404 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698