bug 883582 - use only domains likely to stay on the HSTS preload list in the test...
[gecko.git] / security / manager / ssl / tests / unit / test_sts_preloadlist_perwindowpb.js
blob53ffb39a9ade92739d595b0f3b76786b660cbad6
1 // This test attempts to use only domains that are likely to remain on the
2 // preload list for a long time. Currently this includes bugzilla.mozilla.org
3 // and login.persona.org because they are Mozilla properties and we are
4 // invested in HSTS. Additionally, www.torproject.org was deemed likely to
5 // continue to use HSTS.
7 var gSTSService = Cc["@mozilla.org/stsservice;1"]
8                   .getService(Ci.nsIStrictTransportSecurityService);
10 function Observer() {}
11 Observer.prototype = {
12   observe: function(subject, topic, data) {
13     if (topic == "last-pb-context-exited")
14       run_next_test();
15   }
18 var gObserver = new Observer();
20 // nsIStrictTransportSecurityService.removeStsState removes a given domain's
21 // HSTS status. This means that a domain on the preload list will be
22 // considered not HSTS if this is called. So, to reset everything to its
23 // original state, we have to reach into the permission manager and clear
24 // any HSTS-related state manually.
25 function clearStsState() {
26   var permissionManager = Cc["@mozilla.org/permissionmanager;1"]
27                             .getService(Ci.nsIPermissionManager);
28   // This is a list of every host we call processStsHeader with
29   // (so we can remove any state added to the sts service)
30   var hosts = ["bugzilla.mozilla.org", "login.persona.org",
31                "subdomain.www.torproject.org",
32                "subdomain.bugzilla.mozilla.org" ];
33   for (var host of hosts) {
34     permissionManager.remove(host, "sts/use");
35     permissionManager.remove(host, "sts/subd");
36   }
39 function cleanup() {
40   Services.obs.removeObserver(gObserver, "last-pb-context-exited");
41   clearStsState();
44 function run_test() {
45   do_register_cleanup(cleanup);
46   Services.obs.addObserver(gObserver, "last-pb-context-exited", false);
48   add_test(test_part1);
49   add_test(test_private_browsing1);
50   add_test(test_private_browsing2);
52   run_next_test();
55 function test_part1() {
56   // check that a host not in the list is not identified as an sts host
57   do_check_false(gSTSService.isStsHost("nonexistent.mozilla.com", 0));
59   // check that an ancestor domain is not identified as an sts host
60   do_check_false(gSTSService.isStsHost("com", 0));
62   // check that the pref to toggle using the preload list works
63   Services.prefs.setBoolPref("network.stricttransportsecurity.preloadlist", false);
64   do_check_false(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
65   Services.prefs.setBoolPref("network.stricttransportsecurity.preloadlist", true);
66   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
68   // check that a subdomain is an sts host (includeSubdomains is set)
69   do_check_true(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
71   // check that another subdomain is an sts host (includeSubdomains is set)
72   do_check_true(gSTSService.isStsHost("a.b.c.def.bugzilla.mozilla.org", 0));
74   // check that a subdomain is not an sts host (includeSubdomains is not set)
75   do_check_false(gSTSService.isStsHost("subdomain.www.torproject.org", 0));
77   // check that a host with a dot on the end won't break anything
78   do_check_false(gSTSService.isStsHost("notsts.nonexistent.mozilla.com.", 0));
80   // check that processing a header with max-age: 0 will remove a preloaded
81   // site from the list
82   var uri = Services.io.newURI("http://bugzilla.mozilla.org", null, null);
83   gSTSService.processStsHeader(uri, "max-age=0", 0);
84   do_check_false(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
85   do_check_false(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
86   // check that processing another header (with max-age non-zero) will
87   // re-enable a site's sts status
88   gSTSService.processStsHeader(uri, "max-age=1000", 0);
89   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
90   // but this time include subdomains was not set, so test for that
91   do_check_false(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
92   clearStsState();
94   // check that processing a header with max-age: 0 from a subdomain of a site
95   // will not remove that (ancestor) site from the list
96   var uri = Services.io.newURI("http://subdomain.www.torproject.org", null, null);
97   gSTSService.processStsHeader(uri, "max-age=0", 0);
98   do_check_true(gSTSService.isStsHost("www.torproject.org", 0));
99   do_check_false(gSTSService.isStsHost("subdomain.www.torproject.org", 0));
101   var uri = Services.io.newURI("http://subdomain.bugzilla.mozilla.org", null, null);
102   gSTSService.processStsHeader(uri, "max-age=0", 0);
103   // we received a header with "max-age=0", so we have "no information"
104   // regarding the sts state of subdomain.bugzilla.mozilla.org specifically,
105   // but it is actually still an STS host, because of the preloaded
106   // bugzilla.mozilla.org including subdomains.
107   // Here's a drawing:
108   // |-- bugzilla.mozilla.org (in preload list, includes subdomains) IS sts host
109   //     |-- subdomain.bugzilla.mozilla.org                          IS sts host
110   //     |   `-- another.subdomain.bugzilla.mozilla.org              IS sts host
111   //     `-- sibling.bugzilla.mozilla.org                            IS sts host
112   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
113   do_check_true(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
114   do_check_true(gSTSService.isStsHost("sibling.bugzilla.mozilla.org", 0));
115   do_check_true(gSTSService.isStsHost("another.subdomain.bugzilla.mozilla.org", 0));
117   gSTSService.processStsHeader(uri, "max-age=1000", 0);
118   // Here's what we have now:
119   // |-- bugzilla.mozilla.org (in preload list, includes subdomains) IS sts host
120   //     |-- subdomain.bugzilla.mozilla.org (include subdomains is false) IS sts host
121   //     |   `-- another.subdomain.bugzilla.mozilla.org              IS NOT sts host
122   //     `-- sibling.bugzilla.mozilla.org                            IS sts host
123   do_check_true(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
124   do_check_true(gSTSService.isStsHost("sibling.bugzilla.mozilla.org", 0));
125   do_check_false(gSTSService.isStsHost("another.subdomain.bugzilla.mozilla.org", 0));
127   // Simulate leaving private browsing mode
128   Services.obs.notifyObservers(null, "last-pb-context-exited", null);
131 const IS_PRIVATE = Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
133 function test_private_browsing1() {
134   clearStsState();
135   // sanity - bugzilla.mozilla.org is preloaded, includeSubdomains set
136   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", IS_PRIVATE));
137   do_check_true(gSTSService.isStsHost("a.b.c.subdomain.bugzilla.mozilla.org", IS_PRIVATE));
139   var uri = Services.io.newURI("http://bugzilla.mozilla.org", null, null);
140   gSTSService.processStsHeader(uri, "max-age=0", IS_PRIVATE);
141   do_check_false(gSTSService.isStsHost("bugzilla.mozilla.org", IS_PRIVATE));
142   do_check_false(gSTSService.isStsHost("a.b.subdomain.bugzilla.mozilla.org", IS_PRIVATE));
144   // check adding it back in
145   gSTSService.processStsHeader(uri, "max-age=1000", IS_PRIVATE);
146   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", IS_PRIVATE));
147   // but no includeSubdomains this time
148   do_check_false(gSTSService.isStsHost("b.subdomain.bugzilla.mozilla.org", IS_PRIVATE));
150   // do the hokey-pokey...
151   gSTSService.processStsHeader(uri, "max-age=0", IS_PRIVATE);
152   do_check_false(gSTSService.isStsHost("bugzilla.mozilla.org", IS_PRIVATE));
153   do_check_false(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", IS_PRIVATE));
155   // TODO unfortunately we don't have a good way to know when an entry
156   // has expired in the permission manager, so we can't yet extend this test
157   // to that case.
158   // Test that an expired private browsing entry results in correctly
159   // identifying a host that is on the preload list as no longer sts.
160   // (This happens when we're in private browsing mode, we get a header from
161   // a site on the preload list, and that header later expires. We need to
162   // then treat that host as no longer an sts host.)
163   // (sanity check first - this should be in the preload list)
164   do_check_true(gSTSService.isStsHost("login.persona.org", IS_PRIVATE));
165   var uri = Services.io.newURI("http://login.persona.org", null, null);
166   // according to the rfc, max-age can't be negative, but this is a great
167   // way to test an expired entry
168   gSTSService.processStsHeader(uri, "max-age=-1000", IS_PRIVATE);
169   do_check_false(gSTSService.isStsHost("login.persona.org", IS_PRIVATE));
171   // Simulate leaving private browsing mode
172   Services.obs.notifyObservers(null, "last-pb-context-exited", null);
175 function test_private_browsing2() {
176   // if this test gets this far, it means there's a private browsing service
177   do_check_true(gSTSService.isStsHost("bugzilla.mozilla.org", 0));
178   // the bugzilla.mozilla.org entry has includeSubdomains set
179   do_check_true(gSTSService.isStsHost("subdomain.bugzilla.mozilla.org", 0));
181   // Now that we're out of private browsing mode, we need to make sure
182   // we've "forgotten" that we "forgot" this site's sts status.
183   do_check_true(gSTSService.isStsHost("login.persona.org", 0));
185   run_next_test();