зеркало из https://github.com/mozilla/gecko-dev.git
Bug 406541 - Ensure we agree with java on applet codebase, and run security checks for file: codebase URIs. r=jst
This commit is contained in:
Родитель
e5441bb709
Коммит
92e156858b
|
@ -42,6 +42,7 @@ interface nsIObjectFrame;
|
||||||
interface nsIPluginTag;
|
interface nsIPluginTag;
|
||||||
interface nsIDOMElement;
|
interface nsIDOMElement;
|
||||||
interface nsIDOMClientRect;
|
interface nsIDOMClientRect;
|
||||||
|
interface nsIURI;
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
#include "nsNPAPIPluginInstance.h"
|
#include "nsNPAPIPluginInstance.h"
|
||||||
|
@ -51,7 +52,7 @@ interface nsIDOMClientRect;
|
||||||
/**
|
/**
|
||||||
* This interface represents a content node that loads objects.
|
* This interface represents a content node that loads objects.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
|
[scriptable, uuid(3FF07AB3-5BAC-4D98-9549-5BD15CCEBCD3)]
|
||||||
interface nsIObjectLoadingContent : nsISupports
|
interface nsIObjectLoadingContent : nsISupports
|
||||||
{
|
{
|
||||||
const unsigned long TYPE_LOADING = 0;
|
const unsigned long TYPE_LOADING = 0;
|
||||||
|
@ -79,6 +80,14 @@ interface nsIObjectLoadingContent : nsISupports
|
||||||
*/
|
*/
|
||||||
unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
|
unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the base URI to be used for this object. This differs from
|
||||||
|
* nsIContent::GetBaseURI in that it takes codebase attributes into
|
||||||
|
* account. The MIME type is required as some plugins (java) calculate
|
||||||
|
* this differently.
|
||||||
|
*/
|
||||||
|
nsIURI GetObjectBaseURI(in ACString aMimeType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the plugin instance if it has already been instantiated. This
|
* Returns the plugin instance if it has already been instantiated. This
|
||||||
* will never instantiate the plugin and so is safe to call even when
|
* will never instantiate the plugin and so is safe to call even when
|
||||||
|
|
|
@ -598,7 +598,7 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI*
|
||||||
if (!aURI) {
|
if (!aURI) {
|
||||||
// We need some URI. If we have nothing else, use the base URI.
|
// We need some URI. If we have nothing else, use the base URI.
|
||||||
// XXX(biesi): The code used to do this. Not sure why this is correct...
|
// XXX(biesi): The code used to do this. Not sure why this is correct...
|
||||||
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
GetObjectBaseURI(nsCString(aMimeType), getter_AddRefs(baseURI));
|
||||||
aURI = baseURI;
|
aURI = baseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,7 +1163,7 @@ nsObjectLoadingContent::LoadObject(const nsAString& aURI,
|
||||||
|
|
||||||
nsIDocument* doc = thisContent->OwnerDoc();
|
nsIDocument* doc = thisContent->OwnerDoc();
|
||||||
nsCOMPtr<nsIURI> baseURI;
|
nsCOMPtr<nsIURI> baseURI;
|
||||||
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
GetObjectBaseURI(aTypeHint, getter_AddRefs(baseURI));
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
||||||
|
@ -1194,6 +1194,51 @@ nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsObjectLoadingContent::IsFileCodebaseAllowable(nsIURI* aBaseURI, nsIURI* aOriginURI)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIFileURL> baseFileURL(do_QueryInterface(aBaseURI));
|
||||||
|
nsCOMPtr<nsIFileURL> originFileURL(do_QueryInterface(aOriginURI));
|
||||||
|
|
||||||
|
// get IFile handles and normalize
|
||||||
|
nsCOMPtr<nsIFile> originFile;
|
||||||
|
nsCOMPtr<nsIFile> baseFile;
|
||||||
|
if (!originFileURL || !baseFileURL ||
|
||||||
|
NS_FAILED(originFileURL->GetFile(getter_AddRefs(originFile))) ||
|
||||||
|
NS_FAILED(baseFileURL->GetFile(getter_AddRefs(baseFile))) ||
|
||||||
|
NS_FAILED(baseFile->Normalize()) ||
|
||||||
|
NS_FAILED(originFile->Normalize())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the origin is a directory, it should contain/equal baseURI
|
||||||
|
// Otherwise, its parent directory should contain/equal baseURI
|
||||||
|
bool origin_is_dir;
|
||||||
|
bool contained = false;
|
||||||
|
nsresult rv = originFile->IsDirectory(&origin_is_dir);
|
||||||
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
|
if (origin_is_dir) {
|
||||||
|
// originURI is a directory, ensure it contains the baseURI
|
||||||
|
rv = originFile->Contains(baseFile, true, &contained);
|
||||||
|
if (NS_SUCCEEDED(rv) && !contained) {
|
||||||
|
rv = originFile->Equals(baseFile, &contained);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// originURI is a file, ensure its parent contains the baseURI
|
||||||
|
nsCOMPtr<nsIFile> originParent;
|
||||||
|
rv = originFile->GetParent(getter_AddRefs(originParent));
|
||||||
|
if (NS_SUCCEEDED(rv) && originParent) {
|
||||||
|
rv = originParent->Contains(baseFile, true, &contained);
|
||||||
|
if (NS_SUCCEEDED(rv) && !contained) {
|
||||||
|
rv = originParent->Equals(baseFile, &contained);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_SUCCEEDED(rv) && contained;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||||
bool aNotify,
|
bool aNotify,
|
||||||
|
@ -1291,6 +1336,28 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||||
HandleBeingBlockedByContentPolicy(rv, shouldLoad);
|
HandleBeingBlockedByContentPolicy(rv, shouldLoad);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a file:// URI, require that the codebase (baseURI)
|
||||||
|
// is contained within the same folder as the document origin (originURI)
|
||||||
|
// or within the document origin, if it is a folder.
|
||||||
|
// No originURI implies chrome, which bypasses the check
|
||||||
|
// -- bug 406541
|
||||||
|
nsCOMPtr<nsIURI> originURI;
|
||||||
|
nsCOMPtr<nsIURI> baseURI;
|
||||||
|
GetObjectBaseURI(aTypeHint, getter_AddRefs(baseURI));
|
||||||
|
rv = thisContent->NodePrincipal()->GetURI(getter_AddRefs(originURI));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
Fallback(aNotify);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
if (originURI) {
|
||||||
|
bool isfile;
|
||||||
|
if (NS_FAILED(originURI->SchemeIs("file", &isfile)) ||
|
||||||
|
(isfile && !IsFileCodebaseAllowable(baseURI, originURI))) {
|
||||||
|
Fallback(aNotify);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||||
|
@ -1408,7 +1475,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||||
// XXX(biesi). The plugin instantiation code used to pass the base URI
|
// XXX(biesi). The plugin instantiation code used to pass the base URI
|
||||||
// here instead of the plugin URI for instantiation via class ID, so I
|
// here instead of the plugin URI for instantiation via class ID, so I
|
||||||
// continue to do so. Why that is, no idea...
|
// continue to do so. Why that is, no idea...
|
||||||
GetObjectBaseURI(thisContent, getter_AddRefs(mURI));
|
GetObjectBaseURI(mContentType, getter_AddRefs(mURI));
|
||||||
if (!mURI) {
|
if (!mURI) {
|
||||||
mURI = aURI;
|
mURI = aURI;
|
||||||
}
|
}
|
||||||
|
@ -1785,25 +1852,29 @@ nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
NS_IMETHODIMP
|
||||||
nsObjectLoadingContent::GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI)
|
nsObjectLoadingContent::GetObjectBaseURI(const nsACString & aMimeType, nsIURI** aURI)
|
||||||
{
|
{
|
||||||
// We want to use swap(); since this is just called from this file,
|
nsCOMPtr<nsIContent> thisContent =
|
||||||
// we can assert this (callers use comptrs)
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||||
NS_PRECONDITION(*aURI == nsnull, "URI must be inited to zero");
|
|
||||||
|
|
||||||
// For plugins, the codebase attribute is the base URI
|
// For plugins, the codebase attribute is the base URI
|
||||||
nsCOMPtr<nsIURI> baseURI = thisContent->GetBaseURI();
|
nsCOMPtr<nsIURI> baseURI = thisContent->GetBaseURI();
|
||||||
nsAutoString codebase;
|
nsAutoString codebase;
|
||||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase,
|
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase,
|
||||||
codebase);
|
codebase);
|
||||||
if (!codebase.IsEmpty()) {
|
|
||||||
nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
|
if (codebase.IsEmpty() && aMimeType.Equals("application/x-java-vm")) {
|
||||||
thisContent->OwnerDoc(),
|
// bug 406541
|
||||||
baseURI);
|
// Java resolves codebase="" as "/" -- so we replicate that quirk, to ensure
|
||||||
} else {
|
// we run security checks against the same path.
|
||||||
baseURI.swap(*aURI);
|
codebase.AssignLiteral("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
|
||||||
|
thisContent->OwnerDoc(),
|
||||||
|
baseURI);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsObjectFrame*
|
nsObjectFrame*
|
||||||
|
|
|
@ -253,6 +253,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||||
*/
|
*/
|
||||||
static bool IsSuccessfulRequest(nsIRequest* aRequest);
|
static bool IsSuccessfulRequest(nsIRequest* aRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given baseURI is contained in the same directory as the
|
||||||
|
* aOriginURI (or a child thereof)
|
||||||
|
*/
|
||||||
|
static bool IsFileCodebaseAllowable(nsIURI* aBaseURI, nsIURI* aOriginURI);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the URI can be handled internally.
|
* Check whether the URI can be handled internally.
|
||||||
*/
|
*/
|
||||||
|
@ -299,14 +305,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||||
*/
|
*/
|
||||||
nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
|
nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the base URI to be used for this object. This differs from
|
|
||||||
* nsIContent::GetBaseURI in that it takes codebase attributes into
|
|
||||||
* account.
|
|
||||||
*/
|
|
||||||
void GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the frame that's associated with this content node.
|
* Gets the frame that's associated with this content node.
|
||||||
* Does not flush.
|
* Does not flush.
|
||||||
|
|
|
@ -95,6 +95,7 @@ using mozilla::DefaultXDisplay;
|
||||||
#include "nsIDOMDragEvent.h"
|
#include "nsIDOMDragEvent.h"
|
||||||
#include "nsIScrollableFrame.h"
|
#include "nsIScrollableFrame.h"
|
||||||
#include "nsIImageLoadingContent.h"
|
#include "nsIImageLoadingContent.h"
|
||||||
|
#include "nsIObjectLoadingContent.h"
|
||||||
|
|
||||||
#include "nsContentCID.h"
|
#include "nsContentCID.h"
|
||||||
#include "nsWidgetsCID.h"
|
#include "nsWidgetsCID.h"
|
||||||
|
@ -1195,6 +1196,31 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||||
mNumCachedAttrs++;
|
mNumCachedAttrs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some plugins (java, bug 406541) don't canonicalize the 'codebase' attribute
|
||||||
|
// in a standard way - codebase="" results in / (domain root), but
|
||||||
|
// codebase="blah" results in ./blah; codebase="file:" results in "file:///".
|
||||||
|
// We canonicalize codebase here to ensure the codebase we run security checks
|
||||||
|
// against is the same codebase java uses.
|
||||||
|
// Note that GetObjectBaseURI mimics some of java's quirks for maximal
|
||||||
|
// compatibility.
|
||||||
|
const char* mime = nsnull;
|
||||||
|
bool addCodebase = false;
|
||||||
|
nsCAutoString codebaseSpec;
|
||||||
|
if (mInstance && NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime &&
|
||||||
|
strcmp(mime, "application/x-java-vm") == 0) {
|
||||||
|
addCodebase = true;
|
||||||
|
nsCOMPtr<nsIObjectLoadingContent> objlContent = do_QueryInterface(mContent);
|
||||||
|
nsCOMPtr<nsIURI> codebaseURI;
|
||||||
|
objlContent->GetObjectBaseURI(nsCString(mime), getter_AddRefs(codebaseURI));
|
||||||
|
nsresult rv = codebaseURI->GetSpec(codebaseSpec);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Make space if codebase isn't already set
|
||||||
|
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) {
|
||||||
|
mNumCachedAttrs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
||||||
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
|
||||||
mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
||||||
|
@ -1248,12 +1274,22 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||||
mNumCachedAttrs--;
|
mNumCachedAttrs--;
|
||||||
wmodeSet = true;
|
wmodeSet = true;
|
||||||
}
|
}
|
||||||
|
} else if (addCodebase && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) {
|
||||||
|
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseSpec));
|
||||||
|
addCodebase = false;
|
||||||
} else {
|
} else {
|
||||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
|
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
|
||||||
}
|
}
|
||||||
nextAttrParamIndex++;
|
nextAttrParamIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pontentially add CODEBASE attribute
|
||||||
|
if (addCodebase) {
|
||||||
|
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase"));
|
||||||
|
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseSpec));
|
||||||
|
nextAttrParamIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
// Potentially add WMODE attribute.
|
// Potentially add WMODE attribute.
|
||||||
if (!wmodeType.IsEmpty() && !wmodeSet) {
|
if (!wmodeType.IsEmpty() && !wmodeSet) {
|
||||||
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
|
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче