Bug 1050049 - Implement bindToUntrustedContent attribute restriction. r=smaug

This commit is contained in:
Bobby Holley 2014-08-11 20:06:55 -07:00
Родитель af0cdef94f
Коммит 25f875bfcb
4 изменённых файлов: 70 добавлений и 0 удалений

Просмотреть файл

@ -132,6 +132,7 @@ GK_ATOM(bgsound, "bgsound")
GK_ATOM(big, "big")
GK_ATOM(binding, "binding")
GK_ATOM(bindings, "bindings")
GK_ATOM(bindToUntrustedContent, "bindToUntrustedContent")
GK_ATOM(blankrow, "blankrow")
GK_ATOM(block, "block")
GK_ATOM(blockquote, "blockquote")

Просмотреть файл

@ -100,6 +100,7 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding()
mCheckedBaseProto(false),
mKeyHandlersRegistered(false),
mChromeOnlyContent(false),
mBindToUntrustedContent(false),
mResources(nullptr),
mBaseNameSpaceID(kNameSpaceID_None)
{
@ -213,6 +214,10 @@ nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement)
mChromeOnlyContent = mBinding->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::chromeOnlyContent,
nsGkAtoms::_true, eCaseMatters);
mBindToUntrustedContent = mBinding->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::bindToUntrustedContent,
nsGkAtoms::_true, eCaseMatters);
}
bool

Просмотреть файл

@ -257,6 +257,7 @@ public:
nsIContent* aTemplChild);
bool ChromeOnlyContent() { return mChromeOnlyContent; }
bool BindToUntrustedContent() { return mBindToUntrustedContent; }
typedef nsClassHashtable<nsISupportsHashKey, nsXBLAttributeEntry> InnerAttributeTable;
@ -291,6 +292,7 @@ protected:
bool mCheckedBaseProto;
bool mKeyHandlersRegistered;
bool mChromeOnlyContent;
bool mBindToUntrustedContent;
nsAutoPtr<nsXBLPrototypeResources> mResources; // If we have any resources, this will be non-null.

Просмотреть файл

@ -644,6 +644,53 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
aResult, uris);
}
static bool
MayBindToContent(nsXBLPrototypeBinding* aProtoBinding, nsIContent* aBoundElement,
nsIURI* aURI)
{
// If this binding explicitly allows untrusted content, we're done.
if (aProtoBinding->BindToUntrustedContent()) {
return true;
}
// We let XUL content and content in XUL documents through, since XUL is
// restricted anyway and we want to minimize remote XUL breakage.
if (aBoundElement->IsXUL() || aBoundElement->OwnerDoc()->IsXUL()) {
return true;
}
// Similarly, we make an exception for anonymous content (which
// lives in the XBL scope), because it's already protected from content,
// and tends to use a lot of bindings that we wouldn't otherwise need to
// whitelist.
if (aBoundElement->IsInAnonymousSubtree()) {
return true;
}
// Allow if the bound content subsumes the binding.
nsCOMPtr<nsIDocument> bindingDoc = aProtoBinding->XBLDocumentInfo()->GetDocument();
NS_ENSURE_TRUE(bindingDoc, false);
if (aBoundElement->NodePrincipal()->Subsumes(bindingDoc->NodePrincipal())) {
return true;
}
// One last special case: we need to watch out for in-document data: URI
// bindings from remote-XUL-whitelisted domains (especially tests), because
// they end up with a null principal (rather than inheriting the document's
// principal), which causes them to fail the check above.
if (nsContentUtils::AllowXULXBLForPrincipal(aBoundElement->NodePrincipal())) {
bool isDataURI = false;
nsresult rv = aURI->SchemeIs("data", &isDataURI);
NS_ENSURE_SUCCESS(rv, false);
if (isDataURI) {
return true;
}
}
// Disallow.
return false;
}
nsresult
nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
bool aPeekOnly, nsIPrincipal* aOriginPrincipal,
@ -691,6 +738,21 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
return NS_ERROR_FAILURE;
}
// If the binding isn't whitelisted, refuse to apply it to content that
// doesn't subsume it (modulo a few exceptions).
if (!MayBindToContent(protoBinding, aBoundElement, aURI)) {
#ifdef DEBUG
nsAutoCString uriSpec;
aURI->GetSpec(uriSpec);
nsAutoCString message("Permission denied to apply binding ");
message += uriSpec;
message += " to unprivileged content. Set bindToUntrustedContent=true on "
"the binding to override this restriction.";
NS_WARNING(message.get());
#endif
return NS_ERROR_FAILURE;
}
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(protoBinding->BindingURI()),
NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURI> altBindingURI = protoBinding->AlternateBindingURI();