2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=2 sw=2 et tw=80: */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2003
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Christopher A. Aillon <christopher@aillon.com>
|
|
|
|
* Giorgio Maone <g.maone@informaction.com>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsScriptSecurityManager.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "plstr.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsIURI.h"
|
2008-03-22 09:50:47 -07:00
|
|
|
#include "nsIFileURL.h"
|
|
|
|
#include "nsIProtocolHandler.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsJSPrincipals.h"
|
2009-06-16 05:38:51 -07:00
|
|
|
#include "nsVoidArray.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsHashtable.h"
|
|
|
|
#include "nsIObjectInputStream.h"
|
|
|
|
#include "nsIObjectOutputStream.h"
|
|
|
|
#include "nsIClassInfoImpl.h"
|
2008-02-26 19:45:29 -08:00
|
|
|
#include "nsDOMError.h"
|
2010-01-22 13:38:21 -08:00
|
|
|
#include "nsIContentSecurityPolicy.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsPrincipal.h"
|
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
2009-06-16 04:00:06 -07:00
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
using namespace mozilla;
|
2009-06-16 04:00:06 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
static bool gCodeBasePrincipalSupport = false;
|
|
|
|
static bool gIsObservingCodeBasePrincipalSupport = false;
|
2009-06-16 04:00:06 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
static bool URIIsImmutable(nsIURI* aURI)
|
2007-06-18 08:07:02 -07:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isMutable;
|
2007-06-18 08:07:02 -07:00
|
|
|
return
|
|
|
|
mutableObj &&
|
|
|
|
NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
|
|
|
|
!isMutable;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Static member variables
|
|
|
|
PRInt32 nsPrincipal::sCapabilitiesOrdinal = 0;
|
|
|
|
const char nsPrincipal::sInvalid[] = "Invalid";
|
|
|
|
|
|
|
|
|
2010-06-22 09:59:57 -07:00
|
|
|
NS_IMPL_CLASSINFO(nsPrincipal, NULL, nsIClassInfo::MAIN_THREAD_ONLY,
|
|
|
|
NS_PRINCIPAL_CID)
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
|
|
|
|
nsIPrincipal,
|
|
|
|
nsISerializable)
|
|
|
|
NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
|
|
|
|
nsIPrincipal,
|
|
|
|
nsISerializable)
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
nsPrincipal::AddRef()
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
|
|
|
|
// XXXcaa does this need to be threadsafe? See bug 143559.
|
2011-03-28 12:58:49 -07:00
|
|
|
nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
nsPrincipal::Release()
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
|
2011-03-28 12:58:49 -07:00
|
|
|
nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_LOG_RELEASE(this, count, "nsPrincipal");
|
|
|
|
if (count == 0) {
|
2010-07-05 02:42:18 -07:00
|
|
|
delete this;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPrincipal::nsPrincipal()
|
2007-09-28 07:31:04 -07:00
|
|
|
: mCapabilities(nsnull),
|
2007-03-22 10:30:00 -07:00
|
|
|
mSecurityPolicy(nsnull),
|
|
|
|
mTrusted(PR_FALSE),
|
2007-06-18 08:07:02 -07:00
|
|
|
mInitialized(PR_FALSE),
|
|
|
|
mCodebaseImmutable(PR_FALSE),
|
|
|
|
mDomainImmutable(PR_FALSE)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-06-19 20:00:16 -07:00
|
|
|
if (!gIsObservingCodeBasePrincipalSupport) {
|
|
|
|
nsresult rv =
|
|
|
|
Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
|
|
|
|
"signed.applets.codebase_principal_support",
|
|
|
|
PR_FALSE);
|
|
|
|
gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
|
|
|
|
NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
|
|
|
|
"Installing gCodeBasePrincipalSupport failed!");
|
2009-06-16 04:00:06 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPrincipal::Init(const nsACString& aCertFingerprint,
|
|
|
|
const nsACString& aSubjectName,
|
|
|
|
const nsACString& aPrettyName,
|
|
|
|
nsISupports* aCert,
|
|
|
|
nsIURI *aCodebase)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(!mInitialized);
|
|
|
|
NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() || aCodebase); // better have one of these.
|
|
|
|
|
|
|
|
mInitialized = PR_TRUE;
|
|
|
|
|
2007-06-18 08:07:02 -07:00
|
|
|
mCodebase = NS_TryToMakeImmutable(aCodebase);
|
|
|
|
mCodebaseImmutable = URIIsImmutable(mCodebase);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if (!aCertFingerprint.IsEmpty()) {
|
|
|
|
rv = SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2007-09-28 07:31:04 -07:00
|
|
|
rv = mJSPrincipals.Init(this, mCert->fingerprint);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCAutoString spec;
|
|
|
|
rv = mCodebase->GetSpec(spec);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2007-09-28 07:31:04 -07:00
|
|
|
rv = mJSPrincipals.Init(this, spec);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrincipal::Init() failed");
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPrincipal::~nsPrincipal(void)
|
|
|
|
{
|
|
|
|
SetSecurityPolicy(nsnull);
|
2007-09-28 07:31:04 -07:00
|
|
|
delete mCapabilities;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!");
|
|
|
|
|
|
|
|
JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
|
|
|
|
*jsprin = &mJSPrincipals;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetOrigin(char **aOrigin)
|
|
|
|
{
|
|
|
|
*aOrigin = nsnull;
|
|
|
|
|
2008-03-18 17:27:56 -07:00
|
|
|
nsCOMPtr<nsIURI> origin;
|
|
|
|
if (mCodebase) {
|
|
|
|
origin = NS_GetInnermostURI(mCodebase);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-03-18 17:27:56 -07:00
|
|
|
if (!origin) {
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(mCert, "No Domain or Codebase for a non-cert principal");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCAutoString hostPort;
|
|
|
|
|
|
|
|
// chrome: URLs don't have a meaningful origin, so make
|
|
|
|
// sure we just get the full spec for them.
|
|
|
|
// XXX this should be removed in favor of the solution in
|
|
|
|
// bug 160042.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isChrome;
|
2008-03-18 17:27:56 -07:00
|
|
|
nsresult rv = origin->SchemeIs("chrome", &isChrome);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_SUCCEEDED(rv) && !isChrome) {
|
2008-03-18 17:27:56 -07:00
|
|
|
rv = origin->GetHostPort(hostPort);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && !isChrome) {
|
|
|
|
nsCAutoString scheme;
|
2008-03-18 17:27:56 -07:00
|
|
|
rv = origin->GetScheme(scheme);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
*aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Some URIs (e.g., nsSimpleURI) don't support host. Just
|
|
|
|
// get the full spec.
|
|
|
|
nsCAutoString spec;
|
2008-03-18 17:27:56 -07:00
|
|
|
rv = origin->GetSpec(spec);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
*aOrigin = ToNewCString(spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
|
|
|
|
{
|
|
|
|
if (mSecurityPolicy && mSecurityPolicy->IsInvalid())
|
|
|
|
SetSecurityPolicy(nsnull);
|
|
|
|
|
|
|
|
*aSecurityPolicy = (void *) mSecurityPolicy;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
|
|
|
|
{
|
2007-07-08 00:08:04 -07:00
|
|
|
DomainPolicy *newPolicy = reinterpret_cast<DomainPolicy *>(aSecurityPolicy);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (newPolicy)
|
|
|
|
newPolicy->Hold();
|
|
|
|
|
|
|
|
if (mSecurityPolicy)
|
|
|
|
mSecurityPolicy->Drop();
|
|
|
|
|
|
|
|
mSecurityPolicy = newPolicy;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2011-05-19 04:31:54 -07:00
|
|
|
nsPrincipal::CertificateEquals(nsIPrincipal *aOther)
|
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool otherHasCert;
|
2011-05-19 04:31:54 -07:00
|
|
|
aOther->GetHasCertificate(&otherHasCert);
|
|
|
|
if (otherHasCert != (mCert != nsnull)) {
|
|
|
|
// One has a cert while the other doesn't. Not equal.
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCert)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
nsCAutoString str;
|
|
|
|
aOther->GetFingerprint(str);
|
|
|
|
if (!str.Equals(mCert->fingerprint))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
// If either subject name is empty, just let the result stand (so that
|
|
|
|
// nsScriptSecurityManager::SetCanEnableCapability works), but if they're
|
|
|
|
// both non-empty, only claim equality if they're equal.
|
|
|
|
if (!mCert->subjectName.IsEmpty()) {
|
|
|
|
// Check the other principal's subject name
|
|
|
|
aOther->GetSubjectName(str);
|
|
|
|
return str.Equals(mCert->subjectName) || str.IsEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (!aOther) {
|
|
|
|
NS_WARNING("Need a principal to compare this to!");
|
2011-05-19 04:31:54 -07:00
|
|
|
*aResult = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this != aOther) {
|
2011-05-19 04:31:54 -07:00
|
|
|
if (!CertificateEquals(aOther)) {
|
|
|
|
*aResult = PR_FALSE;
|
2008-03-18 14:14:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-03-18 14:14:49 -07:00
|
|
|
if (mCert) {
|
2007-06-18 08:01:53 -07:00
|
|
|
// If either principal has no URI, it's the saved principal from
|
|
|
|
// preferences; in that case, test true. Do NOT test true if the two
|
|
|
|
// principals have URIs with different codebases.
|
|
|
|
nsCOMPtr<nsIURI> otherURI;
|
|
|
|
nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
*aResult = PR_FALSE;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!otherURI || !mCodebase) {
|
2011-05-19 04:31:54 -07:00
|
|
|
*aResult = PR_TRUE;
|
2007-06-18 08:01:53 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through to the codebase comparison.
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Codebases are equal if they have the same origin.
|
|
|
|
*aResult =
|
2008-03-18 14:14:49 -07:00
|
|
|
NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
|
2010-02-02 02:29:15 -08:00
|
|
|
aOther));
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aResult = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-05-19 04:31:54 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsPrincipal::EqualsIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
|
2011-05-19 04:31:54 -07:00
|
|
|
{
|
|
|
|
if (this == aOther) {
|
|
|
|
*aResult = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aResult = PR_FALSE;
|
|
|
|
if (!CertificateEquals(aOther)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> otherURI;
|
|
|
|
nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(mCodebase,
|
|
|
|
"shouldn't be calling this on principals from preferences");
|
|
|
|
|
|
|
|
// Compare codebases.
|
|
|
|
*aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase,
|
|
|
|
otherURI);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
return Equals(aOther, aResult);
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
static bool
|
2008-03-22 09:50:47 -07:00
|
|
|
URIIsLocalFile(nsIURI *aURI)
|
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isFile;
|
2010-04-12 08:44:28 -07:00
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
|
2008-03-22 09:50:47 -07:00
|
|
|
|
|
|
|
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
|
|
|
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
|
|
|
&isFile)) &&
|
|
|
|
isFile;
|
|
|
|
}
|
|
|
|
|
2008-02-26 19:45:29 -08:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
2008-02-26 19:45:29 -08:00
|
|
|
{
|
|
|
|
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
2008-03-22 09:50:47 -07:00
|
|
|
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
|
|
|
URIIsLocalFile(aURI)) {
|
|
|
|
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
|
|
|
|
|
|
|
|
if (!URIIsLocalFile(mCodebase)) {
|
|
|
|
// If the codebase is not also a file: uri then forget it
|
|
|
|
// (don't want resource: principals in a file: doc)
|
|
|
|
//
|
|
|
|
// note: we're not de-nesting jar: uris here, we want to
|
|
|
|
// keep archive content bottled up in its own little island
|
|
|
|
|
|
|
|
if (aReport) {
|
|
|
|
nsScriptSecurityManager::ReportError(
|
|
|
|
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// pull out the internal files
|
|
|
|
//
|
|
|
|
nsCOMPtr<nsIFileURL> codebaseFileURL(do_QueryInterface(mCodebase));
|
|
|
|
nsCOMPtr<nsIFile> targetFile;
|
|
|
|
nsCOMPtr<nsIFile> codebaseFile;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool targetIsDir;
|
2008-03-22 09:50:47 -07:00
|
|
|
|
|
|
|
// Make sure targetFile is not a directory (bug 209234)
|
|
|
|
// and that it exists w/out unescaping (bug 395343)
|
|
|
|
|
|
|
|
if (!codebaseFileURL || !fileURL ||
|
|
|
|
NS_FAILED(fileURL->GetFile(getter_AddRefs(targetFile))) ||
|
|
|
|
NS_FAILED(codebaseFileURL->GetFile(getter_AddRefs(codebaseFile))) ||
|
|
|
|
!targetFile || !codebaseFile ||
|
|
|
|
NS_FAILED(targetFile->Normalize()) ||
|
|
|
|
NS_FAILED(codebaseFile->Normalize()) ||
|
|
|
|
NS_FAILED(targetFile->IsDirectory(&targetIsDir)) ||
|
|
|
|
targetIsDir) {
|
|
|
|
if (aReport) {
|
|
|
|
nsScriptSecurityManager::ReportError(
|
|
|
|
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If the file to be loaded is in a subdirectory of the codebase
|
|
|
|
// (or same-dir if codebase is not a directory) then it will
|
|
|
|
// inherit its codebase principal and be scriptable by that codebase.
|
|
|
|
//
|
2011-09-28 23:19:26 -07:00
|
|
|
bool codebaseIsDir;
|
|
|
|
bool contained = false;
|
2008-03-22 09:50:47 -07:00
|
|
|
nsresult rv = codebaseFile->IsDirectory(&codebaseIsDir);
|
|
|
|
if (NS_SUCCEEDED(rv) && codebaseIsDir) {
|
|
|
|
rv = codebaseFile->Contains(targetFile, PR_TRUE, &contained);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCOMPtr<nsIFile> codebaseParent;
|
|
|
|
rv = codebaseFile->GetParent(getter_AddRefs(codebaseParent));
|
|
|
|
if (NS_SUCCEEDED(rv) && codebaseParent) {
|
|
|
|
rv = codebaseParent->Contains(targetFile, PR_TRUE, &contained);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && contained) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-26 19:45:29 -08:00
|
|
|
if (aReport) {
|
|
|
|
nsScriptSecurityManager::ReportError(
|
|
|
|
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
|
|
|
|
{
|
|
|
|
// If this principal is marked invalid, can't enable any capabilities
|
2007-09-28 07:31:04 -07:00
|
|
|
if (mCapabilities) {
|
|
|
|
nsCStringKey invalidKey(sInvalid);
|
|
|
|
if (mCapabilities->Exists(&invalidKey)) {
|
|
|
|
*result = nsIPrincipal::ENABLE_DENIED;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-09-28 07:31:04 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCert && !mTrusted) {
|
|
|
|
NS_ASSERTION(mInitialized, "Trying to enable a capability on an "
|
|
|
|
"uninitialized principal");
|
|
|
|
|
|
|
|
// If we are a non-trusted codebase principal, capabilities can not
|
|
|
|
// be enabled if the user has not set the pref allowing scripts to
|
|
|
|
// request enhanced capabilities; however, the file: and resource:
|
|
|
|
// schemes are special and may be able to get extra capabilities
|
|
|
|
// even with the pref disabled.
|
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
if (!gCodeBasePrincipalSupport) {
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mightEnable = false;
|
2009-06-16 04:00:06 -07:00
|
|
|
nsresult rv = mCodebase->SchemeIs("file", &mightEnable);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv) || !mightEnable) {
|
2009-06-16 04:00:06 -07:00
|
|
|
rv = mCodebase->SchemeIs("resource", &mightEnable);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv) || !mightEnable) {
|
2009-06-16 04:00:06 -07:00
|
|
|
*result = nsIPrincipal::ENABLE_DENIED;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-16 04:00:06 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *start = capability;
|
|
|
|
*result = nsIPrincipal::ENABLE_GRANTED;
|
|
|
|
for(;;) {
|
|
|
|
const char *space = PL_strchr(start, ' ');
|
|
|
|
PRInt32 len = space ? space - start : strlen(start);
|
|
|
|
nsCAutoString capString(start, len);
|
|
|
|
nsCStringKey key(capString);
|
2007-09-28 07:31:04 -07:00
|
|
|
PRInt16 value =
|
|
|
|
mCapabilities ? (PRInt16)NS_PTR_TO_INT32(mCapabilities->Get(&key)) : 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (value == 0 || value == nsIPrincipal::ENABLE_UNKNOWN) {
|
|
|
|
// We don't know whether we can enable this capability,
|
|
|
|
// so we should ask the user.
|
|
|
|
value = nsIPrincipal::ENABLE_WITH_USER_PERMISSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value < *result) {
|
|
|
|
*result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!space) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = space + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::SetCanEnableCapability(const char *capability,
|
|
|
|
PRInt16 canEnable)
|
|
|
|
{
|
|
|
|
// If this principal is marked invalid, can't enable any capabilities
|
2007-09-28 07:31:04 -07:00
|
|
|
if (!mCapabilities) {
|
|
|
|
mCapabilities = new nsHashtable(7); // XXXbz gets bumped up to 16 anyway
|
|
|
|
NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCStringKey invalidKey(sInvalid);
|
2007-09-28 07:31:04 -07:00
|
|
|
if (mCapabilities->Exists(&invalidKey)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PL_strcmp(capability, sInvalid) == 0) {
|
2007-09-28 07:31:04 -07:00
|
|
|
mCapabilities->Reset();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *start = capability;
|
|
|
|
for(;;) {
|
|
|
|
const char *space = PL_strchr(start, ' ');
|
|
|
|
int len = space ? space - start : strlen(start);
|
|
|
|
nsCAutoString capString(start, len);
|
|
|
|
nsCStringKey key(capString);
|
2007-09-28 07:31:04 -07:00
|
|
|
mCapabilities->Put(&key, NS_INT32_TO_PTR(canEnable));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!space) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = space + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::IsCapabilityEnabled(const char *capability, void *annotation,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool *result)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
*result = PR_FALSE;
|
|
|
|
nsHashtable *ht = (nsHashtable *) annotation;
|
|
|
|
if (!ht) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
const char *start = capability;
|
|
|
|
for(;;) {
|
|
|
|
const char *space = PL_strchr(start, ' ');
|
|
|
|
int len = space ? space - start : strlen(start);
|
|
|
|
nsCAutoString capString(start, len);
|
|
|
|
nsCStringKey key(capString);
|
|
|
|
*result = (ht->Get(&key) == (void *) AnnotationEnabled);
|
|
|
|
if (!*result) {
|
|
|
|
// If any single capability is not enabled, then return false.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!space) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = space + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::EnableCapability(const char *capability, void **annotation)
|
|
|
|
{
|
|
|
|
return SetCapability(capability, annotation, AnnotationEnabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::DisableCapability(const char *capability, void **annotation)
|
|
|
|
{
|
|
|
|
return SetCapability(capability, annotation, AnnotationDisabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::RevertCapability(const char *capability, void **annotation)
|
|
|
|
{
|
|
|
|
if (*annotation) {
|
|
|
|
nsHashtable *ht = (nsHashtable *) *annotation;
|
|
|
|
const char *start = capability;
|
|
|
|
for(;;) {
|
|
|
|
const char *space = PL_strchr(start, ' ');
|
|
|
|
int len = space ? space - start : strlen(start);
|
|
|
|
nsCAutoString capString(start, len);
|
|
|
|
nsCStringKey key(capString);
|
|
|
|
ht->Remove(&key);
|
|
|
|
if (!space) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = space + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPrincipal::SetCapability(const char *capability, void **annotation,
|
|
|
|
AnnotationValue value)
|
|
|
|
{
|
|
|
|
if (*annotation == nsnull) {
|
2007-09-17 15:18:28 -07:00
|
|
|
nsHashtable* ht = new nsHashtable(5);
|
|
|
|
|
|
|
|
if (!ht) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This object owns its annotations. Save them so we can release
|
|
|
|
// them when we destroy this object.
|
2007-09-17 15:18:28 -07:00
|
|
|
if (!mAnnotations.AppendElement(ht)) {
|
|
|
|
delete ht;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
*annotation = ht;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *start = capability;
|
|
|
|
for(;;) {
|
|
|
|
const char *space = PL_strchr(start, ' ');
|
|
|
|
int len = space ? space - start : strlen(start);
|
|
|
|
nsCAutoString capString(start, len);
|
|
|
|
nsCStringKey key(capString);
|
2007-09-17 15:18:28 -07:00
|
|
|
nsHashtable *ht = static_cast<nsHashtable *>(*annotation);
|
2007-03-22 10:30:00 -07:00
|
|
|
ht->Put(&key, (void *) value);
|
|
|
|
if (!space) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = space + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsPrincipal::GetHasCertificate(bool* aResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
*aResult = (mCert != nsnull);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetURI(nsIURI** aURI)
|
|
|
|
{
|
2007-06-18 08:07:02 -07:00
|
|
|
if (mCodebaseImmutable) {
|
|
|
|
NS_ADDREF(*aURI = mCodebase);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mCodebase) {
|
|
|
|
*aURI = nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_EnsureSafeToReturn(mCodebase, aURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsPrincipal::SetURI(nsIURI* aURI)
|
|
|
|
{
|
|
|
|
mCodebase = NS_TryToMakeImmutable(aURI);
|
2007-06-18 08:07:02 -07:00
|
|
|
mCodebaseImmutable = URIIsImmutable(mCodebase);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPrincipal::SetCertificate(const nsACString& aFingerprint,
|
|
|
|
const nsACString& aSubjectName,
|
|
|
|
const nsACString& aPrettyName,
|
|
|
|
nsISupports* aCert)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(!mCert);
|
|
|
|
|
|
|
|
if (aFingerprint.IsEmpty()) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
mCert = new Certificate(aFingerprint, aSubjectName, aPrettyName, aCert);
|
|
|
|
if (!mCert) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetFingerprint(nsACString& aFingerprint)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCert);
|
|
|
|
|
|
|
|
aFingerprint = mCert->fingerprint;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetPrettyName(nsACString& aName)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCert);
|
|
|
|
|
|
|
|
aName = mCert->prettyName;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetSubjectName(nsACString& aName)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCert);
|
|
|
|
|
|
|
|
aName = mCert->subjectName;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetCertificate(nsISupports** aCertificate)
|
|
|
|
{
|
|
|
|
if (mCert) {
|
|
|
|
NS_IF_ADDREF(*aCertificate = mCert->cert);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*aCertificate = nsnull;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-01-22 13:38:21 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aCsp = mCSP);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
|
|
|
|
{
|
|
|
|
// If CSP was already set, it should not be destroyed! Instead, it should
|
|
|
|
// get set anew when a new principal is created.
|
|
|
|
if (mCSP)
|
|
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
|
|
|
|
|
|
mCSP = aCsp;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetHashValue(PRUint32* aValue)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
|
|
|
|
|
|
|
|
// If there is a certificate, it takes precendence over the codebase.
|
|
|
|
if (mCert) {
|
2007-07-11 14:20:11 -07:00
|
|
|
*aValue = nsCRT::HashCode(mCert->fingerprint.get());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
else {
|
2008-10-08 06:16:27 -07:00
|
|
|
*aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetDomain(nsIURI** aDomain)
|
|
|
|
{
|
|
|
|
if (!mDomain) {
|
|
|
|
*aDomain = nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-06-18 08:07:02 -07:00
|
|
|
if (mDomainImmutable) {
|
|
|
|
NS_ADDREF(*aDomain = mDomain);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_EnsureSafeToReturn(mDomain, aDomain);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::SetDomain(nsIURI* aDomain)
|
|
|
|
{
|
|
|
|
mDomain = NS_TryToMakeImmutable(aDomain);
|
2007-06-18 08:07:02 -07:00
|
|
|
mDomainImmutable = URIIsImmutable(mDomain);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Domain has changed, forget cached security policy
|
|
|
|
SetSecurityPolicy(nsnull);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPrincipal::InitFromPersistent(const char* aPrefName,
|
|
|
|
const nsCString& aToken,
|
|
|
|
const nsCString& aSubjectName,
|
|
|
|
const nsACString& aPrettyName,
|
|
|
|
const char* aGrantedList,
|
|
|
|
const char* aDeniedList,
|
|
|
|
nsISupports* aCert,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aIsCert,
|
|
|
|
bool aTrusted)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-09-28 07:31:04 -07:00
|
|
|
NS_PRECONDITION(!mCapabilities || mCapabilities->Count() == 0,
|
2007-03-22 10:30:00 -07:00
|
|
|
"mCapabilities was already initialized?");
|
2007-09-17 15:18:28 -07:00
|
|
|
NS_PRECONDITION(mAnnotations.Length() == 0,
|
2007-03-22 10:30:00 -07:00
|
|
|
"mAnnotations was already initialized?");
|
|
|
|
NS_PRECONDITION(!mInitialized, "We were already initialized?");
|
|
|
|
|
|
|
|
mInitialized = PR_TRUE;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if (aIsCert) {
|
|
|
|
rv = SetCertificate(aToken, aSubjectName, aPrettyName, aCert);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv = NS_NewURI(getter_AddRefs(mCodebase), aToken, nsnull);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_ERROR("Malformed URI in capability.principal preference.");
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-06-18 08:07:02 -07:00
|
|
|
NS_TryToSetImmutable(mCodebase);
|
|
|
|
mCodebaseImmutable = URIIsImmutable(mCodebase);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
mTrusted = aTrusted;
|
|
|
|
}
|
|
|
|
|
2007-09-28 07:31:04 -07:00
|
|
|
rv = mJSPrincipals.Init(this, aToken);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
//-- Save the preference name
|
|
|
|
mPrefName = aPrefName;
|
|
|
|
|
|
|
|
const char* ordinalBegin = PL_strpbrk(aPrefName, "1234567890");
|
|
|
|
if (ordinalBegin) {
|
|
|
|
PRIntn n = atoi(ordinalBegin);
|
|
|
|
if (sCapabilitiesOrdinal <= n) {
|
|
|
|
sCapabilitiesOrdinal = n + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Store the capabilities
|
|
|
|
rv = NS_OK;
|
|
|
|
if (aGrantedList) {
|
|
|
|
rv = SetCanEnableCapability(aGrantedList, nsIPrincipal::ENABLE_GRANTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && aDeniedList) {
|
|
|
|
rv = SetCanEnableCapability(aDeniedList, nsIPrincipal::ENABLE_DENIED);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPrincipal::EnsureCertData(const nsACString& aSubjectName,
|
|
|
|
const nsACString& aPrettyName,
|
|
|
|
nsISupports* aCert)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCert);
|
|
|
|
|
|
|
|
if (!mCert->subjectName.IsEmpty() &&
|
|
|
|
!mCert->subjectName.Equals(aSubjectName)) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
mCert->subjectName = aSubjectName;
|
|
|
|
mCert->prettyName = aPrettyName;
|
|
|
|
mCert->cert = aCert;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CapabilityList
|
|
|
|
{
|
|
|
|
nsCString* granted;
|
|
|
|
nsCString* denied;
|
|
|
|
};
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
static bool
|
2007-03-22 10:30:00 -07:00
|
|
|
AppendCapability(nsHashKey *aKey, void *aData, void *capListPtr)
|
|
|
|
{
|
|
|
|
CapabilityList* capList = (CapabilityList*)capListPtr;
|
|
|
|
PRInt16 value = (PRInt16)NS_PTR_TO_INT32(aData);
|
|
|
|
nsCStringKey* key = (nsCStringKey *)aKey;
|
|
|
|
if (value == nsIPrincipal::ENABLE_GRANTED) {
|
|
|
|
capList->granted->Append(key->GetString(), key->GetStringLength());
|
|
|
|
capList->granted->Append(' ');
|
|
|
|
}
|
|
|
|
else if (value == nsIPrincipal::ENABLE_DENIED) {
|
|
|
|
capList->denied->Append(key->GetString(), key->GetStringLength());
|
|
|
|
capList->denied->Append(' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::GetPreferences(char** aPrefName, char** aID,
|
|
|
|
char** aSubjectName,
|
|
|
|
char** aGrantedList, char** aDeniedList,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool* aIsTrusted)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (mPrefName.IsEmpty()) {
|
|
|
|
if (mCert) {
|
|
|
|
mPrefName.Assign("capability.principal.certificate.p");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mPrefName.Assign("capability.principal.codebase.p");
|
|
|
|
}
|
|
|
|
|
|
|
|
mPrefName.AppendInt(sCapabilitiesOrdinal++);
|
|
|
|
mPrefName.Append(".id");
|
|
|
|
}
|
|
|
|
|
|
|
|
*aPrefName = nsnull;
|
|
|
|
*aID = nsnull;
|
|
|
|
*aSubjectName = nsnull;
|
|
|
|
*aGrantedList = nsnull;
|
|
|
|
*aDeniedList = nsnull;
|
|
|
|
*aIsTrusted = mTrusted;
|
|
|
|
|
|
|
|
char *prefName = nsnull;
|
|
|
|
char *id = nsnull;
|
|
|
|
char *subjectName = nsnull;
|
|
|
|
char *granted = nsnull;
|
|
|
|
char *denied = nsnull;
|
|
|
|
|
|
|
|
//-- Preference name
|
|
|
|
prefName = ToNewCString(mPrefName);
|
|
|
|
if (!prefName) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- ID
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mCert) {
|
|
|
|
id = ToNewCString(mCert->fingerprint);
|
|
|
|
if (!id) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv = GetOrigin(&id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
nsMemory::Free(prefName);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCert) {
|
|
|
|
subjectName = ToNewCString(mCert->subjectName);
|
|
|
|
} else {
|
|
|
|
subjectName = ToNewCString(EmptyCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!subjectName) {
|
|
|
|
nsMemory::Free(prefName);
|
|
|
|
nsMemory::Free(id);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Capabilities
|
|
|
|
nsCAutoString grantedListStr, deniedListStr;
|
2007-09-28 07:31:04 -07:00
|
|
|
if (mCapabilities) {
|
|
|
|
CapabilityList capList = CapabilityList();
|
|
|
|
capList.granted = &grantedListStr;
|
|
|
|
capList.denied = &deniedListStr;
|
|
|
|
mCapabilities->Enumerate(AppendCapability, (void*)&capList);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!grantedListStr.IsEmpty()) {
|
|
|
|
grantedListStr.Truncate(grantedListStr.Length() - 1);
|
|
|
|
granted = ToNewCString(grantedListStr);
|
|
|
|
if (!granted) {
|
|
|
|
nsMemory::Free(prefName);
|
|
|
|
nsMemory::Free(id);
|
|
|
|
nsMemory::Free(subjectName);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!deniedListStr.IsEmpty()) {
|
|
|
|
deniedListStr.Truncate(deniedListStr.Length() - 1);
|
|
|
|
denied = ToNewCString(deniedListStr);
|
|
|
|
if (!denied) {
|
|
|
|
nsMemory::Free(prefName);
|
|
|
|
nsMemory::Free(id);
|
|
|
|
nsMemory::Free(subjectName);
|
|
|
|
if (granted) {
|
|
|
|
nsMemory::Free(granted);
|
|
|
|
}
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*aPrefName = prefName;
|
|
|
|
*aID = id;
|
|
|
|
*aSubjectName = subjectName;
|
|
|
|
*aGrantedList = granted;
|
|
|
|
*aDeniedList = denied;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-10-10 08:04:34 -07:00
|
|
|
static nsresult
|
2007-03-22 10:30:00 -07:00
|
|
|
ReadAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey** aKey,
|
|
|
|
void** aData)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsCStringKey* key = new nsCStringKey(aStream, &rv);
|
2010-03-11 22:50:11 -08:00
|
|
|
if (!key)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
2010-03-11 22:50:11 -08:00
|
|
|
delete key;
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 value;
|
|
|
|
rv = aStream->Read32(&value);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
delete key;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aKey = key;
|
|
|
|
*aData = (void*) value;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-10-10 08:04:34 -07:00
|
|
|
static void
|
2007-03-22 10:30:00 -07:00
|
|
|
FreeAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey* aKey,
|
|
|
|
void* aData)
|
|
|
|
{
|
|
|
|
delete aKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::Read(nsIObjectInputStream* aStream)
|
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasCapabilities;
|
2007-09-17 15:18:28 -07:00
|
|
|
nsresult rv = aStream->ReadBoolean(&hasCapabilities);
|
|
|
|
if (NS_SUCCEEDED(rv) && hasCapabilities) {
|
2007-09-28 07:31:04 -07:00
|
|
|
mCapabilities = new nsHashtable(aStream, ReadAnnotationEntry,
|
|
|
|
FreeAnnotationEntry, &rv);
|
|
|
|
NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
|
2007-09-17 15:18:28 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = NS_ReadOptionalCString(aStream, mPrefName);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* ordinalBegin = PL_strpbrk(mPrefName.get(), "1234567890");
|
|
|
|
if (ordinalBegin) {
|
|
|
|
PRIntn n = atoi(ordinalBegin);
|
|
|
|
if (sCapabilitiesOrdinal <= n) {
|
|
|
|
sCapabilitiesOrdinal = n + 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-09-17 15:18:28 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool haveCert;
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = aStream->ReadBoolean(&haveCert);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCString fingerprint;
|
|
|
|
nsCString subjectName;
|
|
|
|
nsCString prettyName;
|
|
|
|
nsCOMPtr<nsISupports> cert;
|
|
|
|
if (haveCert) {
|
|
|
|
rv = NS_ReadOptionalCString(aStream, fingerprint);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = NS_ReadOptionalCString(aStream, subjectName);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = NS_ReadOptionalCString(aStream, prettyName);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = aStream->ReadObject(PR_TRUE, getter_AddRefs(cert));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
nsCOMPtr<nsIURI> codebase;
|
|
|
|
rv = NS_ReadOptionalObject(aStream, PR_TRUE, getter_AddRefs(codebase));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = Init(fingerprint, subjectName, prettyName, cert, codebase);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> domain;
|
|
|
|
rv = NS_ReadOptionalObject(aStream, PR_TRUE, getter_AddRefs(domain));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
SetDomain(domain);
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
rv = aStream->ReadBoolean(&mTrusted);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-10-10 08:04:34 -07:00
|
|
|
static nsresult
|
2007-03-22 10:30:00 -07:00
|
|
|
WriteScalarValue(nsIObjectOutputStream* aStream, void* aData)
|
|
|
|
{
|
|
|
|
PRUint32 value = NS_PTR_TO_INT32(aData);
|
|
|
|
|
|
|
|
return aStream->Write32(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPrincipal::Write(nsIObjectOutputStream* aStream)
|
|
|
|
{
|
2007-09-17 15:18:28 -07:00
|
|
|
NS_ENSURE_STATE(mCert || mCodebase);
|
|
|
|
|
|
|
|
// mAnnotations is transient data associated to specific JS stack frames. We
|
|
|
|
// don't want to serialize that.
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasCapabilities = (mCapabilities && mCapabilities->Count() > 0);
|
2007-09-17 15:18:28 -07:00
|
|
|
nsresult rv = aStream->WriteBoolean(hasCapabilities);
|
|
|
|
if (NS_SUCCEEDED(rv) && hasCapabilities) {
|
2007-09-28 07:31:04 -07:00
|
|
|
rv = mCapabilities->Write(aStream, WriteScalarValue);
|
2007-09-17 15:18:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = NS_WriteOptionalStringZ(aStream, mPrefName.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = aStream->WriteBoolean(mCert != nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
if (mCert) {
|
|
|
|
NS_ENSURE_STATE(mCert->cert);
|
|
|
|
|
|
|
|
rv = NS_WriteOptionalStringZ(aStream, mCert->fingerprint.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = NS_WriteOptionalStringZ(aStream, mCert->subjectName.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = NS_WriteOptionalStringZ(aStream, mCert->prettyName.get());
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-09-17 15:18:28 -07:00
|
|
|
|
|
|
|
rv = aStream->WriteCompoundObject(mCert->cert, NS_GET_IID(nsISupports),
|
|
|
|
PR_TRUE);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-09-17 15:18:28 -07:00
|
|
|
|
|
|
|
// mSecurityPolicy is an optimization; it'll get looked up again as needed.
|
|
|
|
// Don't bother saving and restoring it, esp. since it might change if
|
|
|
|
// preferences change.
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
|
|
|
|
PR_TRUE);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI),
|
|
|
|
PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
rv = aStream->Write8(mTrusted);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-09-17 15:18:28 -07:00
|
|
|
// mCodebaseImmutable and mDomainImmutable will be recomputed based
|
|
|
|
// on the deserialized URIs in Read().
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|