tor-browser

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

file_multipart_testserver.sjs (4594B)


      1 // SJS file specifically for the needs of bug
      2 // Bug 1416045/Bug 1223743 - CSP: Check baseChannel for CSP when loading multipart channel
      3 
      4 var CSP = "script-src 'unsafe-inline', img-src 'none'";
      5 var rootCSP = "script-src 'unsafe-inline'";
      6 var part1CSP = "img-src *";
      7 var part2CSP = "img-src 'none'";
      8 var BOUNDARY = "fooboundary";
      9 
     10 // small red image
     11 const IMG_BYTES = atob(
     12   "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
     13     "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
     14 );
     15 
     16 var RESPONSE = `
     17   <script>
     18   var myImg = new Image;
     19   myImg.src = "file_multipart_testserver.sjs?img";
     20   myImg.onerror = function(e) {
     21     window.parent.postMessage({"test": "rootCSP_test",
     22                                "msg": "img-blocked"}, "*");
     23   };
     24   myImg.onload = function() {
     25     window.parent.postMessage({"test": "rootCSP_test",
     26                                "msg": "img-loaded"}, "*");
     27   };
     28   document.body.appendChild(myImg);
     29   </script>
     30 `;
     31 
     32 var RESPONSE1 = `
     33   <body>
     34   <script>
     35   var triggerNextPartFrame = document.createElement('iframe');
     36   var myImg = new Image;
     37   myImg.src = "file_multipart_testserver.sjs?img";
     38   myImg.onerror = function(e) {
     39     window.parent.postMessage({"test": "part1CSP_test",
     40                                "msg": "part1-img-blocked"}, "*");
     41     triggerNextPartFrame.src = 'file_multipart_testserver.sjs?sendnextpart';
     42   };
     43   myImg.onload = function() {
     44     window.parent.postMessage({"test": "part1CSP_test",
     45                                "msg": "part1-img-loaded"}, "*");
     46     triggerNextPartFrame.src = 'file_multipart_testserver.sjs?sendnextpart';
     47   };
     48   document.body.appendChild(myImg);
     49   document.body.appendChild(triggerNextPartFrame);
     50   </script>
     51   </body>
     52 `;
     53 
     54 var RESPONSE2 = `
     55   <body>
     56   <script>
     57   var myImg = new Image;
     58   myImg.src = "file_multipart_testserver.sjs?img";
     59   myImg.onerror = function(e) {
     60     window.parent.postMessage({"test": "part2CSP_test",
     61                                "msg": "part2-img-blocked"}, "*");
     62   };
     63   myImg.onload = function() {
     64     window.parent.postMessage({"test": "part2CSP_test",
     65                                "msg": "part2-img-loaded"}, "*");
     66   };
     67   document.body.appendChild(myImg);
     68   </script>
     69   </body>
     70 `;
     71 
     72 function setGlobalState(data, key) {
     73   x = {
     74     data,
     75     QueryInterface(iid) {
     76       return this;
     77     },
     78   };
     79   x.wrappedJSObject = x;
     80   setObjectState(key, x);
     81 }
     82 
     83 function getGlobalState(key) {
     84   var data;
     85   getObjectState(key, function (x) {
     86     data = x && x.wrappedJSObject.data;
     87   });
     88   return data;
     89 }
     90 
     91 function handleRequest(request, response) {
     92   // avoid confusing cache behaviors
     93   response.setHeader("Cache-Control", "no-cache", false);
     94 
     95   if (request.queryString == "doc") {
     96     response.setHeader("Content-Security-Policy", CSP, false);
     97     response.setHeader(
     98       "Content-Type",
     99       "multipart/x-mixed-replace; boundary=" + BOUNDARY,
    100       false
    101     );
    102     response.write(BOUNDARY + "\r\n");
    103     response.write(RESPONSE);
    104     response.write(BOUNDARY + "\r\n");
    105     return;
    106   }
    107 
    108   if (request.queryString == "partcspdoc") {
    109     response.setHeader("Content-Security-Policy", rootCSP, false);
    110     response.setHeader(
    111       "Content-Type",
    112       "multipart/x-mixed-replace; boundary=" + BOUNDARY,
    113       false
    114     );
    115     response.setStatusLine(request.httpVersion, 200, "OK");
    116     response.processAsync();
    117     response.write("--" + BOUNDARY + "\r\n");
    118     sendNextPart(response, 1);
    119     return;
    120   }
    121 
    122   if (request.queryString == "sendnextpart") {
    123     response.setStatusLine(request.httpVersion, 204, "No content");
    124     var blockedResponse = getGlobalState("root-document-response");
    125     if (typeof blockedResponse == "object") {
    126       sendNextPart(blockedResponse, 2);
    127       sendClose(blockedResponse);
    128     } else {
    129       dump("Couldn't find the stored response object.");
    130     }
    131     return;
    132   }
    133 
    134   if (request.queryString == "img") {
    135     response.setHeader("Content-Type", "image/png");
    136     response.write(IMG_BYTES);
    137     return;
    138   }
    139 
    140   // we should never get here - return something unexpected
    141   response.write("d'oh");
    142 }
    143 
    144 function sendClose(response) {
    145   response.write("--" + BOUNDARY + "--\r\n");
    146   response.finish();
    147 }
    148 
    149 function sendNextPart(response, partNumber) {
    150   response.write("Content-type: text/html" + "\r\n");
    151   if (partNumber == 1) {
    152     response.write("Content-Security-Policy:" + part1CSP + "\r\n");
    153     response.write(RESPONSE1);
    154     setGlobalState(response, "root-document-response");
    155   } else {
    156     response.write("Content-Security-Policy:" + part2CSP + "\r\n");
    157     response.write(RESPONSE2);
    158   }
    159   response.write("--" + BOUNDARY + "\r\n");
    160 }