OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/frame/csp/CSPSource.h" | 5 #include "core/frame/csp/CSPSource.h" |
6 | 6 |
7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
8 #include "core/frame/csp/ContentSecurityPolicy.h" | 8 #include "core/frame/csp/ContentSecurityPolicy.h" |
9 #include "platform/network/ResourceRequest.h" | 9 #include "platform/network/ResourceRequest.h" |
10 #include "platform/weborigin/KURL.h" | 10 #include "platform/weborigin/KURL.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 EXPECT_FALSE(source.matches(KURL(base, "https://example.com:8443/"))); | 116 EXPECT_FALSE(source.matches(KURL(base, "https://example.com:8443/"))); |
117 | 117 |
118 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com/"))); | 118 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com/"))); |
119 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:80/"))); | 119 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:80/"))); |
120 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:443/"))); | 120 EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:443/"))); |
121 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com/"))); | 121 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com/"))); |
122 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:80/"))); | 122 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:80/"))); |
123 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:443/"))); | 123 EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:443/"))); |
124 } | 124 } |
125 | 125 |
| 126 TEST_F(CSPSourceTest, DoesNotSubsume) { |
| 127 struct Source { |
| 128 const char* scheme; |
| 129 const char* host; |
| 130 const char* path; |
| 131 const int port; |
| 132 }; |
| 133 struct TestCase { |
| 134 const Source a; |
| 135 const Source b; |
| 136 } cases[] = { |
| 137 {{"http", "example.com", "/", 0}, {"http", "another.com", "/", 0}}, |
| 138 {{"wss", "example.com", "/", 0}, {"http", "example.com", "/", 0}}, |
| 139 {{"wss", "example.com", "/", 0}, {"about", "example.com", "/", 0}}, |
| 140 {{"http", "example.com", "/", 0}, {"about", "example.com", "/", 0}}, |
| 141 {{"http", "example.com", "/1.html", 0}, |
| 142 {"http", "example.com", "/2.html", 0}}, |
| 143 {{"http", "example.com", "/", 443}, {"about", "example.com", "/", 800}}, |
| 144 }; |
| 145 for (const auto& test : cases) { |
| 146 CSPSource* returned = new CSPSource( |
| 147 csp.get(), test.a.scheme, test.a.host, test.a.port, test.a.path, |
| 148 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 149 |
| 150 CSPSource* required = new CSPSource( |
| 151 csp.get(), test.b.scheme, test.b.host, test.b.port, test.b.path, |
| 152 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 153 |
| 154 EXPECT_FALSE(required->subsumes(returned)); |
| 155 // Verify the same test with a and b swapped. |
| 156 EXPECT_FALSE(required->subsumes(returned)); |
| 157 } |
| 158 } |
| 159 |
| 160 TEST_F(CSPSourceTest, Subsumes) { |
| 161 struct Source { |
| 162 const char* scheme; |
| 163 const char* path; |
| 164 const int port; |
| 165 }; |
| 166 struct TestCase { |
| 167 const Source a; |
| 168 const Source b; |
| 169 bool expected; |
| 170 bool expectedWhenSwapped; |
| 171 } cases[] = { |
| 172 // Equal signals |
| 173 {{"http", "/", 0}, {"http", "/", 0}, true, true}, |
| 174 {{"https", "/", 0}, {"https", "/", 0}, true, true}, |
| 175 {{"https", "/page1.html", 0}, {"https", "/page1.html", 0}, true, true}, |
| 176 {{"http", "/", 70}, {"http", "/", 70}, true, true}, |
| 177 {{"https", "/", 70}, {"https", "/", 70}, true, true}, |
| 178 {{"https", "/page1.html", 0}, {"https", "/page1.html", 0}, true, true}, |
| 179 {{"http", "/page1.html", 70}, {"http", "/page1.html", 70}, true, true}, |
| 180 {{"https", "/page1.html", 70}, {"https", "/page1.html", 70}, true, true}, |
| 181 // One stronger signal in the first CSPSource |
| 182 {{"https", "/", 0}, {"http", "/", 0}, true, false}, |
| 183 {{"http", "/page1.html", 0}, {"http", "/", 0}, true, false}, |
| 184 {{"http", "/", 80}, {"http", "/", 0}, true, true}, |
| 185 {{"http", "/", 700}, {"http", "/", 0}, false, false}, |
| 186 // Two stronger signals in the first CSPSource |
| 187 {{"https", "/page1.html", 0}, {"http", "/", 0}, true, false}, |
| 188 {{"https", "/", 80}, {"http", "/", 0}, false, false}, |
| 189 {{"http", "/page1.html", 80}, {"http", "/", 0}, true, false}, |
| 190 // Three stronger signals in the first CSPSource |
| 191 {{"https", "/page1.html", 70}, {"http", "/", 0}, false, false}, |
| 192 // Mixed signals |
| 193 {{"https", "/", 0}, {"http", "/page1.html", 0}, false, false}, |
| 194 {{"https", "/", 0}, {"http", "/", 70}, false, false}, |
| 195 {{"http", "/page1.html", 0}, {"http", "/", 70}, false, false}, |
| 196 }; |
| 197 |
| 198 for (const auto& test : cases) { |
| 199 CSPSource* returned = new CSPSource( |
| 200 csp.get(), test.a.scheme, "example.com", test.a.port, test.a.path, |
| 201 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 202 |
| 203 CSPSource* required = new CSPSource( |
| 204 csp.get(), test.b.scheme, "example.com", test.b.port, test.b.path, |
| 205 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 206 |
| 207 EXPECT_EQ(required->subsumes(returned), test.expected); |
| 208 // Verify the same test with a and b swapped. |
| 209 EXPECT_EQ(returned->subsumes(required), test.expectedWhenSwapped); |
| 210 } |
| 211 |
| 212 // When returned CSP has a wildcard but the required csp doesn't, then it is |
| 213 // not subsumed. |
| 214 for (const auto& test : cases) { |
| 215 CSPSource* returned = new CSPSource( |
| 216 csp.get(), test.a.scheme, "example.com", test.a.port, test.a.path, |
| 217 CSPSource::HasWildcard, CSPSource::NoWildcard); |
| 218 CSPSource* required = new CSPSource( |
| 219 csp.get(), test.b.scheme, "example.com", test.b.port, test.b.path, |
| 220 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 221 |
| 222 EXPECT_FALSE(required->subsumes(returned)); |
| 223 |
| 224 // If required csp also allows a wildcard in host, then the answer should be |
| 225 // as expected. |
| 226 CSPSource* required2 = new CSPSource( |
| 227 csp.get(), test.b.scheme, "example.com", test.b.port, test.b.path, |
| 228 CSPSource::HasWildcard, CSPSource::NoWildcard); |
| 229 EXPECT_EQ(required2->subsumes(returned), test.expected); |
| 230 } |
| 231 } |
| 232 |
| 233 TEST_F(CSPSourceTest, WildcardsSubsumes) { |
| 234 struct Wildcards { |
| 235 CSPSource::WildcardDisposition hostDispotion; |
| 236 CSPSource::WildcardDisposition portDispotion; |
| 237 }; |
| 238 struct TestCase { |
| 239 const Wildcards a; |
| 240 const Wildcards b; |
| 241 bool expected; |
| 242 } cases[] = { |
| 243 // One out of four possible wildcards. |
| 244 {{CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 245 {CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 246 false}, |
| 247 {{CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 248 {CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 249 false}, |
| 250 {{CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 251 {CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 252 true}, |
| 253 {{CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 254 {CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 255 true}, |
| 256 // Two out of four possible wildcards. |
| 257 {{CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 258 {CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 259 false}, |
| 260 {{CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 261 {CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 262 true}, |
| 263 {{CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 264 {CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 265 false}, |
| 266 {{CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 267 {CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 268 false}, |
| 269 {{CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 270 {CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 271 true}, |
| 272 {{CSPSource::NoWildcard, CSPSource::NoWildcard}, |
| 273 {CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 274 true}, |
| 275 // Three out of four possible wildcards. |
| 276 {{CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 277 {CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 278 false}, |
| 279 {{CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 280 {CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 281 false}, |
| 282 {{CSPSource::HasWildcard, CSPSource::NoWildcard}, |
| 283 {CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 284 true}, |
| 285 {{CSPSource::NoWildcard, CSPSource::HasWildcard}, |
| 286 {CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 287 true}, |
| 288 // Four out of four possible wildcards. |
| 289 {{CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 290 {CSPSource::HasWildcard, CSPSource::HasWildcard}, |
| 291 true}, |
| 292 }; |
| 293 |
| 294 // There are different cases for wildcards but now also the second CSPSource |
| 295 // has a more specific path. |
| 296 for (const auto& test : cases) { |
| 297 CSPSource* returned = |
| 298 new CSPSource(csp.get(), "http", "example.com", 0, "/", |
| 299 test.a.hostDispotion, test.a.portDispotion); |
| 300 CSPSource* required = |
| 301 new CSPSource(csp.get(), "http", "example.com", 0, "/", |
| 302 test.b.hostDispotion, test.b.portDispotion); |
| 303 EXPECT_EQ(required->subsumes(returned), test.expected); |
| 304 |
| 305 // Wildcards should not matter when required csp is stricter than returned |
| 306 // csp. |
| 307 CSPSource* required2 = |
| 308 new CSPSource(csp.get(), "https", "example.com", 0, "/", |
| 309 test.b.hostDispotion, test.b.portDispotion); |
| 310 EXPECT_FALSE(required2->subsumes(returned)); |
| 311 } |
| 312 } |
| 313 |
| 314 TEST_F(CSPSourceTest, SchemesOnlySubsumes) { |
| 315 struct TestCase { |
| 316 String aScheme; |
| 317 String bScheme; |
| 318 bool expected; |
| 319 } cases[] = { |
| 320 // HTTP |
| 321 {"http", "http", true}, |
| 322 {"http", "https", false}, |
| 323 {"https", "http", true}, |
| 324 {"https", "https", true}, |
| 325 // WSS |
| 326 {"ws", "ws", true}, |
| 327 {"ws", "wss", false}, |
| 328 {"wss", "ws", true}, |
| 329 {"wss", "wss", true}, |
| 330 // Unequal |
| 331 {"ws", "http", false}, |
| 332 {"http", "ws", false}, |
| 333 {"http", "about", false}, |
| 334 }; |
| 335 |
| 336 for (const auto& test : cases) { |
| 337 CSPSource* returned = |
| 338 new CSPSource(csp.get(), test.aScheme, "example.com", 0, "/", |
| 339 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 340 CSPSource* required = |
| 341 new CSPSource(csp.get(), test.bScheme, "example.com", 0, "/", |
| 342 CSPSource::NoWildcard, CSPSource::NoWildcard); |
| 343 EXPECT_EQ(required->subsumes(returned), test.expected); |
| 344 } |
| 345 } |
| 346 |
126 } // namespace blink | 347 } // namespace blink |
OLD | NEW |