From 4e48c76d0f4ddb3a462dab88cd8bb71d90c5ff37 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 24 Sep 2014 13:12:57 +0200 Subject: [PATCH] Backed out changeset c6fe8e2c41db (bug 1041180) --- content/base/src/nsCSPService.cpp | 103 ++++++++++++++++++------------ 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/content/base/src/nsCSPService.cpp b/content/base/src/nsCSPService.cpp index 0683e78db0d0..64e1a8dcd7ed 100644 --- a/content/base/src/nsCSPService.cpp +++ b/content/base/src/nsCSPService.cpp @@ -18,7 +18,6 @@ #include "mozilla/Preferences.h" #include "nsIScriptError.h" #include "nsContentUtils.h" -#include "nsContentPolicyUtils.h" #include "nsPrincipal.h" using namespace mozilla; @@ -232,56 +231,53 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel, { nsAsyncRedirectAutoCallback autoCallback(callback); - nsCOMPtr loadInfo; - nsresult rv = oldChannel->GetLoadInfo(getter_AddRefs(loadInfo)); - - // if no loadInfo on the channel, nothing for us to do - if (!loadInfo) { + // get the Content Security Policy and load type from the property bag + nsCOMPtr policyContainer; + nsCOMPtr props(do_QueryInterface(oldChannel)); + if (!props) return NS_OK; - } - // The loadInfo must not necessarily contain a Node, hence we try to query - // the CSP in the following order: - // a) Get the Node, the Principal of that Node, and the CSP of that Principal - // b) Get the Principal and the CSP of that Principal + props->GetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY, + NS_GET_IID(nsISupports), + getter_AddRefs(policyContainer)); - nsCOMPtr loadingNode = loadInfo->LoadingNode(); - nsCOMPtr principal = loadingNode ? - loadingNode->NodePrincipal() : - loadInfo->LoadingPrincipal(); - NS_ASSERTION(principal, "Can not evaluate CSP without a principal"); + // see if we have a valid nsIChannelPolicy containing CSP and load type + nsCOMPtr channelPolicy(do_QueryInterface(policyContainer)); + if (!channelPolicy) + return NS_OK; + + nsCOMPtr supports; nsCOMPtr csp; - rv = principal->GetCsp(getter_AddRefs(csp)); - NS_ENSURE_SUCCESS(rv, rv); + channelPolicy->GetContentSecurityPolicy(getter_AddRefs(supports)); + csp = do_QueryInterface(supports); + uint32_t loadType; + channelPolicy->GetLoadType(&loadType); - // if there is no CSP, nothing for us to do - if (!csp) { + // if no CSP in the channelPolicy, nothing for us to add to the channel + if (!csp) return NS_OK; - } /* Since redirecting channels don't call into nsIContentPolicy, we call our - * Content Policy implementation directly when redirects occur using the - * information set in the LoadInfo when channels are created. - * - * We check if the CSP permits this host for this type of load, if not, - * we cancel the load now. + * Content Policy implementation directly when redirects occur. When channels + * are created using NS_NewChannel(), callers can optionally pass in a + * nsIChannelPolicy containing a CSP object and load type, which is placed in + * the new channel's property bag. This container is propagated forward when + * channels redirect. */ + // Does the CSP permit this host for this type of load? + // If not, cancel the load now. nsCOMPtr newUri; - rv = newChannel->GetURI(getter_AddRefs(newUri)); - NS_ENSURE_SUCCESS(rv, rv); + newChannel->GetURI(getter_AddRefs(newUri)); nsCOMPtr originalUri; - rv = oldChannel->GetOriginalURI(getter_AddRefs(originalUri)); - NS_ENSURE_SUCCESS(rv, rv); - nsContentPolicyType policyType = loadInfo->GetContentPolicyType(); - + oldChannel->GetOriginalURI(getter_AddRefs(originalUri)); int16_t aDecision = nsIContentPolicy::ACCEPT; - csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t) - newUri, // nsIURI - nullptr, // nsIURI - nullptr, // nsISupports - EmptyCString(), // ACString - MIME guess - originalUri, // aMimeTypeGuess + csp->ShouldLoad(loadType, // load type per nsIContentPolicy (uint32_t) + newUri, // nsIURI + nullptr, // nsIURI + nullptr, // nsISupports + EmptyCString(), // ACString - MIME guess + originalUri, // nsISupports - extra &aDecision); #ifdef PR_LOGGING @@ -301,9 +297,36 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel, #endif // if ShouldLoad doesn't accept the load, cancel the request - if (!NS_CP_ACCEPTED(aDecision)) { + if (aDecision != 1) { autoCallback.DontCallback(); return NS_BINDING_FAILED; } - return NS_OK; + + // the redirect is permitted, so propagate the Content Security Policy + // and load type to the redirecting channel + nsresult rv; + nsCOMPtr props2 = do_QueryInterface(newChannel); + if (props2) { + rv = props2->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY, + channelPolicy); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } + } + + // The redirecting channel isn't a writable property bag, we won't be able + // to enforce the load policy if it redirects again, so we stop it now. + nsAutoCString newUriSpec; + rv = newUri->GetSpec(newUriSpec); + NS_ConvertUTF8toUTF16 unicodeSpec(newUriSpec); + const char16_t *formatParams[] = { unicodeSpec.get() }; + if (NS_SUCCEEDED(rv)) { + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Redirect Error"), nullptr, + nsContentUtils::eDOM_PROPERTIES, + "InvalidRedirectChannelWarning", + formatParams, 1); + } + + return NS_BINDING_FAILED; }