LCOV - code coverage report
Current view: top level - dom/cache - PrincipalVerifier.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 90 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/cache/PrincipalVerifier.h"
       8             : 
       9             : #include "mozilla/dom/ContentParent.h"
      10             : #include "mozilla/dom/cache/ManagerId.h"
      11             : #include "mozilla/ipc/BackgroundParent.h"
      12             : #include "mozilla/ipc/PBackgroundParent.h"
      13             : #include "mozilla/ipc/BackgroundUtils.h"
      14             : #include "nsContentUtils.h"
      15             : #include "nsIPrincipal.h"
      16             : #include "nsIScriptSecurityManager.h"
      17             : #include "nsNetUtil.h"
      18             : 
      19             : namespace mozilla {
      20             : namespace dom {
      21             : namespace cache {
      22             : 
      23             : using mozilla::ipc::AssertIsOnBackgroundThread;
      24             : using mozilla::ipc::BackgroundParent;
      25             : using mozilla::ipc::PBackgroundParent;
      26             : using mozilla::ipc::PrincipalInfo;
      27             : using mozilla::ipc::PrincipalInfoToPrincipal;
      28             : 
      29             : // static
      30             : already_AddRefed<PrincipalVerifier>
      31           0 : PrincipalVerifier::CreateAndDispatch(Listener* aListener,
      32             :                                      PBackgroundParent* aActor,
      33             :                                      const PrincipalInfo& aPrincipalInfo)
      34             : {
      35             :   // We must get the ContentParent actor from the PBackgroundParent.  This
      36             :   // only works on the PBackground thread.
      37           0 :   AssertIsOnBackgroundThread();
      38             : 
      39             :   RefPtr<PrincipalVerifier> verifier = new PrincipalVerifier(aListener,
      40             :                                                                aActor,
      41           0 :                                                                aPrincipalInfo);
      42             : 
      43           0 :   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(verifier));
      44             : 
      45           0 :   return verifier.forget();
      46             : }
      47             : 
      48             : void
      49           0 : PrincipalVerifier::AddListener(Listener* aListener)
      50             : {
      51           0 :   AssertIsOnBackgroundThread();
      52           0 :   MOZ_DIAGNOSTIC_ASSERT(aListener);
      53           0 :   MOZ_ASSERT(!mListenerList.Contains(aListener));
      54           0 :   mListenerList.AppendElement(aListener);
      55           0 : }
      56             : 
      57             : void
      58           0 : PrincipalVerifier::RemoveListener(Listener* aListener)
      59             : {
      60           0 :   AssertIsOnBackgroundThread();
      61           0 :   MOZ_DIAGNOSTIC_ASSERT(aListener);
      62           0 :   MOZ_ALWAYS_TRUE(mListenerList.RemoveElement(aListener));
      63           0 : }
      64             : 
      65           0 : PrincipalVerifier::PrincipalVerifier(Listener* aListener,
      66             :                                      PBackgroundParent* aActor,
      67           0 :                                      const PrincipalInfo& aPrincipalInfo)
      68             :   : Runnable("dom::cache::PrincipalVerifier")
      69           0 :   , mActor(BackgroundParent::GetContentParent(aActor))
      70             :   , mPrincipalInfo(aPrincipalInfo)
      71           0 :   , mInitiatingEventTarget(GetCurrentThreadSerialEventTarget())
      72           0 :   , mResult(NS_OK)
      73             : {
      74           0 :   AssertIsOnBackgroundThread();
      75           0 :   MOZ_DIAGNOSTIC_ASSERT(mInitiatingEventTarget);
      76           0 :   MOZ_DIAGNOSTIC_ASSERT(aListener);
      77             : 
      78           0 :   mListenerList.AppendElement(aListener);
      79           0 : }
      80             : 
      81           0 : PrincipalVerifier::~PrincipalVerifier()
      82             : {
      83             :   // Since the PrincipalVerifier is a Runnable that executes on multiple
      84             :   // threads, its a race to see which thread de-refs us last.  Therefore
      85             :   // we cannot guarantee which thread we destruct on.
      86             : 
      87           0 :   MOZ_DIAGNOSTIC_ASSERT(mListenerList.IsEmpty());
      88             : 
      89             :   // We should always be able to explicitly release the actor on the main
      90             :   // thread.
      91           0 :   MOZ_DIAGNOSTIC_ASSERT(!mActor);
      92           0 : }
      93             : 
      94             : NS_IMETHODIMP
      95           0 : PrincipalVerifier::Run()
      96             : {
      97             :   // Executed twice.  First, on the main thread and then back on the
      98             :   // originating thread.
      99             : 
     100           0 :   if (NS_IsMainThread()) {
     101           0 :     VerifyOnMainThread();
     102           0 :     return NS_OK;
     103             :   }
     104             : 
     105           0 :   CompleteOnInitiatingThread();
     106           0 :   return NS_OK;
     107             : }
     108             : 
     109             : void
     110           0 : PrincipalVerifier::VerifyOnMainThread()
     111             : {
     112           0 :   MOZ_ASSERT(NS_IsMainThread());
     113             : 
     114             :   // No matter what happens, we need to release the actor before leaving
     115             :   // this method.
     116           0 :   RefPtr<ContentParent> actor;
     117           0 :   actor.swap(mActor);
     118             : 
     119             :   nsresult rv;
     120           0 :   RefPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(mPrincipalInfo,
     121           0 :                                                               &rv);
     122           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     123           0 :     DispatchToInitiatingThread(rv);
     124           0 :     return;
     125             :   }
     126             : 
     127             :   // We disallow null principal on the client side, but double-check here.
     128           0 :   if (NS_WARN_IF(principal->GetIsNullPrincipal())) {
     129           0 :     DispatchToInitiatingThread(NS_ERROR_FAILURE);
     130           0 :     return;
     131             :   }
     132             : 
     133           0 :   nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
     134           0 :   if (NS_WARN_IF(!ssm)) {
     135           0 :     DispatchToInitiatingThread(NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
     136           0 :     return;
     137             :   }
     138             : 
     139             :   // Verify if a child process uses system principal, which is not allowed
     140             :   // to prevent system principal is spoofed.
     141           0 :   if (NS_WARN_IF(actor && ssm->IsSystemPrincipal(principal))) {
     142           0 :     DispatchToInitiatingThread(NS_ERROR_FAILURE);
     143           0 :     return;
     144             :   }
     145             : 
     146           0 :   actor = nullptr;
     147             : 
     148             : #ifdef DEBUG
     149             :   // Sanity check principal origin by using it to construct a URI and security
     150             :   // checking it.  Don't do this for the system principal, though, as its origin
     151             :   // is a synthetic [System Principal] string.
     152           0 :   if (!ssm->IsSystemPrincipal(principal)) {
     153           0 :     nsAutoCString origin;
     154           0 :     rv = principal->GetOriginNoSuffix(origin);
     155           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     156           0 :       DispatchToInitiatingThread(rv);
     157           0 :       return;
     158             :     }
     159           0 :     nsCOMPtr<nsIURI> uri;
     160           0 :     rv = NS_NewURI(getter_AddRefs(uri), origin);
     161           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     162           0 :       DispatchToInitiatingThread(rv);
     163           0 :       return;
     164             :     }
     165           0 :     rv = principal->CheckMayLoad(uri, false, false);
     166           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     167           0 :       DispatchToInitiatingThread(rv);
     168           0 :       return;
     169             :     }
     170             :   }
     171             : #endif
     172             : 
     173           0 :   rv = ManagerId::Create(principal, getter_AddRefs(mManagerId));
     174           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     175           0 :     DispatchToInitiatingThread(rv);
     176           0 :     return;
     177             :   }
     178             : 
     179           0 :   DispatchToInitiatingThread(NS_OK);
     180             : }
     181             : 
     182             : void
     183           0 : PrincipalVerifier::CompleteOnInitiatingThread()
     184             : {
     185           0 :   AssertIsOnBackgroundThread();
     186           0 :   ListenerList::ForwardIterator iter(mListenerList);
     187           0 :   while (iter.HasMore()) {
     188           0 :     iter.GetNext()->OnPrincipalVerified(mResult, mManagerId);
     189             :   }
     190             : 
     191             :   // The listener must clear its reference in OnPrincipalVerified()
     192           0 :   MOZ_DIAGNOSTIC_ASSERT(mListenerList.IsEmpty());
     193           0 : }
     194             : 
     195             : void
     196           0 : PrincipalVerifier::DispatchToInitiatingThread(nsresult aRv)
     197             : {
     198           0 :   MOZ_ASSERT(NS_IsMainThread());
     199             : 
     200           0 :   mResult = aRv;
     201             : 
     202             :   // The Cache ShutdownObserver does not track all principal verifiers, so we
     203             :   // cannot ensure this always succeeds.  Instead, simply warn on failures.
     204             :   // This will result in a new CacheStorage object delaying operations until
     205             :   // shutdown completes and the browser goes away.  This is as graceful as
     206             :   // we can get here.
     207           0 :   nsresult rv = mInitiatingEventTarget->Dispatch(this, nsIThread::DISPATCH_NORMAL);
     208           0 :   if (NS_FAILED(rv)) {
     209           0 :     NS_WARNING("Cache unable to complete principal verification due to shutdown.");
     210             :   }
     211           0 : }
     212             : 
     213             : } // namespace cache
     214             : } // namespace dom
     215             : } // namespace mozilla

Generated by: LCOV version 1.13