/* * Based on the security flags provided in the loadInfo of the channel, * doContentSecurityCheck() performs the following content security checks * before opening the channel: * * (1) Same Origin Policy Check (if applicable) * (2) Allow Cross Origin but perform sanity checks whether a principal * is allowed to access the following URL. * (3) Perform CORS check (if applicable) * (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...) * * @param aChannel * The channel to perform the security checks on. * @param aInAndOutListener * The streamListener that is passed to channel->AsyncOpen2() that is now potentially * wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs * to be set as new streamListener on the channel. */ nsresult nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr<nsIStreamListener>& aInAndOutListener) { NS_ENSURE_ARG(aChannel); nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); if (!loadInfo) { MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks"); return NS_ERROR_UNEXPECTED; } // if dealing with a redirected channel then we have already installed // streamlistener and redirect proxies and so we are done. if (loadInfo->GetInitialSecurityCheckDone()) { return NS_OK; } // make sure that only one of the five security flags is set in the loadinfo // e.g. do not require same origin and allow cross origin at the same time nsresult rv = ValidateSecurityFlags(loadInfo); NS_ENSURE_SUCCESS(rv, rv); // since aChannel was openend using asyncOpen2() we have to make sure // that redirects of that channel also get openend using asyncOpen2() // please note that some implementations of ::AsyncOpen2 might already // have set that flag to true (e.g. nsViewSourceChannel) in which case // we just set the flag again. rv = loadInfo->SetEnforceSecurity(true); NS_ENSURE_SUCCESS(rv, rv); if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener); NS_ENSURE_SUCCESS(rv, rv); } rv = CheckChannel(aChannel); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> finalChannelURI; rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI)); NS_ENSURE_SUCCESS(rv, rv); // Perform all ContentPolicy checks (MixedContent, CSP, ...) rv = DoContentSecurityChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); // now lets set the initalSecurityFlag for subsequent calls rv = loadInfo->SetInitialSecurityCheckDone(true); NS_ENSURE_SUCCESS(rv, rv); // all security checks passed - lets allow the load return NS_OK; }
/* * Based on the security flags provided in the loadInfo of the channel, * doContentSecurityCheck() performs the following content security checks * before opening the channel: * * (1) Same Origin Policy Check (if applicable) * (2) Allow Cross Origin but perform sanity checks whether a principal * is allowed to access the following URL. * (3) Perform CORS check (if applicable) * (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...) * * @param aChannel * The channel to perform the security checks on. * @param aInAndOutListener * The streamListener that is passed to channel->AsyncOpen2() that is now potentially * wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs * to be set as new streamListener on the channel. */ nsresult nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr<nsIStreamListener>& aInAndOutListener) { NS_ENSURE_ARG(aChannel); nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); if (!loadInfo) { MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks"); return NS_ERROR_UNEXPECTED; } // make sure that only one of the five security flags is set in the loadinfo // e.g. do not require same origin and allow cross origin at the same time nsresult rv = ValidateSecurityFlags(loadInfo); NS_ENSURE_SUCCESS(rv, rv); // lets store the initialSecurityCheckDone flag which indicates whether the channel // was initialy evaluated by the contentSecurityManager. Once the inital // asyncOpen() of the channel went through the contentSecurityManager then // redirects do not have perform all the security checks, e.g. no reason // to setup CORS again. bool initialSecurityCheckDone = loadInfo->GetInitialSecurityCheckDone(); // now lets set the initalSecurityFlag for subsequent calls rv = loadInfo->SetInitialSecurityCheckDone(true); NS_ENSURE_SUCCESS(rv, rv); // since aChannel was openend using asyncOpen2() we have to make sure // that redirects of that channel also get openend using asyncOpen2() // please note that some implementations of ::AsyncOpen2 might already // have set that flag to true (e.g. nsViewSourceChannel) in which case // we just set the flag again. rv = loadInfo->SetEnforceSecurity(true); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> finalChannelURI; rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI)); NS_ENSURE_SUCCESS(rv, rv); nsSecurityFlags securityMode = loadInfo->GetSecurityMode(); // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) || (securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) { rv = DoSOPChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); } // if dealing with a redirected channel then we only enforce SOP // and can return at this point. if (initialSecurityCheckDone) { return NS_OK; } if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) || (securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) { // Please note that DoCheckLoadURIChecks should only be enforced for // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set // within the loadInfo, then then CheckLoadURIWithPrincipal is performed // within nsCorsListenerProxy rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); } if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener); NS_ENSURE_SUCCESS(rv, rv); } // Perform all ContentPolicy checks (MixedContent, CSP, ...) rv = DoContentSecurityChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); // all security checks passed - lets allow the load return NS_OK; }
/* * Based on the security flags provided in the loadInfo of the channel, * doContentSecurityCheck() performs the following content security checks * before opening the channel: * * (1) Same Origin Policy Check (if applicable) * (2) Allow Cross Origin but perform sanity checks whether a principal * is allowed to access the following URL. * (3) Perform CORS check (if applicable) * (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...) * * @param aChannel * The channel to perform the security checks on. * @param aInAndOutListener * The streamListener that is passed to channel->AsyncOpen2() that is now potentially * wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs * to be set as new streamListener on the channel. */ nsresult nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr<nsIStreamListener>& aInAndOutListener) { NS_ENSURE_ARG(aChannel); nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); if (!loadInfo) { MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks"); return NS_ERROR_UNEXPECTED; } // make sure that only one of the five security flags is set in the loadinfo // e.g. do not require same origin and allow cross origin at the same time nsresult rv = ValidateSecurityFlags(loadInfo); NS_ENSURE_SUCCESS(rv, rv); // lets store the initialSecurityCheckDone flag which indicates whether the channel // was initialy evaluated by the contentSecurityManager. Once the inital // asyncOpen() of the channel went through the contentSecurityManager then // redirects do not have perform all the security checks, e.g. no reason // to setup CORS again. bool initialSecurityCheckDone = loadInfo->GetInitialSecurityCheckDone(); // now lets set the initalSecurityFlag for subsequent calls rv = loadInfo->SetInitialSecurityCheckDone(true); NS_ENSURE_SUCCESS(rv, rv); // since aChannel was openend using asyncOpen2() we have to make sure // that redirects of that channel also get openend using asyncOpen2() // please note that some implementations of ::AsyncOpen2 might already // have set that flag to true (e.g. nsViewSourceChannel) in which case // we just set the flag again. rv = loadInfo->SetEnforceSecurity(true); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> finalChannelURI; rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI)); NS_ENSURE_SUCCESS(rv, rv); // Perform Same Origin Policy check rv = DoSOPChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); // if dealing with a redirected channel then we only enforce SOP // and can return at this point. if (initialSecurityCheckDone) { return NS_OK; } rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); // Check if CORS needs to be set up rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener); NS_ENSURE_SUCCESS(rv, rv); // Perform all ContentPolicy checks (MixedContent, CSP, ...) rv = DoContentSecurityChecks(finalChannelURI, loadInfo); NS_ENSURE_SUCCESS(rv, rv); // all security checks passed - lets allow the load return NS_OK; }