Skip to content

Commit

Permalink
Bug 752529 - workers shouldn't use string origins as null principals …
Browse files Browse the repository at this point in the history
…don't have them. Part 2 - nsPrincipal GetBaseDomain (r=bz)
  • Loading branch information
Ian Melven committed Jan 8, 2013
1 parent e1ae879 commit 1b59243
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 48 deletions.
2 changes: 2 additions & 0 deletions caps/include/nsPrincipal.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class nsPrincipal : public nsBasePrincipal
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain);
#ifdef DEBUG
virtual void dumpImpl();
#endif
Expand Down Expand Up @@ -154,6 +155,7 @@ class nsExpandedPrincipal : public nsIExpandedPrincipal, public nsBasePrincipal
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain);
#ifdef DEBUG
virtual void dumpImpl();
#endif
Expand Down
7 changes: 7 additions & 0 deletions caps/src/nsNullPrincipal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ nsNullPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
return NS_OK;
}

NS_IMETHODIMP
nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
{
// For a null principal, we use our unique uuid as the base domain.
return mURI->GetPath(aBaseDomain);
}

/**
* nsISerializable implementation
*/
Expand Down
58 changes: 44 additions & 14 deletions caps/src/nsPrincipal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozIThirdPartyUtil.h"
#include "nscore.h"
#include "nsScriptSecurityManager.h"
#include "nsString.h"
Expand Down Expand Up @@ -441,7 +442,7 @@ nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrinc
nsScriptSecurityManager::ReportError(
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
}

return NS_ERROR_DOM_BAD_URI;
}

Expand Down Expand Up @@ -485,7 +486,7 @@ nsPrincipal::SetDomain(nsIURI* aDomain)
{
mDomain = NS_TryToMakeImmutable(aDomain);
mDomainImmutable = URIIsImmutable(mDomain);

// Domain has changed, forget cached security policy
SetSecurityPolicy(nullptr);

Expand Down Expand Up @@ -556,6 +557,29 @@ nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
return NS_OK;
}

NS_IMETHODIMP
nsPrincipal::GetBaseDomain(nsACString& aBaseDomain)
{
// For a file URI, we return the file path.
if (URIIsLocalFile(mCodebase)) {
nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase);

if (url) {
return url->GetFilePath(aBaseDomain);
}
}

// For everything else, we ask the TLD service via
// the ThirdPartyUtil.
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID);
if (thirdPartyUtil) {
return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
}

return NS_OK;
}

NS_IMETHODIMP
nsPrincipal::Read(nsIObjectInputStream* aStream)
{
Expand Down Expand Up @@ -688,20 +712,20 @@ nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWh
nsExpandedPrincipal::~nsExpandedPrincipal()
{ }

NS_IMETHODIMP
NS_IMETHODIMP
nsExpandedPrincipal::GetDomain(nsIURI** aDomain)
{
*aDomain = nullptr;
return NS_OK;
}

NS_IMETHODIMP
NS_IMETHODIMP
nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
{
return NS_OK;
}

NS_IMETHODIMP
NS_IMETHODIMP
nsExpandedPrincipal::GetOrigin(char** aOrigin)
{
*aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC));
Expand All @@ -713,10 +737,10 @@ typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOt
#define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN))

// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsIgnoringDomain
// shares the same logic. The difference only that Equals requires 'this'
// and 'aOther' to Subsume each other while EqualsIgnoringDomain requires
// shares the same logic. The difference only that Equals requires 'this'
// and 'aOther' to Subsume each other while EqualsIgnoringDomain requires
// bidirectional SubsumesIgnoringDomain.
static nsresult
static nsresult
Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
bool* aResult)
{
Expand Down Expand Up @@ -750,14 +774,14 @@ nsExpandedPrincipal::EqualsIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesIgnoringDomain
// shares the same logic. The difference only that Subsumes calls are replaced
//with SubsumesIgnoringDomain calls in the second case.
static nsresult
Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
static nsresult
Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
bool* aResult)
{
nsresult rv;
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
if (expanded) {
// If aOther is an ExpandedPrincipal too, check if all of its
// If aOther is an ExpandedPrincipal too, check if all of its
// principals are subsumed.
nsTArray< nsCOMPtr<nsIPrincipal> >* otherList;
expanded->GetWhiteList(&otherList);
Expand All @@ -766,7 +790,7 @@ Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther
NS_ENSURE_SUCCESS(rv, rv);
if (!*aResult) {
// If we don't subsume at least one principal of aOther, return false.
return NS_OK;
return NS_OK;
}
}
} else {
Expand Down Expand Up @@ -826,7 +850,7 @@ nsExpandedPrincipal::GetURI(nsIURI** aURI)
return NS_OK;
}

NS_IMETHODIMP
NS_IMETHODIMP
nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
{
*aWhiteList = &mPrincipals;
Expand Down Expand Up @@ -874,6 +898,12 @@ nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
return NS_OK;
}

NS_IMETHODIMP
nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
{
return NS_ERROR_NOT_AVAILABLE;
}

void
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{
Expand Down
7 changes: 7 additions & 0 deletions caps/src/nsSystemPrincipal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ nsSystemPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
return NS_OK;
}

NS_IMETHODIMP
nsSystemPrincipal::GetBaseDomain(nsACString& aBaseDomain)
{
// No base domain for chrome.
return NS_OK;
}

//////////////////////////////////////////
// Methods implementing nsISerializable //
//////////////////////////////////////////
Expand Down
62 changes: 28 additions & 34 deletions dom/workers/WorkerPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "WorkerPrivate.h"

#include "mozIThirdPartyUtil.h"
#include "nsIClassInfo.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIConsoleService.h"
Expand Down Expand Up @@ -2476,41 +2475,36 @@ WorkerPrivate::Create(JSContext* aCx, JSObject* aObj, WorkerPrivate* aParent,
return nullptr;
}

nsCOMPtr<nsIURI> codebase;
if (NS_FAILED(principal->GetURI(getter_AddRefs(codebase)))) {
JS_ReportError(aCx, "Could not determine codebase!");
return nullptr;
}

NS_NAMED_LITERAL_CSTRING(file, "file");

bool isFile;
if (NS_FAILED(codebase->SchemeIs(file.get(), &isFile))) {
JS_ReportError(aCx, "Could not determine if codebase is file!");
return nullptr;
}

if (isFile) {
// XXX Fix this, need a real domain here.
domain = file;
}
// Workaround for workers needing a string domain - will be fixed
// in a followup after this lands.
else if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) {
if (NS_FAILED(codebase->GetAsciiSpec(domain))) {
JS_ReportError(aCx, "Could not get URI's spec for sandboxed document!");
return nullptr;
// We use the document's base domain to limit the number of workers
// each domain can create. For sandboxed documents, we use the domain
// of their first non-sandboxed document, walking up until we find
// one. If we can't find one, we fall back to using the GUID of the
// null principal as the base domain.
if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) {
nsCOMPtr<nsIDocument> tmpDoc = document;
do {
tmpDoc = tmpDoc->GetParentDocument();
} while (tmpDoc && tmpDoc->GetSandboxFlags() & SANDBOXED_ORIGIN);

if (tmpDoc) {
// There was an unsandboxed ancestor, yay!
nsCOMPtr<nsIPrincipal> tmpPrincipal = tmpDoc->NodePrincipal();

if (NS_FAILED(tmpPrincipal->GetBaseDomain(domain))) {
JS_ReportError(aCx, "Could not determine base domain!");
return nullptr;
}
} else {
// No unsandboxed ancestor, use our GUID.
if (NS_FAILED(principal->GetBaseDomain(domain))) {
JS_ReportError(aCx, "Could not determine base domain!");
return nullptr;
}
}
} else {
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID);
if (!thirdPartyUtil) {
JS_ReportError(aCx, "Could not get third party helper service!");
return nullptr;
}

if (NS_FAILED(thirdPartyUtil->GetBaseDomain(codebase, domain))) {
JS_ReportError(aCx, "Could not get domain!");
// Document creating the worker is not sandboxed.
if (NS_FAILED(principal->GetBaseDomain(domain))) {
JS_ReportError(aCx, "Could not determine base domain!");
return nullptr;
}
}
Expand Down

0 comments on commit 1b59243

Please sign in to comment.