nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, nsILoadGroup* aLoadGroup, nsIPrincipal* aCallerPrincipal) { nsCAutoString spec; aUri->GetSpec(spec); PR_LOG(txLog::xslt, PR_LOG_ALWAYS, ("TX_LoadSheet: %s\n", spec.get())); // Content Policy PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, aUri, aCallerPrincipal, aProcessor->GetSourceContentModel(), NS_LITERAL_CSTRING("application/xml"), nsnull, &shouldLoad); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_DOM_BAD_URI; } nsRefPtr<txCompileObserver> observer = new txCompileObserver(aProcessor, aLoadGroup); NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY); nsRefPtr<txStylesheetCompiler> compiler = new txStylesheetCompiler(NS_ConvertUTF8toUTF16(spec), observer); NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY); return observer->startLoad(aUri, compiler, aCallerPrincipal); }
nsresult txSyncCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, txStylesheetCompiler* aCompiler) { if (mProcessor->IsLoadDisabled()) { return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR; } nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> referrerUri; rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIPrincipal> referrerPrincipal; rv = nsContentUtils::GetSecurityManager()-> GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal)); NS_ENSURE_SUCCESS(rv, rv); // Content Policy PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, uri, referrerPrincipal, nsnull, NS_LITERAL_CSTRING("application/xml"), nsnull, &shouldLoad); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_DOM_BAD_URI; } // This is probably called by js, a loadGroup for the channel doesn't // make sense. nsCOMPtr<nsIDOMDocument> document; rv = nsSyncLoadService::LoadDocument(uri, referrerPrincipal, nsnull, PR_FALSE, getter_AddRefs(document)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocument> doc = do_QueryInterface(document); rv = handleNode(doc, aCompiler); if (NS_FAILED(rv)) { nsCAutoString spec; uri->GetSpec(spec); aCompiler->cancel(rv, nsnull, NS_ConvertUTF8toUTF16(spec).get()); return rv; } rv = aCompiler->doneLoading(); return rv; }
void ImportLoader::Open() { AutoError ae(this, false); // Imports should obey to the master documents CSP. nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument(); nsIPrincipal* principal = Principal(); int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SUBDOCUMENT, mURI, principal, mImportParent, NS_LITERAL_CSTRING("text/html"), /* extra = */ nullptr, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { NS_WARN_IF_FALSE(NS_CP_ACCEPTED(shouldLoad), "ImportLoader rejected by CSP"); return; } nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); rv = secMan->CheckLoadURIWithPrincipal(principal, mURI, nsIScriptSecurityManager::STANDARD); NS_ENSURE_SUCCESS_VOID(rv); nsCOMPtr<nsILoadGroup> loadGroup = master->GetDocumentLoadGroup(); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), mURI, mImportParent, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_SUBDOCUMENT, loadGroup, nullptr, // aCallbacks nsIRequest::LOAD_BACKGROUND); NS_ENSURE_SUCCESS_VOID(rv); // Init CORSListenerProxy and omit credentials. nsRefPtr<nsCORSListenerProxy> corsListener = new nsCORSListenerProxy(this, principal, /* aWithCredentials */ false); rv = corsListener->Init(channel, true); NS_ENSURE_SUCCESS_VOID(rv); rv = channel->AsyncOpen(corsListener, nullptr); NS_ENSURE_SUCCESS_VOID(rv); BlockScripts(); ae.Pass(); }
nsresult txCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, txStylesheetCompiler* aCompiler) { if (mProcessor->IsLoadDisabled()) { return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR; } nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> referrerUri; rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIPrincipal> referrerPrincipal; rv = nsContentUtils::GetSecurityManager()-> GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal)); NS_ENSURE_SUCCESS(rv, rv); // Content Policy PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, uri, referrerPrincipal, nsnull, NS_LITERAL_CSTRING("application/xml"), nsnull, &shouldLoad); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_DOM_BAD_URI; } return startLoad(uri, aCompiler, referrerPrincipal); }
nsresult nsFontFaceLoader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, nsISupports* aContext) { nsresult rv; if (!aSourcePrincipal) return NS_OK; // check with the security manager nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); rv = secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI, nsIScriptSecurityManager::STANDARD); if (NS_FAILED(rv)) { return rv; } // check content policy PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_FONT, aTargetURI, aSourcePrincipal, aContext, EmptyCString(), // mime type nsnull, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } return NS_OK; }
void HTMLTrackElement::LoadResource() { // Find our 'src' url nsAutoString src; if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { return; } nsCOMPtr<nsIURI> uri; nsresult rv = NewURIFromString(src, getter_AddRefs(uri)); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); LOG(PR_LOG_ALWAYS, ("%p Trying to load from src=%s", this, NS_ConvertUTF16toUTF8(src).get())); if (mChannel) { mChannel->Cancel(NS_BINDING_ABORTED); mChannel = nullptr; } rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(NodePrincipal(), uri, nsIScriptSecurityManager::STANDARD); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA, uri, NodePrincipal(), static_cast<Element*>(this), NS_LITERAL_CSTRING("text/vtt"), // mime type nullptr, // extra &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); if (NS_CP_REJECTED(shouldLoad)) { return; } CreateTextTrack(); // Check for a Content Security Policy to pass down to the channel // created to load the media content. nsCOMPtr<nsIChannelPolicy> channelPolicy; nsCOMPtr<nsIContentSecurityPolicy> csp; rv = NodePrincipal()->GetCsp(getter_AddRefs(csp)); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); if (csp) { channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); if (!channelPolicy) { return; } channelPolicy->SetContentSecurityPolicy(csp); channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA); } nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup(); rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, nullptr, nsIRequest::LOAD_NORMAL, channelPolicy); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mLoadListener = new WebVTTLoadListener(this); rv = mLoadListener->LoadResource(); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); channel->SetNotificationCallbacks(mLoadListener); LOG(PR_LOG_DEBUG, ("opening webvtt channel")); rv = channel->AsyncOpen(mLoadListener, nullptr); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mChannel = channel; }
static nsresult DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) { nsContentPolicyType contentPolicyType = aLoadInfo->GetExternalContentPolicyType(); nsContentPolicyType internalContentPolicyType = aLoadInfo->InternalContentPolicyType(); nsCString mimeTypeGuess; nsCOMPtr<nsINode> requestingContext = nullptr; switch(contentPolicyType) { case nsIContentPolicy::TYPE_OTHER: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_SCRIPT: { mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript"); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_IMAGE: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_STYLESHEET: { mimeTypeGuess = NS_LITERAL_CSTRING("text/css"); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_OBJECT: case nsIContentPolicy::TYPE_DOCUMENT: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_SUBDOCUMENT: { mimeTypeGuess = NS_LITERAL_CSTRING("text/html"); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_subdocument requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_REFRESH: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_XBL: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_PING: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_XMLHTTPREQUEST: { // alias nsIContentPolicy::TYPE_DATAREQUEST: requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_xml requires requestingContext of type Document"); // We're checking for the external TYPE_XMLHTTPREQUEST here in case // an addon creates a request with that type. if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST || internalContentPolicyType == nsIContentPolicy::TYPE_XMLHTTPREQUEST) { mimeTypeGuess = EmptyCString(); } else { MOZ_ASSERT(internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE, "can not set mime type guess for unexpected internal type"); mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM); } break; } case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, "type_subrequest requires requestingContext of type Element"); break; } case nsIContentPolicy::TYPE_DTD: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_dtd requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_FONT: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_MEDIA: { if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) { mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt"); } else { mimeTypeGuess = EmptyCString(); } requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, "type_media requires requestingContext of type Element"); break; } case nsIContentPolicy::TYPE_WEBSOCKET: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_CSP_REPORT: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_XSLT: { mimeTypeGuess = NS_LITERAL_CSTRING("application/xml"); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_xslt requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_BEACON: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_beacon requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_FETCH: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_IMAGESET: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } default: // nsIContentPolicy::TYPE_INVALID MOZ_ASSERT(false, "can not perform security check without a valid contentType"); } int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(internalContentPolicyType, aURI, aLoadInfo->LoadingPrincipal(), requestingContext, mimeTypeGuess, nullptr, //extra, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } return NS_OK; }
nsresult nsExpatDriver::OpenInputStreamFromExternalDTD(const PRUnichar* aFPIStr, const PRUnichar* aURLStr, const PRUnichar* aBaseURL, nsIInputStream** aStream, nsAString& aAbsURL) { nsCOMPtr<nsIURI> baseURI; nsresult rv = NS_NewURI(getter_AddRefs(baseURI), NS_ConvertUTF16toUTF8(aBaseURL)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURLStr), nsnull, baseURI); NS_ENSURE_SUCCESS(rv, rv); // check if it is alright to load this uri PRBool isChrome = PR_FALSE; uri->SchemeIs("chrome", &isChrome); if (!isChrome) { // since the url is not a chrome url, check to see if we can map the DTD // to a known local DTD, or if a DTD file of the same name exists in the // special DTD directory if (aFPIStr) { // see if the Formal Public Identifier (FPI) maps to a catalog entry mCatalogData = LookupCatalogData(aFPIStr); } nsCOMPtr<nsIURI> localURI; GetLocalDTDURI(mCatalogData, uri, getter_AddRefs(localURI)); if (!localURI) { return NS_ERROR_NOT_IMPLEMENTED; } localURI.swap(uri); } nsCOMPtr<nsIDocument> doc; NS_ASSERTION(mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)), "In nsExpatDriver::OpenInputStreamFromExternalDTD: " "mOriginalSink not the same object as mSink?"); if (mOriginalSink) doc = do_QueryInterface(mOriginalSink->GetTarget()); PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_DTD, uri, (doc ? doc->NodePrincipal() : nsnull), doc, EmptyCString(), //mime guess nsnull, //extra &shouldLoad); if (NS_FAILED(rv)) return rv; if (NS_CP_REJECTED(shouldLoad)) { // Disallowed by content policy return NS_ERROR_CONTENT_BLOCKED; } nsCAutoString absURL; uri->GetSpec(absURL); CopyUTF8toUTF16(absURL, aAbsURL); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), uri); NS_ENSURE_SUCCESS(rv, rv); channel->SetContentType(NS_LITERAL_CSTRING("application/xml")); return channel->Open(aStream); }
nsresult nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) { // We need a document to evaluate scripts. NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); // Check to see if scripts has been turned off. if (!mEnabled || !mDocument->IsScriptEnabled()) { return NS_ERROR_NOT_AVAILABLE; } NS_ASSERTION(!aElement->IsMalformed(), "Executing malformed script"); // Check that the script is not an eventhandler if (IsScriptEventHandler(aElement)) { return NS_CONTENT_SCRIPT_IS_EVENTHANDLER; } // Script evaluation can also be disabled in the current script // context even though it's enabled in the document. // XXX - still hard-coded for JS here, even though another language // may be specified. Should this check be made *after* we examine // the attributes to locate the script-type? // For now though, if JS is disabled we assume every language is // disabled. // XXX is this different from the mDocument->IsScriptEnabled() call? nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject(); if (!globalObject) { return NS_ERROR_NOT_AVAILABLE; } nsIScriptContext *context = globalObject->GetScriptContext( nsIProgrammingLanguage::JAVASCRIPT); // If scripts aren't enabled in the current context, there's no // point in going on. if (!context || !context->GetScriptsEnabled()) { return NS_ERROR_NOT_AVAILABLE; } // Default script language is whatever the root content specifies // (which may come from a header or http-meta tag), or if there // is no root content, from the script global object. nsCOMPtr<nsIContent> rootContent = mDocument->GetRootContent(); PRUint32 typeID = rootContent ? rootContent->GetScriptTypeID() : context->GetScriptTypeID(); PRUint32 version = 0; nsAutoString language, type, src; nsresult rv = NS_OK; // Check the type attribute to determine language and version. // If type exists, it trumps the deprecated 'language=' aElement->GetScriptType(type); if (!type.IsEmpty()) { nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser = do_GetService("@mozilla.org/network/mime-hdrparam;1"); NS_ENSURE_TRUE(mimeHdrParser, NS_ERROR_FAILURE); NS_ConvertUTF16toUTF8 typeAndParams(type); nsAutoString mimeType; rv = mimeHdrParser->GetParameter(typeAndParams, nsnull, EmptyCString(), PR_FALSE, nsnull, mimeType); NS_ENSURE_SUCCESS(rv, rv); // Javascript keeps the fast path, optimized for most-likely type // Table ordered from most to least likely JS MIME types. // See bug 62485, feel free to add <script type="..."> survey data to it, // or to a new bug once 62485 is closed. static const char *jsTypes[] = { "text/javascript", "text/ecmascript", "application/javascript", "application/ecmascript", "application/x-javascript", nsnull }; PRBool isJavaScript = PR_FALSE; for (PRInt32 i = 0; jsTypes[i]; i++) { if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) { isJavaScript = PR_TRUE; break; } } if (isJavaScript) typeID = nsIProgrammingLanguage::JAVASCRIPT; else { // Use the object factory to locate a matching language. nsCOMPtr<nsIScriptRuntime> runtime; rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime)); if (NS_FAILED(rv) || runtime == nsnull) { // Failed to get the explicitly specified language NS_WARNING("Failed to find a scripting language"); typeID = nsIProgrammingLanguage::UNKNOWN; } else typeID = runtime->GetScriptTypeID(); } if (typeID != nsIProgrammingLanguage::UNKNOWN) { // Get the version string, and ensure the language supports it. nsAutoString versionName; rv = mimeHdrParser->GetParameter(typeAndParams, "version", EmptyCString(), PR_FALSE, nsnull, versionName); if (NS_FAILED(rv)) { // no version attribute - version remains 0. if (rv != NS_ERROR_INVALID_ARG) return rv; } else { nsCOMPtr<nsIScriptRuntime> runtime; rv = NS_GetScriptRuntimeByID(typeID, getter_AddRefs(runtime)); if (NS_FAILED(rv)) { NS_ERROR("Failed to locate the language with this ID"); return rv; } rv = runtime->ParseVersion(versionName, &version); if (NS_FAILED(rv)) { NS_WARNING("This script language version is not supported - ignored"); typeID = nsIProgrammingLanguage::UNKNOWN; } } } // Some js specifics yet to be abstracted. if (typeID == nsIProgrammingLanguage::JAVASCRIPT) { nsAutoString value; rv = mimeHdrParser->GetParameter(typeAndParams, "e4x", EmptyCString(), PR_FALSE, nsnull, value); if (NS_FAILED(rv)) { if (rv != NS_ERROR_INVALID_ARG) return rv; } else { if (value.Length() == 1 && value[0] == '1') // This means that we need to set JSOPTION_XML in the JS options. // We re-use our knowledge of the implementation to reuse // JSVERSION_HAS_XML as a safe version flag. // If version has JSVERSION_UNKNOWN (-1), then this is still OK. version |= JSVERSION_HAS_XML; } } } else { // no 'type=' element // "language" is a deprecated attribute of HTML, so we check it only for // HTML script elements. nsCOMPtr<nsIDOMHTMLScriptElement> htmlScriptElement = do_QueryInterface(aElement); if (htmlScriptElement) { htmlScriptElement->GetAttribute(NS_LITERAL_STRING("language"), language); if (!language.IsEmpty()) { if (nsParserUtils::IsJavaScriptLanguage(language, &version)) typeID = nsIProgrammingLanguage::JAVASCRIPT; else typeID = nsIProgrammingLanguage::UNKNOWN; // IE, Opera, etc. do not respect language version, so neither should // we at this late date in the browser wars saga. Note that this change // affects HTML but not XUL or SVG (but note also that XUL has its own // code to check nsParserUtils::IsJavaScriptLanguage -- that's probably // a separate bug, one we may not be able to fix short of XUL2). See // bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895). NS_ASSERTION(JSVERSION_DEFAULT == 0, "We rely on all languages having 0 as a version default"); version = 0; } } } // If we don't know the language, we don't know how to evaluate if (typeID == nsIProgrammingLanguage::UNKNOWN) { return NS_ERROR_NOT_AVAILABLE; } // If not from a chrome document (which is always trusted), we need some way // of checking the language is "safe". Currently the only other language // impl is Python, and that is *not* safe in untrusted code - so fixing // this isn't a priority.! // See also similar code in nsXULContentSink.cpp if (typeID != nsIProgrammingLanguage::JAVASCRIPT && !nsContentUtils::IsChromeDoc(mDocument)) { NS_WARNING("Untrusted language called from non-chrome - ignored"); return NS_ERROR_NOT_AVAILABLE; } nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement)); eltContent->SetScriptTypeID(typeID); // Create a request object for this script nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version); NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY); // First check to see if this is an external script nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI(); if (scriptURI) { // Check that the containing page is allowed to load this URI. rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), scriptURI, nsIScriptSecurityManager::ALLOW_CHROME); NS_ENSURE_SUCCESS(rv, rv); // After the security manager, the content-policy stuff gets a veto PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, scriptURI, mDocument->NodePrincipal(), aElement, NS_LossyConvertUTF16toASCII(type), nsnull, //extra &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) { return NS_ERROR_CONTENT_BLOCKED; } return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; } request->mURI = scriptURI; request->mIsInline = PR_FALSE; request->mLoading = PR_TRUE; nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup(); nsCOMPtr<nsIStreamLoader> loader; nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(globalObject)); nsIDocShell *docshell = window->GetDocShell(); nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell)); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), scriptURI, nsnull, loadGroup, prompter, nsIRequest::LOAD_NORMAL); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { // HTTP content negotation has little value in this context. httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), NS_LITERAL_CSTRING("*/*"), PR_FALSE); httpChannel->SetReferrer(mDocument->GetDocumentURI()); } rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); rv = channel->AsyncOpen(loader, request); NS_ENSURE_SUCCESS(rv, rv); } else { request->mLoading = PR_FALSE; request->mIsInline = PR_TRUE; request->mURI = mDocument->GetDocumentURI(); request->mLineNo = aElement->GetScriptLineNumber(); // If we've got existing pending requests, add ourselves // to this list. if (mPendingRequests.Count() == 0 && ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) { return ProcessRequest(request); } } // Add the request to our pending requests list NS_ENSURE_TRUE(mPendingRequests.AppendObject(request), NS_ERROR_OUT_OF_MEMORY); // If there weren't any pending requests before, and this one is // ready to execute, do that as soon as it's safe. if (mPendingRequests.Count() == 1 && !request->mLoading && ReadyToExecuteScripts()) { nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this, &nsScriptLoader::ProcessPendingRequests)); } // Added as pending request, now we can send blocking back return NS_ERROR_HTMLPARSER_BLOCK; }
FetchDriver::MainFetchOp FetchDriver::SetTaintingAndGetNextOp(bool aCORSFlag) { workers::AssertIsOnMainThread(); nsAutoCString url; mRequest->GetURL(url); nsCOMPtr<nsIURI> requestURI; nsresult rv = NS_NewURI(getter_AddRefs(requestURI), url, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { return MainFetchOp(NETWORK_ERROR); } // CSP/mixed content checks. int16_t shouldLoad; rv = NS_CheckContentLoadPolicy(mRequest->ContentPolicyType(), requestURI, mPrincipal, mDocument, // FIXME(nsm): Should MIME be extracted from // Content-Type header? EmptyCString(), /* mime guess */ nullptr, /* extra */ &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_WARN_IF(NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad))) { // Disallowed by content policy. return MainFetchOp(NETWORK_ERROR); } // Begin Step 8 of the Main Fetch algorithm // https://fetch.spec.whatwg.org/#fetching nsAutoCString scheme; rv = requestURI->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { return MainFetchOp(NETWORK_ERROR); } // request's current url's origin is request's origin and the CORS flag is unset // request's current url's scheme is "data" and request's same-origin data-URL flag is set // request's current url's scheme is "about" rv = mPrincipal->CheckMayLoad(requestURI, false /* report */, false /* allowIfInheritsPrincipal */); if ((!aCORSFlag && NS_SUCCEEDED(rv)) || (scheme.EqualsLiteral("data") && mRequest->SameOriginDataURL()) || scheme.EqualsLiteral("about")) { return MainFetchOp(BASIC_FETCH); } // request's mode is "same-origin" if (mRequest->Mode() == RequestMode::Same_origin) { return MainFetchOp(NETWORK_ERROR); } // request's mode is "no-cors" if (mRequest->Mode() == RequestMode::No_cors) { mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_OPAQUE); return MainFetchOp(BASIC_FETCH); } // request's current url's scheme is not one of "http" and "https" if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) { return MainFetchOp(NETWORK_ERROR); } // request's mode is "cors-with-forced-preflight" // request's unsafe-request flag is set and either request's method is not // a simple method or a header in request's header list is not a simple header if (mRequest->Mode() == RequestMode::Cors_with_forced_preflight || (mRequest->UnsafeRequest() && (!mRequest->HasSimpleMethod() || !mRequest->Headers()->HasOnlySimpleHeaders()))) { mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_CORS); mRequest->SetRedirectMode(RequestRedirect::Error); // Note, the following text from Main Fetch step 8 is handled in // nsCORSListenerProxy when CheckRequestApproved() fails: // // The result of performing an HTTP fetch using request with the CORS // flag and CORS-preflight flag set. If the result is a network error, // clear cache entries using request. return MainFetchOp(HTTP_FETCH, true /* cors */, true /* preflight */); } // Otherwise mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_CORS); return MainFetchOp(HTTP_FETCH, true /* cors */, false /* preflight */); }
void HTMLTrackElement::LoadResource() { // Find our 'src' url nsAutoString src; if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { return; } nsCOMPtr<nsIURI> uri; nsresult rv = NewURIFromString(src, getter_AddRefs(uri)); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); LOG(LogLevel::Info, ("%p Trying to load from src=%s", this, NS_ConvertUTF16toUTF8(src).get())); if (mChannel) { mChannel->Cancel(NS_BINDING_ABORTED); mChannel = nullptr; } rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(NodePrincipal(), uri, nsIScriptSecurityManager::STANDARD); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA, uri, NodePrincipal(), static_cast<Element*>(this), NS_LITERAL_CSTRING("text/vtt"), // mime type nullptr, // extra &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); if (NS_CP_REJECTED(shouldLoad)) { return; } // We may already have a TextTrack at this point if GetTrack() has already // been called. This happens, for instance, if script tries to get the // TextTrack before its mTrackElement has been bound to the DOM tree. if (!mTrack) { CreateTextTrack(); } nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup(); rv = NS_NewChannel(getter_AddRefs(channel), uri, static_cast<Element*>(this), nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_MEDIA, loadGroup); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mListener = new WebVTTListener(this); rv = mListener->LoadResource(); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); channel->SetNotificationCallbacks(mListener); LOG(LogLevel::Debug, ("opening webvtt channel")); rv = channel->AsyncOpen(mListener, nullptr); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mChannel = channel; }
nsresult nsDOMWorkerScriptLoader::RunInternal() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); // Things we need to make all this work... nsCOMPtr<nsIDocument> parentDoc = mWorker->Pool()->ParentDocument(); if (!parentDoc) { // Must have been canceled. return NS_ERROR_ABORT; } nsIPrincipal* principal; nsIURI* baseURI; if (mForWorker) { NS_ASSERTION(mScriptCount == 1, "Bad state!"); nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent(); if (parentWorker) { principal = parentWorker->GetPrincipal(); NS_ENSURE_STATE(principal); baseURI = parentWorker->GetURI(); NS_ENSURE_STATE(baseURI); } else { principal = parentDoc->NodePrincipal(); NS_ENSURE_STATE(principal); baseURI = parentDoc->GetDocBaseURI(); } } else { principal = mWorker->GetPrincipal(); baseURI = mWorker->GetURI(); NS_ASSERTION(principal && baseURI, "Should have been set already!"); } // All of these can potentially be null, but that should be ok. We'll either // succeed without them or fail below. nsCOMPtr<nsILoadGroup> loadGroup(parentDoc->GetDocumentLoadGroup()); nsCOMPtr<nsIIOService> ios(do_GetIOService()); for (PRUint32 index = 0; index < mScriptCount; index++) { ScriptLoadInfo& loadInfo = mLoadInfos[index]; nsresult& rv = loadInfo.result; nsCOMPtr<nsIURI>& uri = loadInfo.finalURI; rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), loadInfo.url, parentDoc, baseURI); if (NS_FAILED(rv)) { return rv; } nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE); PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri, principal, parentDoc, NS_LITERAL_CSTRING("text/javascript"), nsnull, &shouldLoad, nsContentUtils::GetContentPolicy(), secMan); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) { return NS_ERROR_CONTENT_BLOCKED; } return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; } // If this script loader is being used to make a new worker then we need to // do a same-origin check. Otherwise we need to clear the load with the // security manager. if (mForWorker) { rv = principal->CheckMayLoad(uri, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // Set the principal and URI on the new worker. mWorker->SetPrincipal(principal); rv = mWorker->SetURI(uri); NS_ENSURE_SUCCESS(rv, rv); } else { rv = secMan->CheckLoadURIWithPrincipal(principal, uri, 0); NS_ENSURE_SUCCESS(rv, rv); } // We need to know which index we're on in OnStreamComplete so we know where // to put the result. nsCOMPtr<nsISupportsPRUint32> indexSupports = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = indexSupports->SetData(index); NS_ENSURE_SUCCESS(rv, rv); // We don't care about progress so just use the simple stream loader for // OnStreamComplete notification only. nsCOMPtr<nsIStreamLoader> loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); // get Content Security Policy from parent document to pass into channel nsCOMPtr<nsIChannelPolicy> channelPolicy; nsCOMPtr<nsIContentSecurityPolicy> csp; rv = parentDoc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); NS_ENSURE_SUCCESS(rv, rv); if (csp) { channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); channelPolicy->SetContentSecurityPolicy(csp); channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT); } rv = NS_NewChannel(getter_AddRefs(loadInfo.channel), uri, ios, loadGroup, nsnull, // callbacks nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI, // loadFlags channelPolicy); // CSP info NS_ENSURE_SUCCESS(rv, rv); rv = loadInfo.channel->AsyncOpen(loader, indexSupports); if (NS_FAILED(rv)) { // Null this out so we don't try to cancel it later. loadInfo.channel = nsnull; return rv; } } return NS_OK; }
static nsresult DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) { nsCOMPtr<nsIURI> uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); nsContentPolicyType contentPolicyType = aLoadInfo->GetExternalContentPolicyType(); nsContentPolicyType internalContentPolicyType = aLoadInfo->InternalContentPolicyType(); nsCString mimeTypeGuess; nsCOMPtr<nsINode> requestingContext = nullptr; #ifdef DEBUG // Don't enforce TYPE_DOCUMENT assertions for loads // initiated by javascript tests. bool skipContentTypeCheck = false; skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion"); #endif switch(contentPolicyType) { case nsIContentPolicy::TYPE_OTHER: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_SCRIPT: { mimeTypeGuess = NS_LITERAL_CSTRING("application/javascript"); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_IMAGE: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_STYLESHEET: { mimeTypeGuess = NS_LITERAL_CSTRING("text/css"); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_OBJECT: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_DOCUMENT: { MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_SUBDOCUMENT: { mimeTypeGuess = NS_LITERAL_CSTRING("text/html"); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_subdocument requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_REFRESH: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; } case nsIContentPolicy::TYPE_XBL: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_PING: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_XMLHTTPREQUEST: { // alias nsIContentPolicy::TYPE_DATAREQUEST: requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_xml requires requestingContext of type Document"); // We're checking for the external TYPE_XMLHTTPREQUEST here in case // an addon creates a request with that type. if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST || internalContentPolicyType == nsIContentPolicy::TYPE_XMLHTTPREQUEST) { mimeTypeGuess = EmptyCString(); } else { MOZ_ASSERT(internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE, "can not set mime type guess for unexpected internal type"); mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM); } break; } case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, "type_subrequest requires requestingContext of type Element"); break; } case nsIContentPolicy::TYPE_DTD: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_dtd requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_FONT: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_MEDIA: { if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) { mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt"); } else { mimeTypeGuess = EmptyCString(); } requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, "type_media requires requestingContext of type Element"); break; } case nsIContentPolicy::TYPE_WEBSOCKET: { // Websockets have to use the proxied URI: // ws:// instead of http:// for CSP checks nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(aChannel); MOZ_ASSERT(httpChannelInternal); if (httpChannelInternal) { httpChannelInternal->GetProxyURI(getter_AddRefs(uri)); } mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_CSP_REPORT: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_XSLT: { mimeTypeGuess = NS_LITERAL_CSTRING("application/xml"); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_xslt requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_BEACON: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); MOZ_ASSERT(!requestingContext || requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, "type_beacon requires requestingContext of type Document"); break; } case nsIContentPolicy::TYPE_FETCH: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_IMAGESET: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); break; } case nsIContentPolicy::TYPE_WEB_MANIFEST: { mimeTypeGuess = NS_LITERAL_CSTRING("application/manifest+json"); requestingContext = aLoadInfo->LoadingNode(); break; } default: // nsIContentPolicy::TYPE_INVALID MOZ_ASSERT(false, "can not perform security check without a valid contentType"); } int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(internalContentPolicyType, uri, aLoadInfo->LoadingPrincipal(), requestingContext, mimeTypeGuess, nullptr, //extra, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } if (nsMixedContentBlocker::sSendHSTSPriming) { rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri, requestingContext, aLoadInfo); return rv; } return NS_OK; }
nsresult FetchDriver::ContinueFetch(bool aCORSFlag) { workers::AssertIsOnMainThread(); nsAutoCString url; mRequest->GetURL(url); nsCOMPtr<nsIURI> requestURI; nsresult rv = NS_NewURI(getter_AddRefs(requestURI), url, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { return FailWithNetworkError(); } // CSP/mixed content checks. int16_t shouldLoad; rv = NS_CheckContentLoadPolicy(mRequest->ContentPolicyType(), requestURI, mPrincipal, mDocument, // FIXME(nsm): Should MIME be extracted from // Content-Type header? EmptyCString(), /* mime guess */ nullptr, /* extra */ &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_WARN_IF(NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad))) { // Disallowed by content policy. return FailWithNetworkError(); } // Begin Step 4 of the Fetch algorithm // https://fetch.spec.whatwg.org/#fetching nsAutoCString scheme; rv = requestURI->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { return FailWithNetworkError(); } rv = mPrincipal->CheckMayLoad(requestURI, false /* report */, false /* allowIfInheritsPrincipal */); if ((!aCORSFlag && NS_SUCCEEDED(rv)) || (scheme.EqualsLiteral("data") && mRequest->SameOriginDataURL()) || scheme.EqualsLiteral("about")) { return BasicFetch(); } if (mRequest->Mode() == RequestMode::Same_origin) { return FailWithNetworkError(); } if (mRequest->Mode() == RequestMode::No_cors) { mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_OPAQUE); return BasicFetch(); } if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) { return FailWithNetworkError(); } bool corsPreflight = false; if (mRequest->Mode() == RequestMode::Cors_with_forced_preflight || (mRequest->UnsafeRequest() && (!mRequest->HasSimpleMethod() || !mRequest->Headers()->HasOnlySimpleHeaders()))) { corsPreflight = true; } mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_CORS); return HttpFetch(true /* aCORSFlag */, corsPreflight); }
nsresult DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) { nsContentPolicyType contentPolicyType = aLoadInfo->GetContentPolicyType(); nsCString mimeTypeGuess; nsCOMPtr<nsISupports> requestingContext = nullptr; switch(contentPolicyType) { case nsIContentPolicy::TYPE_OTHER: case nsIContentPolicy::TYPE_SCRIPT: case nsIContentPolicy::TYPE_IMAGE: case nsIContentPolicy::TYPE_STYLESHEET: case nsIContentPolicy::TYPE_OBJECT: case nsIContentPolicy::TYPE_DOCUMENT: case nsIContentPolicy::TYPE_SUBDOCUMENT: case nsIContentPolicy::TYPE_REFRESH: case nsIContentPolicy::TYPE_XBL: case nsIContentPolicy::TYPE_PING: case nsIContentPolicy::TYPE_XMLHTTPREQUEST: // alias nsIContentPolicy::TYPE_DATAREQUEST: case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: case nsIContentPolicy::TYPE_DTD: case nsIContentPolicy::TYPE_FONT: MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; case nsIContentPolicy::TYPE_MEDIA: mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); #ifdef DEBUG { nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(requestingContext); NS_ASSERTION(element != nullptr, "type_media requires requestingContext of type Element"); } #endif break; case nsIContentPolicy::TYPE_WEBSOCKET: case nsIContentPolicy::TYPE_CSP_REPORT: case nsIContentPolicy::TYPE_XSLT: case nsIContentPolicy::TYPE_BEACON: case nsIContentPolicy::TYPE_FETCH: case nsIContentPolicy::TYPE_IMAGESET: MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; default: // nsIContentPolicy::TYPE_INVALID MOZ_ASSERT(false, "can not perform security check without a valid contentType"); } int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, aURI, aLoadInfo->LoadingPrincipal(), requestingContext, mimeTypeGuess, nullptr, //extra, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } return NS_OK; }
NS_IMETHODIMP nsXMLDocument::Load(const nsAString& aUrl, bool *aReturn) { bool hasHadScriptObject = true; nsIScriptGlobalObject* scriptObject = GetScriptHandlingObject(hasHadScriptObject); NS_ENSURE_STATE(scriptObject || !hasHadScriptObject); ReportUseOfDeprecatedMethod(this, "UseOfDOM3LoadMethodWarning"); NS_ENSURE_ARG_POINTER(aReturn); *aReturn = false; nsCOMPtr<nsIDocument> callingDoc = do_QueryInterface(nsContentUtils::GetDocumentFromContext()); nsIURI *baseURI = mDocumentURI; nsAutoCString charset; if (callingDoc) { baseURI = callingDoc->GetDocBaseURI(); charset = callingDoc->GetDocumentCharacterSet(); } // Create a new URI nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI); if (NS_FAILED(rv)) { return rv; } // Check to see whether the current document is allowed to load this URI. // It's important to use the current document's principal for this check so // that we don't end up in a case where code with elevated privileges is // calling us and changing the principal of this document. // Enforce same-origin even for chrome loaders to avoid someone accidentally // using a document that content has a reference to and turn that into a // chrome document. nsCOMPtr<nsIPrincipal> principal = NodePrincipal(); if (!nsContentUtils::IsSystemPrincipal(principal)) { rv = principal->CheckMayLoad(uri, false, false); NS_ENSURE_SUCCESS(rv, rv); int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST, uri, principal, callingDoc ? callingDoc.get() : static_cast<nsIDocument*>(this), NS_LITERAL_CSTRING("application/xml"), nullptr, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } } else { // We're called from chrome, check to make sure the URI we're // about to load is also chrome. bool isChrome = false; if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { nsAutoCString spec; if (mDocumentURI) mDocumentURI->GetSpec(spec); nsAutoString error; error.AssignLiteral("Cross site loading using document.load is no " "longer supported. Use XMLHttpRequest instead."); nsCOMPtr<nsIScriptError> errorObject = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = errorObject->InitWithWindowID(error, NS_ConvertUTF8toUTF16(spec), EmptyString(), 0, 0, nsIScriptError::warningFlag, "DOM", callingDoc ? callingDoc->InnerWindowID() : this->InnerWindowID()); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); if (consoleService) { consoleService->LogMessage(errorObject); } return NS_ERROR_DOM_SECURITY_ERR; } } // Partial Reset, need to restore principal for security reasons and // event listener manager so that load listeners etc. will // remain. This should be done before the security check is done to // ensure that the document is reset even if the new document can't // be loaded. Note that we need to hold a strong ref to |principal| // here, because ResetToURI will null out our node principal before // setting the new one. nsRefPtr<nsEventListenerManager> elm(mListenerManager); mListenerManager = nullptr; // When we are called from JS we can find the load group for the page, // and add ourselves to it. This way any pending requests // will be automatically aborted if the user leaves the page. nsCOMPtr<nsILoadGroup> loadGroup; if (callingDoc) { loadGroup = callingDoc->GetDocumentLoadGroup(); } ResetToURI(uri, loadGroup, principal); mListenerManager = elm; // Create a channel nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker(); NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr<nsIChannel> channel; // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, // which in turn keeps STOP button from becoming active rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, req, nsIRequest::LOAD_BACKGROUND); if (NS_FAILED(rv)) { return rv; } // StartDocumentLoad asserts that readyState is uninitialized, so // uninitialize it. SetReadyStateInternal make this transition invisible to // Web content. But before doing that, assert that the current readyState // is complete as it should be after the call to ResetToURI() above. MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE, "Bad readyState"); SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED); // Prepare for loading the XML document "into oneself" nsCOMPtr<nsIStreamListener> listener; if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, loadGroup, nullptr, getter_AddRefs(listener), false))) { NS_ERROR("nsXMLDocument::Load: Failed to start the document load."); return rv; } // After this point, if we error out of this method we should clear // mChannelIsPending. // Start an asynchronous read of the XML document rv = channel->AsyncOpen(listener, nullptr); if (NS_FAILED(rv)) { mChannelIsPending = false; return rv; } if (!mAsync) { nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); nsAutoSyncOperation sync(this); mLoopingForSyncLoad = true; while (mLoopingForSyncLoad) { if (!NS_ProcessNextEvent(thread)) break; } // We set return to true unless there was a parsing error nsCOMPtr<nsIDOMNode> node = do_QueryInterface(GetRootElement()); if (node) { nsAutoString name, ns; if (NS_SUCCEEDED(node->GetLocalName(name)) && name.EqualsLiteral("parsererror") && NS_SUCCEEDED(node->GetNamespaceURI(ns)) && ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { //return is already false } else { *aReturn = true; } } } else { *aReturn = true; } return NS_OK; }