tor-browser

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

nsJSConfigTriggers.cpp (5362B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "nsJSConfigTriggers.h"
      7 
      8 #include "jsapi.h"
      9 #include "nsIXPConnect.h"
     10 #include "nsCOMPtr.h"
     11 #include "nsString.h"
     12 #include "nspr.h"
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/NullPrincipal.h"
     15 #include "mozilla/dom/ScriptSettings.h"
     16 #include "mozilla/dom/ChromeUtilsBinding.h"
     17 #include "nsContentUtils.h"
     18 #include "nsJSPrincipals.h"
     19 #include "nsIScriptError.h"
     20 #include "js/PropertyAndElement.h"  // JS_DefineProperty
     21 #include "js/Wrapper.h"
     22 #include "mozilla/Utf8.h"
     23 
     24 extern mozilla::LazyLogModule MCD;
     25 using mozilla::AutoSafeJSContext;
     26 using mozilla::IsUtf8;
     27 using mozilla::NullPrincipal;
     28 using mozilla::dom::AutoJSAPI;
     29 
     30 //*****************************************************************************
     31 
     32 MOZ_RUNINIT static JS::PersistentRooted<JSObject*> autoconfigSystemSb;
     33 MOZ_RUNINIT static JS::PersistentRooted<JSObject*> autoconfigSb;
     34 bool sandboxEnabled;
     35 
     36 nsresult CentralizedAdminPrefManagerInit(bool aSandboxEnabled) {
     37  // If the sandbox is already created, no need to create it again.
     38  if (autoconfigSb.initialized()) return NS_OK;
     39 
     40  sandboxEnabled = aSandboxEnabled;
     41 
     42  // Grab XPConnect.
     43  nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
     44 
     45  // Grab the system principal.
     46  nsCOMPtr<nsIPrincipal> principal;
     47  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(
     48      getter_AddRefs(principal));
     49 
     50  // Create a sandbox.
     51  AutoSafeJSContext cx;
     52  JS::Rooted<JSObject*> sandbox(cx);
     53  nsresult rv = xpc->CreateSandbox(cx, principal, sandbox.address());
     54  NS_ENSURE_SUCCESS(rv, rv);
     55 
     56  // Unwrap, store and root the sandbox.
     57  NS_ENSURE_STATE(sandbox);
     58  autoconfigSystemSb.init(cx, js::UncheckedUnwrap(sandbox));
     59 
     60  // Create an unprivileged sandbox.
     61  principal = NullPrincipal::CreateWithoutOriginAttributes();
     62  rv = xpc->CreateSandbox(cx, principal, sandbox.address());
     63  NS_ENSURE_SUCCESS(rv, rv);
     64 
     65  autoconfigSb.init(cx, js::UncheckedUnwrap(sandbox));
     66 
     67  // Define gSandbox on system sandbox.
     68  JSAutoRealm ar(cx, autoconfigSystemSb);
     69 
     70  JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*sandbox));
     71 
     72  if (!JS_WrapValue(cx, &value) ||
     73      !JS_DefineProperty(cx, autoconfigSystemSb, "gSandbox", value,
     74                         JSPROP_ENUMERATE)) {
     75    return NS_ERROR_FAILURE;
     76  }
     77 
     78  // Define ChromeUtils for ChromeUtils.import.
     79  if (!mozilla::dom::ChromeUtils_Binding::CreateAndDefineOnGlobal(cx)) {
     80    return NS_ERROR_FAILURE;
     81  }
     82 
     83  return NS_OK;
     84 }
     85 
     86 nsresult CentralizedAdminPrefManagerFinish() {
     87  if (autoconfigSb.initialized()) {
     88    AutoSafeJSContext cx;
     89    autoconfigSb.reset();
     90    autoconfigSystemSb.reset();
     91    JS_MaybeGC(cx);
     92  }
     93  return NS_OK;
     94 }
     95 
     96 nsresult EvaluateAdminConfigScript(const char* js_buffer, size_t length,
     97                                   const char* filename, bool globalContext,
     98                                   bool callbacks, bool skipFirstLine,
     99                                   bool isPrivileged) {
    100  if (!sandboxEnabled) {
    101    isPrivileged = true;
    102  }
    103  return EvaluateAdminConfigScript(
    104      isPrivileged ? autoconfigSystemSb : autoconfigSb, js_buffer, length,
    105      filename, globalContext, callbacks, skipFirstLine);
    106 }
    107 
    108 nsresult EvaluateAdminConfigScript(JS::Handle<JSObject*> sandbox,
    109                                   const char* js_buffer, size_t length,
    110                                   const char* filename, bool globalContext,
    111                                   bool callbacks, bool skipFirstLine) {
    112  if (skipFirstLine) {
    113    /* In order to protect the privacy of the JavaScript preferences file
    114     * from loading by the browser, we make the first line unparseable
    115     * by JavaScript. We must skip that line here before executing
    116     * the JavaScript code.
    117     */
    118    unsigned int i = 0;
    119    while (i < length) {
    120      char c = js_buffer[i++];
    121      if (c == '\r') {
    122        if (js_buffer[i] == '\n') i++;
    123        break;
    124      }
    125      if (c == '\n') break;
    126    }
    127 
    128    length -= i;
    129    js_buffer += i;
    130  }
    131 
    132  // Grab XPConnect.
    133  nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
    134 
    135  AutoJSAPI jsapi;
    136  if (!jsapi.Init(sandbox)) {
    137    return NS_ERROR_UNEXPECTED;
    138  }
    139  JSContext* cx = jsapi.cx();
    140 
    141  nsAutoCString script(js_buffer, length);
    142  JS::Rooted<JS::Value> v(cx);
    143 
    144  nsString convertedScript;
    145  bool isUTF8 = IsUtf8(script);
    146  if (isUTF8) {
    147    CopyUTF8toUTF16(script, convertedScript);
    148  } else {
    149    nsContentUtils::ReportToConsoleNonLocalized(
    150        nsLiteralString(
    151            u"Your AutoConfig file is ASCII. Please convert it to UTF-8."),
    152        nsIScriptError::warningFlag, "autoconfig"_ns, nullptr);
    153    /* If the length is 0, the conversion failed. Fallback to ASCII */
    154    convertedScript = NS_ConvertASCIItoUTF16(script);
    155  }
    156  {
    157    JSAutoRealm ar(cx, autoconfigSystemSb);
    158    JS::Rooted<JS::Value> value(cx, JS::BooleanValue(isUTF8));
    159    if (!JS_DefineProperty(cx, autoconfigSystemSb, "gIsUTF8", value,
    160                           JSPROP_ENUMERATE)) {
    161      return NS_ERROR_UNEXPECTED;
    162    }
    163  }
    164  nsresult rv =
    165      xpc->EvalInSandboxObject(convertedScript, filename, cx, sandbox, &v);
    166  NS_ENSURE_SUCCESS(rv, rv);
    167 
    168  return NS_OK;
    169 }