diff options
Diffstat (limited to '')
-rw-r--r-- | dom/security/test/referrer-policy/referrer_testserver.sjs | 691 |
1 files changed, 691 insertions, 0 deletions
diff --git a/dom/security/test/referrer-policy/referrer_testserver.sjs b/dom/security/test/referrer-policy/referrer_testserver.sjs new file mode 100644 index 0000000000..10350b5da5 --- /dev/null +++ b/dom/security/test/referrer-policy/referrer_testserver.sjs @@ -0,0 +1,691 @@ +/* + * Test server for iframe, anchor, and area referrer attributes. + * https://bugzilla.mozilla.org/show_bug.cgi?id=1175736 + * Also server for further referrer tests such as redirecting tests + * bug 1174913, bug 1175736, bug 1184781 + */ + +Cu.importGlobalProperties(["URLSearchParams"]); +const SJS = "referrer_testserver.sjs?"; +const SJS_PATH = "/tests/dom/security/test/referrer-policy/"; +const BASE_ORIGIN = "example.com"; +const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS; +const SHARED_KEY = SJS; +const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS; +const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS; + +const IMG_BYTES = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + + "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" +); + +function createTestUrl( + aPolicy, + aAction, + aName, + aType, + aSchemeFrom, + aSchemeTo, + crossOrigin, + referrerPolicyHeader +) { + var schemeTo = aSchemeTo || "http"; + var schemeFrom = aSchemeFrom || "http"; + var rpHeader = referrerPolicyHeader || ""; + var url = schemeTo + "://"; + url += crossOrigin ? CROSS_ORIGIN_URL : BASE_URL; + url += + "ACTION=" + + aAction + + "&" + + "policy=" + + aPolicy + + "&" + + "NAME=" + + aName + + "&" + + "type=" + + aType + + "&" + + "RP_HEADER=" + + rpHeader + + "&" + + "SCHEME_FROM=" + + schemeFrom; + return url; +} + +// test page using iframe referrer attribute +// if aParams are set this creates a test where the iframe url is a redirect +function createIframeTestPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aParams, + aSchemeFrom, + aSchemeTo, + aChangingMethod +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = `<meta name="referrer" content="${aMetaPolicy}">`; + } + var changeString = ""; + if (aChangingMethod === "setAttribute") { + changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; + } else if (aChangingMethod === "property") { + changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`; + } + var iFrameString = `<iframe src="" id="myframe" ${ + aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : "" + }>iframe</iframe>`; + var iframeUrl = ""; + if (aParams) { + aParams.delete("ACTION"); + aParams.append("ACTION", "redirectIframe"); + iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); + } else { + iframeUrl = createTestUrl( + aAttributePolicy, + "test", + aName, + "iframe", + aSchemeFrom, + aSchemeTo + ); + } + + return `<!DOCTYPE HTML> + <html> + <head> + ${metaString} + </head> + <body> + ${iFrameString} + <script> + window.addEventListener("load", function() { + ${changeString} + document.getElementById("myframe").onload = function(){ + parent.postMessage("childLoadComplete", "http://mochi.test:8888"); + }; + document.getElementById("myframe").src = "${iframeUrl}"; + }.bind(window), false); + </script> + </body> + </html>`; +} + +function buildAnchorString( + aMetaPolicy, + aReferrerPolicy, + aName, + aRelString, + aSchemeFrom, + aSchemeTo +) { + if (aReferrerPolicy) { + return `<a href="${createTestUrl( + aReferrerPolicy, + "test", + aName, + "link", + aSchemeFrom, + aSchemeTo + )}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`; + } + return `<a href="${createTestUrl( + aMetaPolicy, + "test", + aName, + "link", + aSchemeFrom, + aSchemeTo + )}" id="link" ${aRelString}>link</a>`; +} + +function buildAreaString( + aMetaPolicy, + aReferrerPolicy, + aName, + aRelString, + aSchemeFrom, + aSchemeTo +) { + var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`; + result += `<map name="imageMap">`; + if (aReferrerPolicy) { + result += `<area shape="circle" coords="1,1,1" href="${createTestUrl( + aReferrerPolicy, + "test", + aName, + "link", + aSchemeFrom, + aSchemeTo + )}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`; + } else { + result += `<area shape="circle" coords="1,1,1" href="${createTestUrl( + aMetaPolicy, + "test", + aName, + "link", + aSchemeFrom, + aSchemeTo + )}" alt="theArea" id="link" ${aRelString}>`; + } + result += `</map>`; + + return result; +} + +// test page using anchor or area referrer attribute +function createAETestPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aRel, + aStringBuilder, + aSchemeFrom, + aSchemeTo, + aChangingMethod +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; + } + var changeString = ""; + if (aChangingMethod === "setAttribute") { + changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; + } else if (aChangingMethod === "property") { + changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`; + } + var relString = ""; + if (aRel) { + relString = `rel="noreferrer"`; + } + var elementString = aStringBuilder( + aMetaPolicy, + aAttributePolicy, + aName, + relString, + aSchemeFrom, + aSchemeTo + ); + + return `<!DOCTYPE HTML> + <html> + ${metaString} + <body> + ${elementString} + <script> + window.addEventListener("load", function() { + ${changeString} + document.getElementById("link").click(); + }.bind(window), false); + </script> + </body> + </html>`; +} + +// test page using anchor target=_blank rel=noopener +function createTargetBlankRefferer( + aMetaPolicy, + aName, + aSchemeFrom, + aSchemeTo, + aRpHeader +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; + } + var elementString = `<a href="${createTestUrl( + aMetaPolicy, + "test", + aName, + "link", + aSchemeFrom, + aSchemeTo, + aRpHeader + )}" target=_blank rel="noopener" id="link">link</a>`; + + return `<!DOCTYPE HTML> + <html> + ${metaString} + <body> + ${elementString} + <script> + window.addEventListener("load", function() { + let link = document.getElementById("link"); + SpecialPowers.wrap(window).parent.postMessage("childLoadReady", "*"); + link.click(); + }.bind(window), false); + </script> + </body> + </html>`; +} + +// creates test page with img that is a redirect +function createRedirectImgTestCase(aParams, aAttributePolicy) { + var metaString = ""; + if (aParams.has("META_POLICY")) { + metaString = `<meta name="referrer" content="${aParams.get( + "META_POLICY" + )}">`; + } + aParams.delete("ACTION"); + aParams.append("ACTION", "redirectImg"); + var imgUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); + + return `<!DOCTYPE HTML> + <html> + <head> + <meta charset="utf-8"> + ${metaString} + <title>Test referrer policies on redirect (img)</title> + </head> + <body> + <img id="testImg" src="${imgUrl}" ${ + aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : "" + }> + <script> + window.addEventListener("load", function() { + parent.postMessage("childLoadComplete", "http://mochi.test:8888"); + }.bind(window), false); + </script> + </body> + </html>`; +} + +// test page using link referrer attribute +function createLinkPageUsingRefferer( + aMetaPolicy, + aAttributePolicy, + aNewAttributePolicy, + aName, + aRel, + aStringBuilder, + aSchemeFrom, + aSchemeTo, + aTestType +) { + var metaString = ""; + if (aMetaPolicy) { + metaString = `<meta name="referrer" content="${aMetaPolicy}">`; + } + + var changeString = ""; + var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy; + var elementString = aStringBuilder( + policy, + aName, + aRel, + aSchemeFrom, + aSchemeTo, + aTestType + ); + + if (aTestType === "setAttribute") { + changeString = `var link = document.getElementById("test_link"); + link.setAttribute("referrerpolicy", "${aNewAttributePolicy}"); + link.href = "${createTestUrl( + policy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}";`; + } else if (aTestType === "property") { + changeString = `var link = document.getElementById("test_link"); + link.referrerPolicy = "${aNewAttributePolicy}"; + link.href = "${createTestUrl( + policy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}";`; + } + + return `<!DOCTYPE HTML> + <html> + <head> + ${metaString} + </head> + <body> + ${elementString} + <script> + ${changeString} + </script> + </body> + </html>`; +} + +function createFetchUserControlRPTestCase( + aName, + aSchemeFrom, + aSchemeTo, + crossOrigin +) { + var srcUrl = createTestUrl( + "", + "test", + aName, + "fetch", + aSchemeFrom, + aSchemeTo, + crossOrigin + ); + + return `<!DOCTYPE HTML> + <html> + <head> + <meta charset="utf-8"> + <title>Test user control referrer policies</title> + </head> + <body> + <script> + fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) { + window.parent.postMessage("childLoadComplete", "http://mochi.test:8888"); + }); + </script> + </body> + </html>`; +} + +function buildLinkString( + aPolicy, + aName, + aRel, + aSchemeFrom, + aSchemeTo, + aTestType +) { + var href = ""; + var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`; + var policy = ""; + var asString = ""; + var relString = ""; + + if (aRel) { + relString = `rel="${aRel}"`; + } + + if (aPolicy) { + policy = `referrerpolicy=${aPolicy}`; + } + + if (aRel == "preload") { + asString = 'as="image"'; + } + + if (!aTestType) { + href = `href=${createTestUrl( + aPolicy, + "test", + aName, + "link_element_" + aRel, + aSchemeFrom, + aSchemeTo + )}`; + } + + return `<link ${relString} ${href} ${policy} ${asString} id="test_link" onload='${onChildComplete}' onerror='${onChildComplete}'>`; +} +// eslint-disable-next-line complexity +function handleRequest(request, response) { + var params = new URLSearchParams(request.queryString); + var action = params.get("ACTION"); + var schemeFrom = params.get("SCHEME_FROM") || "http"; + var schemeTo = params.get("SCHEME_TO") || "http"; + var crossOrigin = params.get("CROSS_ORIGIN") || false; + var referrerPolicyHeader = params.get("RP_HEADER") || ""; + + response.setHeader("Access-Control-Allow-Origin", "*", false); + if (referrerPolicyHeader) { + response.setHeader("Referrer-Policy", referrerPolicyHeader, false); + } + + if (action === "resetState") { + setSharedState(SHARED_KEY, "{}"); + response.write(""); + return; + } + if (action === "get-test-results") { + // ?action=get-result + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/plain", false); + response.write(getSharedState(SHARED_KEY)); + return; + } + if (action === "redirect") { + response.write( + '<script>parent.postMessage("childLoadComplete", "http://mochi.test:8888");</script>' + ); + return; + } + if (action === "redirectImg") { + params.delete("ACTION"); + params.append("ACTION", "test"); + params.append("type", "img"); + // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect + response.setStatusLine("1.1", 302, "found"); + response.setHeader( + "Location", + "http://" + CROSS_ORIGIN_URL + params.toString(), + false + ); + return; + } + if (action === "redirectIframe") { + params.delete("ACTION"); + params.append("ACTION", "test"); + params.append("type", "iframe"); + // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect + response.setStatusLine("1.1", 302, "found"); + response.setHeader( + "Location", + "http://" + CROSS_ORIGIN_URL + params.toString(), + false + ); + return; + } + if (action === "test") { + // ?action=test&policy=origin&name=name + let policy = params.get("policy"); + let name = params.get("NAME"); + let type = params.get("type"); + let result = getSharedState(SHARED_KEY); + + result = result ? JSON.parse(result) : {}; + + var referrerLevel = "none"; + var test = {}; + if (request.hasHeader("Referer")) { + var referrer = request.getHeader("Referer"); + if (referrer.indexOf("referrer_testserver") > 0) { + referrerLevel = "full"; + } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) { + referrerLevel = "origin"; + } else { + // this is never supposed to happen + referrerLevel = "other-origin"; + } + test.referrer = referrer; + } else { + test.referrer = ""; + } + test.policy = referrerLevel; + test.expected = policy; + + result[name] = test; + + setSharedState(SHARED_KEY, JSON.stringify(result)); + + if (type === "img" || type == "link_element_preload") { + // return image + response.setHeader("Content-Type", "image/png"); + response.write(IMG_BYTES); + return; + } + if (type === "iframe") { + // return iframe page + response.write("<html><body>I am the iframe</body></html>"); + return; + } + if (type === "link") { + // forward link click to redirect URL to finish test + var loc = "http://" + BASE_URL + "ACTION=redirect"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + } + return; + } + + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + + // parse test arguments and start test + var attributePolicy = params.get("ATTRIBUTE_POLICY") || ""; + var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || ""; + var metaPolicy = params.get("META_POLICY") || ""; + var rel = params.get("REL") || ""; + var name = params.get("NAME"); + + // anchor & area + var _getPage = createAETestPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + rel + ); + var _getAnchorPage = _getPage.bind( + null, + buildAnchorString, + schemeFrom, + schemeTo + ); + var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo); + + // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder + if (action === "generate-anchor-policy-test") { + response.write(_getAnchorPage()); + return; + } + if (action === "generate-anchor-changing-policy-test-set-attribute") { + response.write(_getAnchorPage("setAttribute")); + return; + } + if (action === "generate-anchor-changing-policy-test-property") { + response.write(_getAnchorPage("property")); + return; + } + if (action === "generate-area-policy-test") { + response.write(_getAreaPage()); + return; + } + if (action === "generate-area-changing-policy-test-set-attribute") { + response.write(_getAreaPage("setAttribute")); + return; + } + if (action === "generate-area-changing-policy-test-property") { + response.write(_getAreaPage("property")); + return; + } + if (action === "generate-anchor-target-blank-policy-test") { + response.write( + createTargetBlankRefferer( + metaPolicy, + name, + schemeFrom, + schemeTo, + referrerPolicyHeader + ) + ); + return; + } + + // iframe + _getPage = createIframeTestPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + "", + schemeFrom, + schemeTo + ); + + // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod + if (action === "generate-iframe-policy-test") { + response.write(_getPage()); + return; + } + if (action === "generate-iframe-changing-policy-test-set-attribute") { + response.write(_getPage("setAttribute")); + return; + } + if (action === "generate-iframe-changing-policy-test-property") { + response.write(_getPage("property")); + return; + } + + // redirect tests with img and iframe + if (action === "generate-img-redirect-policy-test") { + response.write(createRedirectImgTestCase(params, attributePolicy)); + return; + } + if (action === "generate-iframe-redirect-policy-test") { + response.write( + createIframeTestPageUsingRefferer( + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + params, + schemeFrom, + schemeTo + ) + ); + return; + } + + _getPage = createLinkPageUsingRefferer.bind( + null, + metaPolicy, + attributePolicy, + newAttributePolicy, + name, + rel + ); + var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo); + + // link + if (action === "generate-link-policy-test") { + response.write(_getLinkPage()); + return; + } + if (action === "generate-link-policy-test-set-attribute") { + response.write(_getLinkPage("setAttribute")); + return; + } + if (action === "generate-link-policy-test-property") { + response.write(_getLinkPage("property")); + return; + } + + if (action === "generate-fetch-user-control-policy-test") { + response.write( + createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin) + ); + return; + } + + response.write("I don't know action " + action); +} |