| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google, Inc. All rights reserved. | 2 * Copyright (C) 2011 Google, Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
| 35 #include "core/dom/SecurityPolicyViolationEvent.h" | 35 #include "core/dom/SecurityPolicyViolationEvent.h" |
| 36 #include "core/inspector/InspectorInstrumentation.h" | 36 #include "core/inspector/InspectorInstrumentation.h" |
| 37 #include "core/inspector/ScriptCallStack.h" | 37 #include "core/inspector/ScriptCallStack.h" |
| 38 #include "core/loader/DocumentLoader.h" | 38 #include "core/loader/DocumentLoader.h" |
| 39 #include "core/loader/PingLoader.h" | 39 #include "core/loader/PingLoader.h" |
| 40 #include "core/page/ContentSecurityPolicyResponseHeaders.h" | 40 #include "core/page/ContentSecurityPolicyResponseHeaders.h" |
| 41 #include "core/page/Frame.h" | 41 #include "core/page/Frame.h" |
| 42 #include "core/page/UseCounter.h" | 42 #include "core/page/UseCounter.h" |
| 43 #include "core/platform/JSONValues.h" | 43 #include "core/platform/JSONValues.h" |
| 44 #include "core/platform/ParsingUtilities.h" |
| 44 #include "core/platform/network/FormData.h" | 45 #include "core/platform/network/FormData.h" |
| 45 #include "core/platform/network/ResourceResponse.h" | 46 #include "core/platform/network/ResourceResponse.h" |
| 46 #include "weborigin/KURL.h" | 47 #include "weborigin/KURL.h" |
| 47 #include "weborigin/KnownPorts.h" | 48 #include "weborigin/KnownPorts.h" |
| 48 #include "weborigin/SchemeRegistry.h" | 49 #include "weborigin/SchemeRegistry.h" |
| 49 #include "weborigin/SecurityOrigin.h" | 50 #include "weborigin/SecurityOrigin.h" |
| 50 #include "wtf/HashSet.h" | 51 #include "wtf/HashSet.h" |
| 51 #include "wtf/text/TextPosition.h" | 52 #include "wtf/text/TextPosition.h" |
| 52 #include "wtf/text/WTFString.h" | 53 #include "wtf/text/WTFString.h" |
| 53 | 54 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 return UseCounter::PrefixedContentSecurityPolicyReportOnly; | 159 return UseCounter::PrefixedContentSecurityPolicyReportOnly; |
| 159 case ContentSecurityPolicy::Report: | 160 case ContentSecurityPolicy::Report: |
| 160 return UseCounter::ContentSecurityPolicyReportOnly; | 161 return UseCounter::ContentSecurityPolicyReportOnly; |
| 161 } | 162 } |
| 162 ASSERT_NOT_REACHED(); | 163 ASSERT_NOT_REACHED(); |
| 163 return UseCounter::NumberOfFeatures; | 164 return UseCounter::NumberOfFeatures; |
| 164 } | 165 } |
| 165 | 166 |
| 166 } // namespace | 167 } // namespace |
| 167 | 168 |
| 168 static bool skipExactly(const UChar*& position, const UChar* end, UChar delimite
r) | |
| 169 { | |
| 170 if (position < end && *position == delimiter) { | |
| 171 ++position; | |
| 172 return true; | |
| 173 } | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 template<bool characterPredicate(UChar)> | |
| 178 static bool skipExactly(const UChar*& position, const UChar* end) | |
| 179 { | |
| 180 if (position < end && characterPredicate(*position)) { | |
| 181 ++position; | |
| 182 return true; | |
| 183 } | |
| 184 return false; | |
| 185 } | |
| 186 | |
| 187 static void skipUntil(const UChar*& position, const UChar* end, UChar delimiter) | |
| 188 { | |
| 189 while (position < end && *position != delimiter) | |
| 190 ++position; | |
| 191 } | |
| 192 | |
| 193 template<bool characterPredicate(UChar)> | |
| 194 static void skipWhile(const UChar*& position, const UChar* end) | |
| 195 { | |
| 196 while (position < end && characterPredicate(*position)) | |
| 197 ++position; | |
| 198 } | |
| 199 | |
| 200 static bool isSourceListNone(const UChar* begin, const UChar* end) | 169 static bool isSourceListNone(const UChar* begin, const UChar* end) |
| 201 { | 170 { |
| 202 skipWhile<isASCIISpace>(begin, end); | 171 skipWhile<UChar, isASCIISpace>(begin, end); |
| 203 | 172 |
| 204 const UChar* position = begin; | 173 const UChar* position = begin; |
| 205 skipWhile<isSourceCharacter>(position, end); | 174 skipWhile<UChar, isSourceCharacter>(position, end); |
| 206 if (!equalIgnoringCase("'none'", begin, position - begin)) | 175 if (!equalIgnoringCase("'none'", begin, position - begin)) |
| 207 return false; | 176 return false; |
| 208 | 177 |
| 209 skipWhile<isASCIISpace>(position, end); | 178 skipWhile<UChar, isASCIISpace>(position, end); |
| 210 if (position != end) | 179 if (position != end) |
| 211 return false; | 180 return false; |
| 212 | 181 |
| 213 return true; | 182 return true; |
| 214 } | 183 } |
| 215 | 184 |
| 216 class CSPSource { | 185 class CSPSource { |
| 217 public: | 186 public: |
| 218 CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String&
host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) | 187 CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String&
host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) |
| 219 : m_policy(policy) | 188 : m_policy(policy) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 // / *WSP "'none'" *WSP | 331 // / *WSP "'none'" *WSP |
| 363 // | 332 // |
| 364 void CSPSourceList::parse(const UChar* begin, const UChar* end) | 333 void CSPSourceList::parse(const UChar* begin, const UChar* end) |
| 365 { | 334 { |
| 366 // We represent 'none' as an empty m_list. | 335 // We represent 'none' as an empty m_list. |
| 367 if (isSourceListNone(begin, end)) | 336 if (isSourceListNone(begin, end)) |
| 368 return; | 337 return; |
| 369 | 338 |
| 370 const UChar* position = begin; | 339 const UChar* position = begin; |
| 371 while (position < end) { | 340 while (position < end) { |
| 372 skipWhile<isASCIISpace>(position, end); | 341 skipWhile<UChar, isASCIISpace>(position, end); |
| 373 if (position == end) | 342 if (position == end) |
| 374 return; | 343 return; |
| 375 | 344 |
| 376 const UChar* beginSource = position; | 345 const UChar* beginSource = position; |
| 377 skipWhile<isSourceCharacter>(position, end); | 346 skipWhile<UChar, isSourceCharacter>(position, end); |
| 378 | 347 |
| 379 String scheme, host, path; | 348 String scheme, host, path; |
| 380 int port = 0; | 349 int port = 0; |
| 381 bool hostHasWildcard = false; | 350 bool hostHasWildcard = false; |
| 382 bool portHasWildcard = false; | 351 bool portHasWildcard = false; |
| 383 | 352 |
| 384 if (parseSource(beginSource, position, scheme, host, port, path, hostHas
Wildcard, portHasWildcard)) { | 353 if (parseSource(beginSource, position, scheme, host, port, path, hostHas
Wildcard, portHasWildcard)) { |
| 385 // Wildcard hosts and keyword sources ('self', 'unsafe-inline', | 354 // Wildcard hosts and keyword sources ('self', 'unsafe-inline', |
| 386 // etc.) aren't stored in m_list, but as attributes on the source | 355 // etc.) aren't stored in m_list, but as attributes on the source |
| 387 // list itself. | 356 // list itself. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 addSourceNonce(nonce); | 409 addSourceNonce(nonce); |
| 441 return true; | 410 return true; |
| 442 } | 411 } |
| 443 } | 412 } |
| 444 | 413 |
| 445 const UChar* position = begin; | 414 const UChar* position = begin; |
| 446 const UChar* beginHost = begin; | 415 const UChar* beginHost = begin; |
| 447 const UChar* beginPath = end; | 416 const UChar* beginPath = end; |
| 448 const UChar* beginPort = 0; | 417 const UChar* beginPort = 0; |
| 449 | 418 |
| 450 skipWhile<isNotColonOrSlash>(position, end); | 419 skipWhile<UChar, isNotColonOrSlash>(position, end); |
| 451 | 420 |
| 452 if (position == end) { | 421 if (position == end) { |
| 453 // host | 422 // host |
| 454 // ^ | 423 // ^ |
| 455 return parseHost(beginHost, position, host, hostHasWildcard); | 424 return parseHost(beginHost, position, host, hostHasWildcard); |
| 456 } | 425 } |
| 457 | 426 |
| 458 if (position < end && *position == '/') { | 427 if (position < end && *position == '/') { |
| 459 // host/path || host/ || / | 428 // host/path || host/ || / |
| 460 // ^ ^ ^ | 429 // ^ ^ ^ |
| 461 return parseHost(beginHost, position, host, hostHasWildcard) && parsePat
h(position, end, path); | 430 return parseHost(beginHost, position, host, hostHasWildcard) && parsePat
h(position, end, path); |
| 462 } | 431 } |
| 463 | 432 |
| 464 if (position < end && *position == ':') { | 433 if (position < end && *position == ':') { |
| 465 if (end - position == 1) { | 434 if (end - position == 1) { |
| 466 // scheme: | 435 // scheme: |
| 467 // ^ | 436 // ^ |
| 468 return parseScheme(begin, position, scheme); | 437 return parseScheme(begin, position, scheme); |
| 469 } | 438 } |
| 470 | 439 |
| 471 if (position[1] == '/') { | 440 if (position[1] == '/') { |
| 472 // scheme://host || scheme:// | 441 // scheme://host || scheme:// |
| 473 // ^ ^ | 442 // ^ ^ |
| 474 if (!parseScheme(begin, position, scheme) | 443 if (!parseScheme(begin, position, scheme) |
| 475 || !skipExactly(position, end, ':') | 444 || !skipExactly<UChar>(position, end, ':') |
| 476 || !skipExactly(position, end, '/') | 445 || !skipExactly<UChar>(position, end, '/') |
| 477 || !skipExactly(position, end, '/')) | 446 || !skipExactly<UChar>(position, end, '/')) |
| 478 return false; | 447 return false; |
| 479 if (position == end) | 448 if (position == end) |
| 480 return true; | 449 return true; |
| 481 beginHost = position; | 450 beginHost = position; |
| 482 skipWhile<isNotColonOrSlash>(position, end); | 451 skipWhile<UChar, isNotColonOrSlash>(position, end); |
| 483 } | 452 } |
| 484 | 453 |
| 485 if (position < end && *position == ':') { | 454 if (position < end && *position == ':') { |
| 486 // host:port || scheme://host:port | 455 // host:port || scheme://host:port |
| 487 // ^ ^ | 456 // ^ ^ |
| 488 beginPort = position; | 457 beginPort = position; |
| 489 skipUntil(position, end, '/'); | 458 skipUntil<UChar>(position, end, '/'); |
| 490 } | 459 } |
| 491 } | 460 } |
| 492 | 461 |
| 493 if (position < end && *position == '/') { | 462 if (position < end && *position == '/') { |
| 494 // scheme://host/path || scheme://host:port/path | 463 // scheme://host/path || scheme://host:port/path |
| 495 // ^ ^ | 464 // ^ ^ |
| 496 if (position == beginHost) | 465 if (position == beginHost) |
| 497 return false; | 466 return false; |
| 498 beginPath = position; | 467 beginPath = position; |
| 499 } | 468 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 522 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non
ce) | 491 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non
ce) |
| 523 { | 492 { |
| 524 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); | 493 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); |
| 525 | 494 |
| 526 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length(
))) | 495 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length(
))) |
| 527 return true; | 496 return true; |
| 528 | 497 |
| 529 const UChar* position = begin + noncePrefix.length(); | 498 const UChar* position = begin + noncePrefix.length(); |
| 530 const UChar* nonceBegin = position; | 499 const UChar* nonceBegin = position; |
| 531 | 500 |
| 532 skipWhile<isNonceCharacter>(position, end); | 501 skipWhile<UChar, isNonceCharacter>(position, end); |
| 533 ASSERT(nonceBegin <= position); | 502 ASSERT(nonceBegin <= position); |
| 534 | 503 |
| 535 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin
)) | 504 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin
)) |
| 536 return false; | 505 return false; |
| 537 | 506 |
| 538 nonce = String(nonceBegin, position - nonceBegin); | 507 nonce = String(nonceBegin, position - nonceBegin); |
| 539 return true; | 508 return true; |
| 540 } | 509 } |
| 541 | 510 |
| 542 // ; <scheme> production from RFC 3986 | 511 // ; <scheme> production from RFC 3986 |
| 543 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | 512 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
| 544 // | 513 // |
| 545 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc
heme) | 514 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc
heme) |
| 546 { | 515 { |
| 547 ASSERT(begin <= end); | 516 ASSERT(begin <= end); |
| 548 ASSERT(scheme.isEmpty()); | 517 ASSERT(scheme.isEmpty()); |
| 549 | 518 |
| 550 if (begin == end) | 519 if (begin == end) |
| 551 return false; | 520 return false; |
| 552 | 521 |
| 553 const UChar* position = begin; | 522 const UChar* position = begin; |
| 554 | 523 |
| 555 if (!skipExactly<isASCIIAlpha>(position, end)) | 524 if (!skipExactly<UChar, isASCIIAlpha>(position, end)) |
| 556 return false; | 525 return false; |
| 557 | 526 |
| 558 skipWhile<isSchemeContinuationCharacter>(position, end); | 527 skipWhile<UChar, isSchemeContinuationCharacter>(position, end); |
| 559 | 528 |
| 560 if (position != end) | 529 if (position != end) |
| 561 return false; | 530 return false; |
| 562 | 531 |
| 563 scheme = String(begin, end - begin); | 532 scheme = String(begin, end - begin); |
| 564 return true; | 533 return true; |
| 565 } | 534 } |
| 566 | 535 |
| 567 // host = [ "*." ] 1*host-char *( "." 1*host-char ) | 536 // host = [ "*." ] 1*host-char *( "." 1*host-char ) |
| 568 // / "*" | 537 // / "*" |
| 569 // host-char = ALPHA / DIGIT / "-" | 538 // host-char = ALPHA / DIGIT / "-" |
| 570 // | 539 // |
| 571 bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host
, bool& hostHasWildcard) | 540 bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host
, bool& hostHasWildcard) |
| 572 { | 541 { |
| 573 ASSERT(begin <= end); | 542 ASSERT(begin <= end); |
| 574 ASSERT(host.isEmpty()); | 543 ASSERT(host.isEmpty()); |
| 575 ASSERT(!hostHasWildcard); | 544 ASSERT(!hostHasWildcard); |
| 576 | 545 |
| 577 if (begin == end) | 546 if (begin == end) |
| 578 return false; | 547 return false; |
| 579 | 548 |
| 580 const UChar* position = begin; | 549 const UChar* position = begin; |
| 581 | 550 |
| 582 if (skipExactly(position, end, '*')) { | 551 if (skipExactly<UChar>(position, end, '*')) { |
| 583 hostHasWildcard = true; | 552 hostHasWildcard = true; |
| 584 | 553 |
| 585 if (position == end) | 554 if (position == end) |
| 586 return true; | 555 return true; |
| 587 | 556 |
| 588 if (!skipExactly(position, end, '.')) | 557 if (!skipExactly<UChar>(position, end, '.')) |
| 589 return false; | 558 return false; |
| 590 } | 559 } |
| 591 | 560 |
| 592 const UChar* hostBegin = position; | 561 const UChar* hostBegin = position; |
| 593 | 562 |
| 594 while (position < end) { | 563 while (position < end) { |
| 595 if (!skipExactly<isHostCharacter>(position, end)) | 564 if (!skipExactly<UChar, isHostCharacter>(position, end)) |
| 596 return false; | 565 return false; |
| 597 | 566 |
| 598 skipWhile<isHostCharacter>(position, end); | 567 skipWhile<UChar, isHostCharacter>(position, end); |
| 599 | 568 |
| 600 if (position < end && !skipExactly(position, end, '.')) | 569 if (position < end && !skipExactly<UChar>(position, end, '.')) |
| 601 return false; | 570 return false; |
| 602 } | 571 } |
| 603 | 572 |
| 604 ASSERT(position == end); | 573 ASSERT(position == end); |
| 605 host = String(hostBegin, end - hostBegin); | 574 host = String(hostBegin, end - hostBegin); |
| 606 return true; | 575 return true; |
| 607 } | 576 } |
| 608 | 577 |
| 609 bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path
) | 578 bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path
) |
| 610 { | 579 { |
| 611 ASSERT(begin <= end); | 580 ASSERT(begin <= end); |
| 612 ASSERT(path.isEmpty()); | 581 ASSERT(path.isEmpty()); |
| 613 | 582 |
| 614 const UChar* position = begin; | 583 const UChar* position = begin; |
| 615 skipWhile<isPathComponentCharacter>(position, end); | 584 skipWhile<UChar, isPathComponentCharacter>(position, end); |
| 616 // path/to/file.js?query=string || path/to/file.js#anchor | 585 // path/to/file.js?query=string || path/to/file.js#anchor |
| 617 // ^ ^ | 586 // ^ ^ |
| 618 if (position < end) | 587 if (position < end) |
| 619 m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end
- begin), *position); | 588 m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end
- begin), *position); |
| 620 | 589 |
| 621 path = decodeURLEscapeSequences(String(begin, position - begin)); | 590 path = decodeURLEscapeSequences(String(begin, position - begin)); |
| 622 | 591 |
| 623 ASSERT(position <= end); | 592 ASSERT(position <= end); |
| 624 ASSERT(position == end || (*position == '#' || *position == '?')); | 593 ASSERT(position == end || (*position == '#' || *position == '?')); |
| 625 return true; | 594 return true; |
| 626 } | 595 } |
| 627 | 596 |
| 628 // port = ":" ( 1*DIGIT / "*" ) | 597 // port = ":" ( 1*DIGIT / "*" ) |
| 629 // | 598 // |
| 630 bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, b
ool& portHasWildcard) | 599 bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, b
ool& portHasWildcard) |
| 631 { | 600 { |
| 632 ASSERT(begin <= end); | 601 ASSERT(begin <= end); |
| 633 ASSERT(!port); | 602 ASSERT(!port); |
| 634 ASSERT(!portHasWildcard); | 603 ASSERT(!portHasWildcard); |
| 635 | 604 |
| 636 if (!skipExactly(begin, end, ':')) | 605 if (!skipExactly<UChar>(begin, end, ':')) |
| 637 ASSERT_NOT_REACHED(); | 606 ASSERT_NOT_REACHED(); |
| 638 | 607 |
| 639 if (begin == end) | 608 if (begin == end) |
| 640 return false; | 609 return false; |
| 641 | 610 |
| 642 if (end - begin == 1 && *begin == '*') { | 611 if (end - begin == 1 && *begin == '*') { |
| 643 port = 0; | 612 port = 0; |
| 644 portHasWildcard = true; | 613 portHasWildcard = true; |
| 645 return true; | 614 return true; |
| 646 } | 615 } |
| 647 | 616 |
| 648 const UChar* position = begin; | 617 const UChar* position = begin; |
| 649 skipWhile<isASCIIDigit>(position, end); | 618 skipWhile<UChar, isASCIIDigit>(position, end); |
| 650 | 619 |
| 651 if (position != end) | 620 if (position != end) |
| 652 return false; | 621 return false; |
| 653 | 622 |
| 654 bool ok; | 623 bool ok; |
| 655 port = charactersToIntStrict(begin, end - begin, &ok); | 624 port = charactersToIntStrict(begin, end - begin, &ok); |
| 656 return ok; | 625 return ok; |
| 657 } | 626 } |
| 658 | 627 |
| 659 void CSPSourceList::addSourceSelf() | 628 void CSPSourceList::addSourceSelf() |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 | 692 |
| 724 // 'plugin-types ____;' OR 'plugin-types;' | 693 // 'plugin-types ____;' OR 'plugin-types;' |
| 725 if (position == end) { | 694 if (position == end) { |
| 726 policy()->reportInvalidPluginTypes(String()); | 695 policy()->reportInvalidPluginTypes(String()); |
| 727 return; | 696 return; |
| 728 } | 697 } |
| 729 | 698 |
| 730 while (position < end) { | 699 while (position < end) { |
| 731 // _____ OR _____mime1/mime1 | 700 // _____ OR _____mime1/mime1 |
| 732 // ^ ^ | 701 // ^ ^ |
| 733 skipWhile<isASCIISpace>(position, end); | 702 skipWhile<UChar, isASCIISpace>(position, end); |
| 734 if (position == end) | 703 if (position == end) |
| 735 return; | 704 return; |
| 736 | 705 |
| 737 // mime1/mime1 mime2/mime2 | 706 // mime1/mime1 mime2/mime2 |
| 738 // ^ | 707 // ^ |
| 739 begin = position; | 708 begin = position; |
| 740 if (!skipExactly<isMediaTypeCharacter>(position, end)) { | 709 if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { |
| 741 skipWhile<isNotASCIISpace>(position, end); | 710 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 742 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 711 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
| 743 continue; | 712 continue; |
| 744 } | 713 } |
| 745 skipWhile<isMediaTypeCharacter>(position, end); | 714 skipWhile<UChar, isMediaTypeCharacter>(position, end); |
| 746 | 715 |
| 747 // mime1/mime1 mime2/mime2 | 716 // mime1/mime1 mime2/mime2 |
| 748 // ^ | 717 // ^ |
| 749 if (!skipExactly(position, end, '/')) { | 718 if (!skipExactly<UChar>(position, end, '/')) { |
| 750 skipWhile<isNotASCIISpace>(position, end); | 719 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 751 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 720 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
| 752 continue; | 721 continue; |
| 753 } | 722 } |
| 754 | 723 |
| 755 // mime1/mime1 mime2/mime2 | 724 // mime1/mime1 mime2/mime2 |
| 756 // ^ | 725 // ^ |
| 757 if (!skipExactly<isMediaTypeCharacter>(position, end)) { | 726 if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { |
| 758 skipWhile<isNotASCIISpace>(position, end); | 727 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 759 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 728 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
| 760 continue; | 729 continue; |
| 761 } | 730 } |
| 762 skipWhile<isMediaTypeCharacter>(position, end); | 731 skipWhile<UChar, isMediaTypeCharacter>(position, end); |
| 763 | 732 |
| 764 // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error | 733 // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error |
| 765 // ^ ^ ^ | 734 // ^ ^ ^ |
| 766 if (position < end && isNotASCIISpace(*position)) { | 735 if (position < end && isNotASCIISpace(*position)) { |
| 767 skipWhile<isNotASCIISpace>(position, end); | 736 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 768 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 737 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
| 769 continue; | 738 continue; |
| 770 } | 739 } |
| 771 m_pluginTypes.add(String(begin, position - begin)); | 740 m_pluginTypes.add(String(begin, position - begin)); |
| 772 | 741 |
| 773 ASSERT(position == end || isASCIISpace(*position)); | 742 ASSERT(position == end || isASCIISpace(*position)); |
| 774 } | 743 } |
| 775 } | 744 } |
| 776 | 745 |
| 777 HashSet<String> m_pluginTypes; | 746 HashSet<String> m_pluginTypes; |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1206 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) | 1175 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) |
| 1207 { | 1176 { |
| 1208 m_header = String(begin, end - begin); | 1177 m_header = String(begin, end - begin); |
| 1209 | 1178 |
| 1210 if (begin == end) | 1179 if (begin == end) |
| 1211 return; | 1180 return; |
| 1212 | 1181 |
| 1213 const UChar* position = begin; | 1182 const UChar* position = begin; |
| 1214 while (position < end) { | 1183 while (position < end) { |
| 1215 const UChar* directiveBegin = position; | 1184 const UChar* directiveBegin = position; |
| 1216 skipUntil(position, end, ';'); | 1185 skipUntil<UChar>(position, end, ';'); |
| 1217 | 1186 |
| 1218 String name, value; | 1187 String name, value; |
| 1219 if (parseDirective(directiveBegin, position, name, value)) { | 1188 if (parseDirective(directiveBegin, position, name, value)) { |
| 1220 ASSERT(!name.isEmpty()); | 1189 ASSERT(!name.isEmpty()); |
| 1221 addDirective(name, value); | 1190 addDirective(name, value); |
| 1222 } | 1191 } |
| 1223 | 1192 |
| 1224 ASSERT(position == end || *position == ';'); | 1193 ASSERT(position == end || *position == ';'); |
| 1225 skipExactly(position, end, ';'); | 1194 skipExactly<UChar>(position, end, ';'); |
| 1226 } | 1195 } |
| 1227 } | 1196 } |
| 1228 | 1197 |
| 1229 // directive = *WSP [ directive-name [ WSP directive-value ] ] | 1198 // directive = *WSP [ directive-name [ WSP directive-value ] ] |
| 1230 // directive-name = 1*( ALPHA / DIGIT / "-" ) | 1199 // directive-name = 1*( ALPHA / DIGIT / "-" ) |
| 1231 // directive-value = *( WSP / <VCHAR except ";"> ) | 1200 // directive-value = *( WSP / <VCHAR except ";"> ) |
| 1232 // | 1201 // |
| 1233 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, Stri
ng& name, String& value) | 1202 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, Stri
ng& name, String& value) |
| 1234 { | 1203 { |
| 1235 ASSERT(name.isEmpty()); | 1204 ASSERT(name.isEmpty()); |
| 1236 ASSERT(value.isEmpty()); | 1205 ASSERT(value.isEmpty()); |
| 1237 | 1206 |
| 1238 const UChar* position = begin; | 1207 const UChar* position = begin; |
| 1239 skipWhile<isASCIISpace>(position, end); | 1208 skipWhile<UChar, isASCIISpace>(position, end); |
| 1240 | 1209 |
| 1241 // Empty directive (e.g. ";;;"). Exit early. | 1210 // Empty directive (e.g. ";;;"). Exit early. |
| 1242 if (position == end) | 1211 if (position == end) |
| 1243 return false; | 1212 return false; |
| 1244 | 1213 |
| 1245 const UChar* nameBegin = position; | 1214 const UChar* nameBegin = position; |
| 1246 skipWhile<isDirectiveNameCharacter>(position, end); | 1215 skipWhile<UChar, isDirectiveNameCharacter>(position, end); |
| 1247 | 1216 |
| 1248 // The directive-name must be non-empty. | 1217 // The directive-name must be non-empty. |
| 1249 if (nameBegin == position) { | 1218 if (nameBegin == position) { |
| 1250 skipWhile<isNotASCIISpace>(position, end); | 1219 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 1251 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); | 1220 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); |
| 1252 return false; | 1221 return false; |
| 1253 } | 1222 } |
| 1254 | 1223 |
| 1255 name = String(nameBegin, position - nameBegin); | 1224 name = String(nameBegin, position - nameBegin); |
| 1256 | 1225 |
| 1257 if (position == end) | 1226 if (position == end) |
| 1258 return true; | 1227 return true; |
| 1259 | 1228 |
| 1260 if (!skipExactly<isASCIISpace>(position, end)) { | 1229 if (!skipExactly<UChar, isASCIISpace>(position, end)) { |
| 1261 skipWhile<isNotASCIISpace>(position, end); | 1230 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 1262 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); | 1231 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); |
| 1263 return false; | 1232 return false; |
| 1264 } | 1233 } |
| 1265 | 1234 |
| 1266 skipWhile<isASCIISpace>(position, end); | 1235 skipWhile<UChar, isASCIISpace>(position, end); |
| 1267 | 1236 |
| 1268 const UChar* valueBegin = position; | 1237 const UChar* valueBegin = position; |
| 1269 skipWhile<isDirectiveValueCharacter>(position, end); | 1238 skipWhile<UChar, isDirectiveValueCharacter>(position, end); |
| 1270 | 1239 |
| 1271 if (position != end) { | 1240 if (position != end) { |
| 1272 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin,
end - valueBegin)); | 1241 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin,
end - valueBegin)); |
| 1273 return false; | 1242 return false; |
| 1274 } | 1243 } |
| 1275 | 1244 |
| 1276 // The directive-value may be empty. | 1245 // The directive-value may be empty. |
| 1277 if (valueBegin == position) | 1246 if (valueBegin == position) |
| 1278 return true; | 1247 return true; |
| 1279 | 1248 |
| 1280 value = String(valueBegin, position - valueBegin); | 1249 value = String(valueBegin, position - valueBegin); |
| 1281 return true; | 1250 return true; |
| 1282 } | 1251 } |
| 1283 | 1252 |
| 1284 void CSPDirectiveList::parseReportURI(const String& name, const String& value) | 1253 void CSPDirectiveList::parseReportURI(const String& name, const String& value) |
| 1285 { | 1254 { |
| 1286 if (!m_reportURIs.isEmpty()) { | 1255 if (!m_reportURIs.isEmpty()) { |
| 1287 m_policy->reportDuplicateDirective(name); | 1256 m_policy->reportDuplicateDirective(name); |
| 1288 return; | 1257 return; |
| 1289 } | 1258 } |
| 1290 | 1259 |
| 1291 Vector<UChar> characters; | 1260 Vector<UChar> characters; |
| 1292 value.appendTo(characters); | 1261 value.appendTo(characters); |
| 1293 | 1262 |
| 1294 const UChar* position = characters.data(); | 1263 const UChar* position = characters.data(); |
| 1295 const UChar* end = position + characters.size(); | 1264 const UChar* end = position + characters.size(); |
| 1296 | 1265 |
| 1297 while (position < end) { | 1266 while (position < end) { |
| 1298 skipWhile<isASCIISpace>(position, end); | 1267 skipWhile<UChar, isASCIISpace>(position, end); |
| 1299 | 1268 |
| 1300 const UChar* urlBegin = position; | 1269 const UChar* urlBegin = position; |
| 1301 skipWhile<isNotASCIISpace>(position, end); | 1270 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 1302 | 1271 |
| 1303 if (urlBegin < position) { | 1272 if (urlBegin < position) { |
| 1304 String url = String(urlBegin, position - urlBegin); | 1273 String url = String(urlBegin, position - urlBegin); |
| 1305 m_reportURIs.append(m_policy->completeURL(url)); | 1274 m_reportURIs.append(m_policy->completeURL(url)); |
| 1306 } | 1275 } |
| 1307 } | 1276 } |
| 1308 } | 1277 } |
| 1309 | 1278 |
| 1310 | 1279 |
| 1311 template<class CSPDirectiveType> | 1280 template<class CSPDirectiveType> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 m_policy->reportInvalidReflectedXSS(value); | 1313 m_policy->reportInvalidReflectedXSS(value); |
| 1345 return; | 1314 return; |
| 1346 } | 1315 } |
| 1347 | 1316 |
| 1348 Vector<UChar> characters; | 1317 Vector<UChar> characters; |
| 1349 value.appendTo(characters); | 1318 value.appendTo(characters); |
| 1350 | 1319 |
| 1351 const UChar* position = characters.data(); | 1320 const UChar* position = characters.data(); |
| 1352 const UChar* end = position + characters.size(); | 1321 const UChar* end = position + characters.size(); |
| 1353 | 1322 |
| 1354 skipWhile<isASCIISpace>(position, end); | 1323 skipWhile<UChar, isASCIISpace>(position, end); |
| 1355 const UChar* begin = position; | 1324 const UChar* begin = position; |
| 1356 skipWhile<isNotASCIISpace>(position, end); | 1325 skipWhile<UChar, isNotASCIISpace>(position, end); |
| 1357 | 1326 |
| 1358 // value1 | 1327 // value1 |
| 1359 // ^ | 1328 // ^ |
| 1360 if (equalIgnoringCase("allow", begin, position - begin)) | 1329 if (equalIgnoringCase("allow", begin, position - begin)) |
| 1361 m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS; | 1330 m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS; |
| 1362 else if (equalIgnoringCase("filter", begin, position - begin)) | 1331 else if (equalIgnoringCase("filter", begin, position - begin)) |
| 1363 m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS; | 1332 m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS; |
| 1364 else if (equalIgnoringCase("block", begin, position - begin)) | 1333 else if (equalIgnoringCase("block", begin, position - begin)) |
| 1365 m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS; | 1334 m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS; |
| 1366 else { | 1335 else { |
| 1367 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; | 1336 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; |
| 1368 m_policy->reportInvalidReflectedXSS(value); | 1337 m_policy->reportInvalidReflectedXSS(value); |
| 1369 return; | 1338 return; |
| 1370 } | 1339 } |
| 1371 | 1340 |
| 1372 skipWhile<isASCIISpace>(position, end); | 1341 skipWhile<UChar, isASCIISpace>(position, end); |
| 1373 if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::R
eflectedXSSUnset) | 1342 if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::R
eflectedXSSUnset) |
| 1374 return; | 1343 return; |
| 1375 | 1344 |
| 1376 // value1 value2 | 1345 // value1 value2 |
| 1377 // ^ | 1346 // ^ |
| 1378 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; | 1347 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; |
| 1379 m_policy->reportInvalidReflectedXSS(value); | 1348 m_policy->reportInvalidReflectedXSS(value); |
| 1380 } | 1349 } |
| 1381 | 1350 |
| 1382 void CSPDirectiveList::addDirective(const String& name, const String& value) | 1351 void CSPDirectiveList::addDirective(const String& name, const String& value) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 header.appendTo(characters); | 1438 header.appendTo(characters); |
| 1470 | 1439 |
| 1471 const UChar* begin = characters.data(); | 1440 const UChar* begin = characters.data(); |
| 1472 const UChar* end = begin + characters.size(); | 1441 const UChar* end = begin + characters.size(); |
| 1473 | 1442 |
| 1474 // RFC2616, section 4.2 specifies that headers appearing multiple times can | 1443 // RFC2616, section 4.2 specifies that headers appearing multiple times can |
| 1475 // be combined with a comma. Walk the header string, and parse each comma | 1444 // be combined with a comma. Walk the header string, and parse each comma |
| 1476 // separated chunk as a separate header. | 1445 // separated chunk as a separate header. |
| 1477 const UChar* position = begin; | 1446 const UChar* position = begin; |
| 1478 while (position < end) { | 1447 while (position < end) { |
| 1479 skipUntil(position, end, ','); | 1448 skipUntil<UChar>(position, end, ','); |
| 1480 | 1449 |
| 1481 // header1,header2 OR header1 | 1450 // header1,header2 OR header1 |
| 1482 // ^ ^ | 1451 // ^ ^ |
| 1483 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin,
position, type); | 1452 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin,
position, type); |
| 1484 | 1453 |
| 1485 // We disable 'eval()' even in the case of report-only policies, and rel
y on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread cal
lback to determine whether the call should execute or not. | 1454 // We disable 'eval()' even in the case of report-only policies, and rel
y on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread cal
lback to determine whether the call should execute or not. |
| 1486 if (!policy->allowEval(0, SuppressReport)) | 1455 if (!policy->allowEval(0, SuppressReport)) |
| 1487 m_scriptExecutionContext->disableEval(policy->evalDisabledErrorMessa
ge()); | 1456 m_scriptExecutionContext->disableEval(policy->evalDisabledErrorMessa
ge()); |
| 1488 | 1457 |
| 1489 m_policies.append(policy.release()); | 1458 m_policies.append(policy.release()); |
| 1490 | 1459 |
| 1491 // Skip the comma, and begin the next header from the current position. | 1460 // Skip the comma, and begin the next header from the current position. |
| 1492 ASSERT(position == end || *position == ','); | 1461 ASSERT(position == end || *position == ','); |
| 1493 skipExactly(position, end, ','); | 1462 skipExactly<UChar>(position, end, ','); |
| 1494 begin = position; | 1463 begin = position; |
| 1495 } | 1464 } |
| 1496 } | 1465 } |
| 1497 | 1466 |
| 1498 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) | 1467 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) |
| 1499 { | 1468 { |
| 1500 m_overrideInlineStyleAllowed = value; | 1469 m_overrideInlineStyleAllowed = value; |
| 1501 } | 1470 } |
| 1502 | 1471 |
| 1503 const String& ContentSecurityPolicy::deprecatedHeader() const | 1472 const String& ContentSecurityPolicy::deprecatedHeader() const |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 1889 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
| 1921 return !m_violationReportsSent.contains(report.impl()->hash()); | 1890 return !m_violationReportsSent.contains(report.impl()->hash()); |
| 1922 } | 1891 } |
| 1923 | 1892 |
| 1924 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 1893 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
| 1925 { | 1894 { |
| 1926 m_violationReportsSent.add(report.impl()->hash()); | 1895 m_violationReportsSent.add(report.impl()->hash()); |
| 1927 } | 1896 } |
| 1928 | 1897 |
| 1929 } // namespace WebCore | 1898 } // namespace WebCore |
| OLD | NEW |