LCOV - code coverage report
Current view: top level - dom/security - nsContentSecurityManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 184 320 57.5 %
Date: 2017-07-14 16:53:18 Functions: 12 17 70.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "nsContentSecurityManager.h"
       2             : #include "nsIChannel.h"
       3             : #include "nsIHttpChannelInternal.h"
       4             : #include "nsIStreamListener.h"
       5             : #include "nsILoadInfo.h"
       6             : #include "nsContentUtils.h"
       7             : #include "nsCORSListenerProxy.h"
       8             : #include "nsIStreamListener.h"
       9             : #include "nsIDocument.h"
      10             : #include "nsMixedContentBlocker.h"
      11             : #include "nsCDefaultURIFixup.h"
      12             : #include "nsIURIFixup.h"
      13             : #include "nsIImageLoadingContent.h"
      14             : 
      15             : #include "mozilla/dom/Element.h"
      16             : 
      17          33 : NS_IMPL_ISUPPORTS(nsContentSecurityManager,
      18             :                   nsIContentSecurityManager,
      19             :                   nsIChannelEventSink)
      20             : 
      21             : static nsresult
      22         187 : ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
      23             : {
      24         187 :   nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
      25             : 
      26         187 :   if (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS &&
      27         185 :       securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED &&
      28          83 :       securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS &&
      29           1 :       securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
      30             :       securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
      31           0 :     MOZ_ASSERT(false, "need one securityflag from nsILoadInfo to perform security checks");
      32             :     return NS_ERROR_FAILURE;
      33             :   }
      34             : 
      35             :   // all good, found the right security flags
      36         187 :   return NS_OK;
      37             : }
      38             : 
      39           0 : static bool SchemeIs(nsIURI* aURI, const char* aScheme)
      40             : {
      41           0 :   nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
      42           0 :   NS_ENSURE_TRUE(baseURI, false);
      43             : 
      44           0 :   bool isScheme = false;
      45           0 :   return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
      46             : }
      47             : 
      48             : 
      49          52 : static bool IsImageLoadInEditorAppType(nsILoadInfo* aLoadInfo)
      50             : {
      51             :   // Editor apps get special treatment here, editors can load images
      52             :   // from anywhere.  This allows editor to insert images from file://
      53             :   // into documents that are being edited.
      54          52 :   nsContentPolicyType type = aLoadInfo->InternalContentPolicyType();
      55          52 :   if (type != nsIContentPolicy::TYPE_INTERNAL_IMAGE  &&
      56          14 :       type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD &&
      57          12 :       type != nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON &&
      58             :       type != nsIContentPolicy::TYPE_IMAGESET) {
      59          12 :     return false;
      60             :   }
      61             : 
      62          40 :   uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
      63          40 :   nsINode* node = aLoadInfo->LoadingNode();
      64          40 :   if (!node) {
      65           1 :     return false;
      66             :   }
      67          39 :   nsIDocument* doc = node->OwnerDoc();
      68          39 :   if (!doc) {
      69           0 :     return false;
      70             :   }
      71             : 
      72          78 :   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
      73          39 :   if (!docShellTreeItem) {
      74           0 :     return false;
      75             :   }
      76             : 
      77          78 :   nsCOMPtr<nsIDocShellTreeItem> root;
      78          39 :   docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
      79          78 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
      80          39 :   if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
      81           0 :     appType = nsIDocShell::APP_TYPE_UNKNOWN;
      82             :   }
      83             : 
      84          39 :   return appType == nsIDocShell::APP_TYPE_EDITOR;
      85             : }
      86             : 
      87             : static nsresult
      88          52 : DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
      89             : {
      90             :   // Bug 1228117: determine the correct security policy for DTD loads
      91          52 :   if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DTD) {
      92           0 :     return NS_OK;
      93             :   }
      94             : 
      95          52 :   if (IsImageLoadInEditorAppType(aLoadInfo)) {
      96           0 :     return NS_OK;
      97             :   }
      98             : 
      99          52 :   uint32_t flags = nsIScriptSecurityManager::STANDARD;
     100          52 :   if (aLoadInfo->GetAllowChrome()) {
     101          46 :     flags |= nsIScriptSecurityManager::ALLOW_CHROME;
     102             :   }
     103          52 :   if (aLoadInfo->GetDisallowScript()) {
     104           1 :     flags |= nsIScriptSecurityManager::DISALLOW_SCRIPT;
     105             :   }
     106             : 
     107             :   // Only call CheckLoadURIWithPrincipal() using the TriggeringPrincipal and not
     108             :   // the LoadingPrincipal when SEC_ALLOW_CROSS_ORIGIN_* security flags are set,
     109             :   // to allow, e.g. user stylesheets to load chrome:// URIs.
     110          52 :   return nsContentUtils::GetSecurityManager()->
     111          52 :            CheckLoadURIWithPrincipal(aLoadInfo->TriggeringPrincipal(),
     112             :                                      aURI,
     113         104 :                                      flags);
     114             : }
     115             : 
     116             : static bool
     117           0 : URIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
     118             : {
     119             :   bool hasFlags;
     120           0 :   nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
     121           0 :   NS_ENSURE_SUCCESS(rv, false);
     122             : 
     123           0 :   return hasFlags;
     124             : }
     125             : 
     126             : static nsresult
     127           0 : DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel* aChannel)
     128             : {
     129           0 :   if (aLoadInfo->GetAllowChrome() &&
     130           0 :       (URIHasFlags(aURI, nsIProtocolHandler::URI_IS_UI_RESOURCE) ||
     131           0 :        SchemeIs(aURI, "moz-safe-about"))) {
     132             :     // UI resources are allowed.
     133           0 :     return DoCheckLoadURIChecks(aURI, aLoadInfo);
     134             :   }
     135             : 
     136           0 :   NS_ENSURE_FALSE(NS_HasBeenCrossOrigin(aChannel, true),
     137             :                   NS_ERROR_DOM_BAD_URI);
     138             : 
     139           0 :   return NS_OK;
     140             : }
     141             : 
     142             : static nsresult
     143           1 : DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
     144             :              nsCOMPtr<nsIStreamListener>& aInAndOutListener)
     145             : {
     146           1 :   MOZ_RELEASE_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
     147             : 
     148             :   // No need to set up CORS if TriggeringPrincipal is the SystemPrincipal.
     149             :   // For example, allow user stylesheets to load XBL from external files
     150             :   // without requiring CORS.
     151           1 :   if (nsContentUtils::IsSystemPrincipal(aLoadInfo->TriggeringPrincipal())) {
     152           1 :     return NS_OK;
     153             :   }
     154             : 
     155           0 :   nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
     156             :   RefPtr<nsCORSListenerProxy> corsListener =
     157             :     new nsCORSListenerProxy(aInAndOutListener,
     158             :                             loadingPrincipal,
     159           0 :                             aLoadInfo->GetCookiePolicy() ==
     160           0 :                               nsILoadInfo::SEC_COOKIES_INCLUDE);
     161             :   // XXX: @arg: DataURIHandling::Allow
     162             :   // lets use  DataURIHandling::Allow for now and then decide on callsite basis. see also:
     163             :   // http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33
     164           0 :   nsresult rv = corsListener->Init(aChannel, DataURIHandling::Allow);
     165           0 :   NS_ENSURE_SUCCESS(rv, rv);
     166           0 :   aInAndOutListener = corsListener;
     167           0 :   return NS_OK;
     168             : }
     169             : 
     170             : static nsresult
     171         187 : DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
     172             : {
     173             :   nsContentPolicyType contentPolicyType =
     174         187 :     aLoadInfo->GetExternalContentPolicyType();
     175             :   nsContentPolicyType internalContentPolicyType =
     176         187 :     aLoadInfo->InternalContentPolicyType();
     177         374 :   nsCString mimeTypeGuess;
     178         374 :   nsCOMPtr<nsINode> requestingContext = nullptr;
     179             : 
     180         374 :   nsCOMPtr<nsIURI> uri;
     181         187 :   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
     182         187 :   NS_ENSURE_SUCCESS(rv, rv);
     183             : 
     184         187 :   if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
     185             :       contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
     186             :     // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
     187             :     // be wyciwyg:// channels. Let's fix up the URI so we can
     188             :     // perform proper security checks.
     189          12 :     nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
     190           6 :     if (NS_SUCCEEDED(rv) && urifixup) {
     191          12 :       nsCOMPtr<nsIURI> fixedURI;
     192           6 :       rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
     193           6 :       if (NS_SUCCEEDED(rv)) {
     194           6 :         uri = fixedURI;
     195             :       }
     196             :     }
     197             :   }
     198             : 
     199         187 :   switch(contentPolicyType) {
     200             :     case nsIContentPolicy::TYPE_OTHER: {
     201          70 :       mimeTypeGuess = EmptyCString();
     202          70 :       requestingContext = aLoadInfo->LoadingNode();
     203          70 :       break;
     204             :     }
     205             : 
     206             :     case nsIContentPolicy::TYPE_SCRIPT: {
     207          12 :       mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript");
     208          12 :       requestingContext = aLoadInfo->LoadingNode();
     209          12 :       break;
     210             :     }
     211             : 
     212             :     case nsIContentPolicy::TYPE_IMAGE: {
     213          42 :       mimeTypeGuess = EmptyCString();
     214          42 :       requestingContext = aLoadInfo->LoadingNode();
     215          42 :       break;
     216             :     }
     217             : 
     218             :     case nsIContentPolicy::TYPE_STYLESHEET: {
     219          53 :       mimeTypeGuess = NS_LITERAL_CSTRING("text/css");
     220          53 :       requestingContext = aLoadInfo->LoadingNode();
     221          53 :       break;
     222             :     }
     223             : 
     224             :     case nsIContentPolicy::TYPE_OBJECT: {
     225           0 :       mimeTypeGuess = EmptyCString();
     226           0 :       requestingContext = aLoadInfo->LoadingNode();
     227           0 :       break;
     228             :     }
     229             : 
     230             :     case nsIContentPolicy::TYPE_DOCUMENT: {
     231           5 :       mimeTypeGuess = EmptyCString();
     232           5 :       requestingContext = aLoadInfo->LoadingNode();
     233           5 :       break;
     234             :     }
     235             : 
     236             :     case nsIContentPolicy::TYPE_SUBDOCUMENT: {
     237           1 :       mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
     238           1 :       requestingContext = aLoadInfo->LoadingNode();
     239           1 :       break;
     240             :     }
     241             : 
     242             :     case nsIContentPolicy::TYPE_REFRESH: {
     243           0 :       MOZ_ASSERT(false, "contentPolicyType not supported yet");
     244             :       break;
     245             :     }
     246             : 
     247             :     case nsIContentPolicy::TYPE_XBL: {
     248           1 :       mimeTypeGuess = EmptyCString();
     249           1 :       requestingContext = aLoadInfo->LoadingNode();
     250           1 :       break;
     251             :     }
     252             : 
     253             :     case nsIContentPolicy::TYPE_PING: {
     254           0 :       mimeTypeGuess = EmptyCString();
     255           0 :       requestingContext = aLoadInfo->LoadingNode();
     256           0 :       break;
     257             :     }
     258             : 
     259             :     case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
     260             :       // alias nsIContentPolicy::TYPE_DATAREQUEST:
     261           2 :       requestingContext = aLoadInfo->LoadingNode();
     262           2 :       MOZ_ASSERT(!requestingContext ||
     263             :                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
     264             :                  "type_xml requires requestingContext of type Document");
     265             : 
     266             :       // We're checking for the external TYPE_XMLHTTPREQUEST here in case
     267             :       // an addon creates a request with that type.
     268           2 :       if (internalContentPolicyType ==
     269           0 :             nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST ||
     270             :           internalContentPolicyType ==
     271             :             nsIContentPolicy::TYPE_XMLHTTPREQUEST) {
     272           2 :         mimeTypeGuess = EmptyCString();
     273             :       }
     274             :       else {
     275           0 :         MOZ_ASSERT(internalContentPolicyType ==
     276             :                    nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
     277             :                    "can not set mime type guess for unexpected internal type");
     278           0 :         mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM);
     279             :       }
     280           2 :       break;
     281             :     }
     282             : 
     283             :     case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
     284           0 :       mimeTypeGuess = EmptyCString();
     285           0 :       requestingContext = aLoadInfo->LoadingNode();
     286           0 :       MOZ_ASSERT(!requestingContext ||
     287             :                  requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
     288             :                  "type_subrequest requires requestingContext of type Element");
     289           0 :       break;
     290             :     }
     291             : 
     292             :     case nsIContentPolicy::TYPE_DTD: {
     293           0 :       mimeTypeGuess = EmptyCString();
     294           0 :       requestingContext = aLoadInfo->LoadingNode();
     295           0 :       MOZ_ASSERT(!requestingContext ||
     296             :                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
     297             :                  "type_dtd requires requestingContext of type Document");
     298           0 :       break;
     299             :     }
     300             : 
     301             :     case nsIContentPolicy::TYPE_FONT: {
     302           0 :       mimeTypeGuess = EmptyCString();
     303           0 :       requestingContext = aLoadInfo->LoadingNode();
     304           0 :       break;
     305             :     }
     306             : 
     307             :     case nsIContentPolicy::TYPE_MEDIA: {
     308           0 :       if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) {
     309           0 :         mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt");
     310             :       }
     311             :       else {
     312           0 :         mimeTypeGuess = EmptyCString();
     313             :       }
     314           0 :       requestingContext = aLoadInfo->LoadingNode();
     315           0 :       MOZ_ASSERT(!requestingContext ||
     316             :                  requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
     317             :                  "type_media requires requestingContext of type Element");
     318           0 :       break;
     319             :     }
     320             : 
     321             :     case nsIContentPolicy::TYPE_WEBSOCKET: {
     322             :       // Websockets have to use the proxied URI:
     323             :       // ws:// instead of http:// for CSP checks
     324             :       nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal
     325           0 :         = do_QueryInterface(aChannel);
     326           0 :       MOZ_ASSERT(httpChannelInternal);
     327           0 :       if (httpChannelInternal) {
     328           0 :         rv = httpChannelInternal->GetProxyURI(getter_AddRefs(uri));
     329           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
     330             :       }
     331           0 :       mimeTypeGuess = EmptyCString();
     332           0 :       requestingContext = aLoadInfo->LoadingNode();
     333           0 :       break;
     334             :     }
     335             : 
     336             :     case nsIContentPolicy::TYPE_CSP_REPORT: {
     337           0 :       mimeTypeGuess = EmptyCString();
     338           0 :       requestingContext = aLoadInfo->LoadingNode();
     339           0 :       break;
     340             :     }
     341             : 
     342             :     case nsIContentPolicy::TYPE_XSLT: {
     343           0 :       mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
     344           0 :       requestingContext = aLoadInfo->LoadingNode();
     345           0 :       MOZ_ASSERT(!requestingContext ||
     346             :                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
     347             :                  "type_xslt requires requestingContext of type Document");
     348           0 :       break;
     349             :     }
     350             : 
     351             :     case nsIContentPolicy::TYPE_BEACON: {
     352           0 :       mimeTypeGuess = EmptyCString();
     353           0 :       requestingContext = aLoadInfo->LoadingNode();
     354           0 :       MOZ_ASSERT(!requestingContext ||
     355             :                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
     356             :                  "type_beacon requires requestingContext of type Document");
     357           0 :       break;
     358             :     }
     359             : 
     360             :     case nsIContentPolicy::TYPE_FETCH: {
     361           1 :       mimeTypeGuess = EmptyCString();
     362           1 :       requestingContext = aLoadInfo->LoadingNode();
     363           1 :       break;
     364             :     }
     365             : 
     366             :     case nsIContentPolicy::TYPE_IMAGESET: {
     367           0 :       mimeTypeGuess = EmptyCString();
     368           0 :       requestingContext = aLoadInfo->LoadingNode();
     369           0 :       break;
     370             :     }
     371             : 
     372             :     case nsIContentPolicy::TYPE_WEB_MANIFEST: {
     373           0 :       mimeTypeGuess = NS_LITERAL_CSTRING("application/manifest+json");
     374           0 :       requestingContext = aLoadInfo->LoadingNode();
     375           0 :       break;
     376             :     }
     377             : 
     378             :     default:
     379             :       // nsIContentPolicy::TYPE_INVALID
     380           0 :       MOZ_ASSERT(false, "can not perform security check without a valid contentType");
     381             :   }
     382             : 
     383             :   // For document loads we use the triggeringPrincipal as the originPrincipal.
     384             :   // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
     385             :   nsCOMPtr<nsIPrincipal> principal =
     386         182 :     (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
     387             :      contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
     388           6 :     ? aLoadInfo->TriggeringPrincipal()
     389         380 :     : aLoadInfo->LoadingPrincipal();
     390             : 
     391         187 :   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
     392         374 :   rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
     393             :                                  uri,
     394             :                                  principal,
     395             :                                  requestingContext,
     396             :                                  mimeTypeGuess,
     397             :                                  nullptr,        //extra,
     398             :                                  &shouldLoad,
     399             :                                  nsContentUtils::GetContentPolicy(),
     400         187 :                                  nsContentUtils::GetSecurityManager());
     401             : 
     402         187 :   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     403           0 :     if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
     404           0 :         (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
     405             :          contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
     406             :       // for docshell loads we might have to return SHOW_ALT.
     407           0 :       return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
     408             :     }
     409           0 :     return NS_ERROR_CONTENT_BLOCKED;
     410             :   }
     411             : 
     412         187 :   if (nsMixedContentBlocker::sSendHSTSPriming) {
     413         187 :     rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri,
     414             :                                                        requestingContext,
     415         187 :                                                        aLoadInfo);
     416         187 :     return rv;
     417             :   }
     418             : 
     419           0 :   return NS_OK;
     420             : }
     421             : 
     422             : /*
     423             :  * Based on the security flags provided in the loadInfo of the channel,
     424             :  * doContentSecurityCheck() performs the following content security checks
     425             :  * before opening the channel:
     426             :  *
     427             :  * (1) Same Origin Policy Check (if applicable)
     428             :  * (2) Allow Cross Origin but perform sanity checks whether a principal
     429             :  *     is allowed to access the following URL.
     430             :  * (3) Perform CORS check (if applicable)
     431             :  * (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...)
     432             :  *
     433             :  * @param aChannel
     434             :  *    The channel to perform the security checks on.
     435             :  * @param aInAndOutListener
     436             :  *    The streamListener that is passed to channel->AsyncOpen2() that is now potentially
     437             :  *    wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs
     438             :  *    to be set as new streamListener on the channel.
     439             :  */
     440             : nsresult
     441         190 : nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
     442             :                                                  nsCOMPtr<nsIStreamListener>& aInAndOutListener)
     443             : {
     444         190 :   NS_ENSURE_ARG(aChannel);
     445         380 :   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
     446             : 
     447         190 :   if (!loadInfo) {
     448           0 :     MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks");
     449             :     return NS_ERROR_UNEXPECTED;
     450             :   }
     451             : 
     452             :   // if dealing with a redirected channel then we have already installed
     453             :   // streamlistener and redirect proxies and so we are done.
     454         190 :   if (loadInfo->GetInitialSecurityCheckDone()) {
     455           3 :     return NS_OK;
     456             :   }
     457             : 
     458             :   // make sure that only one of the five security flags is set in the loadinfo
     459             :   // e.g. do not require same origin and allow cross origin at the same time
     460         187 :   nsresult rv = ValidateSecurityFlags(loadInfo);
     461         187 :   NS_ENSURE_SUCCESS(rv, rv);
     462             : 
     463             :   // since aChannel was openend using asyncOpen2() we have to make sure
     464             :   // that redirects of that channel also get openend using asyncOpen2()
     465             :   // please note that some implementations of ::AsyncOpen2 might already
     466             :   // have set that flag to true (e.g. nsViewSourceChannel) in which case
     467             :   // we just set the flag again.
     468         187 :   loadInfo->SetEnforceSecurity(true);
     469             : 
     470         187 :   if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
     471           1 :     rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
     472           1 :     NS_ENSURE_SUCCESS(rv, rv);
     473             :   }
     474             : 
     475         187 :   rv = CheckChannel(aChannel);
     476         187 :   NS_ENSURE_SUCCESS(rv, rv);
     477             : 
     478             :   // Perform all ContentPolicy checks (MixedContent, CSP, ...)
     479         187 :   rv = DoContentSecurityChecks(aChannel, loadInfo);
     480         187 :   NS_ENSURE_SUCCESS(rv, rv);
     481             : 
     482             :   // now lets set the initalSecurityFlag for subsequent calls
     483         187 :   loadInfo->SetInitialSecurityCheckDone(true);
     484             : 
     485             :   // all security checks passed - lets allow the load
     486         187 :   return NS_OK;
     487             : }
     488             : 
     489             : NS_IMETHODIMP
     490           0 : nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
     491             :                                                  nsIChannel* aNewChannel,
     492             :                                                  uint32_t aRedirFlags,
     493             :                                                  nsIAsyncVerifyRedirectCallback *aCb)
     494             : {
     495           0 :   nsCOMPtr<nsILoadInfo> loadInfo = aOldChannel->GetLoadInfo();
     496             :   // Are we enforcing security using LoadInfo?
     497           0 :   if (loadInfo && loadInfo->GetEnforceSecurity()) {
     498           0 :     nsresult rv = CheckChannel(aNewChannel);
     499           0 :     if (NS_FAILED(rv)) {
     500           0 :       aOldChannel->Cancel(rv);
     501           0 :       return rv;
     502             :     }
     503             :   }
     504             : 
     505             :   // Also verify that the redirecting server is allowed to redirect to the
     506             :   // given URI
     507           0 :   nsCOMPtr<nsIPrincipal> oldPrincipal;
     508           0 :   nsContentUtils::GetSecurityManager()->
     509           0 :     GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
     510             : 
     511           0 :   nsCOMPtr<nsIURI> newURI;
     512           0 :   Unused << NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
     513           0 :   NS_ENSURE_STATE(oldPrincipal && newURI);
     514             : 
     515             :   const uint32_t flags =
     516             :       nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
     517           0 :       nsIScriptSecurityManager::DISALLOW_SCRIPT;
     518           0 :   nsresult rv = nsContentUtils::GetSecurityManager()->
     519           0 :     CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
     520           0 :   NS_ENSURE_SUCCESS(rv, rv);
     521             : 
     522           0 :   aCb->OnRedirectVerifyCallback(NS_OK);
     523           0 :   return NS_OK;
     524             : }
     525             : 
     526             : static void
     527           1 : AddLoadFlags(nsIRequest *aRequest, nsLoadFlags aNewFlags)
     528             : {
     529             :   nsLoadFlags flags;
     530           1 :   aRequest->GetLoadFlags(&flags);
     531           1 :   flags |= aNewFlags;
     532           1 :   aRequest->SetLoadFlags(flags);
     533           1 : }
     534             : 
     535             : /*
     536             :  * Check that this channel passes all security checks. Returns an error code
     537             :  * if this requesst should not be permitted.
     538             :  */
     539             : nsresult
     540         187 : nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
     541             : {
     542         374 :   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
     543         187 :   MOZ_ASSERT(loadInfo);
     544             : 
     545         374 :   nsCOMPtr<nsIURI> uri;
     546         187 :   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
     547         187 :   NS_ENSURE_SUCCESS(rv, rv);
     548             : 
     549             :   nsContentPolicyType contentPolicyType =
     550         187 :     loadInfo->GetExternalContentPolicyType();
     551             : 
     552         187 :   if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
     553             :       contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
     554             :     // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
     555             :     // be wyciwyg:// channels. Let's fix up the URI so we can
     556             :     // perform proper security checks.
     557          12 :     nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
     558           6 :     if (NS_SUCCEEDED(rv) && urifixup) {
     559          12 :       nsCOMPtr<nsIURI> fixedURI;
     560           6 :       rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
     561           6 :       if (NS_SUCCEEDED(rv)) {
     562           6 :         uri = fixedURI;
     563             :       }
     564             :     }
     565             :   }
     566             : 
     567             :   // Handle cookie policies
     568         187 :   uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
     569         187 :   if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
     570             : 
     571             :     // We shouldn't have the SEC_COOKIES_SAME_ORIGIN flag for top level loads
     572           0 :     MOZ_ASSERT(loadInfo->GetExternalContentPolicyType() !=
     573             :                nsIContentPolicy::TYPE_DOCUMENT);
     574           0 :     nsIPrincipal* loadingPrincipal = loadInfo->LoadingPrincipal();
     575             : 
     576             :     // It doesn't matter what we pass for the third, data-inherits, argument.
     577             :     // Any protocol which inherits won't pay attention to cookies anyway.
     578           0 :     rv = loadingPrincipal->CheckMayLoad(uri, false, false);
     579           0 :     if (NS_FAILED(rv)) {
     580           0 :       AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
     581             :     }
     582             :   }
     583         187 :   else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
     584           1 :     AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
     585             :   }
     586             : 
     587         187 :   nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
     588             : 
     589             :   // CORS mode is handled by nsCORSListenerProxy
     590         187 :   if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
     591           1 :     if (NS_HasBeenCrossOrigin(aChannel)) {
     592           0 :       loadInfo->MaybeIncreaseTainting(LoadTainting::CORS);
     593             :     }
     594           1 :     return NS_OK;
     595             :   }
     596             : 
     597             :   // Allow subresource loads if TriggeringPrincipal is the SystemPrincipal.
     598             :   // For example, allow user stylesheets to load XBL from external files.
     599         512 :   if (nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) &&
     600         321 :       loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT &&
     601         135 :       loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_SUBDOCUMENT) {
     602         134 :     return NS_OK;
     603             :   }
     604             : 
     605             :   // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
     606          52 :   if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
     607             :       (securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
     608           0 :     rv = DoSOPChecks(uri, loadInfo, aChannel);
     609           0 :     NS_ENSURE_SUCCESS(rv, rv);
     610             :   }
     611             : 
     612          52 :   if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) ||
     613             :       (securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
     614          52 :     if (NS_HasBeenCrossOrigin(aChannel)) {
     615           2 :       loadInfo->MaybeIncreaseTainting(LoadTainting::Opaque);
     616             :     }
     617             :     // Please note that DoCheckLoadURIChecks should only be enforced for
     618             :     // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
     619             :     // within the loadInfo, then then CheckLoadURIWithPrincipal is performed
     620             :     // within nsCorsListenerProxy
     621          52 :     rv = DoCheckLoadURIChecks(uri, loadInfo);
     622          52 :     NS_ENSURE_SUCCESS(rv, rv);
     623             :     // TODO: Bug 1371237
     624             :     // consider calling SetBlockedRequest in nsContentSecurityManager::CheckChannel
     625             :   }
     626             : 
     627          52 :   return NS_OK;
     628             : }
     629             : 
     630             : // ==== nsIContentSecurityManager implementation =====
     631             : 
     632             : NS_IMETHODIMP
     633           0 : nsContentSecurityManager::PerformSecurityCheck(nsIChannel* aChannel,
     634             :                                                nsIStreamListener* aStreamListener,
     635             :                                                nsIStreamListener** outStreamListener)
     636             : {
     637           0 :   nsCOMPtr<nsIStreamListener> inAndOutListener = aStreamListener;
     638           0 :   nsresult rv = doContentSecurityCheck(aChannel, inAndOutListener);
     639           0 :   NS_ENSURE_SUCCESS(rv, rv);
     640             : 
     641           0 :   inAndOutListener.forget(outStreamListener);
     642           0 :   return NS_OK;
     643             : }
     644             : 
     645             : NS_IMETHODIMP
     646           8 : nsContentSecurityManager::IsOriginPotentiallyTrustworthy(nsIPrincipal* aPrincipal,
     647             :                                                          bool* aIsTrustWorthy)
     648             : {
     649           8 :   MOZ_ASSERT(NS_IsMainThread());
     650           8 :   NS_ENSURE_ARG_POINTER(aPrincipal);
     651           8 :   NS_ENSURE_ARG_POINTER(aIsTrustWorthy);
     652             : 
     653           8 :   if (aPrincipal->GetIsSystemPrincipal()) {
     654           0 :     *aIsTrustWorthy = true;
     655           0 :     return NS_OK;
     656             :   }
     657             : 
     658             :   // The following implements:
     659             :   // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
     660             : 
     661           8 :   *aIsTrustWorthy = false;
     662             : 
     663           8 :   if (aPrincipal->GetIsNullPrincipal()) {
     664           4 :     return NS_OK;
     665             :   }
     666             : 
     667           4 :   MOZ_ASSERT(aPrincipal->GetIsCodebasePrincipal(),
     668             :              "Nobody is expected to call us with an nsIExpandedPrincipal");
     669             : 
     670           8 :   nsCOMPtr<nsIURI> uri;
     671           4 :   aPrincipal->GetURI(getter_AddRefs(uri));
     672             : 
     673           8 :   nsAutoCString scheme;
     674           4 :   nsresult rv = uri->GetScheme(scheme);
     675           4 :   if (NS_FAILED(rv)) {
     676           0 :     return NS_OK;
     677             :   }
     678             : 
     679             :   // Blobs are expected to inherit their principal so we don't expect to have
     680             :   // a codebase principal with scheme 'blob' here.  We can't assert that though
     681             :   // since someone could mess with a non-blob URI to give it that scheme.
     682           4 :   NS_WARNING_ASSERTION(!scheme.EqualsLiteral("blob"),
     683             :                        "IsOriginPotentiallyTrustworthy ignoring blob scheme");
     684             : 
     685             :   // According to the specification, the user agent may choose to extend the
     686             :   // trust to other, vendor-specific URL schemes. We use this for "resource:",
     687             :   // which is technically a substituting protocol handler that is not limited to
     688             :   // local resource mapping, but in practice is never mapped remotely as this
     689             :   // would violate assumptions a lot of code makes.
     690          12 :   if (scheme.EqualsLiteral("https") ||
     691           8 :       scheme.EqualsLiteral("file") ||
     692           6 :       scheme.EqualsLiteral("resource") ||
     693           4 :       scheme.EqualsLiteral("app") ||
     694           8 :       scheme.EqualsLiteral("moz-extension") ||
     695           2 :       scheme.EqualsLiteral("wss")) {
     696           2 :     *aIsTrustWorthy = true;
     697           2 :     return NS_OK;
     698             :   }
     699             : 
     700           4 :   nsAutoCString host;
     701           2 :   rv = uri->GetHost(host);
     702           2 :   if (NS_FAILED(rv)) {
     703           0 :     return NS_OK;
     704             :   }
     705             : 
     706           6 :   if (host.Equals("127.0.0.1") ||
     707           2 :       host.Equals("localhost") ||
     708           0 :       host.Equals("::1")) {
     709           2 :     *aIsTrustWorthy = true;
     710           2 :     return NS_OK;
     711             :   }
     712             : 
     713             :   // If a host is not considered secure according to the default algorithm, then
     714             :   // check to see if it has been whitelisted by the user.  We only apply this
     715             :   // whitelist for network resources, i.e., those with scheme "http" or "ws".
     716             :   // The pref should contain a comma-separated list of hostnames.
     717           0 :   if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("ws")) {
     718           0 :     nsAdoptingCString whitelist = Preferences::GetCString("dom.securecontext.whitelist");
     719           0 :     if (whitelist) {
     720           0 :       nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
     721           0 :       while (tokenizer.hasMoreTokens()) {
     722           0 :         const nsACString& allowedHost = tokenizer.nextToken();
     723           0 :         if (host.Equals(allowedHost)) {
     724           0 :           *aIsTrustWorthy = true;
     725           0 :           return NS_OK;
     726             :         }
     727             :       }
     728             :     }
     729             :   }
     730             : 
     731           0 :   return NS_OK;
     732             : }

Generated by: LCOV version 1.13