Skip to content

Commit

Permalink
Cookies: Test IDN/non-ASCII in domain attributes
Browse files Browse the repository at this point in the history
This is for httpwg/http-extensions#1707.

I took some inspiration from #26170 and used a python server instead of a header file in order to better control which bytes are served as part of the header.

The test runs exclusively on the élève. subdomain through opening a new window that then runs all test and reports back to the main test window.
  • Loading branch information
johannhof committed Feb 7, 2022
1 parent 1c1e48b commit 48d28a8
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
18 changes: 18 additions & 0 deletions cookies/domain/domain-attribute-idn-host.sub.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
</head>
<body>
<script>
let url = new URL(document.location);
url.host = "{{hosts[][élève]}}";
let url2 = new URL("support/idn-child.sub.https.html", url);
let child_window = window.open(url2.href);
fetch_tests_from_window(child_window);
</script>
</body>
</html>
72 changes: 72 additions & 0 deletions cookies/domain/support/idn-child.sub.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/cookies/resources/cookie-test.js"></script>
</head>
<body>
<script>
async function assert_cookie(response, cookie) {
const get = await response.text();
assert_equals(get, cookie);
assert_equals(document.cookie, cookie);
}

async function assert_no_cookie(response) {
const get = await response.text();
assert_equals(get, "no cookies");
assert_equals(document.cookie, "");
}

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-utf8&host={{host}}") });
let response = await fetch("idn.py?set-utf8&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_no_cookie(response);
}, "UTF8-encoded IDN in domain attribute");

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-utf8-dot&host={{host}}") });
let response = await fetch("idn.py?set-utf8-dot&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_no_cookie(response);
}, "UTF8-encoded IDN with non-ASCII dot in domain attribute");

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-wrong-utf8&host={{host}}") });
let response = await fetch("idn.py?set-wrong-utf8&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_no_cookie(response);
}, "wrong UTF8-encoded IDN in domain attribute");

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-punycode&host={{host}}") });
let response = await fetch("idn.py?set-punycode&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_cookie(response, "punycode=set");
}, "punycode IDN in domain attribute");

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-wrong-punycode&host={{host}}") });
let response = await fetch("idn.py?set-wrong-punycode&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_no_cookie(response);
}, "wrong punycode IDN in domain attribute");

promise_test(async t => {
t.add_cleanup(async () => { await fetch("idn.py?delete-invalid-byte&host={{host}}") });
let response = await fetch("idn.py?set-invalid-byte&host={{host}}");
assert_equals(await response.text(), "set");
response = await fetch("idn.py?get&host={{host}}");
await assert_no_cookie(response);
}, "IDN with invalid UTF-8 bytes in domain attribute");
</script>
</body>
</html>
61 changes: 61 additions & 0 deletions cookies/domain/support/idn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# élève.
utf8_subdomain = b"Domain=\xC3\xA9\x6C\xC3\xA8\x76\x65."
# élève。
utf8_dot_subdomain = b"Domain=\xC3\xA9\x6C\xC3\xA8\x76\x65\xE3\x80\x82"
# élève.
punycode_subdomain = b"Domain=xn--lve-6lad."
# ÿlève.
wrong_utf8_subdomain = b"Domain=\xC3\xBF\x6C\xC3\xA8\x76\x65."
# ÿlève.
wrong_punycode_subdomain = b"Domain=xn--lve-6la7i."
# élève with invalid FF byte at the end
invalid_byte_subdomain = b"Domain=\xC3\xA9\x6C\xC3\xA8\x76\x65\xFF."

def main(request, response):
host = request.GET.get(b"host")

if b"set-utf8" in request.GET:
response.headers.append(b"Set-Cookie", b"utf8=set;" + utf8_subdomain + host)
response.content = "set"
if b"set-utf8-dot" in request.GET:
response.headers.append(b"Set-Cookie", b"utf8-dot=set;" + utf8_dot_subdomain + host)
response.content = "set"
elif b"set-wrong-utf8" in request.GET:
response.headers.append(b"Set-Cookie", b"wrong-utf8=set;" + wrong_utf8_subdomain + host)
response.content = "set"
elif b"set-punycode" in request.GET:
response.headers.append(b"Set-Cookie", b"punycode=set;" + punycode_subdomain + host)
response.content = "set"
elif b"set-wrong-punycode" in request.GET:
response.headers.append(b"Set-Cookie", b"wrong-punycode=set;" + wrong_punycode_subdomain + host)
response.content = "set"
elif b"set-invalid-byte" in request.GET:
response.headers.append(b"Set-Cookie", b"invalid-byte=set;" + invalid_byte_subdomain + host)
response.content = "set"

elif b"get" in request.GET:
if b"Cookie" in request.headers:
response.content = request.headers[b"Cookie"]
else:
response.content = "no cookies"

elif b"delete-utf8" in request.GET:
response.headers.append(b"Set-Cookie", b"utf8=unset;Max-Age=0;" + utf8_subdomain + host)
response.content = "delete"
elif b"delete-utf8-dot" in request.GET:
response.headers.append(b"Set-Cookie", b"utf8-dot=unset;Max-Age=0;" + utf8_dot_subdomain + host)
response.content = "delete"
elif b"delete-wrong-utf8" in request.GET:
response.headers.append(b"Set-Cookie", b"wrong-utf8=unset;Max-Age=0;" + wrong_utf8_subdomain + host)
response.content = "delete"
elif b"delete-punycode" in request.GET:
response.headers.append(b"Set-Cookie", b"punycode=unset;Max-Age=0;" + punycode_subdomain + host)
response.content = "delete"
elif b"delete-wrong-punycode" in request.GET:
response.headers.append(b"Set-Cookie", b"wrong-punycode=unset;Max-Age=0;" + wrong_punycode_subdomain + host)
response.content = "delete"
elif b"delete-invalid-byte" in request.GET:
response.headers.append(b"Set-Cookie", b"invalid-byte=unset;Max-Age=0;" + invalid_byte_subdomain + host)
response.content = "delete"

response.headers.append(b"Content-Type", b"text/plain")

0 comments on commit 48d28a8

Please sign in to comment.