Bug 414812 - document.domain = "0.0.1" on a page on 127.0.0.1 should not work. r=dwitte, sr=jst, a=schrep

This commit is contained in:
jwalden@mit.edu 2008-02-07 12:58:56 -08:00
Родитель 7e4141edec
Коммит ecffb80fcc
9 изменённых файлов: 367 добавлений и 8 удалений

Просмотреть файл

@ -1739,26 +1739,28 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain)
// For example, a page from foo.bar.com may set domain to bar.com,
// but not to ar.com, baz.com, or fi.foo.bar.com.
nsCAutoString current, domain;
if (NS_FAILED(uri->GetHost(current)))
if (NS_FAILED(uri->GetAsciiHost(current)))
current.Truncate();
if (NS_FAILED(newURI->GetHost(domain)))
if (NS_FAILED(newURI->GetAsciiHost(domain)))
domain.Truncate();
PRBool ok = current.Equals(domain);
if (current.Length() > domain.Length() &&
StringEndsWith(current, domain) &&
current.CharAt(current.Length() - domain.Length() - 1) == '.') {
// Using only a TLD is forbidden (bug 368700)
// We're golden if the new domain is the current page's base domain or a
// subdomain of it.
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
if (!tldService)
return NS_ERROR_NOT_AVAILABLE;
// try to get the base domain; if this works, we're ok.
// if we're dealing with an IP address, getting the base domain
// will fail, as required.
nsCAutoString baseDomain;
ok = NS_SUCCEEDED(tldService->GetBaseDomain(newURI, 0, baseDomain));
nsCAutoString currentBaseDomain;
ok = NS_SUCCEEDED(tldService->GetBaseDomain(uri, 0, currentBaseDomain));
NS_ASSERTION(StringEndsWith(domain, currentBaseDomain) ==
(domain.Length() >= currentBaseDomain.Length()),
"uh-oh! slight optimization wasn't valid somehow!");
ok = ok && domain.Length() >= currentBaseDomain.Length();
}
if (!ok) {
// Error: illegal domain

Просмотреть файл

@ -47,6 +47,10 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_crossdomainprops.html \
file_crossdomainprops_inner.html \
test_setting_document.domain_to_shortened_ipaddr.html \
child_ip_address.html \
test_setting_document.domain_idn.html \
idn_child.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Child window at 127.0.0.1</title>
<script type="application/javascript">
function run()
{
var target = document.getElementById("location");
target.textContent = location.hostname + ":" + (location.port || 80);
var message = "child-response";
var domain = document.domain;
if (domain !== "127.0.0.1")
message += " wrong-initial-domain(" + domain + ")";
try
{
document.domain = "0.0.1";
domain = document.domain;
message += " ip-address-shortened-to(" + domain + ")";
}
catch (e)
{
domain = document.domain;
if (domain !== "127.0.0.1")
message += " ip-address-mutated-on-throw(" + domain + ")";
}
window.parent.postMessage(message);
}
window.addEventListener("load", run, false);
</script>
</head>
<body>
<h1 id="location">Somewhere!</h1>
</body>
</html>

Просмотреть файл

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Child window on a site whose "base" domain contains IDN</title>
<script type="application/javascript">
function run()
{
var target = document.getElementById("location");
target.textContent = location.hostname + ":" + (location.port || 80);
}
function receiveMessage(evt)
{
if (evt.domain !== "localhost")
return;
var message = evt.data + "-response";
var domain = document.domain;
if (/test$/.test(domain))
{
// XXX should really be IDN (bug 414090)
//if (domain !== "sub1.exämple.test")
// message += " wrong-initial-domain(" + domain + ")";
// for now expect the punycode value
if (domain !== "sub1.xn--exmple-cua.test")
message += " wrong-initial-domain(" + domain + ")";
}
else
{
if (domain !== "sub1.παράδειγμα.δοκιμή")
message += " wrong-initial-domain(" + domain + ")";
}
switch (location.search)
{
case "?idn-whitelist":
message += idnTest("παράδειγμα.δοκιμή");
break;
case "?punycode-whitelist":
message += punycodeTest("xn--hxajbheg2az3al.xn--jxalpdlp");
break;
case "?idn-nowhitelist":
message += idnTest("exämple.test");
break;
case "?punycode-nowhitelist":
message += punycodeTest("xn--exmple-cua.test");
break;
default:
message += " unexpected-query(" + location.search + ")";
break;
}
evt.source.postMessage(message);
}
function idnTest(newDomain)
{
var errors = "";
try
{
document.domain = newDomain;
}
catch (e)
{
errors += " error-thrown-setting-to-idn(" + String(e).split("").join(",") + ")";
}
return errors;
}
function punycodeTest(newDomain)
{
var errors = "";
try
{
document.domain = newDomain;
}
catch (e)
{
errors += " error-thrown-setting-to-punycode(" + String(e).split("").join(",") + ")";
}
return errors;
}
document.addEventListener("message", receiveMessage, false);
window.addEventListener("load", run, false);
</script>
</head>
<body>
<h1 id="location">Somewhere!</h1>
</body>
</html>

Просмотреть файл

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Setting document.domain and IDN</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<!--
This testing all gets a bit complicated here; the problem is that our
document.domain implementation will do a suffix comparison of the value to which
it's being set against the current URI's base domain (where "base domain" is
defined as the effective TLD plus one; see nsIEffectiveTLDService.idl). Seems
simple enough, right? Wrong.
The problem, as usual, is IDN. Our current, wholly-inadequate solution to
preventing Unicode domain-name spoofing is done at the level of the URL
implementation, not at the presentation level. However, the value of the
base domain for the current URI is always calculated in punycode; if the
provided domain is one which is whitelisted, we'll get an IDN name and the
suffix-comparison will fail. Nice great big mess, huh?
Anyway: "test" currently fits the bill as a TLD which is not whitelisted, while
"δοκιμή" (the Greek IDN TLD for "test") fits the bill as a TLD which is
whitelisted. RFC 2606 reserves "test" for DNS testing, so nobody's going to
clamor for it to be whitelisted any time soon. The latter is as of February
2008 undergoing testing for IDN TLDs, and it's at least temporarily whitelisted
for now. Once the testing period ends the latter's probably going to be
un-whitelisted, so we're going to have to do a careful bit of stepping to ensure
that in the future this test tests what it was intended to test (and, until
bug 414090 is fixed, that it doesn't break when the Greek TLD is
un-whitelisted).
-->
<div>
<h2>Whitelisted</h2>
<iframe name="idnKidWhitelist" src="http://sub1.παράδειγμα.δοκιμή/tests/dom/tests/mochitest/dom-level0/idn_child.html?idn-whitelist"></iframe>
<iframe name="punycodeKidWhitelist" src="http://sub1.παράδειγμα.δοκιμή/tests/dom/tests/mochitest/dom-level0/idn_child.html?punycode-whitelist"></iframe>
</div>
<div>
<h2>Not whitelisted</h2>
<iframe name="idnKidNoWhitelist" src="http://sub1.exämple.test/tests/dom/tests/mochitest/dom-level0/idn_child.html?idn-nowhitelist"></iframe>
<iframe name="punycodeKidNoWhitelist" src="http://sub1.exämple.test/tests/dom/tests/mochitest/dom-level0/idn_child.html?punycode-nowhitelist"></iframe>
</div>
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var gotIDNNoWhitelist = false;
var gotPunycodeNoWhitelist = false;
var gotIDNWhitelist = false;
var gotPunycodeWhitelist = false;
var whitelistRegex =
new RegExp("^http://sub1\\.παράδειγμα\\.δοκιμή/tests/dom/tests/" +
"mochitest/dom-level0/idn_child\\.html\\?(.+)$");
var noWhitelistRegex =
new RegExp("^http://sub1\\.exämple\\.test/tests/dom/tests/" +
"mochitest/dom-level0/idn_child\\.html\\?(.+)$");
function receiveMessage(evt)
{
var domain = evt.domain;
var match;
if (/test$/.test(domain))
{
// XXX bug 414090
// The value of MessageEvent.domain with postMessage *should* always be IDN;
// unfortunately, given our current setup for dealing with Unicode-based
// domain-name spoofing, whether a domain is in the safe-for-IDN whitelist
// affects the value of this property (likewise for window.location,
// document.location, MessageEvent.uri, document.domain, and probably a slew
// of other things). :-(
//
// These two tests should illustrate what currently happens and what should
// happen once bug 414090 is fixed.
todo_is(evt.domain, "sub1.exämple.test", "wrong sender");
todo_isnot(evt.domain, "sub1.xn--exmple-cua.test", "wrong sender");
match = noWhitelistRegex.exec(evt.uri);
todo(match, "unexpected sender");
if (!match)
match = [, evt.uri.substring(evt.uri.indexOf("?") + 1)];
}
else
{
// We're receiving data from the Greek IDN name; since that TLD is
// whitelisted for now, the domain we get isn't going to be punycoded.
is(evt.domain, "sub1.παράδειγμα.δοκιμή", "wrong sender");
match = whitelistRegex.exec(evt.uri);
ok(match, "should have matched, unexpected sender");
}
is(match[1] + "-response", evt.data.split(" ")[0],
"unexpected data: " + evt.data);
switch (match[1])
{
case "idn-whitelist":
gotIDNWhitelist = true;
ok(evt.source === window.frames.idnKidWhitelist, "wrong source");
is(evt.data, "idn-whitelist-response", "wrong response for IDN");
break;
case "punycode-whitelist":
gotPunycodeWhitelist = true;
ok(evt.source === window.frames.punycodeKidWhitelist, "wrong source");
is(evt.data, "punycode-whitelist-response", "wrong response for punycode");
break;
case "idn-nowhitelist":
gotIDNNoWhitelist = true;
ok(evt.source === window.frames.idnKidNoWhitelist, "wrong source");
is(evt.data, "idn-nowhitelist-response", "wrong response for IDN");
break;
case "punycode-nowhitelist":
gotPunycodeNoWhitelist = true;
ok(evt.source === window.frames.punycodeKidNoWhitelist, "wrong source");
is(evt.data, "punycode-nowhitelist-response", "wrong response for punycode");
break;
default:
ok(false, "unreached");
break;
}
}
function run()
{
window.frames.idnKidWhitelist.postMessage("idn-whitelist");
ok(gotIDNWhitelist, "IDN whitelist message not received");
window.frames.punycodeKidWhitelist.postMessage("punycode-whitelist");
ok(gotPunycodeWhitelist, "punycode whitelist message not received");
window.frames.idnKidNoWhitelist.postMessage("idn-nowhitelist");
ok(gotIDNNoWhitelist, "IDN no-whitelist message not received");
window.frames.punycodeKidNoWhitelist.postMessage("punycode-nowhitelist");
ok(gotPunycodeNoWhitelist, "punycode no-whitelist message not received");
SimpleTest.finish();
}
document.addEventListener("message", receiveMessage, false);
window.addEventListener("load", run, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<title>document.domain can't be meaningfully set on pages at IP address hosts</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe name="child" src="http://127.0.0.1:8888/tests/dom/tests/mochitest/dom-level0/child_ip_address.html"></iframe>
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.domain, "127.0.0.1", "wrong sender");
ok(evt.source === window.frames.child, "wrong sender");
is(evt.data, "child-response", "got wrong response");
SimpleTest.finish();
}
document.addEventListener("message", receiveMessage, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -657,6 +657,10 @@ pref("network.IDN.whitelist.info", true);
pref("network.IDN.whitelist.museum", true);
pref("network.IDN.whitelist.org", true);
// NOTE: Before these can be removed, one of bug 414812's tests must be updated
// or it will likely fail! Please CC jwalden+bmo on the bug associated
// with removing these so he can provide a patch to make the necessary
// changes to avoid bustage.
// ".test" localised TLDs for ICANN's top-level IDN trial
pref("network.IDN.whitelist.xn--0zwm56d", true);
pref("network.IDN.whitelist.xn--11b5bs3a9aj6g", true);

Просмотреть файл

@ -132,6 +132,10 @@ my @servers = (
"sub.sectest2.example.org:80",
"sub1.xn--lt-uia.example.org:8000", # U+00E4 U+006C U+0074
"sub2.xn--lt-uia.example.org:80", # U+00E4 U+006C U+0074
"xn--exmple-cua.test:80",
"sub1.xn--exmple-cua.test:80",
"xn--hxajbheg2az3al.xn--jxalpdlp:80", # Greek IDN for example.test
"sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80",
);

Просмотреть файл

@ -106,6 +106,10 @@ servers = [
"sub.sectest2.example.org:80",
"sub1.xn--lt-uia.example.org:8000", # U+00E4 U+006C U+0074
"sub2.xn--lt-uia.example.org:80", # U+00E4 U+006C U+0074
"xn--exmple-cua.test:80",
"sub1.xn--exmple-cua.test:80",
"xn--hxajbheg2az3al.xn--jxalpdlp:80", # Greek IDN for example.test
"sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80",
]
unprivilegedServers = [