tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

referrer_testserver.sjs (18318B)


      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 
      8 const SJS = "referrer_testserver.sjs?";
      9 const SJS_PATH = "/tests/dom/base/test/";
     10 const BASE_ORIGIN = "example.com";
     11 const BASE_URL = BASE_ORIGIN + SJS_PATH + SJS;
     12 const SHARED_KEY = SJS;
     13 const SAME_ORIGIN = "mochi.test:8888" + SJS_PATH + SJS;
     14 const CROSS_ORIGIN_URL = "test1.example.com" + SJS_PATH + SJS;
     15 
     16 const IMG_BYTES = atob(
     17   "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
     18     "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
     19 );
     20 
     21 function createTestUrl(
     22   aPolicy,
     23   aAction,
     24   aName,
     25   aType,
     26   aSchemeFrom,
     27   aSchemeTo,
     28   crossOrigin,
     29   referrerPolicyHeader
     30 ) {
     31   var schemeTo = aSchemeTo || "http";
     32   var schemeFrom = aSchemeFrom || "http";
     33   var rpHeader = referrerPolicyHeader || "";
     34   var url = schemeTo + "://";
     35   url += crossOrigin ? CROSS_ORIGIN_URL : BASE_URL;
     36   url +=
     37     "ACTION=" +
     38     aAction +
     39     "&" +
     40     "policy=" +
     41     aPolicy +
     42     "&" +
     43     "NAME=" +
     44     aName +
     45     "&" +
     46     "type=" +
     47     aType +
     48     "&" +
     49     "RP_HEADER=" +
     50     rpHeader +
     51     "&" +
     52     "SCHEME_FROM=" +
     53     schemeFrom;
     54   return url;
     55 }
     56 
     57 // test page using iframe referrer attribute
     58 // if aParams are set this creates a test where the iframe url is a redirect
     59 function createIframeTestPageUsingRefferer(
     60   aMetaPolicy,
     61   aAttributePolicy,
     62   aNewAttributePolicy,
     63   aName,
     64   aParams,
     65   aSchemeFrom,
     66   aSchemeTo,
     67   aChangingMethod
     68 ) {
     69   var metaString = "";
     70   if (aMetaPolicy) {
     71     metaString = `<meta name="referrer" content="${aMetaPolicy}">`;
     72   }
     73   var changeString = "";
     74   if (aChangingMethod === "setAttribute") {
     75     changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
     76   } else if (aChangingMethod === "property") {
     77     changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`;
     78   }
     79   var iFrameString = `<iframe src="" id="myframe" ${
     80     aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""
     81   }>iframe</iframe>`;
     82   var iframeUrl = "";
     83   if (aParams) {
     84     aParams.delete("ACTION");
     85     aParams.append("ACTION", "redirectIframe");
     86     iframeUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString();
     87   } else {
     88     iframeUrl = createTestUrl(
     89       aAttributePolicy,
     90       "test",
     91       aName,
     92       "iframe",
     93       aSchemeFrom,
     94       aSchemeTo
     95     );
     96   }
     97 
     98   return `<!DOCTYPE HTML>
     99            <html>
    100              <head>
    101              ${metaString}
    102              </head>
    103              <body>
    104                ${iFrameString}
    105                <script>
    106                  window.addEventListener("load", function() {
    107                    ${changeString}
    108                    document.getElementById("myframe").onload = function(){
    109                     parent.postMessage("childLoadComplete", "http://mochi.test:8888");
    110                    };
    111                    document.getElementById("myframe").src = "${iframeUrl}";
    112                  }.bind(window), false);
    113                </script>
    114              </body>
    115            </html>`;
    116 }
    117 
    118 function buildAnchorString(
    119   aMetaPolicy,
    120   aReferrerPolicy,
    121   aName,
    122   aRelString,
    123   aSchemeFrom,
    124   aSchemeTo
    125 ) {
    126   if (aReferrerPolicy) {
    127     return `<a href="${createTestUrl(
    128       aReferrerPolicy,
    129       "test",
    130       aName,
    131       "link",
    132       aSchemeFrom,
    133       aSchemeTo
    134     )}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
    135   }
    136   return `<a href="${createTestUrl(
    137     aMetaPolicy,
    138     "test",
    139     aName,
    140     "link",
    141     aSchemeFrom,
    142     aSchemeTo
    143   )}" id="link" ${aRelString}>link</a>`;
    144 }
    145 
    146 function buildAreaString(
    147   aMetaPolicy,
    148   aReferrerPolicy,
    149   aName,
    150   aRelString,
    151   aSchemeFrom,
    152   aSchemeTo
    153 ) {
    154   var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`;
    155   result += `<map name="imageMap">`;
    156   if (aReferrerPolicy) {
    157     result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(
    158       aReferrerPolicy,
    159       "test",
    160       aName,
    161       "link",
    162       aSchemeFrom,
    163       aSchemeTo
    164     )}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`;
    165   } else {
    166     result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(
    167       aMetaPolicy,
    168       "test",
    169       aName,
    170       "link",
    171       aSchemeFrom,
    172       aSchemeTo
    173     )}" alt="theArea" id="link" ${aRelString}>`;
    174   }
    175   result += `</map>`;
    176 
    177   return result;
    178 }
    179 
    180 // test page using anchor or area referrer attribute
    181 function createAETestPageUsingRefferer(
    182   aMetaPolicy,
    183   aAttributePolicy,
    184   aNewAttributePolicy,
    185   aName,
    186   aRel,
    187   aStringBuilder,
    188   aSchemeFrom,
    189   aSchemeTo,
    190   aChangingMethod
    191 ) {
    192   var metaString = "";
    193   if (aMetaPolicy) {
    194     metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`;
    195   }
    196   var changeString = "";
    197   if (aChangingMethod === "setAttribute") {
    198     changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
    199   } else if (aChangingMethod === "property") {
    200     changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`;
    201   }
    202   var relString = "";
    203   if (aRel) {
    204     relString = `rel="noreferrer"`;
    205   }
    206   var elementString = aStringBuilder(
    207     aMetaPolicy,
    208     aAttributePolicy,
    209     aName,
    210     relString,
    211     aSchemeFrom,
    212     aSchemeTo
    213   );
    214 
    215   return `<!DOCTYPE HTML>
    216            <html>
    217              ${metaString}
    218              <body>
    219                ${elementString}
    220                <script>
    221                  window.addEventListener("load", function() {
    222                    ${changeString}
    223                    document.getElementById("link").click();
    224                  }.bind(window), false);
    225                </script>
    226              </body>
    227            </html>`;
    228 }
    229 
    230 // test page using anchor target=_blank rel=noopener
    231 function createTargetBlankRefferer(
    232   aMetaPolicy,
    233   aName,
    234   aSchemeFrom,
    235   aSchemeTo,
    236   aRpHeader
    237 ) {
    238   var metaString = "";
    239   if (aMetaPolicy) {
    240     metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`;
    241   }
    242   var elementString = `<a href="${createTestUrl(
    243     aMetaPolicy,
    244     "test",
    245     aName,
    246     "link",
    247     aSchemeFrom,
    248     aSchemeTo,
    249     aRpHeader
    250   )}" target=_blank rel="noopener" id="link">link</a>`;
    251 
    252   return `<!DOCTYPE HTML>
    253            <html>
    254              ${metaString}
    255              <body>
    256                ${elementString}
    257                <script>
    258                  window.addEventListener("load", function() {
    259                    let link = document.getElementById("link");
    260                    SpecialPowers.wrap(window).parent.postMessage("childLoadReady", "*");
    261                    link.click();
    262                  }.bind(window), false);
    263                </script>
    264              </body>
    265            </html>`;
    266 }
    267 
    268 // creates test page with img that is a redirect
    269 function createRedirectImgTestCase(aParams, aAttributePolicy) {
    270   var metaString = "";
    271   if (aParams.has("META_POLICY")) {
    272     metaString = `<meta name="referrer" content="${aParams.get(
    273       "META_POLICY"
    274     )}">`;
    275   }
    276   aParams.delete("ACTION");
    277   aParams.append("ACTION", "redirectImg");
    278   var imgUrl = "http://" + CROSS_ORIGIN_URL + aParams.toString();
    279 
    280   return `<!DOCTYPE HTML>
    281           <html>
    282           <head>
    283           <meta charset="utf-8">
    284           ${metaString}
    285           <title>Test referrer policies on redirect (img)</title>
    286           </head>
    287           <body>
    288           <img id="testImg" src="${imgUrl}" ${
    289             aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""
    290           }>
    291           <script>
    292             window.addEventListener("load", function() {
    293               parent.postMessage("childLoadComplete", "http://mochi.test:8888");
    294             }.bind(window), false);
    295           </script>
    296           </body>
    297           </html>`;
    298 }
    299 
    300 // test page using link referrer attribute
    301 function createLinkPageUsingRefferer(
    302   aMetaPolicy,
    303   aAttributePolicy,
    304   aNewAttributePolicy,
    305   aName,
    306   aRel,
    307   aStringBuilder,
    308   aSchemeFrom,
    309   aSchemeTo,
    310   aTestType
    311 ) {
    312   var metaString = "";
    313   if (aMetaPolicy) {
    314     metaString = `<meta name="referrer" content="${aMetaPolicy}">`;
    315   }
    316 
    317   var changeString = "";
    318   var policy = aAttributePolicy ? aAttributePolicy : aMetaPolicy;
    319   var elementString = aStringBuilder(
    320     policy,
    321     aName,
    322     aRel,
    323     aSchemeFrom,
    324     aSchemeTo,
    325     aTestType
    326   );
    327 
    328   if (aTestType === "setAttribute") {
    329     changeString = `var link = document.getElementById("test_link");
    330                     link.setAttribute("referrerpolicy", "${aNewAttributePolicy}");
    331                     link.href = "${createTestUrl(
    332                       policy,
    333                       "test",
    334                       aName,
    335                       "link_element_" + aRel,
    336                       aSchemeFrom,
    337                       aSchemeTo
    338                     )}";`;
    339   } else if (aTestType === "property") {
    340     changeString = `var link = document.getElementById("test_link");
    341                     link.referrerPolicy = "${aNewAttributePolicy}";
    342                     link.href = "${createTestUrl(
    343                       policy,
    344                       "test",
    345                       aName,
    346                       "link_element_" + aRel,
    347                       aSchemeFrom,
    348                       aSchemeTo
    349                     )}";`;
    350   }
    351 
    352   return `<!DOCTYPE HTML>
    353            <html>
    354              <head>
    355                ${metaString}
    356              </head>
    357              <body>
    358                 ${elementString}
    359                 <script>
    360                   ${changeString}
    361                 </script>
    362              </body>
    363            </html>`;
    364 }
    365 
    366 function createFetchUserControlRPTestCase(
    367   aName,
    368   aSchemeFrom,
    369   aSchemeTo,
    370   crossOrigin
    371 ) {
    372   var srcUrl = createTestUrl(
    373     "",
    374     "test",
    375     aName,
    376     "fetch",
    377     aSchemeFrom,
    378     aSchemeTo,
    379     crossOrigin
    380   );
    381 
    382   return `<!DOCTYPE HTML>
    383           <html>
    384           <head>
    385           <meta charset="utf-8">
    386           <title>Test user control referrer policies</title>
    387           </head>
    388           <body>
    389           <script>
    390             fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) {
    391               window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");
    392             });
    393           </script>
    394           </body>
    395           </html>`;
    396 }
    397 
    398 function buildLinkString(
    399   aPolicy,
    400   aName,
    401   aRel,
    402   aSchemeFrom,
    403   aSchemeTo,
    404   aTestType
    405 ) {
    406   var href = "";
    407   var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`;
    408   var policy = "";
    409   var asString = "";
    410   var relString = "";
    411 
    412   if (aRel) {
    413     relString = `rel="${aRel}"`;
    414   }
    415 
    416   if (aPolicy) {
    417     policy = `referrerpolicy=${aPolicy}`;
    418   }
    419 
    420   if (aRel == "preload") {
    421     asString = 'as="image"';
    422   }
    423 
    424   if (!aTestType) {
    425     href = `href=${createTestUrl(
    426       aPolicy,
    427       "test",
    428       aName,
    429       "link_element_" + aRel,
    430       aSchemeFrom,
    431       aSchemeTo
    432     )}`;
    433   }
    434 
    435   return `<link ${relString} ${href} ${policy} ${asString} id="test_link" onload='${onChildComplete}' onerror='${onChildComplete}'>`;
    436 }
    437 
    438 // eslint-disable-next-line complexity
    439 function handleRequest(request, response) {
    440   var params = new URLSearchParams(request.queryString);
    441   var action = params.get("ACTION");
    442   var schemeFrom = params.get("SCHEME_FROM") || "http";
    443   var schemeTo = params.get("SCHEME_TO") || "http";
    444   var crossOrigin = params.get("CROSS_ORIGIN") || false;
    445   var referrerPolicyHeader = params.get("RP_HEADER") || "";
    446 
    447   response.setHeader("Access-Control-Allow-Origin", "*", false);
    448   if (referrerPolicyHeader) {
    449     response.setHeader("Referrer-Policy", referrerPolicyHeader, false);
    450   }
    451 
    452   if (action === "resetState") {
    453     setSharedState(SHARED_KEY, "{}");
    454     response.write("");
    455     return;
    456   }
    457   if (action === "get-test-results") {
    458     // ?action=get-result
    459     response.setHeader("Cache-Control", "no-cache", false);
    460     response.setHeader("Content-Type", "text/plain", false);
    461     response.write(getSharedState(SHARED_KEY));
    462     return;
    463   }
    464   if (action === "redirect") {
    465     response.write(
    466       '<script>parent.postMessage("childLoadComplete", "http://mochi.test:8888");</script>'
    467     );
    468     return;
    469   }
    470   if (action === "redirectImg") {
    471     params.delete("ACTION");
    472     params.append("ACTION", "test");
    473     params.append("type", "img");
    474     // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect
    475     response.setStatusLine("1.1", 302, "found");
    476     response.setHeader(
    477       "Location",
    478       "http://" + CROSS_ORIGIN_URL + params.toString(),
    479       false
    480     );
    481     return;
    482   }
    483   if (action === "redirectIframe") {
    484     params.delete("ACTION");
    485     params.append("ACTION", "test");
    486     params.append("type", "iframe");
    487     // 302 found, 301 Moved Permanently, 303 See Other, 307 Temporary Redirect
    488     response.setStatusLine("1.1", 302, "found");
    489     response.setHeader(
    490       "Location",
    491       "http://" + CROSS_ORIGIN_URL + params.toString(),
    492       false
    493     );
    494     return;
    495   }
    496   if (action === "test") {
    497     // ?action=test&policy=origin&name=name
    498     var policy = params.get("policy");
    499     var name = params.get("NAME");
    500     var type = params.get("type");
    501     var result = getSharedState(SHARED_KEY);
    502 
    503     result = result ? JSON.parse(result) : {};
    504 
    505     var referrerLevel = "none";
    506     var test = {};
    507     if (request.hasHeader("Referer")) {
    508       var referrer = request.getHeader("Referer");
    509       if (referrer.indexOf("referrer_testserver") > 0) {
    510         referrerLevel = "full";
    511       } else if (referrer.indexOf(schemeFrom + "://example.com") == 0) {
    512         referrerLevel = "origin";
    513       } else {
    514         // this is never supposed to happen
    515         referrerLevel = "other-origin";
    516       }
    517       test.referrer = referrer;
    518     } else {
    519       test.referrer = "";
    520     }
    521     test.policy = referrerLevel;
    522     test.expected = policy;
    523 
    524     result[name] = test;
    525 
    526     setSharedState(SHARED_KEY, JSON.stringify(result));
    527 
    528     if (type === "img" || type == "link_element_preload") {
    529       // return image
    530       response.setHeader("Content-Type", "image/png");
    531       response.write(IMG_BYTES);
    532       return;
    533     }
    534     if (type === "iframe") {
    535       // return iframe page
    536       response.write("<html><body>I am the iframe</body></html>");
    537       return;
    538     }
    539     if (type === "link") {
    540       // forward link click to redirect URL to finish test
    541       var loc = "http://" + BASE_URL + "ACTION=redirect";
    542       response.setStatusLine("1.1", 302, "Found");
    543       response.setHeader("Location", loc, false);
    544     }
    545     return;
    546   }
    547 
    548   response.setHeader("Cache-Control", "no-cache", false);
    549   response.setHeader("Content-Type", "text/html; charset=utf-8", false);
    550 
    551   // parse test arguments and start test
    552   var attributePolicy = params.get("ATTRIBUTE_POLICY") || "";
    553   var newAttributePolicy = params.get("NEW_ATTRIBUTE_POLICY") || "";
    554   var metaPolicy = params.get("META_POLICY") || "";
    555   var rel = params.get("REL") || "";
    556   var name = params.get("NAME");
    557 
    558   // anchor & area
    559   var _getPage = createAETestPageUsingRefferer.bind(
    560     null,
    561     metaPolicy,
    562     attributePolicy,
    563     newAttributePolicy,
    564     name,
    565     rel
    566   );
    567   var _getAnchorPage = _getPage.bind(
    568     null,
    569     buildAnchorString,
    570     schemeFrom,
    571     schemeTo
    572   );
    573   var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo);
    574 
    575   // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder
    576   if (action === "generate-anchor-policy-test") {
    577     response.write(_getAnchorPage());
    578     return;
    579   }
    580   if (action === "generate-anchor-changing-policy-test-set-attribute") {
    581     response.write(_getAnchorPage("setAttribute"));
    582     return;
    583   }
    584   if (action === "generate-anchor-changing-policy-test-property") {
    585     response.write(_getAnchorPage("property"));
    586     return;
    587   }
    588   if (action === "generate-area-policy-test") {
    589     response.write(_getAreaPage());
    590     return;
    591   }
    592   if (action === "generate-area-changing-policy-test-set-attribute") {
    593     response.write(_getAreaPage("setAttribute"));
    594     return;
    595   }
    596   if (action === "generate-area-changing-policy-test-property") {
    597     response.write(_getAreaPage("property"));
    598     return;
    599   }
    600   if (action === "generate-anchor-target-blank-policy-test") {
    601     response.write(
    602       createTargetBlankRefferer(
    603         metaPolicy,
    604         name,
    605         schemeFrom,
    606         schemeTo,
    607         referrerPolicyHeader
    608       )
    609     );
    610     return;
    611   }
    612 
    613   // iframe
    614   _getPage = createIframeTestPageUsingRefferer.bind(
    615     null,
    616     metaPolicy,
    617     attributePolicy,
    618     newAttributePolicy,
    619     name,
    620     "",
    621     schemeFrom,
    622     schemeTo
    623   );
    624 
    625   // aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod
    626   if (action === "generate-iframe-policy-test") {
    627     response.write(_getPage());
    628     return;
    629   }
    630   if (action === "generate-iframe-changing-policy-test-set-attribute") {
    631     response.write(_getPage("setAttribute"));
    632     return;
    633   }
    634   if (action === "generate-iframe-changing-policy-test-property") {
    635     response.write(_getPage("property"));
    636     return;
    637   }
    638 
    639   // redirect tests with img and iframe
    640   if (action === "generate-img-redirect-policy-test") {
    641     response.write(createRedirectImgTestCase(params, attributePolicy));
    642     return;
    643   }
    644   if (action === "generate-iframe-redirect-policy-test") {
    645     response.write(
    646       createIframeTestPageUsingRefferer(
    647         metaPolicy,
    648         attributePolicy,
    649         newAttributePolicy,
    650         name,
    651         params,
    652         schemeFrom,
    653         schemeTo
    654       )
    655     );
    656     return;
    657   }
    658 
    659   var _getPage = createLinkPageUsingRefferer.bind(
    660     null,
    661     metaPolicy,
    662     attributePolicy,
    663     newAttributePolicy,
    664     name,
    665     rel
    666   );
    667   var _getLinkPage = _getPage.bind(null, buildLinkString, schemeFrom, schemeTo);
    668 
    669   // link
    670   if (action === "generate-link-policy-test") {
    671     response.write(_getLinkPage());
    672     return;
    673   }
    674   if (action === "generate-link-policy-test-set-attribute") {
    675     response.write(_getLinkPage("setAttribute"));
    676     return;
    677   }
    678   if (action === "generate-link-policy-test-property") {
    679     response.write(_getLinkPage("property"));
    680     return;
    681   }
    682 
    683   if (action === "generate-fetch-user-control-policy-test") {
    684     response.write(
    685       createFetchUserControlRPTestCase(name, schemeFrom, schemeTo, crossOrigin)
    686     );
    687     return;
    688   }
    689 
    690   response.write("I don't know action " + action);
    691 }