tor-browser

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

nsSecureBrowserUI.cpp (6359B)


      1 /* -*- Mode: C++; tab-width: 2; 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 "nsSecureBrowserUI.h"
      7 
      8 #include "mozilla/Assertions.h"
      9 #include "mozilla/Logging.h"
     10 #include "mozilla/dom/Document.h"
     11 #include "mozilla/dom/nsMixedContentBlocker.h"
     12 #include "nsContentUtils.h"
     13 #include "nsIChannel.h"
     14 #include "nsDocShell.h"
     15 #include "nsIDocShellTreeItem.h"
     16 #include "nsIInterfaceRequestorUtils.h"
     17 #include "nsITransportSecurityInfo.h"
     18 #include "nsIWebProgress.h"
     19 #include "nsNetUtil.h"
     20 #include "mozilla/dom/CanonicalBrowsingContext.h"
     21 #include "mozilla/dom/WindowGlobalParent.h"
     22 #include "mozilla/dom/Element.h"
     23 #include "nsIBrowser.h"
     24 
     25 using namespace mozilla;
     26 using namespace mozilla::dom;
     27 
     28 LazyLogModule gSecureBrowserUILog("nsSecureBrowserUI");
     29 
     30 nsSecureBrowserUI::nsSecureBrowserUI(CanonicalBrowsingContext* aBrowsingContext)
     31    : mState(0) {
     32  MOZ_ASSERT(NS_IsMainThread());
     33 
     34  // The BrowsingContext will own the SecureBrowserUI object, we keep a weak
     35  // ref.
     36  mBrowsingContextId = aBrowsingContext->Id();
     37 }
     38 
     39 NS_IMPL_ISUPPORTS(nsSecureBrowserUI, nsISecureBrowserUI,
     40                  nsISupportsWeakReference)
     41 
     42 NS_IMETHODIMP
     43 nsSecureBrowserUI::GetState(uint32_t* aState) {
     44  MOZ_ASSERT(NS_IsMainThread());
     45  NS_ENSURE_ARG(aState);
     46 
     47  MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
     48          ("GetState %p mState: %x", this, mState));
     49  *aState = mState;
     50  return NS_OK;
     51 }
     52 
     53 void nsSecureBrowserUI::RecomputeSecurityFlags() {
     54  // Our BrowsingContext either has a new WindowGlobalParent, or the
     55  // existing one has mutated its security state.
     56  // Recompute our security state and fire notifications to listeners
     57 
     58  RefPtr<WindowGlobalParent> win = GetCurrentWindow();
     59  mState = nsIWebProgressListener::STATE_IS_INSECURE;
     60 
     61  // Only https is considered secure (it is possible to have e.g. an http URI
     62  // with a channel that has a securityInfo that indicates the connection is
     63  // secure - e.g. h2/alt-svc or by visiting an http URI over an https proxy).
     64  nsCOMPtr<nsITransportSecurityInfo> securityInfo;
     65  if (win && win->GetIsSecure()) {
     66    securityInfo = win->GetSecurityInfo();
     67    if (securityInfo) {
     68      MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
     69              ("  we have a security info %p", securityInfo.get()));
     70 
     71      nsresult rv = securityInfo->GetSecurityState(&mState);
     72 
     73      // If the security state is STATE_IS_INSECURE, the TLS handshake never
     74      // completed. Don't set any further state.
     75      if (NS_SUCCEEDED(rv) &&
     76          mState != nsIWebProgressListener::STATE_IS_INSECURE) {
     77        MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug,
     78                ("  set mTopLevelSecurityInfo"));
     79        bool isEV;
     80        rv = securityInfo->GetIsExtendedValidation(&isEV);
     81        if (NS_SUCCEEDED(rv) && isEV) {
     82          MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("  is EV"));
     83          mState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
     84        }
     85      }
     86    }
     87 
     88    // any protocol routed over tor is secure
     89    if (!(mState & nsIWebProgressListener::STATE_IS_SECURE)) {
     90      nsCOMPtr<nsIURI> innerDocURI = NS_GetInnermostURI(win->GetDocumentURI());
     91      if (innerDocURI &&
     92          nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innerDocURI)) {
     93        MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("  is onion"));
     94        mState = (mState & ~nsIWebProgressListener::STATE_IS_INSECURE) |
     95                 nsIWebProgressListener::STATE_IS_SECURE;
     96      }
     97    }
     98  }
     99 
    100  // Add upgraded-state flags when request has been
    101  // upgraded with HTTPS-Only Mode
    102  if (win) {
    103    // Check if top-level load has been upgraded
    104    uint32_t httpsOnlyStatus = win->HttpsOnlyStatus();
    105    if (!(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UNINITIALIZED) &&
    106        !(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_EXEMPT)) {
    107      mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED;
    108    }
    109    if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST) {
    110      if (win->GetDocumentURI()->SchemeIs("https")) {
    111        mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADED_FIRST;
    112      } else {
    113        mState |= nsIWebProgressListener::STATE_HTTPS_ONLY_MODE_UPGRADE_FAILED;
    114      }
    115    }
    116    // Add the secruity flags from the window
    117    mState |= win->GetSecurityFlags();
    118  }
    119 
    120  // If we have loaded mixed content and this is a secure page,
    121  // then clear secure flags and add broken instead.
    122  static const uint32_t kLoadedMixedContentFlags =
    123      nsIWebProgressListener::STATE_LOADED_MIXED_DISPLAY_CONTENT |
    124      nsIWebProgressListener::STATE_LOADED_MIXED_ACTIVE_CONTENT;
    125  if (win && win->GetIsSecure() && (mState & kLoadedMixedContentFlags)) {
    126    // reset state security flag
    127    mState = mState >> 4 << 4;
    128    // set state security flag to broken, since there is mixed content
    129    mState |= nsIWebProgressListener::STATE_IS_BROKEN;
    130  }
    131 
    132  RefPtr<CanonicalBrowsingContext> ctx =
    133      CanonicalBrowsingContext::Get(mBrowsingContextId);
    134  if (!ctx) {
    135    return;
    136  }
    137 
    138  if (ctx->GetDocShell()) {
    139    nsDocShell* nativeDocShell = nsDocShell::Cast(ctx->GetDocShell());
    140    nativeDocShell->nsDocLoader::OnSecurityChange(nullptr, mState);
    141  } else if (ctx->GetWebProgress()) {
    142    ctx->GetWebProgress()->OnSecurityChange(ctx->GetWebProgress(), nullptr,
    143                                            mState);
    144  }
    145 }
    146 
    147 NS_IMETHODIMP
    148 nsSecureBrowserUI::GetIsSecureContext(bool* aIsSecureContext) {
    149  MOZ_ASSERT(NS_IsMainThread());
    150  NS_ENSURE_ARG(aIsSecureContext);
    151 
    152  if (WindowGlobalParent* parent = GetCurrentWindow()) {
    153    *aIsSecureContext = parent->GetIsSecureContext();
    154  } else {
    155    *aIsSecureContext = false;
    156  }
    157  return NS_OK;
    158 }
    159 
    160 NS_IMETHODIMP
    161 nsSecureBrowserUI::GetSecInfo(nsITransportSecurityInfo** result) {
    162  MOZ_ASSERT(NS_IsMainThread());
    163  NS_ENSURE_ARG_POINTER(result);
    164 
    165  if (WindowGlobalParent* parent = GetCurrentWindow()) {
    166    *result = parent->GetSecurityInfo();
    167  }
    168  NS_IF_ADDREF(*result);
    169 
    170  return NS_OK;
    171 }
    172 
    173 WindowGlobalParent* nsSecureBrowserUI::GetCurrentWindow() {
    174  RefPtr<CanonicalBrowsingContext> ctx =
    175      CanonicalBrowsingContext::Get(mBrowsingContextId);
    176  if (!ctx) {
    177    return nullptr;
    178  }
    179  return ctx->GetCurrentWindowGlobal();
    180 }