1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=80: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2003
21 * the Initial Developer. All Rights Reserved.
24 * Christopher A. Aillon <christopher@aillon.com>
25 * Giorgio Maone <g.maone@informaction.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 #include "nsScriptSecurityManager.h"
44 #include "nsReadableUtils.h"
48 #include "nsIFileURL.h"
49 #include "nsIProtocolHandler.h"
50 #include "nsNetUtil.h"
51 #include "nsJSPrincipals.h"
52 #include "nsVoidArray.h"
53 #include "nsHashtable.h"
54 #include "nsIObjectInputStream.h"
55 #include "nsIObjectOutputStream.h"
56 #include "nsIPrefBranch2.h"
57 #include "nsIPrefService.h"
58 #include "nsIClassInfoImpl.h"
59 #include "nsDOMError.h"
60 #include "nsIContentSecurityPolicy.h"
62 #include "nsPrincipal.h"
64 class nsCodeBasePrefObserver
: nsIObserver
67 nsCodeBasePrefObserver()
69 NS_ASSERTION(!sObserverInstalled
, "Shouldn't recreate observer\n");
71 ~nsCodeBasePrefObserver()
73 sObserverInstalled
= PR_FALSE
;
78 nsCOMPtr
<nsIPrefBranch2
> prefBranch
=
79 do_GetService(NS_PREFSERVICE_CONTRACTID
);
81 if (NS_FAILED(prefBranch
->GetBoolPref(PrefName(), &sPrefValue
))) {
82 sPrefValue
= PR_FALSE
;
84 if (NS_SUCCEEDED(prefBranch
->AddObserver(PrefName(), this, PR_FALSE
))) {
85 sObserverInstalled
= PR_TRUE
;
92 NS_IMETHOD
Observe(nsISupports
* aSubject
,
94 const PRUnichar
* aData
)
96 NS_ASSERTION(!strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
),
98 NS_ASSERTION(!strcmp(NS_ConvertUTF16toUTF8(aData
).get(), PrefName()),
101 nsCOMPtr
<nsIPrefBranch
> prefBranch(do_QueryInterface(aSubject
));
103 NS_FAILED(prefBranch
->GetBoolPref(PrefName(), &sPrefValue
))) {
104 sPrefValue
= PR_FALSE
;
109 const char* PrefName()
111 static const char pref
[] = "signed.applets.codebase_principal_support";
115 static PRBool
PrefValue() { return sPrefValue
; }
116 static PRBool
Installed() { return sObserverInstalled
; }
120 static PRBool sPrefValue
;
121 static PRBool sObserverInstalled
;
124 PRBool
nsCodeBasePrefObserver::sPrefValue
= PR_FALSE
;
125 PRBool
nsCodeBasePrefObserver::sObserverInstalled
= PR_FALSE
;
126 NS_IMPL_ISUPPORTS1(nsCodeBasePrefObserver
, nsIObserver
)
128 static PRBool
URIIsImmutable(nsIURI
* aURI
)
130 nsCOMPtr
<nsIMutable
> mutableObj(do_QueryInterface(aURI
));
134 NS_SUCCEEDED(mutableObj
->GetMutable(&isMutable
)) &&
138 // Static member variables
139 PRInt32
nsPrincipal::sCapabilitiesOrdinal
= 0;
140 const char nsPrincipal::sInvalid
[] = "Invalid";
143 NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal
,
146 NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal
,
150 NS_IMETHODIMP_(nsrefcnt
)
151 nsPrincipal::AddRef()
153 NS_PRECONDITION(PRInt32(mJSPrincipals
.refcount
) >= 0, "illegal refcnt");
154 // XXXcaa does this need to be threadsafe? See bug 143559.
155 nsrefcnt count
= PR_AtomicIncrement((PRInt32
*)&mJSPrincipals
.refcount
);
156 NS_LOG_ADDREF(this, count
, "nsPrincipal", sizeof(*this));
160 NS_IMETHODIMP_(nsrefcnt
)
161 nsPrincipal::Release()
163 NS_PRECONDITION(0 != mJSPrincipals
.refcount
, "dup release");
164 nsrefcnt count
= PR_AtomicDecrement((PRInt32
*)&mJSPrincipals
.refcount
);
165 NS_LOG_RELEASE(this, count
, "nsPrincipal");
167 NS_DELETEXPCOM(this);
173 nsPrincipal::nsPrincipal()
174 : mCapabilities(nsnull
),
175 mSecurityPolicy(nsnull
),
177 mInitialized(PR_FALSE
),
178 mCodebaseImmutable(PR_FALSE
),
179 mDomainImmutable(PR_FALSE
)
181 if (!nsCodeBasePrefObserver::Installed()) {
182 nsRefPtr
<nsCodeBasePrefObserver
> obs
= new nsCodeBasePrefObserver();
185 NS_WARN_IF_FALSE(nsCodeBasePrefObserver::Installed(),
186 "Installing nsCodeBasePrefObserver failed!");
191 nsPrincipal::Init(const nsACString
& aCertFingerprint
,
192 const nsACString
& aSubjectName
,
193 const nsACString
& aPrettyName
,
197 NS_ENSURE_STATE(!mInitialized
);
198 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty() || aCodebase
); // better have one of these.
200 mInitialized
= PR_TRUE
;
202 mCodebase
= NS_TryToMakeImmutable(aCodebase
);
203 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
206 if (!aCertFingerprint
.IsEmpty()) {
207 rv
= SetCertificate(aCertFingerprint
, aSubjectName
, aPrettyName
, aCert
);
208 if (NS_SUCCEEDED(rv
)) {
209 rv
= mJSPrincipals
.Init(this, mCert
->fingerprint
);
214 rv
= mCodebase
->GetSpec(spec
);
215 if (NS_SUCCEEDED(rv
)) {
216 rv
= mJSPrincipals
.Init(this, spec
);
220 NS_ASSERTION(NS_SUCCEEDED(rv
), "nsPrincipal::Init() failed");
225 nsPrincipal::~nsPrincipal(void)
227 SetSecurityPolicy(nsnull
);
228 delete mCapabilities
;
232 nsPrincipal::GetJSPrincipals(JSContext
*cx
, JSPrincipals
**jsprin
)
234 NS_PRECONDITION(mJSPrincipals
.nsIPrincipalPtr
, "mJSPrincipals is uninitialized!");
236 JSPRINCIPALS_HOLD(cx
, &mJSPrincipals
);
237 *jsprin
= &mJSPrincipals
;
242 nsPrincipal::GetOrigin(char **aOrigin
)
246 nsCOMPtr
<nsIURI
> origin
;
248 origin
= NS_GetInnermostURI(mCodebase
);
252 NS_ASSERTION(mCert
, "No Domain or Codebase for a non-cert principal");
253 return NS_ERROR_FAILURE
;
256 nsCAutoString hostPort
;
258 // chrome: URLs don't have a meaningful origin, so make
259 // sure we just get the full spec for them.
260 // XXX this should be removed in favor of the solution in
263 nsresult rv
= origin
->SchemeIs("chrome", &isChrome
);
264 if (NS_SUCCEEDED(rv
) && !isChrome
) {
265 rv
= origin
->GetHostPort(hostPort
);
268 if (NS_SUCCEEDED(rv
) && !isChrome
) {
269 nsCAutoString scheme
;
270 rv
= origin
->GetScheme(scheme
);
271 NS_ENSURE_SUCCESS(rv
, rv
);
272 *aOrigin
= ToNewCString(scheme
+ NS_LITERAL_CSTRING("://") + hostPort
);
275 // Some URIs (e.g., nsSimpleURI) don't support host. Just
276 // get the full spec.
278 rv
= origin
->GetSpec(spec
);
279 NS_ENSURE_SUCCESS(rv
, rv
);
280 *aOrigin
= ToNewCString(spec
);
283 return *aOrigin
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
287 nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy
)
289 if (mSecurityPolicy
&& mSecurityPolicy
->IsInvalid())
290 SetSecurityPolicy(nsnull
);
292 *aSecurityPolicy
= (void *) mSecurityPolicy
;
297 nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy
)
299 DomainPolicy
*newPolicy
= reinterpret_cast<DomainPolicy
*>(aSecurityPolicy
);
304 mSecurityPolicy
->Drop();
306 mSecurityPolicy
= newPolicy
;
311 nsPrincipal::Equals(nsIPrincipal
*aOther
, PRBool
*aResult
)
316 NS_WARNING("Need a principal to compare this to!");
320 if (this != aOther
) {
322 aOther
->GetHasCertificate(&otherHasCert
);
323 if (otherHasCert
!= (mCert
!= nsnull
)) {
324 // One has a cert while the other doesn't. Not equal.
330 aOther
->GetFingerprint(str
);
331 *aResult
= str
.Equals(mCert
->fingerprint
);
333 // If either subject name is empty, just let the result stand (so that
334 // nsScriptSecurityManager::SetCanEnableCapability works), but if they're
335 // both non-empty, only claim equality if they're equal.
336 if (*aResult
&& !mCert
->subjectName
.IsEmpty()) {
337 // Check the other principal's subject name
338 aOther
->GetSubjectName(str
);
339 *aResult
= str
.Equals(mCert
->subjectName
) || str
.IsEmpty();
346 // If either principal has no URI, it's the saved principal from
347 // preferences; in that case, test true. Do NOT test true if the two
348 // principals have URIs with different codebases.
349 nsCOMPtr
<nsIURI
> otherURI
;
350 nsresult rv
= aOther
->GetURI(getter_AddRefs(otherURI
));
356 if (!otherURI
|| !mCodebase
) {
360 // Fall through to the codebase comparison.
363 // Codebases are equal if they have the same origin.
365 NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
375 nsPrincipal::Subsumes(nsIPrincipal
*aOther
, PRBool
*aResult
)
377 return Equals(aOther
, aResult
);
381 URIIsLocalFile(nsIURI
*aURI
)
384 nsCOMPtr
<nsINetUtil
> util
= do_GetIOService();
386 return util
&& NS_SUCCEEDED(util
->ProtocolHasFlags(aURI
,
387 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
393 nsPrincipal::CheckMayLoad(nsIURI
* aURI
, PRBool aReport
)
395 if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase
, aURI
)) {
396 if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
397 URIIsLocalFile(aURI
)) {
398 nsCOMPtr
<nsIFileURL
> fileURL(do_QueryInterface(aURI
));
400 if (!URIIsLocalFile(mCodebase
)) {
401 // If the codebase is not also a file: uri then forget it
402 // (don't want resource: principals in a file: doc)
404 // note: we're not de-nesting jar: uris here, we want to
405 // keep archive content bottled up in its own little island
408 nsScriptSecurityManager::ReportError(
409 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
412 return NS_ERROR_DOM_BAD_URI
;
416 // pull out the internal files
418 nsCOMPtr
<nsIFileURL
> codebaseFileURL(do_QueryInterface(mCodebase
));
419 nsCOMPtr
<nsIFile
> targetFile
;
420 nsCOMPtr
<nsIFile
> codebaseFile
;
423 // Make sure targetFile is not a directory (bug 209234)
424 // and that it exists w/out unescaping (bug 395343)
426 if (!codebaseFileURL
|| !fileURL
||
427 NS_FAILED(fileURL
->GetFile(getter_AddRefs(targetFile
))) ||
428 NS_FAILED(codebaseFileURL
->GetFile(getter_AddRefs(codebaseFile
))) ||
429 !targetFile
|| !codebaseFile
||
430 NS_FAILED(targetFile
->Normalize()) ||
431 NS_FAILED(codebaseFile
->Normalize()) ||
432 NS_FAILED(targetFile
->IsDirectory(&targetIsDir
)) ||
435 nsScriptSecurityManager::ReportError(
436 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
439 return NS_ERROR_DOM_BAD_URI
;
443 // If the file to be loaded is in a subdirectory of the codebase
444 // (or same-dir if codebase is not a directory) then it will
445 // inherit its codebase principal and be scriptable by that codebase.
447 PRBool codebaseIsDir
;
448 PRBool contained
= PR_FALSE
;
449 nsresult rv
= codebaseFile
->IsDirectory(&codebaseIsDir
);
450 if (NS_SUCCEEDED(rv
) && codebaseIsDir
) {
451 rv
= codebaseFile
->Contains(targetFile
, PR_TRUE
, &contained
);
454 nsCOMPtr
<nsIFile
> codebaseParent
;
455 rv
= codebaseFile
->GetParent(getter_AddRefs(codebaseParent
));
456 if (NS_SUCCEEDED(rv
) && codebaseParent
) {
457 rv
= codebaseParent
->Contains(targetFile
, PR_TRUE
, &contained
);
461 if (NS_SUCCEEDED(rv
) && contained
) {
467 nsScriptSecurityManager::ReportError(
468 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
471 return NS_ERROR_DOM_BAD_URI
;
478 nsPrincipal::CanEnableCapability(const char *capability
, PRInt16
*result
)
480 // If this principal is marked invalid, can't enable any capabilities
482 nsCStringKey
invalidKey(sInvalid
);
483 if (mCapabilities
->Exists(&invalidKey
)) {
484 *result
= nsIPrincipal::ENABLE_DENIED
;
490 if (!mCert
&& !mTrusted
) {
491 NS_ASSERTION(mInitialized
, "Trying to enable a capability on an "
492 "uninitialized principal");
494 // If we are a non-trusted codebase principal, capabilities can not
495 // be enabled if the user has not set the pref allowing scripts to
496 // request enhanced capabilities; however, the file: and resource:
497 // schemes are special and may be able to get extra capabilities
498 // even with the pref disabled.
500 if (!nsCodeBasePrefObserver::PrefValue()) {
501 PRBool mightEnable
= PR_FALSE
;
502 nsresult rv
= mCodebase
->SchemeIs("file", &mightEnable
);
503 if (NS_FAILED(rv
) || !mightEnable
) {
504 rv
= mCodebase
->SchemeIs("resource", &mightEnable
);
505 if (NS_FAILED(rv
) || !mightEnable
) {
506 *result
= nsIPrincipal::ENABLE_DENIED
;
514 const char *start
= capability
;
515 *result
= nsIPrincipal::ENABLE_GRANTED
;
517 const char *space
= PL_strchr(start
, ' ');
518 PRInt32 len
= space
? space
- start
: strlen(start
);
519 nsCAutoString
capString(start
, len
);
520 nsCStringKey
key(capString
);
522 mCapabilities
? (PRInt16
)NS_PTR_TO_INT32(mCapabilities
->Get(&key
)) : 0;
523 if (value
== 0 || value
== nsIPrincipal::ENABLE_UNKNOWN
) {
524 // We don't know whether we can enable this capability,
525 // so we should ask the user.
526 value
= nsIPrincipal::ENABLE_WITH_USER_PERMISSION
;
529 if (value
< *result
) {
544 nsPrincipal::SetCanEnableCapability(const char *capability
,
547 // If this principal is marked invalid, can't enable any capabilities
548 if (!mCapabilities
) {
549 mCapabilities
= new nsHashtable(7); // XXXbz gets bumped up to 16 anyway
550 NS_ENSURE_TRUE(mCapabilities
, NS_ERROR_OUT_OF_MEMORY
);
553 nsCStringKey
invalidKey(sInvalid
);
554 if (mCapabilities
->Exists(&invalidKey
)) {
558 if (PL_strcmp(capability
, sInvalid
) == 0) {
559 mCapabilities
->Reset();
562 const char *start
= capability
;
564 const char *space
= PL_strchr(start
, ' ');
565 int len
= space
? space
- start
: strlen(start
);
566 nsCAutoString
capString(start
, len
);
567 nsCStringKey
key(capString
);
568 mCapabilities
->Put(&key
, NS_INT32_TO_PTR(canEnable
));
580 nsPrincipal::IsCapabilityEnabled(const char *capability
, void *annotation
,
584 nsHashtable
*ht
= (nsHashtable
*) annotation
;
588 const char *start
= capability
;
590 const char *space
= PL_strchr(start
, ' ');
591 int len
= space
? space
- start
: strlen(start
);
592 nsCAutoString
capString(start
, len
);
593 nsCStringKey
key(capString
);
594 *result
= (ht
->Get(&key
) == (void *) AnnotationEnabled
);
596 // If any single capability is not enabled, then return false.
611 nsPrincipal::EnableCapability(const char *capability
, void **annotation
)
613 return SetCapability(capability
, annotation
, AnnotationEnabled
);
617 nsPrincipal::DisableCapability(const char *capability
, void **annotation
)
619 return SetCapability(capability
, annotation
, AnnotationDisabled
);
623 nsPrincipal::RevertCapability(const char *capability
, void **annotation
)
626 nsHashtable
*ht
= (nsHashtable
*) *annotation
;
627 const char *start
= capability
;
629 const char *space
= PL_strchr(start
, ' ');
630 int len
= space
? space
- start
: strlen(start
);
631 nsCAutoString
capString(start
, len
);
632 nsCStringKey
key(capString
);
645 nsPrincipal::SetCapability(const char *capability
, void **annotation
,
646 AnnotationValue value
)
648 if (*annotation
== nsnull
) {
649 nsHashtable
* ht
= new nsHashtable(5);
652 return NS_ERROR_OUT_OF_MEMORY
;
655 // This object owns its annotations. Save them so we can release
656 // them when we destroy this object.
657 if (!mAnnotations
.AppendElement(ht
)) {
659 return NS_ERROR_OUT_OF_MEMORY
;
665 const char *start
= capability
;
667 const char *space
= PL_strchr(start
, ' ');
668 int len
= space
? space
- start
: strlen(start
);
669 nsCAutoString
capString(start
, len
);
670 nsCStringKey
key(capString
);
671 nsHashtable
*ht
= static_cast<nsHashtable
*>(*annotation
);
672 ht
->Put(&key
, (void *) value
);
684 nsPrincipal::GetHasCertificate(PRBool
* aResult
)
686 *aResult
= (mCert
!= nsnull
);
692 nsPrincipal::GetURI(nsIURI
** aURI
)
694 if (mCodebaseImmutable
) {
695 NS_ADDREF(*aURI
= mCodebase
);
704 return NS_EnsureSafeToReturn(mCodebase
, aURI
);
708 nsPrincipal::SetURI(nsIURI
* aURI
)
710 mCodebase
= NS_TryToMakeImmutable(aURI
);
711 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
716 nsPrincipal::SetCertificate(const nsACString
& aFingerprint
,
717 const nsACString
& aSubjectName
,
718 const nsACString
& aPrettyName
,
721 NS_ENSURE_STATE(!mCert
);
723 if (aFingerprint
.IsEmpty()) {
724 return NS_ERROR_INVALID_ARG
;
727 mCert
= new Certificate(aFingerprint
, aSubjectName
, aPrettyName
, aCert
);
729 return NS_ERROR_OUT_OF_MEMORY
;
736 nsPrincipal::GetFingerprint(nsACString
& aFingerprint
)
738 NS_ENSURE_STATE(mCert
);
740 aFingerprint
= mCert
->fingerprint
;
746 nsPrincipal::GetPrettyName(nsACString
& aName
)
748 NS_ENSURE_STATE(mCert
);
750 aName
= mCert
->prettyName
;
756 nsPrincipal::GetSubjectName(nsACString
& aName
)
758 NS_ENSURE_STATE(mCert
);
760 aName
= mCert
->subjectName
;
766 nsPrincipal::GetCertificate(nsISupports
** aCertificate
)
769 NS_IF_ADDREF(*aCertificate
= mCert
->cert
);
772 *aCertificate
= nsnull
;
778 nsPrincipal::GetCsp(nsIContentSecurityPolicy
** aCsp
)
780 NS_IF_ADDREF(*aCsp
= mCSP
);
785 nsPrincipal::SetCsp(nsIContentSecurityPolicy
* aCsp
)
787 // If CSP was already set, it should not be destroyed! Instead, it should
788 // get set anew when a new principal is created.
790 return NS_ERROR_ALREADY_INITIALIZED
;
797 nsPrincipal::GetHashValue(PRUint32
* aValue
)
799 NS_PRECONDITION(mCert
|| mCodebase
, "Need a cert or codebase");
801 // If there is a certificate, it takes precendence over the codebase.
803 *aValue
= nsCRT::HashCode(mCert
->fingerprint
.get());
806 *aValue
= nsScriptSecurityManager::HashPrincipalByOrigin(this);
813 nsPrincipal::GetDomain(nsIURI
** aDomain
)
820 if (mDomainImmutable
) {
821 NS_ADDREF(*aDomain
= mDomain
);
825 return NS_EnsureSafeToReturn(mDomain
, aDomain
);
829 nsPrincipal::SetDomain(nsIURI
* aDomain
)
831 mDomain
= NS_TryToMakeImmutable(aDomain
);
832 mDomainImmutable
= URIIsImmutable(mDomain
);
834 // Domain has changed, forget cached security policy
835 SetSecurityPolicy(nsnull
);
841 nsPrincipal::InitFromPersistent(const char* aPrefName
,
842 const nsCString
& aToken
,
843 const nsCString
& aSubjectName
,
844 const nsACString
& aPrettyName
,
845 const char* aGrantedList
,
846 const char* aDeniedList
,
851 NS_PRECONDITION(!mCapabilities
|| mCapabilities
->Count() == 0,
852 "mCapabilities was already initialized?");
853 NS_PRECONDITION(mAnnotations
.Length() == 0,
854 "mAnnotations was already initialized?");
855 NS_PRECONDITION(!mInitialized
, "We were already initialized?");
857 mInitialized
= PR_TRUE
;
861 rv
= SetCertificate(aToken
, aSubjectName
, aPrettyName
, aCert
);
868 rv
= NS_NewURI(getter_AddRefs(mCodebase
), aToken
, nsnull
);
870 NS_ERROR("Malformed URI in capability.principal preference.");
874 NS_TryToSetImmutable(mCodebase
);
875 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
880 rv
= mJSPrincipals
.Init(this, aToken
);
881 NS_ENSURE_SUCCESS(rv
, rv
);
883 //-- Save the preference name
884 mPrefName
= aPrefName
;
886 const char* ordinalBegin
= PL_strpbrk(aPrefName
, "1234567890");
888 PRIntn n
= atoi(ordinalBegin
);
889 if (sCapabilitiesOrdinal
<= n
) {
890 sCapabilitiesOrdinal
= n
+ 1;
894 //-- Store the capabilities
897 rv
= SetCanEnableCapability(aGrantedList
, nsIPrincipal::ENABLE_GRANTED
);
900 if (NS_SUCCEEDED(rv
) && aDeniedList
) {
901 rv
= SetCanEnableCapability(aDeniedList
, nsIPrincipal::ENABLE_DENIED
);
908 nsPrincipal::EnsureCertData(const nsACString
& aSubjectName
,
909 const nsACString
& aPrettyName
,
912 NS_ENSURE_STATE(mCert
);
914 if (!mCert
->subjectName
.IsEmpty() &&
915 !mCert
->subjectName
.Equals(aSubjectName
)) {
916 return NS_ERROR_INVALID_ARG
;
919 mCert
->subjectName
= aSubjectName
;
920 mCert
->prettyName
= aPrettyName
;
925 struct CapabilityList
932 AppendCapability(nsHashKey
*aKey
, void *aData
, void *capListPtr
)
934 CapabilityList
* capList
= (CapabilityList
*)capListPtr
;
935 PRInt16 value
= (PRInt16
)NS_PTR_TO_INT32(aData
);
936 nsCStringKey
* key
= (nsCStringKey
*)aKey
;
937 if (value
== nsIPrincipal::ENABLE_GRANTED
) {
938 capList
->granted
->Append(key
->GetString(), key
->GetStringLength());
939 capList
->granted
->Append(' ');
941 else if (value
== nsIPrincipal::ENABLE_DENIED
) {
942 capList
->denied
->Append(key
->GetString(), key
->GetStringLength());
943 capList
->denied
->Append(' ');
950 nsPrincipal::GetPreferences(char** aPrefName
, char** aID
,
952 char** aGrantedList
, char** aDeniedList
,
955 if (mPrefName
.IsEmpty()) {
957 mPrefName
.Assign("capability.principal.certificate.p");
960 mPrefName
.Assign("capability.principal.codebase.p");
963 mPrefName
.AppendInt(sCapabilitiesOrdinal
++);
964 mPrefName
.Append(".id");
969 *aSubjectName
= nsnull
;
970 *aGrantedList
= nsnull
;
971 *aDeniedList
= nsnull
;
972 *aIsTrusted
= mTrusted
;
974 char *prefName
= nsnull
;
976 char *subjectName
= nsnull
;
977 char *granted
= nsnull
;
978 char *denied
= nsnull
;
981 prefName
= ToNewCString(mPrefName
);
983 return NS_ERROR_OUT_OF_MEMORY
;
989 id
= ToNewCString(mCert
->fingerprint
);
991 rv
= NS_ERROR_OUT_OF_MEMORY
;
999 nsMemory::Free(prefName
);
1004 subjectName
= ToNewCString(mCert
->subjectName
);
1006 subjectName
= ToNewCString(EmptyCString());
1010 nsMemory::Free(prefName
);
1012 return NS_ERROR_OUT_OF_MEMORY
;
1016 nsCAutoString grantedListStr
, deniedListStr
;
1017 if (mCapabilities
) {
1018 CapabilityList capList
= CapabilityList();
1019 capList
.granted
= &grantedListStr
;
1020 capList
.denied
= &deniedListStr
;
1021 mCapabilities
->Enumerate(AppendCapability
, (void*)&capList
);
1024 if (!grantedListStr
.IsEmpty()) {
1025 grantedListStr
.Truncate(grantedListStr
.Length() - 1);
1026 granted
= ToNewCString(grantedListStr
);
1028 nsMemory::Free(prefName
);
1030 nsMemory::Free(subjectName
);
1031 return NS_ERROR_OUT_OF_MEMORY
;
1035 if (!deniedListStr
.IsEmpty()) {
1036 deniedListStr
.Truncate(deniedListStr
.Length() - 1);
1037 denied
= ToNewCString(deniedListStr
);
1039 nsMemory::Free(prefName
);
1041 nsMemory::Free(subjectName
);
1043 nsMemory::Free(granted
);
1045 return NS_ERROR_OUT_OF_MEMORY
;
1049 *aPrefName
= prefName
;
1051 *aSubjectName
= subjectName
;
1052 *aGrantedList
= granted
;
1053 *aDeniedList
= denied
;
1059 ReadAnnotationEntry(nsIObjectInputStream
* aStream
, nsHashKey
** aKey
,
1063 nsCStringKey
* key
= new nsCStringKey(aStream
, &rv
);
1065 return NS_ERROR_OUT_OF_MEMORY
;
1067 if (NS_FAILED(rv
)) {
1073 rv
= aStream
->Read32(&value
);
1074 if (NS_FAILED(rv
)) {
1080 *aData
= (void*) value
;
1085 FreeAnnotationEntry(nsIObjectInputStream
* aStream
, nsHashKey
* aKey
,
1092 nsPrincipal::Read(nsIObjectInputStream
* aStream
)
1094 PRBool hasCapabilities
;
1095 nsresult rv
= aStream
->ReadBoolean(&hasCapabilities
);
1096 if (NS_SUCCEEDED(rv
) && hasCapabilities
) {
1097 mCapabilities
= new nsHashtable(aStream
, ReadAnnotationEntry
,
1098 FreeAnnotationEntry
, &rv
);
1099 NS_ENSURE_TRUE(mCapabilities
, NS_ERROR_OUT_OF_MEMORY
);
1102 if (NS_FAILED(rv
)) {
1106 rv
= NS_ReadOptionalCString(aStream
, mPrefName
);
1107 if (NS_FAILED(rv
)) {
1111 const char* ordinalBegin
= PL_strpbrk(mPrefName
.get(), "1234567890");
1113 PRIntn n
= atoi(ordinalBegin
);
1114 if (sCapabilitiesOrdinal
<= n
) {
1115 sCapabilitiesOrdinal
= n
+ 1;
1120 rv
= aStream
->ReadBoolean(&haveCert
);
1121 if (NS_FAILED(rv
)) {
1125 nsCString fingerprint
;
1126 nsCString subjectName
;
1127 nsCString prettyName
;
1128 nsCOMPtr
<nsISupports
> cert
;
1130 rv
= NS_ReadOptionalCString(aStream
, fingerprint
);
1131 if (NS_FAILED(rv
)) {
1135 rv
= NS_ReadOptionalCString(aStream
, subjectName
);
1136 if (NS_FAILED(rv
)) {
1140 rv
= NS_ReadOptionalCString(aStream
, prettyName
);
1141 if (NS_FAILED(rv
)) {
1145 rv
= aStream
->ReadObject(PR_TRUE
, getter_AddRefs(cert
));
1146 if (NS_FAILED(rv
)) {
1151 nsCOMPtr
<nsIURI
> codebase
;
1152 rv
= NS_ReadOptionalObject(aStream
, PR_TRUE
, getter_AddRefs(codebase
));
1153 if (NS_FAILED(rv
)) {
1157 rv
= Init(fingerprint
, subjectName
, prettyName
, cert
, codebase
);
1158 NS_ENSURE_SUCCESS(rv
, rv
);
1160 nsCOMPtr
<nsIURI
> domain
;
1161 rv
= NS_ReadOptionalObject(aStream
, PR_TRUE
, getter_AddRefs(domain
));
1162 if (NS_FAILED(rv
)) {
1168 rv
= aStream
->Read8(&mTrusted
);
1169 if (NS_FAILED(rv
)) {
1177 WriteScalarValue(nsIObjectOutputStream
* aStream
, void* aData
)
1179 PRUint32 value
= NS_PTR_TO_INT32(aData
);
1181 return aStream
->Write32(value
);
1185 nsPrincipal::Write(nsIObjectOutputStream
* aStream
)
1187 NS_ENSURE_STATE(mCert
|| mCodebase
);
1189 // mAnnotations is transient data associated to specific JS stack frames. We
1190 // don't want to serialize that.
1192 PRBool hasCapabilities
= (mCapabilities
&& mCapabilities
->Count() > 0);
1193 nsresult rv
= aStream
->WriteBoolean(hasCapabilities
);
1194 if (NS_SUCCEEDED(rv
) && hasCapabilities
) {
1195 rv
= mCapabilities
->Write(aStream
, WriteScalarValue
);
1198 if (NS_FAILED(rv
)) {
1202 rv
= NS_WriteOptionalStringZ(aStream
, mPrefName
.get());
1203 if (NS_FAILED(rv
)) {
1207 rv
= aStream
->WriteBoolean(mCert
!= nsnull
);
1208 if (NS_FAILED(rv
)) {
1213 NS_ENSURE_STATE(mCert
->cert
);
1215 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->fingerprint
.get());
1216 if (NS_FAILED(rv
)) {
1220 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->subjectName
.get());
1221 if (NS_FAILED(rv
)) {
1225 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->prettyName
.get());
1226 if (NS_FAILED(rv
)) {
1230 rv
= aStream
->WriteCompoundObject(mCert
->cert
, NS_GET_IID(nsISupports
),
1232 if (NS_FAILED(rv
)) {
1237 // mSecurityPolicy is an optimization; it'll get looked up again as needed.
1238 // Don't bother saving and restoring it, esp. since it might change if
1239 // preferences change.
1241 rv
= NS_WriteOptionalCompoundObject(aStream
, mCodebase
, NS_GET_IID(nsIURI
),
1243 if (NS_FAILED(rv
)) {
1247 rv
= NS_WriteOptionalCompoundObject(aStream
, mDomain
, NS_GET_IID(nsIURI
),
1249 if (NS_FAILED(rv
)) {
1253 rv
= aStream
->Write8(mTrusted
);
1254 if (NS_FAILED(rv
)) {
1258 // mCodebaseImmutable and mDomainImmutable will be recomputed based
1259 // on the deserialized URIs in Read().