mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Landing followup fix for bug 402983 and re-enabling the new stricter file URI security policies. r+sr=bzbarsky@mit.edu
This commit is contained in:
parent
6329269a7d
commit
a4d3a2e2e3
@ -410,6 +410,13 @@ public:
|
||||
CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
||||
nsIPrincipal* aObject,
|
||||
PRBool aIsCheckConnect);
|
||||
|
||||
static PRBool
|
||||
GetStrictFileOriginPolicy()
|
||||
{
|
||||
return sStrictFileOriginPolicy;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// GetScriptSecurityManager is the only call that can make one
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "plstr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIFileURL.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsVoidArray.h"
|
||||
@ -304,10 +306,92 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, PRBool *aResult)
|
||||
return Equals(aOther, aResult);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
URIIsLocalFile(nsIURI *aURI)
|
||||
{
|
||||
PRBool isFile;
|
||||
nsCOMPtr<nsINetUtil> util = do_GetIOService();
|
||||
|
||||
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
||||
&isFile)) &&
|
||||
isFile;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, PRBool aReport)
|
||||
{
|
||||
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
URIIsLocalFile(aURI)) {
|
||||
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
|
||||
|
||||
if (!URIIsLocalFile(mCodebase)) {
|
||||
// If the codebase is not also a file: uri then forget it
|
||||
// (don't want resource: principals in a file: doc)
|
||||
//
|
||||
// note: we're not de-nesting jar: uris here, we want to
|
||||
// keep archive content bottled up in its own little island
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
//
|
||||
// pull out the internal files
|
||||
//
|
||||
nsCOMPtr<nsIFileURL> codebaseFileURL(do_QueryInterface(mCodebase));
|
||||
nsCOMPtr<nsIFile> targetFile;
|
||||
nsCOMPtr<nsIFile> codebaseFile;
|
||||
PRBool targetIsDir;
|
||||
|
||||
// Make sure targetFile is not a directory (bug 209234)
|
||||
// and that it exists w/out unescaping (bug 395343)
|
||||
|
||||
if (!codebaseFileURL || !fileURL ||
|
||||
NS_FAILED(fileURL->GetFile(getter_AddRefs(targetFile))) ||
|
||||
NS_FAILED(codebaseFileURL->GetFile(getter_AddRefs(codebaseFile))) ||
|
||||
!targetFile || !codebaseFile ||
|
||||
NS_FAILED(targetFile->Normalize()) ||
|
||||
NS_FAILED(codebaseFile->Normalize()) ||
|
||||
NS_FAILED(targetFile->IsDirectory(&targetIsDir)) ||
|
||||
targetIsDir) {
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
//
|
||||
// If the file to be loaded is in a subdirectory of the codebase
|
||||
// (or same-dir if codebase is not a directory) then it will
|
||||
// inherit its codebase principal and be scriptable by that codebase.
|
||||
//
|
||||
PRBool codebaseIsDir;
|
||||
PRBool contained = PR_FALSE;
|
||||
nsresult rv = codebaseFile->IsDirectory(&codebaseIsDir);
|
||||
if (NS_SUCCEEDED(rv) && codebaseIsDir) {
|
||||
rv = codebaseFile->Contains(targetFile, PR_TRUE, &contained);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIFile> codebaseParent;
|
||||
rv = codebaseFile->GetParent(getter_AddRefs(codebaseParent));
|
||||
if (NS_SUCCEEDED(rv) && codebaseParent) {
|
||||
rv = codebaseParent->Contains(targetFile, PR_TRUE, &contained);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && contained) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
|
@ -1163,6 +1163,11 @@ public:
|
||||
*/
|
||||
static void HidePopupsInDocument(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Return true if aURI is a local file URI (i.e. file://).
|
||||
*/
|
||||
static PRBool URIIsLocalFile(nsIURI *aURI);
|
||||
|
||||
/**
|
||||
* Get the application manifest URI for this context. The manifest URI
|
||||
* is specified in the manifest= attribute of the root element of the
|
||||
|
@ -4065,6 +4065,19 @@ nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsContentUtils::URIIsLocalFile(nsIURI *aURI)
|
||||
{
|
||||
PRBool isFile;
|
||||
nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
|
||||
|
||||
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
||||
&isFile)) &&
|
||||
isFile;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsAutoGCRoot::Shutdown()
|
||||
|
@ -1245,7 +1245,10 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&inheritPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (inheritPrincipal || IsAboutBlank(aURI)) {
|
||||
if (inheritPrincipal || IsAboutBlank(aURI) ||
|
||||
(nsContentUtils::URIIsLocalFile(aURI) &&
|
||||
NS_SUCCEEDED(thisContent->NodePrincipal()->CheckMayLoad(aURI,
|
||||
PR_FALSE)))) {
|
||||
chan->SetOwner(thisContent->NodePrincipal());
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,6 @@ nsDocShell::nsDocShell():
|
||||
mObserveErrorPages(PR_TRUE),
|
||||
mAllowAuth(PR_TRUE),
|
||||
mAllowKeywordFixup(PR_FALSE),
|
||||
mStrictFilePolicy(PR_TRUE),
|
||||
mFiredUnloadEvent(PR_FALSE),
|
||||
mEODForCurrentDocument(PR_FALSE),
|
||||
mURIResultedInDocument(PR_FALSE),
|
||||
@ -3593,10 +3592,6 @@ nsDocShell::Create()
|
||||
}
|
||||
}
|
||||
|
||||
rv = mPrefs->GetBoolPref("security.fileuri.strict_origin_policy", &tmpbool);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mStrictFilePolicy = tmpbool;
|
||||
|
||||
// Should we use XUL error pages instead of alerts if possible?
|
||||
rv = mPrefs->GetBoolPref("browser.xul.error_pages.enabled", &tmpbool);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
@ -7357,66 +7352,10 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
||||
// If we don't set the owner explicitly then each file: gets an owner
|
||||
// based on its own codebase later.
|
||||
//
|
||||
if (mStrictFilePolicy && URIIsLocalFile(aURI)) {
|
||||
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal(do_QueryInterface(aOwner));
|
||||
nsCOMPtr<nsIURI> ownerURI;
|
||||
if (ownerPrincipal) {
|
||||
ownerPrincipal->GetURI(getter_AddRefs(ownerURI));
|
||||
}
|
||||
|
||||
if (!URIIsLocalFile(ownerURI)) {
|
||||
// If the owner is not also a file: uri then forget it
|
||||
// (don't want resource: principals in a file: doc)
|
||||
//
|
||||
// note: we're not de-nesting jar: uris here, we want to
|
||||
// keep archive content bottled up in its own little island
|
||||
ownerURI = nsnull;
|
||||
}
|
||||
|
||||
//
|
||||
// pull out the internal files
|
||||
//
|
||||
nsCOMPtr<nsIFileURL> ownerFileURL(do_QueryInterface(ownerURI));
|
||||
nsCOMPtr<nsIFile> targetFile;
|
||||
nsCOMPtr<nsIFile> ownerFile;
|
||||
if (ownerFileURL &&
|
||||
NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(targetFile))) &&
|
||||
NS_SUCCEEDED(ownerFileURL->GetFile(getter_AddRefs(ownerFile)))) {
|
||||
//
|
||||
// Make sure targetFile is not a directory (bug 209234)
|
||||
// and that it exists w/out unescaping (bug 395343)
|
||||
//
|
||||
PRBool targetIsDir;
|
||||
if (targetFile && ownerFile &&
|
||||
NS_SUCCEEDED(targetFile->Normalize()) &&
|
||||
NS_SUCCEEDED(ownerFile->Normalize()) &&
|
||||
NS_SUCCEEDED(targetFile->IsDirectory(&targetIsDir)) &&
|
||||
!targetIsDir) {
|
||||
//
|
||||
// If the file to be loaded is in a subdirectory of the owner
|
||||
// (or same-dir if owner is not a directory) then it will
|
||||
// inherit its owner principal and be scriptable by that owner.
|
||||
//
|
||||
PRBool ownerIsDir;
|
||||
PRBool contained = PR_FALSE;
|
||||
rv = ownerFile->IsDirectory(&ownerIsDir);
|
||||
if (NS_SUCCEEDED(rv) && ownerIsDir) {
|
||||
rv = ownerFile->Contains(targetFile, PR_TRUE, &contained);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIFile> ownerParent;
|
||||
rv = ownerFile->GetParent(getter_AddRefs(ownerParent));
|
||||
if (NS_SUCCEEDED(rv) && ownerParent) {
|
||||
rv = ownerParent->Contains(targetFile, PR_TRUE, &contained);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && contained) {
|
||||
channel->SetOwner(aOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal(do_QueryInterface(aOwner));
|
||||
if (URIIsLocalFile(aURI) && ownerPrincipal &&
|
||||
NS_SUCCEEDED(ownerPrincipal->CheckMayLoad(aURI, PR_FALSE))) {
|
||||
channel->SetOwner(aOwner);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
|
||||
|
@ -551,7 +551,6 @@ protected:
|
||||
PRPackedBool mObserveErrorPages;
|
||||
PRPackedBool mAllowAuth;
|
||||
PRPackedBool mAllowKeywordFixup;
|
||||
PRPackedBool mStrictFilePolicy;
|
||||
|
||||
// This boolean is set to true right before we fire pagehide and generally
|
||||
// unset when we embed a new content viewer. While it's true no navigation
|
||||
|
@ -1436,7 +1436,10 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
||||
rv = NS_URIChainHasFlags(aLoadData->mURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&inherit);
|
||||
if (NS_SUCCEEDED(rv) && inherit) {
|
||||
if ((NS_SUCCEEDED(rv) && inherit) ||
|
||||
(nsContentUtils::URIIsLocalFile(aLoadData->mURI) &&
|
||||
NS_SUCCEEDED(aLoadData->mLoaderPrincipal->
|
||||
CheckMayLoad(aLoadData->mURI, PR_FALSE)))) {
|
||||
channel->SetOwner(aLoadData->mLoaderPrincipal);
|
||||
}
|
||||
}
|
||||
@ -1445,8 +1448,7 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
||||
// model is: Necko owns the stream loader, which owns the load data,
|
||||
// which owns us
|
||||
nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
|
||||
rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader),
|
||||
aLoadData);
|
||||
rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = channel->AsyncOpen(streamLoader, nsnull);
|
||||
|
@ -501,7 +501,7 @@ pref("advanced.mailftp", false);
|
||||
pref("image.animation_mode", "normal");
|
||||
|
||||
// Same-origin policy for file URIs, "false" is traditional
|
||||
pref("security.fileuri.strict_origin_policy", false);
|
||||
pref("security.fileuri.strict_origin_policy", true);
|
||||
|
||||
// If there is ever a security firedrill that requires
|
||||
// us to block certian ports global, this is the pref
|
||||
|
Loading…
Reference in New Issue
Block a user