netwerk/test/TestSTSParser.cpp

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "TestHarness.h"
michael@0 6 #include <stdio.h>
michael@0 7 #include "nsNetUtil.h"
michael@0 8 #include "nsISiteSecurityService.h"
michael@0 9
michael@0 10 #define EXPECT_SUCCESS(rv, ...) \
michael@0 11 PR_BEGIN_MACRO \
michael@0 12 if (NS_FAILED(rv)) { \
michael@0 13 fail(__VA_ARGS__); \
michael@0 14 return false; \
michael@0 15 } \
michael@0 16 PR_END_MACRO
michael@0 17
michael@0 18
michael@0 19 #define EXPECT_FAILURE(rv, ...) \
michael@0 20 PR_BEGIN_MACRO \
michael@0 21 if (NS_SUCCEEDED(rv)) { \
michael@0 22 fail(__VA_ARGS__); \
michael@0 23 return false; \
michael@0 24 } \
michael@0 25 PR_END_MACRO
michael@0 26
michael@0 27 #define REQUIRE_EQUAL(a, b, ...) \
michael@0 28 PR_BEGIN_MACRO \
michael@0 29 if (a != b) { \
michael@0 30 fail(__VA_ARGS__); \
michael@0 31 return false; \
michael@0 32 } \
michael@0 33 PR_END_MACRO
michael@0 34
michael@0 35 bool
michael@0 36 TestSuccess(const char* hdr, bool extraTokens,
michael@0 37 uint64_t expectedMaxAge, bool expectedIncludeSubdomains,
michael@0 38 nsISiteSecurityService* sss)
michael@0 39 {
michael@0 40 nsCOMPtr<nsIURI> dummyUri;
michael@0 41 nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
michael@0 42 EXPECT_SUCCESS(rv, "Failed to create URI");
michael@0 43
michael@0 44 uint64_t maxAge = 0;
michael@0 45 bool includeSubdomains = false;
michael@0 46 rv = sss->ProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri, hdr,
michael@0 47 0, &maxAge, &includeSubdomains);
michael@0 48 EXPECT_SUCCESS(rv, "Failed to process valid header: %s", hdr);
michael@0 49
michael@0 50 REQUIRE_EQUAL(maxAge, expectedMaxAge, "Did not correctly parse maxAge");
michael@0 51 REQUIRE_EQUAL(includeSubdomains, expectedIncludeSubdomains, "Did not correctly parse presence/absence of includeSubdomains");
michael@0 52
michael@0 53 if (extraTokens) {
michael@0 54 REQUIRE_EQUAL(rv, NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA,
michael@0 55 "Extra tokens were expected when parsing, but were not encountered.");
michael@0 56 } else {
michael@0 57 REQUIRE_EQUAL(rv, NS_OK, "Unexpected tokens found during parsing.");
michael@0 58 }
michael@0 59
michael@0 60 passed(hdr);
michael@0 61 return true;
michael@0 62 }
michael@0 63
michael@0 64 bool TestFailure(const char* hdr,
michael@0 65 nsISiteSecurityService* sss)
michael@0 66 {
michael@0 67 nsCOMPtr<nsIURI> dummyUri;
michael@0 68 nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
michael@0 69 EXPECT_SUCCESS(rv, "Failed to create URI");
michael@0 70
michael@0 71 rv = sss->ProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri, hdr,
michael@0 72 0, nullptr, nullptr);
michael@0 73 EXPECT_FAILURE(rv, "Parsed invalid header: %s", hdr);
michael@0 74 passed(hdr);
michael@0 75 return true;
michael@0 76 }
michael@0 77
michael@0 78
michael@0 79 int
michael@0 80 main(int32_t argc, char *argv[])
michael@0 81 {
michael@0 82 nsresult rv;
michael@0 83 ScopedXPCOM xpcom("STS Parser Tests");
michael@0 84 if (xpcom.failed())
michael@0 85 return -1;
michael@0 86 // Initialize a profile folder to ensure a clean shutdown.
michael@0 87 nsCOMPtr<nsIFile> profile = xpcom.GetProfileDirectory();
michael@0 88 if (!profile) {
michael@0 89 fail("Couldn't get the profile directory.");
michael@0 90 return -1;
michael@0 91 }
michael@0 92
michael@0 93 // grab handle to the service
michael@0 94 nsCOMPtr<nsISiteSecurityService> sss;
michael@0 95 sss = do_GetService("@mozilla.org/ssservice;1", &rv);
michael@0 96 NS_ENSURE_SUCCESS(rv, -1);
michael@0 97
michael@0 98 int rv0, rv1;
michael@0 99
michael@0 100 nsTArray<bool> rvs(24);
michael@0 101
michael@0 102 // *** parsing tests
michael@0 103 printf("*** Attempting to parse valid STS headers ...\n");
michael@0 104
michael@0 105 // SHOULD SUCCEED:
michael@0 106 rvs.AppendElement(TestSuccess("max-age=100", false, 100, false, sss));
michael@0 107 rvs.AppendElement(TestSuccess("max-age =100", false, 100, false, sss));
michael@0 108 rvs.AppendElement(TestSuccess(" max-age=100", false, 100, false, sss));
michael@0 109 rvs.AppendElement(TestSuccess("max-age = 100 ", false, 100, false, sss));
michael@0 110 rvs.AppendElement(TestSuccess("max-age = \"100\" ", false, 100, false, sss));
michael@0 111 rvs.AppendElement(TestSuccess("max-age=\"100\"", false, 100, false, sss));
michael@0 112 rvs.AppendElement(TestSuccess(" max-age =\"100\" ", false, 100, false, sss));
michael@0 113 rvs.AppendElement(TestSuccess("\tmax-age\t=\t\"100\"\t", false, 100, false, sss));
michael@0 114 rvs.AppendElement(TestSuccess("max-age = 100 ", false, 100, false, sss));
michael@0 115
michael@0 116 rvs.AppendElement(TestSuccess("maX-aGe=100", false, 100, false, sss));
michael@0 117 rvs.AppendElement(TestSuccess("MAX-age =100", false, 100, false, sss));
michael@0 118 rvs.AppendElement(TestSuccess("max-AGE=100", false, 100, false, sss));
michael@0 119 rvs.AppendElement(TestSuccess("Max-Age = 100 ", false, 100, false, sss));
michael@0 120 rvs.AppendElement(TestSuccess("MAX-AGE = 100 ", false, 100, false, sss));
michael@0 121
michael@0 122 rvs.AppendElement(TestSuccess("max-age=100;includeSubdomains", false, 100, true, sss));
michael@0 123 rvs.AppendElement(TestSuccess("max-age=100\t; includeSubdomains", false, 100, true, sss));
michael@0 124 rvs.AppendElement(TestSuccess(" max-age=100; includeSubdomains", false, 100, true, sss));
michael@0 125 rvs.AppendElement(TestSuccess("max-age = 100 ; includeSubdomains", false, 100, true, sss));
michael@0 126 rvs.AppendElement(TestSuccess("max-age = 100 ; includeSubdomains", false, 100, true, sss));
michael@0 127
michael@0 128 rvs.AppendElement(TestSuccess("maX-aGe=100; includeSUBDOMAINS", false, 100, true, sss));
michael@0 129 rvs.AppendElement(TestSuccess("MAX-age =100; includeSubDomains", false, 100, true, sss));
michael@0 130 rvs.AppendElement(TestSuccess("max-AGE=100; iNcLuDeSuBdoMaInS", false, 100, true, sss));
michael@0 131 rvs.AppendElement(TestSuccess("Max-Age = 100; includesubdomains ", false, 100, true, sss));
michael@0 132 rvs.AppendElement(TestSuccess("INCLUDESUBDOMAINS;MaX-AgE = 100 ", false, 100, true, sss));
michael@0 133 // Turns out, the actual directive is entirely optional (hence the
michael@0 134 // trailing semicolon)
michael@0 135 rvs.AppendElement(TestSuccess("max-age=100;includeSubdomains;", true, 100, true, sss));
michael@0 136
michael@0 137 // these are weird tests, but are testing that some extended syntax is
michael@0 138 // still allowed (but it is ignored)
michael@0 139 rvs.AppendElement(TestSuccess("max-age=100 ; includesubdomainsSomeStuff", true, 100, false, sss));
michael@0 140 rvs.AppendElement(TestSuccess("\r\n\t\t \tcompletelyUnrelated = foobar; max-age= 34520103 \t \t; alsoUnrelated;asIsThis;\tincludeSubdomains\t\t \t", true, 34520103, true, sss));
michael@0 141 rvs.AppendElement(TestSuccess("max-age=100; unrelated=\"quoted \\\"thingy\\\"\"", true, 100, false, sss));
michael@0 142
michael@0 143 rv0 = rvs.Contains(false) ? 1 : 0;
michael@0 144 if (rv0 == 0)
michael@0 145 passed("Successfully Parsed STS headers with mixed case and LWS");
michael@0 146
michael@0 147 rvs.Clear();
michael@0 148
michael@0 149 // SHOULD FAIL:
michael@0 150 printf("*** Attempting to parse invalid STS headers (should not parse)...\n");
michael@0 151 // invalid max-ages
michael@0 152 rvs.AppendElement(TestFailure("max-age", sss));
michael@0 153 rvs.AppendElement(TestFailure("max-age ", sss));
michael@0 154 rvs.AppendElement(TestFailure("max-age=p", sss));
michael@0 155 rvs.AppendElement(TestFailure("max-age=*1p2", sss));
michael@0 156 rvs.AppendElement(TestFailure("max-age=.20032", sss));
michael@0 157 rvs.AppendElement(TestFailure("max-age=!20032", sss));
michael@0 158 rvs.AppendElement(TestFailure("max-age==20032", sss));
michael@0 159
michael@0 160 // invalid headers
michael@0 161 rvs.AppendElement(TestFailure("foobar", sss));
michael@0 162 rvs.AppendElement(TestFailure("maxage=100", sss));
michael@0 163 rvs.AppendElement(TestFailure("maxa-ge=100", sss));
michael@0 164 rvs.AppendElement(TestFailure("max-ag=100", sss));
michael@0 165 rvs.AppendElement(TestFailure("includesubdomains", sss));
michael@0 166 rvs.AppendElement(TestFailure(";", sss));
michael@0 167 rvs.AppendElement(TestFailure("max-age=\"100", sss));
michael@0 168 // The max-age directive here doesn't conform to the spec, so it MUST
michael@0 169 // be ignored. Consequently, the REQUIRED max-age directive is not
michael@0 170 // present in this header, and so it is invalid.
michael@0 171 rvs.AppendElement(TestFailure("max-age=100, max-age=200; includeSubdomains", sss));
michael@0 172 rvs.AppendElement(TestFailure("max-age=100 includesubdomains", sss));
michael@0 173 rvs.AppendElement(TestFailure("max-age=100 bar foo", sss));
michael@0 174 rvs.AppendElement(TestFailure("max-age=100randomstuffhere", sss));
michael@0 175 // All directives MUST appear only once in an STS header field.
michael@0 176 rvs.AppendElement(TestFailure("max-age=100; max-age=200", sss));
michael@0 177 rvs.AppendElement(TestFailure("includeSubdomains; max-age=200; includeSubdomains", sss));
michael@0 178 rvs.AppendElement(TestFailure("max-age=200; includeSubdomains; includeSubdomains", sss));
michael@0 179 // The includeSubdomains directive is valueless.
michael@0 180 rvs.AppendElement(TestFailure("max-age=100; includeSubdomains=unexpected", sss));
michael@0 181 // LWS must have at least one space or horizontal tab
michael@0 182 rvs.AppendElement(TestFailure("\r\nmax-age=200", sss));
michael@0 183
michael@0 184 rv1 = rvs.Contains(false) ? 1 : 0;
michael@0 185 if (rv1 == 0)
michael@0 186 passed("Avoided parsing invalid STS headers");
michael@0 187
michael@0 188 return (rv0 + rv1);
michael@0 189 }

mercurial