这是indexloc提供的服务,不要输入任何密码
| Differences between
and this patch
- Source/WebCore/ChangeLog +32 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2016-11-29  John Wilander  <wilander@apple.com>
2
3
        Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
4
        https://bugs.webkit.org/show_bug.cgi?id=165178
5
        <rdar://problem/18792250>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Test: http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html
10
11
        * loader/CrossOriginAccessControl.cpp:
12
        (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist):
13
            Now makes a call to WebCore:: isValidAcceptHeaderValue for Accept headers
14
            and WebCore:: isValidLanguageHeaderValue for Accept-Language and
15
            Content-Language headers.
16
        * platform/Language.cpp:
17
        (WebCore::isValidLanguageHeaderValue):
18
            Basic check that the characters are all ASCII alphanumeric, ' ', '*', '-', '.', ';', or '='.
19
        * platform/Language.h:
20
        * platform/network/HTTPParsers.cpp:
21
        (WebCore::isValidAcceptHeaderValue):
22
            Basic check that the characters are all ASCII alphanumeric, ' ', '*', '.', '/', ';', or '='.
23
        (WebCore::isSimpleHeader):
24
            Now makes a call to WebCore:: isValidAcceptHeaderValue for Accept headers
25
            and WebCore:: isValidLanguageHeaderValue for Accept-Language and
26
            Content-Language headers.
27
        (WebCore::isCrossOriginSafeRequestHeader):
28
            Now makes a call to WebCore:: isValidAcceptHeaderValue for Accept headers
29
            and WebCore:: isValidLanguageHeaderValue for Accept-Language and
30
            Content-Language headers.
31
        * platform/network/HTTPParsers.h:
32
1
2016-11-29  Brady Eidson  <beidson@apple.com>
33
2016-11-29  Brady Eidson  <beidson@apple.com>
2
34
3
        Followup to:
35
        Followup to:
- Source/WebCore/loader/CrossOriginAccessControl.cpp -1 / +3 lines
Lines 29-34 Source/WebCore/loader/CrossOriginAccessControl.cpp_sec1
29
29
30
#include "HTTPHeaderNames.h"
30
#include "HTTPHeaderNames.h"
31
#include "HTTPParsers.h"
31
#include "HTTPParsers.h"
32
#include "Language.h"
32
#include "ResourceRequest.h"
33
#include "ResourceRequest.h"
33
#include "ResourceResponse.h"
34
#include "ResourceResponse.h"
34
#include "SchemeRegistry.h"
35
#include "SchemeRegistry.h"
Lines 49-57 bool isOnAccessControlSimpleRequestHeade Source/WebCore/loader/CrossOriginAccessControl.cpp_sec2
49
{
50
{
50
    switch (name) {
51
    switch (name) {
51
    case HTTPHeaderName::Accept:
52
    case HTTPHeaderName::Accept:
53
        return isValidAcceptHeaderValue(value);
52
    case HTTPHeaderName::AcceptLanguage:
54
    case HTTPHeaderName::AcceptLanguage:
53
    case HTTPHeaderName::ContentLanguage:
55
    case HTTPHeaderName::ContentLanguage:
54
        return true;
56
        return isValidLanguageHeaderValue(value);
55
    case HTTPHeaderName::ContentType: {
57
    case HTTPHeaderName::ContentType: {
56
        // Preflight is required for MIME types that can not be sent via form submission.
58
        // Preflight is required for MIME types that can not be sent via form submission.
57
        String mimeType = extractMIMETypeFromMediaType(value);
59
        String mimeType = extractMIMETypeFromMediaType(value);
- Source/WebCore/platform/Language.cpp +27 lines
Lines 26-31 Source/WebCore/platform/Language.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "Language.h"
27
#include "Language.h"
28
28
29
#include <wtf/ASCIICType.h>
29
#include <wtf/HashMap.h>
30
#include <wtf/HashMap.h>
30
#include <wtf/NeverDestroyed.h>
31
#include <wtf/NeverDestroyed.h>
31
#include <wtf/PlatformUserPreferredLanguages.h>
32
#include <wtf/PlatformUserPreferredLanguages.h>
Lines 188-191 String displayNameForLanguageLocale(cons Source/WebCore/platform/Language.cpp_sec2
188
    return localeName;
189
    return localeName;
189
}
190
}
190
191
192
193
bool isValidLanguageHeaderValue(const String& value)
194
{
195
    // Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
196
    // Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
197
    // Language range https://tools.ietf.org/html/rfc4647#section-2.1
198
    // Language tags https://tools.ietf.org/html/rfc7231#section-3.1.3.1
199
    // Language tag syntax https://tools.ietf.org/html/bcp47#section-2.1
200
    UChar c;
201
    for (unsigned i = 0; i < value.length(); ++i) {
202
        c = value[i];
203
        if (!isASCIIAlphanumeric(c)
204
            && c != ' '
205
            && c != '*'
206
            && c != '-'
207
            && c != '.'
208
            && c != ';'
209
            && c != '=')
210
            return false;
211
    }
212
213
    // FIXME: Validate further by splitting into language tags and optional quality
214
    // values (q=) and then check each language tag.
215
    return true;
216
}
217
191
}
218
}
- Source/WebCore/platform/Language.h +2 lines
Lines 44-49 WEBCORE_EXPORT void removeLanguageChange Source/WebCore/platform/Language.h_sec1
44
44
45
String displayNameForLanguageLocale(const String&);
45
String displayNameForLanguageLocale(const String&);
46
46
47
bool isValidLanguageHeaderValue(const String&);
48
47
// Called from platform specific code when the user's preferred language(s) change.
49
// Called from platform specific code when the user's preferred language(s) change.
48
WEBCORE_EXPORT void languageDidChange();
50
WEBCORE_EXPORT void languageDidChange();
49
}
51
}
- Source/WebCore/platform/network/HTTPParsers.cpp -3 / +25 lines
Lines 34-39 Source/WebCore/platform/network/HTTPParsers.cpp_sec1
34
#include "HTTPParsers.h"
34
#include "HTTPParsers.h"
35
35
36
#include "HTTPHeaderNames.h"
36
#include "HTTPHeaderNames.h"
37
#include "Language.h"
37
#include <wtf/DateMath.h>
38
#include <wtf/DateMath.h>
38
#include <wtf/NeverDestroyed.h>
39
#include <wtf/NeverDestroyed.h>
39
#include <wtf/text/CString.h>
40
#include <wtf/text/CString.h>
Lines 126-131 bool isValidHTTPHeaderValue(const String Source/WebCore/platform/network/HTTPParsers.cpp_sec2
126
    return true;
127
    return true;
127
}
128
}
128
129
130
// See RFC 7231, Section 5.3.2
131
bool isValidAcceptHeaderValue(const String& value)
132
{
133
    UChar c;
134
    for (unsigned i = 0; i < value.length(); ++i) {
135
        c = value[i];
136
        if (!isASCIIAlphanumeric(c)
137
            && c != ' '
138
            && c != '*'
139
            && c != '.'
140
            && c != '/'
141
            && c != ';'
142
            && c != '=')
143
            return false;
144
    }
145
    
146
    return true;
147
}
148
    
129
// See RFC 7230, Section 3.2.6.
149
// See RFC 7230, Section 3.2.6.
130
bool isValidHTTPToken(const String& value)
150
bool isValidHTTPToken(const String& value)
131
{
151
{
Lines 732-738 void parseAccessControlExposeHeadersAllo Source/WebCore/platform/network/HTTPParsers.cpp_sec3
732
    }
752
    }
733
}
753
}
734
754
735
// Implememtnation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
755
// Implementation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
736
bool isForbiddenHeaderName(const String& name)
756
bool isForbiddenHeaderName(const String& name)
737
{
757
{
738
    HTTPHeaderName headerName;
758
    HTTPHeaderName headerName;
Lines 778-786 bool isSimpleHeader(const String& name, Source/WebCore/platform/network/HTTPParsers.cpp_sec4
778
        return false;
798
        return false;
779
    switch (headerName) {
799
    switch (headerName) {
780
    case HTTPHeaderName::Accept:
800
    case HTTPHeaderName::Accept:
801
        return isValidAcceptHeaderValue(value);
781
    case HTTPHeaderName::AcceptLanguage:
802
    case HTTPHeaderName::AcceptLanguage:
782
    case HTTPHeaderName::ContentLanguage:
803
    case HTTPHeaderName::ContentLanguage:
783
        return true;
804
        return isValidLanguageHeaderValue(value);
784
    case HTTPHeaderName::ContentType: {
805
    case HTTPHeaderName::ContentType: {
785
        String mimeType = extractMIMETypeFromMediaType(value);
806
        String mimeType = extractMIMETypeFromMediaType(value);
786
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
807
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
Lines 824-832 bool isCrossOriginSafeRequestHeader(HTTP Source/WebCore/platform/network/HTTPParsers.cpp_sec5
824
{
845
{
825
    switch (name) {
846
    switch (name) {
826
    case HTTPHeaderName::Accept:
847
    case HTTPHeaderName::Accept:
848
        return isValidAcceptHeaderValue(value);
827
    case HTTPHeaderName::AcceptLanguage:
849
    case HTTPHeaderName::AcceptLanguage:
828
    case HTTPHeaderName::ContentLanguage:
850
    case HTTPHeaderName::ContentLanguage:
829
        return true;
851
        return isValidLanguageHeaderValue(value);
830
    case HTTPHeaderName::ContentType: {
852
    case HTTPHeaderName::ContentType: {
831
        String mimeType = extractMIMETypeFromMediaType(value);
853
        String mimeType = extractMIMETypeFromMediaType(value);
832
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
854
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
- Source/WebCore/platform/network/HTTPParsers.h +1 lines
Lines 69-74 enum XFrameOptionsDisposition { Source/WebCore/platform/network/HTTPParsers.h_sec1
69
69
70
bool isValidReasonPhrase(const String&);
70
bool isValidReasonPhrase(const String&);
71
bool isValidHTTPHeaderValue(const String&);
71
bool isValidHTTPHeaderValue(const String&);
72
bool isValidAcceptHeaderValue(const String&);
72
bool isValidHTTPToken(const String&);
73
bool isValidHTTPToken(const String&);
73
bool parseHTTPRefresh(const String& refresh, double& delay, String& url);
74
bool parseHTTPRefresh(const String& refresh, double& delay, String& url);
74
std::optional<std::chrono::system_clock::time_point> parseHTTPDate(const String&);
75
std::optional<std::chrono::system_clock::time_point> parseHTTPDate(const String&);
- LayoutTests/ChangeLog +16 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2016-11-29  John Wilander  <wilander@apple.com>
2
3
        Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
4
        https://bugs.webkit.org/show_bug.cgi?id=165178
5
        <rdar://problem/18792250>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt: Added.
10
        * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html: Added.
11
            Tests that:
12
                Normal Accept, Accept-Language, and Content-Language headers don't trigger a preflight.
13
                Abnormal Accept, Accept-Language, and Content-Language headers do trigger a preflight.
14
                Abnormal Accept, Accept-Language, and Content-Language headers are accepted if the server whitelists them.
15
        * http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php: Added.
16
1
2016-11-28  Antti Koivisto  <antti@apple.com>
17
2016-11-28  Antti Koivisto  <antti@apple.com>
2
18
3
        Remove FIRST_LINE_INHERITED fake pseudo style
19
        Remove FIRST_LINE_INHERITED fake pseudo style
- LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt +18 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt_sec1
1
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
2
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept-Language is not allowed by Access-Control-Allow-Headers.
3
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
4
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
5
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
6
PASS Accept header with normal value SHOULD NOT cause a preflight
7
PASS Accept-Language header with normal value SHOULD NOT cause a preflight
8
PASS Content-Language header with normal value SHOULD NOT cause a preflight
9
PASS Accept header with abnormal value SHOULD cause a preflight
10
PASS Accept-Language header with abnormal value SHOULD cause a preflight
11
PASS Content-Language header with abnormal value SHOULD cause a preflight
12
PASS Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight
13
PASS Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight
14
PASS Accept header with abnormal value and explicitly allowed headers SHOULD be allowed
15
PASS Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed
16
PASS Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed
17
PASS Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed
18
- LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html +147 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html_sec1
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
    <meta charset="UTF-8">
5
    <title>Non-Standard Safelisted Headers SHOULD Trigger a Preflight</title>
6
    <script src="../resources/js-test-pre.js"></script>
7
</head>
8
<body>
9
<!-- https://fetch.spec.whatwg.org/#cors-safelisted-request-header -->
10
<script>
11
    if (window.testRunner) {
12
        testRunner.dumpAsText();
13
        testRunner.waitUntilDone();
14
    }
15
16
    var invocation;
17
    var url = 'http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php';
18
19
    function createReadyStateHandler (description, testNumber) {
20
        return function handler (e) {
21
            if (invocation.readyState === XMLHttpRequest.DONE) {
22
                testPassed(description);
23
                if (testNumber === (testCases.length - 1)) {
24
                    if (window.testRunner) {
25
                        testRunner.notifyDone();
26
                    }
27
                } else {
28
                    runTestCase(testNumber + 1);
29
                }
30
            }
31
        }
32
    }
33
34
    function createOnErrorHandler (description, testNumber) {
35
        return function handler (e) {
36
                e.preventDefault();
37
                testPassed(description);
38
                if (testNumber === (testCases.length - 1)) {
39
                    if (window.testRunner) {
40
                        testRunner.notifyDone();
41
                    }
42
                } else {
43
                    runTestCase(testNumber + 1);
44
                }
45
            }
46
    }
47
48
    var abnormalSimpleCorsHeaderValue = "() { :;};"
49
    var testCases = [
50
        // Positive test cases with normal headers
51
        {
52
            headersToAdd: [{ name : "Accept", value: "text/*" }],
53
            explicitlyAllowHeaders: false,
54
            shouldCausePreflight: false,
55
            description: "Accept header with normal value SHOULD NOT cause a preflight"
56
        }
57
        ,{
58
            headersToAdd: [{ name : "Accept-Language", value: "en" }],
59
            explicitlyAllowHeaders: false,
60
            shouldCausePreflight: false,
61
            description: "Accept-Language header with normal value SHOULD NOT cause a preflight"
62
        }
63
        ,{
64
            headersToAdd: [{ name : "Content-Language", value: "en" }],
65
            explicitlyAllowHeaders: false,
66
            shouldCausePreflight: false,
67
            description: "Content-Language header with normal value SHOULD NOT cause a preflight"
68
        }
69
        // Negative test cases with abnormal headers
70
        ,{
71
            headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
72
            explicitlyAllowHeaders: false,
73
            shouldCausePreflight: true,
74
            description: "Accept header with abnormal value SHOULD cause a preflight"
75
        }
76
        ,{
77
            headersToAdd: [{ name : "Accept-Language", value: abnormalSimpleCorsHeaderValue }],
78
            explicitlyAllowHeaders: false,
79
            shouldCausePreflight: true,
80
            description: "Accept-Language header with abnormal value SHOULD cause a preflight"
81
        }
82
        ,{
83
            headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
84
            explicitlyAllowHeaders: false,
85
            shouldCausePreflight: true,
86
            description: "Content-Language header with abnormal value SHOULD cause a preflight"
87
        }
88
        ,{
89
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
90
            explicitlyAllowHeaders: false,
91
            shouldCausePreflight: true,
92
            description: "Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight"
93
        }
94
        ,{
95
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
96
            explicitlyAllowHeaders: false,
97
            shouldCausePreflight: true,
98
            description: "Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight"
99
        }
100
        // Positive test cases with abnormal headers
101
        ,{
102
            headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
103
            explicitlyAllowHeaders: true,
104
            shouldCausePreflight: true,
105
            description: "Accept header with abnormal value and explicitly allowed headers SHOULD be allowed"
106
        }
107
        ,{
108
            headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
109
            explicitlyAllowHeaders: true,
110
            shouldCausePreflight: true,
111
            description: "Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed"
112
        }
113
        ,{
114
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
115
            explicitlyAllowHeaders: true,
116
            shouldCausePreflight: true,
117
            description: "Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed"
118
        }
119
        ,{
120
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
121
            explicitlyAllowHeaders: true,
122
            shouldCausePreflight: true,
123
            description: "Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed"
124
        }
125
    ];
126
127
    function runTestCase(testNumber) {
128
        var testCase = testCases[testNumber];
129
        invocation = new XMLHttpRequest();
130
        if(invocation) {
131
            invocation.open('GET', url + (testCase.explicitlyAllowHeaders ? "/?explicitlyAllowHeaders=true" : ""), true);
132
            for (var i = 0; i < testCase.headersToAdd.length; i++) {
133
                invocation.setRequestHeader(testCase.headersToAdd[i].name, testCase.headersToAdd[i].value);
134
            }
135
            if (testCase.shouldCausePreflight && !testCase.explicitlyAllowHeaders) {
136
                invocation.onerror = createOnErrorHandler(testCase.description, testNumber);
137
            } else {
138
                invocation.onreadystatechange = createReadyStateHandler(testCase.description, testNumber);
139
            }
140
            invocation.send();
141
        }
142
    }
143
144
    runTestCase(0);
145
</script>
146
</body>
147
</html>
- LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php +8 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php_sec1
1
<?php
2
header('Access-Control-Allow-Origin: http://127.0.0.1:8000');
3
4
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_GET['explicitlyAllowHeaders'])) {
5
    header('Access-Control-Allow-Methods: GET, OPTIONS');
6
    header('Access-Control-Allow-Headers: Accept, Accept-Language, Content-Language');
7
}
8
?>

Return to Bug 165178