tor-browser

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

ChallengeHeaderParser.sys.mjs (2224B)


      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 file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /**
      6 * Parse the parameter in a name/value pair and remove quotes.
      7 *
      8 * @param {string} paramValue
      9 *     A string representing a challenge parameter.
     10 *
     11 * @returns {object}
     12 *     An object with name and value string properties.
     13 */
     14 function parseChallengeParameter(paramValue) {
     15  const [name, value] = paramValue.split("=");
     16  return { name, value: value?.replace(/["']/g, "") };
     17 }
     18 
     19 /**
     20 * Simple parser for authenticate (WWW-Authenticate or Proxy-Authenticate)
     21 * headers.
     22 *
     23 * Bug 1857847: Replace with Necko's ChallengeParser once exposed to JS.
     24 *
     25 * @param {string} headerValue
     26 *     The value of an authenticate header.
     27 *
     28 * @returns {Array<object>}
     29 *     Array of challenge objects containing two properties:
     30 *     - {string} scheme: The scheme for the challenge
     31 *     - {Array<object>} params: Array of { name, value } objects representing
     32 *       all the parameters of the challenge.
     33 */
     34 export function parseChallengeHeader(headerValue) {
     35  const challenges = [];
     36  const parts = headerValue.split(",").map(part => part.trim());
     37 
     38  let scheme = null;
     39  let params = [];
     40 
     41  const schemeRegex = /^(\w+)(?:\s+(.*))?$/;
     42  for (const part of parts) {
     43    const matches = part.match(schemeRegex);
     44    if (matches !== null) {
     45      // This is a new scheme.
     46      if (scheme !== null) {
     47        // If we have a challenge recorded, add it to the array.
     48        challenges.push({ scheme, params });
     49      }
     50 
     51      // Reset the state for a new scheme.
     52      scheme = matches[1];
     53      params = [];
     54      if (matches[2]) {
     55        params.push(parseChallengeParameter(matches[2]));
     56      }
     57    } else {
     58      if (scheme === null) {
     59        // A scheme should always be found before parameters, this header
     60        // probably needs a more careful parsing solution.
     61        return [];
     62      }
     63 
     64      params.push(parseChallengeParameter(part));
     65    }
     66  }
     67 
     68  if (scheme !== null) {
     69    // If we have a challenge recorded, add it to the array.
     70    challenges.push({ scheme, params });
     71  }
     72 
     73  return challenges;
     74 }