1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Strict-Transport-Security.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2010
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Sid Stamm <sid@mozilla.com>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : //#define MOZILLA_INTERNAL_API
39 :
40 : #include "TestHarness.h"
41 : #include <stdio.h>
42 : #include "plstr.h"
43 : #include "nsNetUtil.h"
44 : #include "nsStringGlue.h"
45 : #include "nsIStrictTransportSecurityService.h"
46 : #include "nsIPermissionManager.h"
47 :
48 : #define EXPECT_SUCCESS(rv, ...) \
49 : PR_BEGIN_MACRO \
50 : if (NS_FAILED(rv)) { \
51 : fail(__VA_ARGS__); \
52 : return false; \
53 : } \
54 : PR_END_MACRO
55 :
56 :
57 : #define EXPECT_FAILURE(rv, ...) \
58 : PR_BEGIN_MACRO \
59 : if (NS_SUCCEEDED(rv)) { \
60 : fail(__VA_ARGS__); \
61 : return false; \
62 : } \
63 : PR_END_MACRO
64 :
65 : #define REQUIRE_EQUAL(a, b, ...) \
66 : PR_BEGIN_MACRO \
67 : if (a != b) { \
68 : fail(__VA_ARGS__); \
69 : return false; \
70 : } \
71 : PR_END_MACRO
72 :
73 : bool
74 24 : TestSuccess(const char* hdr, bool extraTokens,
75 : nsIStrictTransportSecurityService* stss,
76 : nsIPermissionManager* pm)
77 : {
78 48 : nsCOMPtr<nsIURI> dummyUri;
79 24 : nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
80 24 : EXPECT_SUCCESS(rv, "Failed to create URI");
81 :
82 24 : rv = stss->ProcessStsHeader(dummyUri, hdr);
83 24 : EXPECT_SUCCESS(rv, "Failed to process valid header: %s", hdr);
84 :
85 24 : if (extraTokens) {
86 4 : REQUIRE_EQUAL(rv, NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA,
87 : "Extra tokens were expected when parsing, but were not encountered.");
88 : } else {
89 20 : REQUIRE_EQUAL(rv, NS_OK, "Unexpected tokens found during parsing.");
90 : }
91 :
92 24 : passed(hdr);
93 24 : return true;
94 : }
95 :
96 12 : bool TestFailure(const char* hdr,
97 : nsIStrictTransportSecurityService* stss,
98 : nsIPermissionManager* pm)
99 : {
100 24 : nsCOMPtr<nsIURI> dummyUri;
101 12 : nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
102 12 : EXPECT_SUCCESS(rv, "Failed to create URI");
103 :
104 12 : rv = stss->ProcessStsHeader(dummyUri, hdr);
105 12 : EXPECT_FAILURE(rv, "Parsed invalid header: %s", hdr);
106 12 : passed(hdr);
107 12 : return true;
108 : }
109 :
110 :
111 : int
112 1 : main(PRInt32 argc, char *argv[])
113 : {
114 : nsresult rv;
115 2 : ScopedXPCOM xpcom("STS Parser Tests");
116 1 : if (xpcom.failed())
117 0 : return -1;
118 : // Initialize a profile folder to ensure a clean shutdown.
119 2 : nsCOMPtr<nsIFile> profile = xpcom.GetProfileDirectory();
120 1 : if (!profile) {
121 0 : fail("Couldn't get the profile directory.");
122 0 : return -1;
123 : }
124 :
125 : // grab handle to the service
126 2 : nsCOMPtr<nsIStrictTransportSecurityService> stss;
127 1 : stss = do_GetService("@mozilla.org/stsservice;1", &rv);
128 1 : NS_ENSURE_SUCCESS(rv, rv);
129 :
130 2 : nsCOMPtr<nsIPermissionManager> pm;
131 1 : pm = do_GetService("@mozilla.org/permissionmanager;1", &rv);
132 1 : NS_ENSURE_SUCCESS(rv, rv);
133 :
134 : int rv0, rv1;
135 :
136 2 : nsTArray<bool> rvs(24);
137 :
138 : // *** parsing tests
139 1 : printf("*** Attempting to parse valid STS headers ...\n");
140 :
141 : // SHOULD SUCCEED:
142 1 : rvs.AppendElement(TestSuccess("max-age=100", false, stss, pm));
143 1 : rvs.AppendElement(TestSuccess("max-age =100", false, stss, pm));
144 1 : rvs.AppendElement(TestSuccess(" max-age=100", false, stss, pm));
145 1 : rvs.AppendElement(TestSuccess("max-age = 100 ", false, stss, pm));
146 1 : rvs.AppendElement(TestSuccess("max-age = 100 ", false, stss, pm));
147 :
148 1 : rvs.AppendElement(TestSuccess("maX-aGe=100", false, stss, pm));
149 1 : rvs.AppendElement(TestSuccess("MAX-age =100", false, stss, pm));
150 1 : rvs.AppendElement(TestSuccess("max-AGE=100", false, stss, pm));
151 1 : rvs.AppendElement(TestSuccess("Max-Age = 100 ", false, stss, pm));
152 1 : rvs.AppendElement(TestSuccess("MAX-AGE = 100 ", false, stss, pm));
153 :
154 1 : rvs.AppendElement(TestSuccess("max-age=100;includeSubdomains", false, stss, pm));
155 1 : rvs.AppendElement(TestSuccess("max-age=100; includeSubdomains", false, stss, pm));
156 1 : rvs.AppendElement(TestSuccess(" max-age=100; includeSubdomains", false, stss, pm));
157 1 : rvs.AppendElement(TestSuccess("max-age = 100 ; includeSubdomains", false, stss, pm));
158 1 : rvs.AppendElement(TestSuccess("max-age = 100 ; includeSubdomains", false, stss, pm));
159 :
160 1 : rvs.AppendElement(TestSuccess("maX-aGe=100; includeSUBDOMAINS", false, stss, pm));
161 1 : rvs.AppendElement(TestSuccess("MAX-age =100; includeSubDomains", false, stss, pm));
162 1 : rvs.AppendElement(TestSuccess("max-AGE=100; iNcLuDeSuBdoMaInS", false, stss, pm));
163 1 : rvs.AppendElement(TestSuccess("Max-Age = 100; includesubdomains ", false, stss, pm));
164 1 : rvs.AppendElement(TestSuccess("INCLUDESUBDOMAINS;MaX-AgE = 100 ", false, stss, pm));
165 :
166 : // these are weird tests, but are testing that some extended syntax is
167 : // still allowed (but it is ignored)
168 1 : rvs.AppendElement(TestSuccess("max-age=100randomstuffhere", true, stss, pm));
169 1 : rvs.AppendElement(TestSuccess("max-age=100 includesubdomains", true, stss, pm));
170 1 : rvs.AppendElement(TestSuccess("max-age=100 bar foo", true, stss, pm));
171 1 : rvs.AppendElement(TestSuccess("max-age=100 ; includesubdomainsSomeStuff", true, stss, pm));
172 :
173 1 : rv0 = rvs.Contains(false) ? 1 : 0;
174 1 : if (rv0 == 0)
175 1 : passed("Successfully Parsed STS headers with mixed case and LWS");
176 :
177 1 : rvs.Clear();
178 :
179 : // SHOULD FAIL:
180 1 : printf("*** Attempting to parse invalid STS headers (should not parse)...\n");
181 : // invalid max-ages
182 1 : rvs.AppendElement(TestFailure("max-age ", stss, pm));
183 1 : rvs.AppendElement(TestFailure("max-age=p", stss, pm));
184 1 : rvs.AppendElement(TestFailure("max-age=*1p2", stss, pm));
185 1 : rvs.AppendElement(TestFailure("max-age=.20032", stss, pm));
186 1 : rvs.AppendElement(TestFailure("max-age=!20032", stss, pm));
187 1 : rvs.AppendElement(TestFailure("max-age==20032", stss, pm));
188 :
189 : // invalid headers
190 1 : rvs.AppendElement(TestFailure("foobar", stss, pm));
191 1 : rvs.AppendElement(TestFailure("maxage=100", stss, pm));
192 1 : rvs.AppendElement(TestFailure("maxa-ge=100", stss, pm));
193 1 : rvs.AppendElement(TestFailure("max-ag=100", stss, pm));
194 1 : rvs.AppendElement(TestFailure("includesubdomains", stss, pm));
195 1 : rvs.AppendElement(TestFailure(";", stss, pm));
196 :
197 1 : rv1 = rvs.Contains(false) ? 1 : 0;
198 1 : if (rv1 == 0)
199 1 : passed("Avoided parsing invalid STS headers");
200 :
201 1 : return (rv0 + rv1);
202 : }
|