Bug 475636: Disallow refresh to javascript uris. r/sr=bz a=dveditz
git-svn-id: svn://10.0.0.236/trunk@256571 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -692,6 +692,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
||||
nsCOMPtr<nsIInputStream> headersStream;
|
||||
nsCOMPtr<nsISupports> owner;
|
||||
PRBool inheritOwner = PR_FALSE;
|
||||
PRBool ownerIsExplicit = PR_FALSE;
|
||||
PRBool sendReferrer = PR_TRUE;
|
||||
nsCOMPtr<nsISHEntry> shEntry;
|
||||
nsXPIDLString target;
|
||||
@@ -715,6 +716,12 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
||||
aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
|
||||
aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
|
||||
aLoadInfo->GetSendReferrer(&sendReferrer);
|
||||
|
||||
nsCOMPtr<nsIDocShellLoadInfo_1_9_0_BRANCH> info19 =
|
||||
do_QueryInterface(aLoadInfo);
|
||||
if (info19) {
|
||||
info19->GetOwnerIsExplicit(&ownerIsExplicit);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PR_LOGGING) && defined(DEBUG)
|
||||
@@ -827,84 +834,99 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
||||
("nsDocShell[%p]: loading from session history", this));
|
||||
#endif
|
||||
|
||||
rv = LoadHistoryEntry(shEntry, loadType);
|
||||
return LoadHistoryEntry(shEntry, loadType);
|
||||
}
|
||||
|
||||
// Perform the load...
|
||||
else {
|
||||
// We need an owner (a referring principal). 4 possibilities:
|
||||
// (1) If the system principal was passed in and we're a typeContent
|
||||
// docshell, inherit the principal from the current document
|
||||
// instead.
|
||||
// (2) In all other cases when the principal passed in is not null,
|
||||
// use that principal.
|
||||
// (3) If the caller has allowed inheriting from the current document,
|
||||
// or if we're being called from system code (eg chrome JS or pure
|
||||
// C++) then inheritOwner should be true and InternalLoad will get
|
||||
// an owner from the current document. If none of these things are
|
||||
// true, then
|
||||
// (4) we pass a null owner into the channel, and an owner will be
|
||||
// created later from the channel's internal data.
|
||||
//
|
||||
// NOTE: This all only works because the only thing the owner is used
|
||||
// for in InternalLoad is data:, javascript:, and about:blank
|
||||
// URIs. For other URIs this would all be dead wrong!
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
|
||||
// We need an owner (a referring principal).
|
||||
//
|
||||
// If ownerIsExplicit is not set there are 4 possibilities:
|
||||
// (1) If the system principal was passed in and we're a typeContent
|
||||
// docshell, inherit the principal from the current document
|
||||
// instead.
|
||||
// (2) In all other cases when the principal passed in is not null,
|
||||
// use that principal.
|
||||
// (3) If the caller has allowed inheriting from the current document,
|
||||
// or if we're being called from system code (eg chrome JS or pure
|
||||
// C++) then inheritOwner should be true and InternalLoad will get
|
||||
// an owner from the current document. If none of these things are
|
||||
// true, then
|
||||
// (4) we pass a null owner into the channel, and an owner will be
|
||||
// created later from the channel's internal data.
|
||||
//
|
||||
// If ownerIsExplicit *is* set, there are 4 possibilities
|
||||
// (1) If the system principal was passed in and we're a typeContent
|
||||
// docshell, return an error.
|
||||
// (2) In all other cases when the principal passed in is not null,
|
||||
// use that principal.
|
||||
// (3) If the caller has allowed inheriting from the current document,
|
||||
// then inheritOwner should be true and InternalLoad will get an owner
|
||||
// from the current document. If none of these things are true, then
|
||||
// (4) we pass a null owner into the channel, and an owner will be
|
||||
// created later from the channel's internal data.
|
||||
//
|
||||
// NOTE: This all only works because the only thing the owner is used
|
||||
// for in InternalLoad is data:, javascript:, and about:blank
|
||||
// URIs. For other URIs this would all be dead wrong!
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (owner && mItemType != typeChrome) {
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
|
||||
PRBool isSystem;
|
||||
rv = secMan->IsSystemPrincipal(ownerPrincipal, &isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (owner && mItemType != typeChrome) {
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
|
||||
PRBool isSystem;
|
||||
rv = secMan->IsSystemPrincipal(ownerPrincipal, &isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isSystem) {
|
||||
owner = nsnull;
|
||||
inheritOwner = PR_TRUE;
|
||||
if (isSystem) {
|
||||
if (ownerIsExplicit) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
owner = nsnull;
|
||||
inheritOwner = PR_TRUE;
|
||||
}
|
||||
if (!owner && !inheritOwner) {
|
||||
// See if there's system or chrome JS code running
|
||||
rv = secMan->SubjectPrincipalIsSystem(&inheritOwner);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Set it back to false
|
||||
inheritOwner = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (!owner && !inheritOwner && !ownerIsExplicit) {
|
||||
// See if there's system or chrome JS code running
|
||||
rv = secMan->SubjectPrincipalIsSystem(&inheritOwner);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Set it back to false
|
||||
inheritOwner = PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint32 flags = 0;
|
||||
|
||||
if (inheritOwner)
|
||||
flags |= INTERNAL_LOAD_FLAGS_INHERIT_OWNER;
|
||||
|
||||
if (!sendReferrer)
|
||||
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
|
||||
flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
|
||||
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER)
|
||||
flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
|
||||
|
||||
rv = InternalLoad(aURI,
|
||||
referrer,
|
||||
owner,
|
||||
flags,
|
||||
target.get(),
|
||||
nsnull, // No type hint
|
||||
postStream,
|
||||
headersStream,
|
||||
loadType,
|
||||
nsnull, // No SHEntry
|
||||
aFirstParty,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
}
|
||||
|
||||
return rv;
|
||||
PRUint32 flags = 0;
|
||||
|
||||
if (inheritOwner)
|
||||
flags |= INTERNAL_LOAD_FLAGS_INHERIT_OWNER;
|
||||
|
||||
if (!sendReferrer)
|
||||
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
|
||||
flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
|
||||
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER)
|
||||
flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
|
||||
|
||||
return InternalLoad(aURI,
|
||||
referrer,
|
||||
owner,
|
||||
flags,
|
||||
target.get(),
|
||||
nsnull, // No type hint
|
||||
postStream,
|
||||
headersStream,
|
||||
loadType,
|
||||
nsnull, // No SHEntry
|
||||
aFirstParty,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -4440,41 +4462,45 @@ nsDocShell::ForceRefreshURI(nsIURI * aURI,
|
||||
*/
|
||||
loadInfo->SetReferrer(mCurrentURI);
|
||||
|
||||
/* Don't ever "guess" on which owner to use to avoid picking
|
||||
* the current owner.
|
||||
*/
|
||||
nsCOMPtr<nsIDocShellLoadInfo_1_9_0_BRANCH> info19 =
|
||||
do_QueryInterface(loadInfo);
|
||||
NS_ENSURE_TRUE(info19, NS_ERROR_NO_INTERFACE);
|
||||
info19->SetOwnerIsExplicit(PR_TRUE);
|
||||
|
||||
/* Check if this META refresh causes a redirection
|
||||
* to another site.
|
||||
*/
|
||||
PRBool equalUri = PR_FALSE;
|
||||
nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
|
||||
if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh) {
|
||||
if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
|
||||
aDelay <= REFRESH_REDIRECT_TIMER) {
|
||||
|
||||
/* It is a META refresh based redirection. Now check if it happened
|
||||
within the threshold time we have in mind(15000 ms as defined by
|
||||
REFRESH_REDIRECT_TIMER). If so, pass a REPLACE flag to LoadURI().
|
||||
/* It is a META refresh based redirection within the threshold time
|
||||
* we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
|
||||
* Pass a REPLACE flag to LoadURI().
|
||||
*/
|
||||
if (aDelay <= REFRESH_REDIRECT_TIMER) {
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
|
||||
|
||||
/* for redirects we mimic HTTP, which passes the
|
||||
* original referrer
|
||||
*/
|
||||
nsCOMPtr<nsIURI> internalReferrer;
|
||||
GetReferringURI(getter_AddRefs(internalReferrer));
|
||||
if (internalReferrer) {
|
||||
loadInfo->SetReferrer(internalReferrer);
|
||||
}
|
||||
}
|
||||
else
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
|
||||
/*
|
||||
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||
* Timer and its refreshData instance to be released...
|
||||
/* for redirects we mimic HTTP, which passes the
|
||||
* original referrer
|
||||
*/
|
||||
LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE);
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIURI> internalReferrer;
|
||||
GetReferringURI(getter_AddRefs(internalReferrer));
|
||||
if (internalReferrer) {
|
||||
loadInfo->SetReferrer(internalReferrer);
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
|
||||
}
|
||||
|
||||
/*
|
||||
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||
* Timer and its refreshData instance to be released...
|
||||
*/
|
||||
LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
@@ -4690,6 +4716,20 @@ nsDocShell::SetupRefreshURIFromHeader(nsIURI * aBaseURI,
|
||||
CheckLoadURI(aBaseURI, uri,
|
||||
nsIScriptSecurityManager::
|
||||
LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
|
||||
NS_ENSURE_TRUE(innerURI, NS_ERROR_FAILURE);
|
||||
|
||||
PRBool isjs = PR_TRUE;
|
||||
rv = innerURI->SchemeIs("javascript", &isjs);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isjs) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Since we can't travel back in time yet, just pretend
|
||||
// negative numbers do nothing at all.
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
|
||||
nsDocShellLoadInfo::nsDocShellLoadInfo()
|
||||
: mInheritOwner(PR_FALSE),
|
||||
mOwnerIsExplicit(PR_FALSE),
|
||||
mSendReferrer(PR_TRUE),
|
||||
mLoadType(nsIDocShellLoadInfo::loadNormal)
|
||||
{
|
||||
@@ -68,6 +69,7 @@ NS_IMPL_RELEASE(nsDocShellLoadInfo)
|
||||
NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_1_9_0_BRANCH)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
//*****************************************************************************
|
||||
@@ -118,6 +120,18 @@ NS_IMETHODIMP nsDocShellLoadInfo::SetInheritOwner(PRBool aInheritOwner)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShellLoadInfo::GetOwnerIsExplicit(PRBool* aOwnerIsExplicit)
|
||||
{
|
||||
*aOwnerIsExplicit = mOwnerIsExplicit;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShellLoadInfo::SetOwnerIsExplicit(PRBool aOwnerIsExplicit)
|
||||
{
|
||||
mOwnerIsExplicit = aOwnerIsExplicit;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShellLoadInfo::GetLoadType(nsDocShellInfoLoadType * aLoadType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoadType);
|
||||
|
||||
@@ -51,13 +51,14 @@
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISHEntry.h"
|
||||
|
||||
class nsDocShellLoadInfo : public nsIDocShellLoadInfo
|
||||
class nsDocShellLoadInfo : public nsIDocShellLoadInfo_1_9_0_BRANCH
|
||||
{
|
||||
public:
|
||||
nsDocShellLoadInfo();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOCSHELLLOADINFO
|
||||
NS_DECL_NSIDOCSHELLLOADINFO_1_9_0_BRANCH
|
||||
|
||||
protected:
|
||||
virtual ~nsDocShellLoadInfo();
|
||||
@@ -66,6 +67,7 @@ protected:
|
||||
nsCOMPtr<nsIURI> mReferrer;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
PRPackedBool mInheritOwner;
|
||||
PRPackedBool mOwnerIsExplicit;
|
||||
PRPackedBool mSendReferrer;
|
||||
nsDocShellInfoLoadType mLoadType;
|
||||
nsCOMPtr<nsISHEntry> mSHEntry;
|
||||
|
||||
@@ -106,3 +106,15 @@ interface nsIDocShellLoadInfo : nsISupports
|
||||
*/
|
||||
attribute boolean sendReferrer;
|
||||
};
|
||||
|
||||
[scriptable, uuid(b66d94ba-4457-41b1-9507-79c1cd873da0)]
|
||||
interface nsIDocShellLoadInfo_1_9_0_BRANCH : nsIDocShellLoadInfo
|
||||
{
|
||||
/** If this attribute is true only ever use the owner specify by
|
||||
* the owner and inheritOwner attributes.
|
||||
* If there are security reasons for why this is unsafe, such
|
||||
* as trying to use a systemprincipal owner for a content docshell
|
||||
* the load fails.
|
||||
*/
|
||||
attribute boolean ownerIsExplicit;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user