tor-browser

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

test_bug1984469.js (3106B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /* import-globals-from head_cache.js */
      8 /* import-globals-from head_cookies.js */
      9 /* import-globals-from head_channels.js */
     10 
     11 const { NodeHTTP2Server } = ChromeUtils.importESModule(
     12  "resource://testing-common/NodeServer.sys.mjs"
     13 );
     14 
     15 function makeChan(uri, loadingUrl) {
     16  let principal = Services.scriptSecurityManager.createContentPrincipal(
     17    Services.io.newURI(loadingUrl),
     18    {}
     19  );
     20  return NetUtil.newChannel({
     21    uri,
     22    loadingPrincipal: principal,
     23    securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
     24    contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
     25  });
     26 }
     27 
     28 class AuthPrompt {
     29  constructor() {
     30    this.QueryInterface = ChromeUtils.generateQI(["nsIAuthPrompt2"]);
     31  }
     32  asyncPromptAuth(channel, callback, context, encryptionLevel, authInfo) {
     33    executeSoon(function () {
     34      authInfo.username = "guest";
     35      authInfo.password = "guest";
     36      callback.onAuthAvailable(context, authInfo);
     37    });
     38  }
     39 }
     40 
     41 class AuthRequestor {
     42  constructor(prompt) {
     43    this.prompt = prompt;
     44    this.QueryInterface = ChromeUtils.generateQI(["nsIInterfaceRequestor"]);
     45  }
     46  getInterface(iid) {
     47    if (iid.equals(Ci.nsIAuthPrompt2)) {
     48      return this.prompt();
     49    }
     50    throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
     51  }
     52 }
     53 
     54 /**
     55 * Verify HTTP/2 auth retry behavior: the server issues two 401 challenges
     56 * and only returns 200 OK on the third request.
     57 *
     58 * This test ensures the channel performs two auth retries and succeeds on the
     59 * third attempt.
     60 *
     61 */
     62 add_task(async function test_http2_auth_retry_twice() {
     63  Services.prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
     64 
     65  let server = new NodeHTTP2Server();
     66  await server.start();
     67  registerCleanupFunction(async () => {
     68    await server.stop();
     69  });
     70 
     71  await server.registerPathHandler("/test", (req, res) => {
     72    const hasAuth =
     73      typeof req.headers.authorization === "string" &&
     74      !!req.headers.authorization.length;
     75    global.count ??= 0;
     76    global.count++;
     77    if (!hasAuth || global.count < 3) {
     78      res.stream.respond({
     79        ":status": 401,
     80        "content-type": "text/plain; charset=utf-8",
     81        "www-authenticate": 'Basic realm="secret"',
     82      });
     83      res.end("Unauthorized\n");
     84      return;
     85    }
     86 
     87    res.stream.respond({
     88      ":status": 200,
     89      "content-type": "text/plain; charset=utf-8",
     90    });
     91    res.end("OK\n");
     92  });
     93 
     94  let chan = makeChan(
     95    `https://localhost:${server.port()}/test`,
     96    `https://localhost:${server.port()}`
     97  );
     98  chan.notificationCallbacks = new AuthRequestor(() => new AuthPrompt());
     99 
    100  let req = await new Promise(resolve => {
    101    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    102  });
    103  equal(req.status, Cr.NS_OK);
    104  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    105  equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "h2");
    106 });