tor-browser

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

file_CrossSiteXHR_server.sjs (6256B)


      1 const CC = Components.Constructor;
      2 const BinaryInputStream = CC(
      3   "@mozilla.org/binaryinputstream;1",
      4   "nsIBinaryInputStream",
      5   "setInputStream"
      6 );
      7 Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
      8 
      9 // eslint-disable-next-line complexity
     10 function handleRequest(request, response) {
     11   var query = {};
     12   request.queryString.split("&").forEach(function (val) {
     13     var [name, value] = val.split("=");
     14     query[name] = unescape(value);
     15   });
     16 
     17   var isPreflight = request.method == "OPTIONS";
     18 
     19   var bodyStream = new BinaryInputStream(request.bodyInputStream);
     20   var bodyBytes = [];
     21   while ((bodyAvail = bodyStream.available()) > 0) {
     22     Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
     23   }
     24 
     25   var body = decodeURIComponent(
     26     escape(String.fromCharCode.apply(null, bodyBytes))
     27   );
     28 
     29   if (query.hop) {
     30     query.hop = parseInt(query.hop, 10);
     31     hops = JSON.parse(query.hops);
     32     var curHop = hops[query.hop - 1];
     33     query.allowOrigin = curHop.allowOrigin;
     34     query.allowHeaders = curHop.allowHeaders;
     35     query.allowMethods = curHop.allowMethods;
     36     query.allowCred = curHop.allowCred;
     37     query.noAllowPreflight = curHop.noAllowPreflight;
     38     if (curHop.setCookie) {
     39       query.setCookie = unescape(curHop.setCookie);
     40     }
     41     if (curHop.cookie) {
     42       query.cookie = unescape(curHop.cookie);
     43     }
     44     query.noCookie = curHop.noCookie;
     45   }
     46 
     47   // Check that request was correct
     48 
     49   if (!isPreflight && query.body && body != query.body) {
     50     sendHttp500(
     51       response,
     52       "Wrong body. Expected " + query.body + " got " + body
     53     );
     54     return;
     55   }
     56 
     57   if (!isPreflight && "headers" in query) {
     58     headers = JSON.parse(query.headers);
     59     for (headerName in headers) {
     60       // Content-Type is changed if there was a body
     61       if (
     62         !(headerName == "Content-Type" && body) &&
     63         (!request.hasHeader(headerName) ||
     64           request.getHeader(headerName) != headers[headerName])
     65       ) {
     66         var actual = request.hasHeader(headerName)
     67           ? request.getHeader(headerName)
     68           : "<missing header>";
     69         sendHttp500(
     70           response,
     71           "Header " +
     72             headerName +
     73             " had wrong value. Expected " +
     74             headers[headerName] +
     75             " got " +
     76             actual
     77         );
     78         return;
     79       }
     80     }
     81   }
     82 
     83   if (
     84     isPreflight &&
     85     "requestHeaders" in query &&
     86     request.getHeader("Access-Control-Request-Headers") != query.requestHeaders
     87   ) {
     88     sendHttp500(
     89       response,
     90       "Access-Control-Request-Headers had wrong value. Expected " +
     91         query.requestHeaders +
     92         " got " +
     93         request.getHeader("Access-Control-Request-Headers")
     94     );
     95     return;
     96   }
     97 
     98   if (
     99     isPreflight &&
    100     "requestMethod" in query &&
    101     request.getHeader("Access-Control-Request-Method") != query.requestMethod
    102   ) {
    103     sendHttp500(
    104       response,
    105       "Access-Control-Request-Method had wrong value. Expected " +
    106         query.requestMethod +
    107         " got " +
    108         request.getHeader("Access-Control-Request-Method")
    109     );
    110     return;
    111   }
    112 
    113   if ("origin" in query && request.getHeader("Origin") != query.origin) {
    114     sendHttp500(
    115       response,
    116       "Origin had wrong value. Expected " +
    117         query.origin +
    118         " got " +
    119         request.getHeader("Origin")
    120     );
    121     return;
    122   }
    123 
    124   if ("cookie" in query) {
    125     cookies = {};
    126     request
    127       .getHeader("Cookie")
    128       .split(/ *; */)
    129       .forEach(function (val) {
    130         var [name, value] = val.split("=");
    131         cookies[name] = unescape(value);
    132       });
    133 
    134     query.cookie.split(",").forEach(function (val) {
    135       var [name, value] = val.split("=");
    136       if (cookies[name] != value) {
    137         sendHttp500(
    138           response,
    139           "Cookie " +
    140             name +
    141             " had wrong value. Expected " +
    142             value +
    143             " got " +
    144             cookies[name]
    145         );
    146       }
    147     });
    148   }
    149 
    150   if (query.noCookie && request.hasHeader("Cookie")) {
    151     sendHttp500(
    152       response,
    153       "Got cookies when didn't expect to: " + request.getHeader("Cookie")
    154     );
    155     return;
    156   }
    157 
    158   // Send response
    159 
    160   if (!isPreflight && query.status) {
    161     response.setStatusLine(null, query.status, query.statusMessage);
    162   }
    163   if (isPreflight && query.preflightStatus) {
    164     response.setStatusLine(null, query.preflightStatus, "preflight status");
    165   }
    166 
    167   if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight)) {
    168     response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
    169   }
    170 
    171   if (query.allowCred) {
    172     response.setHeader("Access-Control-Allow-Credentials", "true");
    173   }
    174 
    175   if (query.setCookie) {
    176     response.setHeader("Set-Cookie", query.setCookie + "; path=/");
    177   }
    178 
    179   if (isPreflight) {
    180     if (query.allowHeaders) {
    181       response.setHeader("Access-Control-Allow-Headers", query.allowHeaders);
    182     }
    183 
    184     if (query.allowMethods) {
    185       response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
    186     }
    187   } else {
    188     if (query.responseHeaders) {
    189       let responseHeaders = JSON.parse(query.responseHeaders);
    190       for (let responseHeader in responseHeaders) {
    191         response.setHeader(responseHeader, responseHeaders[responseHeader]);
    192       }
    193     }
    194 
    195     if (query.exposeHeaders) {
    196       response.setHeader("Access-Control-Expose-Headers", query.exposeHeaders);
    197     }
    198   }
    199 
    200   if (!isPreflight && query.hop && query.hop < hops.length) {
    201     newURL =
    202       hops[query.hop].server +
    203       "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?" +
    204       "hop=" +
    205       (query.hop + 1) +
    206       "&hops=" +
    207       escape(query.hops);
    208     if ("headers" in query) {
    209       newURL += "&headers=" + escape(query.headers);
    210     }
    211     response.setStatusLine(null, 307, "redirect");
    212     response.setHeader("Location", newURL);
    213 
    214     return;
    215   }
    216 
    217   // Send response body
    218   if (!isPreflight && request.method != "HEAD") {
    219     response.setHeader("Content-Type", "application/xml", false);
    220     response.write("<res>hello pass</res>\n");
    221   }
    222   if (isPreflight && "preflightBody" in query) {
    223     response.setHeader("Content-Type", "text/plain", false);
    224     response.write(query.preflightBody);
    225   }
    226 }
    227 
    228 function sendHttp500(response, text) {
    229   response.setStatusLine(null, 500, text);
    230 }