1/* 2* Test server for iframe, anchor, and area referrer attributes. 3* https://bugzilla.mozilla.org/show_bug.cgi?id=1175736 4* Also server for further referrer tests such as redirecting tests 5* bug 1174913, bug 1175736, bug 1184781 6*/ 7 8Components.utils.importGlobalProperties(["URLSearchParams"]); 9const SJS = "referrer_testserver.sjs?"; 10const SJS_PATH = "/tests/dom/security/test/referrer-policy/"; 11const BASE_ORIGIN = "example.com" 12const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS; 13const SHARED_KEY = SJS; 14const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS; 15const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS; 16 17const IMG_BYTES = atob( 18 "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + 19 "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="); 20 21function createTestUrl(aPolicy, aAction, aName, aType, aSchemeFrom, aSchemeTo, 22 crossOrigin, referrerPolicyHeader) { 23 var schemeTo = aSchemeTo || "http"; 24 var schemeFrom = aSchemeFrom || "http"; 25 var rpHeader = referrerPolicyHeader || ""; 26 var url = schemeTo + "://"; 27 url += (crossOrigin ? CROSS_ORIGIN_URL : BASE_URL); 28 url += 29 "ACTION=" + aAction + "&" + 30 "policy=" + aPolicy + "&" + 31 "NAME=" + aName + "&" + 32 "type=" + aType + "&" + 33 "RP_HEADER=" + rpHeader + "&" + 34 "SCHEME_FROM=" + schemeFrom; 35 return url; 36 } 37 38// test page using iframe referrer attribute 39// if aParams are set this creates a test where the iframe url is a redirect 40function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aParams, 41 aSchemeFrom, aSchemeTo, aChangingMethod) { 42 var metaString = ""; 43 if (aMetaPolicy) { 44 metaString = `<meta name="referrer" content="${aMetaPolicy}">`; 45 } 46 var changeString = ""; 47 if (aChangingMethod === "setAttribute") { 48 changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; 49 } else if (aChangingMethod === "property") { 50 changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`; 51 } 52 var iFrameString = `<iframe src="" id="myframe" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}>iframe</iframe>`; 53 var iframeUrl = ""; 54 if (aParams) { 55 aParams.delete("ACTION"); 56 aParams.append("ACTION", "redirectIframe"); 57 iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); 58 } else { 59 iframeUrl = createTestUrl(aAttributePolicy, "test", aName, "iframe", aSchemeFrom, aSchemeTo); 60 } 61 62 return `<!DOCTYPE HTML> 63 <html> 64 <head> 65 ${metaString} 66 </head> 67 <body> 68 ${iFrameString} 69 <script> 70 window.addEventListener("load", function() { 71 ${changeString} 72 document.getElementById("myframe").onload = function(){ 73 parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 74 }; 75 document.getElementById("myframe").src = "${iframeUrl}"; 76 }.bind(window), false); 77 </script> 78 </body> 79 </html>`; 80} 81 82function buildAnchorString(aMetaPolicy, aReferrerPolicy, aName, aRelString, aSchemeFrom, aSchemeTo){ 83 if (aReferrerPolicy) { 84 return `<a href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`; 85 } 86 return `<a href="${createTestUrl(aMetaPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" id="link" ${aRelString}>link</a>`; 87} 88 89function buildAreaString(aMetaPolicy, aReferrerPolicy, aName, aRelString, aSchemeFrom, aSchemeTo){ 90 var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`; 91 result += `<map name="imageMap">`; 92 if (aReferrerPolicy) { 93 result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`; 94 } else { 95 result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aMetaPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" alt="theArea" id="link" ${aRelString}>`; 96 } 97 result += `</map>`; 98 99 return result; 100} 101 102// test page using anchor or area referrer attribute 103function createAETestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aRel, aStringBuilder, aSchemeFrom, aSchemeTo, aChangingMethod) { 104 var metaString = ""; 105 if (aMetaPolicy) { 106 metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; 107 } 108 var changeString = ""; 109 if (aChangingMethod === "setAttribute") { 110 changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`; 111 } else if (aChangingMethod === "property") { 112 changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`; 113 } 114 var relString = ""; 115 if (aRel) { 116 relString = `rel="noreferrer"`; 117 } 118 var elementString = aStringBuilder(aMetaPolicy, aAttributePolicy, aName, relString, aSchemeFrom, aSchemeTo); 119 120 return `<!DOCTYPE HTML> 121 <html> 122 ${metaString} 123 <body> 124 ${elementString} 125 <script> 126 window.addEventListener("load", function() { 127 ${changeString} 128 document.getElementById("link").click(); 129 }.bind(window), false); 130 </script> 131 </body> 132 </html>`; 133} 134 135// test page using anchor target=_blank rel=noopener 136function createTargetBlankRefferer(aMetaPolicy, aName, aSchemeFrom, 137 aSchemeTo, aRpHeader) { 138 var metaString = ""; 139 if (aMetaPolicy) { 140 metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`; 141 } 142 var elementString = `<a href="${createTestUrl(aMetaPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo, aRpHeader)}" target=_blank rel="noopener" id="link">link</a>`; 143 144 return `<!DOCTYPE HTML> 145 <html> 146 ${metaString} 147 <body> 148 ${elementString} 149 <script> 150 window.addEventListener("load", function() { 151 let link = document.getElementById("link"); 152 SpecialPowers.wrap(window).parent.postMessage("childLoadReady", "*"); 153 link.click(); 154 }.bind(window), false); 155 </script> 156 </body> 157 </html>`; 158} 159 160// creates test page with img that is a redirect 161function createRedirectImgTestCase(aParams, aAttributePolicy) { 162 var metaString = ""; 163 if (aParams.has("META_POLICY")) { 164 metaString = `<meta name="referrer" content="${aParams.get('META_POLICY')}">`; 165 } 166 aParams.delete("ACTION"); 167 aParams.append("ACTION", "redirectImg"); 168 var imgUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString(); 169 170 return `<!DOCTYPE HTML> 171 <html> 172 <head> 173 <meta charset="utf-8"> 174 ${metaString} 175 <title>Test referrer policies on redirect (img)</title> 176 </head> 177 <body> 178 <img id="testImg" src="${imgUrl}" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}> 179 <script> 180 window.addEventListener("load", function() { 181 parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 182 }.bind(window), false); 183 </script> 184 </body> 185 </html>`; 186} 187 188// test page using link referrer attribute 189function createLinkPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aRel, aStringBuilder, aSchemeFrom, aSchemeTo, aTestType) { 190 var metaString = ""; 191 if (aMetaPolicy) { 192 metaString = `<meta name="referrer" content="${aMetaPolicy}">`; 193 } 194 195 var changeString = ""; 196 var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy; 197 var elementString = aStringBuilder(policy, aName, aRel, aSchemeFrom, aSchemeTo, aTestType); 198 199 if (aTestType === "setAttribute") { 200 changeString = `var link = document.getElementById("test_link"); 201 link.setAttribute("referrerpolicy", "${aNewAttributePolicy}"); 202 link.href = "${createTestUrl(policy, "test", aName, "link_element_" + aRel, aSchemeFrom, aSchemeTo)}";`; 203 } else if (aTestType === "property") { 204 changeString = `var link = document.getElementById("test_link"); 205 link.referrerPolicy = "${aNewAttributePolicy}"; 206 link.href = "${createTestUrl(policy, "test", aName, "link_element_" + aRel, aSchemeFrom, aSchemeTo)}";`; 207 } 208 209 return `<!DOCTYPE HTML> 210 <html> 211 <head> 212 ${metaString} 213 </head> 214 <body> 215 ${elementString} 216 <script> 217 ${changeString} 218 </script> 219 </body> 220 </html>`; 221} 222 223function createFetchUserControlRPTestCase(aName, aSchemeFrom, aSchemeTo, crossOrigin) { 224 var srcUrl = createTestUrl("", "test", aName, "fetch", aSchemeFrom, aSchemeTo, crossOrigin); 225 226 return `<!DOCTYPE HTML> 227 <html> 228 <head> 229 <meta charset="utf-8"> 230 <title>Test user control referrer policies</title> 231 </head> 232 <body> 233 <script> 234 fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) { 235 window.parent.postMessage("childLoadComplete", "http://mochi.test:8888"); 236 }); 237 </script> 238 </body> 239 </html>`; 240} 241 242function buildLinkString(aPolicy, aName, aRel, aSchemeFrom, aSchemeTo, aTestType) { 243 var href = ''; 244 var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");` 245 var policy = ''; 246 var asString = ''; 247 var relString = ''; 248 249 if (aRel) { 250 relString = `rel="${aRel}"`; 251 } 252 253 if (aPolicy) { 254 policy = `referrerpolicy=${aPolicy}`; 255 } 256 257 if (aRel == "preload") { 258 asString = 'as="image"'; 259 } 260 261 if (!aTestType) { 262 href = `href=${createTestUrl(aPolicy, "test", aName, "link_element_" + aRel, aSchemeFrom, aSchemeTo)}`; 263 } 264 265 return `<link ${relString} ${href} ${policy} ${asString} id="test_link" onload='${onChildComplete}' onerror='${onChildComplete}'>`; 266} 267 268function handleRequest(request, response) { 269 var params = new URLSearchParams(request.queryString); 270 var action = params.get("ACTION"); 271 var schemeFrom = params.get("SCHEME_FROM") || "http"; 272 var schemeTo = params.get("SCHEME_TO") || "http"; 273 var crossOrigin = params.get("CROSS_ORIGIN") || false; 274 var referrerPolicyHeader = params.get("RP_HEADER") || ""; 275 276 response.setHeader("Access-Control-Allow-Origin", "*", false); 277 if (referrerPolicyHeader) { 278 response.setHeader("Referrer-Policy", referrerPolicyHeader, false); 279 } 280 281 if (action === "resetState") { 282 setSharedState(SHARED_KEY, "{}"); 283 response.write(""); 284 return; 285 } 286 if (action === "get-test-results") { 287 // ?action=get-result 288 response.setHeader("Cache-Control", "no-cache", false); 289 response.setHeader("Content-Type", "text/plain", false); 290 response.write(getSharedState(SHARED_KEY)); 291 return; 292 } 293 if (action === "redirect") { 294 response.write('<script>parent.postMessage("childLoadComplete", "http://mochi.test:8888");</script>'); 295 return; 296 } 297 if (action === "redirectImg"){ 298 params.delete("ACTION"); 299 params.append("ACTION", "test"); 300 params.append("type", "img"); 301 // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect 302 response.setStatusLine("1.1", 302, "found"); 303 response.setHeader("Location", "http://" + CROSS_ORIGIN_URL + params.toString(), false); 304 return; 305 } 306 if (action === "redirectIframe"){ 307 params.delete("ACTION"); 308 params.append("ACTION", "test"); 309 params.append("type", "iframe"); 310 // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect 311 response.setStatusLine("1.1", 302, "found"); 312 response.setHeader("Location", "http://" + CROSS_ORIGIN_URL + params.toString(), false); 313 return; 314 } 315 if (action === "test") { 316 // ?action=test&policy=origin&name=name 317 var policy = params.get("policy"); 318 var name = params.get("NAME"); 319 var type = params.get("type"); 320 var result = getSharedState(SHARED_KEY); 321 322 result = result ? JSON.parse(result) : {}; 323 324 var referrerLevel = "none"; 325 var test = {} 326 if (request.hasHeader("Referer")) { 327 var referrer = request.getHeader("Referer"); 328 if (referrer.indexOf("referrer_testserver") > 0) { 329 referrerLevel = "full"; 330 } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) { 331 referrerLevel = "origin"; 332 } else { 333 // this is never supposed to happen 334 referrerLevel = "other-origin"; 335 } 336 test.referrer = referrer; 337 } else { 338 test.referrer = ""; 339 } 340 test.policy = referrerLevel; 341 test.expected = policy; 342 343 result[name] = test; 344 345 setSharedState(SHARED_KEY, JSON.stringify(result)); 346 347 if (type === "img" || type == "link_element_preload") { 348 // return image 349 response.setHeader("Content-Type", "image/png"); 350 response.write(IMG_BYTES); 351 return; 352 } 353 if (type === "iframe") { 354 // return iframe page 355 response.write("<html><body>I am the iframe</body></html>"); 356 return; 357 } 358 if (type === "link") { 359 // forward link click to redirect URL to finish test 360 var loc = "http://" + BASE_URL + "ACTION=redirect"; 361 response.setStatusLine("1.1", 302, "Found"); 362 response.setHeader("Location", loc, false); 363 } 364 return; 365 } 366 367 response.setHeader("Cache-Control", "no-cache", false); 368 response.setHeader("Content-Type", "text/html; charset=utf-8", false); 369 370 // parse test arguments and start test 371 var attributePolicy = params.get("ATTRIBUTE_POLICY") || ""; 372 var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || ""; 373 var metaPolicy = params.get("META_POLICY") || ""; 374 var rel = params.get("REL") || ""; 375 var name = params.get("NAME"); 376 377 // anchor & area 378 var _getPage = createAETestPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, rel); 379 var _getAnchorPage = _getPage.bind(null, buildAnchorString, schemeFrom, schemeTo); 380 var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo); 381 382 // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder 383 if (action === "generate-anchor-policy-test") { 384 response.write(_getAnchorPage()); 385 return; 386 } 387 if (action === "generate-anchor-changing-policy-test-set-attribute") { 388 response.write(_getAnchorPage("setAttribute")); 389 return; 390 } 391 if (action === "generate-anchor-changing-policy-test-property") { 392 response.write(_getAnchorPage("property")); 393 return; 394 } 395 if (action === "generate-area-policy-test") { 396 response.write(_getAreaPage()); 397 return; 398 } 399 if (action === "generate-area-changing-policy-test-set-attribute") { 400 response.write(_getAreaPage("setAttribute")); 401 return; 402 } 403 if (action === "generate-area-changing-policy-test-property") { 404 response.write(_getAreaPage("property")); 405 return; 406 } 407 if (action === "generate-anchor-target-blank-policy-test") { 408 response.write(createTargetBlankRefferer(metaPolicy, name, schemeFrom, schemeTo, referrerPolicyHeader)); 409 return; 410 } 411 412 // iframe 413 _getPage = createIframeTestPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, "", 414 schemeFrom, schemeTo); 415 416 // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod 417 if (action === "generate-iframe-policy-test") { 418 response.write(_getPage()); 419 return; 420 } 421 if (action === "generate-iframe-changing-policy-test-set-attribute") { 422 response.write(_getPage("setAttribute")); 423 return; 424 } 425 if (action === "generate-iframe-changing-policy-test-property") { 426 response.write(_getPage("property")); 427 return; 428 } 429 430 // redirect tests with img and iframe 431 if (action === "generate-img-redirect-policy-test") { 432 response.write(createRedirectImgTestCase(params, attributePolicy)); 433 return; 434 } 435 if (action === "generate-iframe-redirect-policy-test") { 436 response.write(createIframeTestPageUsingRefferer(metaPolicy, attributePolicy, newAttributePolicy, name, params, 437 schemeFrom, schemeTo)); 438 return; 439 } 440 441 var _getPage = createLinkPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, rel); 442 var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo); 443 444 // link 445 if (action === "generate-link-policy-test") { 446 response.write(_getLinkPage()); 447 return; 448 } 449 if (action === "generate-link-policy-test-set-attribute") { 450 response.write(_getLinkPage("setAttribute")); 451 return; 452 } 453 if (action === "generate-link-policy-test-property") { 454 response.write(_getLinkPage("property")); 455 return; 456 } 457 458 if (action === "generate-fetch-user-control-policy-test") { 459 response.write(createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin)); 460 return; 461 } 462 463 response.write("I don't know action " + action); 464 return; 465} 466