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.
|
||||
|
||||
Reference in New Issue
Block a user