178 lines
5.7 KiB
HTML
178 lines
5.7 KiB
HTML
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
</head>
|
|
<body>
|
|
<script class="testbody" type="application/javascript">
|
|
"use strict";
|
|
var { IdpSandbox } = SpecialPowers.ChromeUtils.importESModule(
|
|
"resource://gre/modules/media/IdpSandbox.sys.mjs"
|
|
);
|
|
var dummyPayload = JSON.stringify({
|
|
this: 'is',
|
|
a: ['stu', 6],
|
|
obj: null
|
|
});
|
|
|
|
function test_domain_sandbox() {
|
|
var diabolical = {
|
|
toString() {
|
|
return 'example.com/path';
|
|
}
|
|
};
|
|
var domains = [ 'ex/foo', 'user@ex', 'user:pass@ex', 'ex#foo', 'ex?foo',
|
|
'', 12, null, diabolical, true ];
|
|
domains.forEach(function(domain) {
|
|
try {
|
|
var idp = new IdpSandbox(domain, undefined, window);
|
|
ok(false, 'IdpSandbox allowed a bad domain: ' + domain);
|
|
} catch (e) {
|
|
var str = (typeof domain === 'string') ? domain : typeof domain;
|
|
ok(true, 'Evil domain "' + str + '" raises exception');
|
|
}
|
|
});
|
|
}
|
|
|
|
function test_protocol_sandbox() {
|
|
var protos = [ '../evil/proto', '..%2Fevil%2Fproto',
|
|
'\\evil', '%5cevil', 12, true, {} ];
|
|
protos.forEach(function(proto) {
|
|
try {
|
|
var idp = new IdpSandbox('example.com', proto, window);
|
|
ok(false, 'IdpSandbox allowed a bad protocol: ' + proto);
|
|
} catch (e) {
|
|
var str = (typeof proto === 'string') ? proto : typeof proto;
|
|
ok(true, 'Evil protocol "' + proto + '" raises exception');
|
|
}
|
|
});
|
|
}
|
|
|
|
function idpName(hash) {
|
|
return 'idp.js' + (hash ? ('#' + hash) : '');
|
|
}
|
|
|
|
function makeSandbox(js) {
|
|
var name = js || idpName();
|
|
info('Creating a sandbox for the protocol: ' + name);
|
|
var sandbox = new IdpSandbox('example.com', name, window);
|
|
return sandbox.start().then(idp => SpecialPowers.wrap(idp));
|
|
}
|
|
|
|
function test_generate_assertion() {
|
|
return makeSandbox()
|
|
.then(idp => idp.generateAssertion(dummyPayload,
|
|
'https://example.net',
|
|
{}))
|
|
.then(response => {
|
|
response = SpecialPowers.wrap(response);
|
|
is(response.idp.domain, 'example.com', 'domain is correct');
|
|
is(response.idp.protocol, 'idp.js', 'protocol is correct');
|
|
ok(typeof response.assertion === 'string', 'assertion is present');
|
|
});
|
|
}
|
|
|
|
// test that the test IdP can eat its own dogfood; which is the only way to test
|
|
// validateAssertion, since that consumes the output of generateAssertion (in
|
|
// theory, generateAssertion could identify a different IdP domain).
|
|
|
|
function test_validate_assertion() {
|
|
return makeSandbox()
|
|
.then(idp => idp.generateAssertion(dummyPayload,
|
|
'https://example.net',
|
|
{ usernameHint: 'user' }))
|
|
.then(assertion => {
|
|
var wrapped = SpecialPowers.wrap(assertion);
|
|
return makeSandbox()
|
|
.then(idp => idp.validateAssertion(wrapped.assertion,
|
|
'https://example.net'));
|
|
}).then(response => {
|
|
response = SpecialPowers.wrap(response);
|
|
is(response.identity, 'user@example.com');
|
|
is(response.contents, dummyPayload);
|
|
});
|
|
}
|
|
|
|
// We don't want to test the #bad or the #hang instructions,
|
|
// errors of the sort those generate aren't handled by the sandbox code.
|
|
function test_assertion_failure(reason) {
|
|
return () => {
|
|
return makeSandbox(idpName(reason))
|
|
.then(idp => idp.generateAssertion('hello', 'example.net', {}))
|
|
.then(r => ok(false, 'should not succeed on ' + reason),
|
|
e => ok(true, 'failed correctly on ' + reason));
|
|
};
|
|
}
|
|
|
|
function test_load_failure() {
|
|
return makeSandbox('non-existent-file')
|
|
.then(() => ok(false, 'Should fail to load non-existent file'),
|
|
e => ok(e, 'Should fail to load non-existent file'));
|
|
}
|
|
|
|
function test_redirect_ok(from) {
|
|
return () => {
|
|
return makeSandbox(from)
|
|
.then(idp => idp.generateAssertion('hello', 'example.net'))
|
|
.then(r => ok(SpecialPowers.wrap(r).assertion,
|
|
'Redirect to https should be OK'));
|
|
};
|
|
}
|
|
|
|
function test_redirect_fail(from) {
|
|
return () => {
|
|
return makeSandbox(from)
|
|
.then(() => ok(false, 'Redirect to https should fail'),
|
|
e => ok(e, 'Redirect to https should fail'));
|
|
};
|
|
}
|
|
|
|
function test_bad_js() {
|
|
return makeSandbox('idp-bad.js')
|
|
.then(() => ok(false, 'Bad JS should not load'),
|
|
e => ok(e, 'Bad JS should not load'));
|
|
}
|
|
|
|
function run_all_tests() {
|
|
[
|
|
test_domain_sandbox,
|
|
test_protocol_sandbox,
|
|
test_generate_assertion,
|
|
test_validate_assertion,
|
|
|
|
// fail of the IdP fails
|
|
test_assertion_failure('fail'),
|
|
// fail if the IdP throws
|
|
test_assertion_failure('throw'),
|
|
// fail if the IdP is not ready
|
|
test_assertion_failure('not_ready'),
|
|
|
|
test_load_failure(),
|
|
// Test a redirect to an HTTPS origin, which should be OK
|
|
test_redirect_ok('idp-redirect-https.js'),
|
|
// Two redirects is fine too
|
|
test_redirect_ok('idp-redirect-https-double.js'),
|
|
// A secure redirect to a path other than /.well-known/idp-proxy/* should
|
|
// also work fine.
|
|
test_redirect_ok('idp-redirect-https-odd-path.js'),
|
|
// A redirect to HTTP is not-cool
|
|
test_redirect_fail('idp-redirect-http.js'),
|
|
// Also catch tricks like https->http->https
|
|
test_redirect_fail('idp-redirect-http-trick.js'),
|
|
|
|
test_bad_js
|
|
].reduce((p, test) => {
|
|
return p.then(test)
|
|
.catch(e => ok(false, test.name + ' failed: ' +
|
|
SpecialPowers.wrap(e).message + '\n' +
|
|
SpecialPowers.wrap(e).stack));
|
|
}, Promise.resolve())
|
|
.then(() => SimpleTest.finish());
|
|
}
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
run_all_tests();
|
|
</script>
|
|
</body>
|
|
</html>
|