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 "nsIPrefBranch.h"
57 #include "nsIPrefService.h"
58 #include "nsIClassInfoImpl.h"
59 #include "nsDOMError.h"
61 #include "nsPrincipal.h"
63 static PRBool
URIIsImmutable(nsIURI
* aURI
)
65 nsCOMPtr
<nsIMutable
> mutableObj(do_QueryInterface(aURI
));
69 NS_SUCCEEDED(mutableObj
->GetMutable(&isMutable
)) &&
73 // Static member variables
74 PRInt32
nsPrincipal::sCapabilitiesOrdinal
= 0;
75 const char nsPrincipal::sInvalid
[] = "Invalid";
78 NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal
,
81 NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal
,
85 NS_IMETHODIMP_(nsrefcnt
)
88 NS_PRECONDITION(PRInt32(mJSPrincipals
.refcount
) >= 0, "illegal refcnt");
89 // XXXcaa does this need to be threadsafe? See bug 143559.
90 nsrefcnt count
= PR_AtomicIncrement((PRInt32
*)&mJSPrincipals
.refcount
);
91 NS_LOG_ADDREF(this, count
, "nsPrincipal", sizeof(*this));
95 NS_IMETHODIMP_(nsrefcnt
)
96 nsPrincipal::Release()
98 NS_PRECONDITION(0 != mJSPrincipals
.refcount
, "dup release");
99 nsrefcnt count
= PR_AtomicDecrement((PRInt32
*)&mJSPrincipals
.refcount
);
100 NS_LOG_RELEASE(this, count
, "nsPrincipal");
102 NS_DELETEXPCOM(this);
108 nsPrincipal::nsPrincipal()
109 : mCapabilities(nsnull
),
110 mSecurityPolicy(nsnull
),
112 mInitialized(PR_FALSE
),
113 mCodebaseImmutable(PR_FALSE
),
114 mDomainImmutable(PR_FALSE
)
119 nsPrincipal::Init(const nsACString
& aCertFingerprint
,
120 const nsACString
& aSubjectName
,
121 const nsACString
& aPrettyName
,
125 NS_ENSURE_STATE(!mInitialized
);
126 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty() || aCodebase
); // better have one of these.
128 mInitialized
= PR_TRUE
;
130 mCodebase
= NS_TryToMakeImmutable(aCodebase
);
131 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
134 if (!aCertFingerprint
.IsEmpty()) {
135 rv
= SetCertificate(aCertFingerprint
, aSubjectName
, aPrettyName
, aCert
);
136 if (NS_SUCCEEDED(rv
)) {
137 rv
= mJSPrincipals
.Init(this, mCert
->fingerprint
);
142 rv
= mCodebase
->GetSpec(spec
);
143 if (NS_SUCCEEDED(rv
)) {
144 rv
= mJSPrincipals
.Init(this, spec
);
148 NS_ASSERTION(NS_SUCCEEDED(rv
), "nsPrincipal::Init() failed");
153 nsPrincipal::~nsPrincipal(void)
155 SetSecurityPolicy(nsnull
);
156 delete mCapabilities
;
160 nsPrincipal::GetJSPrincipals(JSContext
*cx
, JSPrincipals
**jsprin
)
162 NS_PRECONDITION(mJSPrincipals
.nsIPrincipalPtr
, "mJSPrincipals is uninitialized!");
164 JSPRINCIPALS_HOLD(cx
, &mJSPrincipals
);
165 *jsprin
= &mJSPrincipals
;
170 nsPrincipal::GetOrigin(char **aOrigin
)
174 nsCOMPtr
<nsIURI
> origin
;
176 origin
= NS_GetInnermostURI(mCodebase
);
180 NS_ASSERTION(mCert
, "No Domain or Codebase for a non-cert principal");
181 return NS_ERROR_FAILURE
;
184 nsCAutoString hostPort
;
186 // chrome: URLs don't have a meaningful origin, so make
187 // sure we just get the full spec for them.
188 // XXX this should be removed in favor of the solution in
191 nsresult rv
= origin
->SchemeIs("chrome", &isChrome
);
192 if (NS_SUCCEEDED(rv
) && !isChrome
) {
193 rv
= origin
->GetHostPort(hostPort
);
196 if (NS_SUCCEEDED(rv
) && !isChrome
) {
197 nsCAutoString scheme
;
198 rv
= origin
->GetScheme(scheme
);
199 NS_ENSURE_SUCCESS(rv
, rv
);
200 *aOrigin
= ToNewCString(scheme
+ NS_LITERAL_CSTRING("://") + hostPort
);
203 // Some URIs (e.g., nsSimpleURI) don't support host. Just
204 // get the full spec.
206 rv
= origin
->GetSpec(spec
);
207 NS_ENSURE_SUCCESS(rv
, rv
);
208 *aOrigin
= ToNewCString(spec
);
211 return *aOrigin
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
215 nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy
)
217 if (mSecurityPolicy
&& mSecurityPolicy
->IsInvalid())
218 SetSecurityPolicy(nsnull
);
220 *aSecurityPolicy
= (void *) mSecurityPolicy
;
225 nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy
)
227 DomainPolicy
*newPolicy
= reinterpret_cast<DomainPolicy
*>(aSecurityPolicy
);
232 mSecurityPolicy
->Drop();
234 mSecurityPolicy
= newPolicy
;
239 nsPrincipal::Equals(nsIPrincipal
*aOther
, PRBool
*aResult
)
244 NS_WARNING("Need a principal to compare this to!");
248 if (this != aOther
) {
250 aOther
->GetHasCertificate(&otherHasCert
);
251 if (otherHasCert
!= (mCert
!= nsnull
)) {
252 // One has a cert while the other doesn't. Not equal.
258 aOther
->GetFingerprint(str
);
259 *aResult
= str
.Equals(mCert
->fingerprint
);
261 // If either subject name is empty, just let the result stand (so that
262 // nsScriptSecurityManager::SetCanEnableCapability works), but if they're
263 // both non-empty, only claim equality if they're equal.
264 if (*aResult
&& !mCert
->subjectName
.IsEmpty()) {
265 // Check the other principal's subject name
266 aOther
->GetSubjectName(str
);
267 *aResult
= str
.Equals(mCert
->subjectName
) || str
.IsEmpty();
274 // If either principal has no URI, it's the saved principal from
275 // preferences; in that case, test true. Do NOT test true if the two
276 // principals have URIs with different codebases.
277 nsCOMPtr
<nsIURI
> otherURI
;
278 nsresult rv
= aOther
->GetURI(getter_AddRefs(otherURI
));
284 if (!otherURI
|| !mCodebase
) {
288 // Fall through to the codebase comparison.
291 // Codebases are equal if they have the same origin.
293 NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
304 nsPrincipal::Subsumes(nsIPrincipal
*aOther
, PRBool
*aResult
)
306 return Equals(aOther
, aResult
);
310 URIIsLocalFile(nsIURI
*aURI
)
313 nsCOMPtr
<nsINetUtil
> util
= do_GetIOService();
315 return util
&& NS_SUCCEEDED(util
->ProtocolHasFlags(aURI
,
316 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
322 nsPrincipal::CheckMayLoad(nsIURI
* aURI
, PRBool aReport
)
324 if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase
, aURI
)) {
325 if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
326 URIIsLocalFile(aURI
)) {
327 nsCOMPtr
<nsIFileURL
> fileURL(do_QueryInterface(aURI
));
329 if (!URIIsLocalFile(mCodebase
)) {
330 // If the codebase is not also a file: uri then forget it
331 // (don't want resource: principals in a file: doc)
333 // note: we're not de-nesting jar: uris here, we want to
334 // keep archive content bottled up in its own little island
337 nsScriptSecurityManager::ReportError(
338 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
341 return NS_ERROR_DOM_BAD_URI
;
345 // pull out the internal files
347 nsCOMPtr
<nsIFileURL
> codebaseFileURL(do_QueryInterface(mCodebase
));
348 nsCOMPtr
<nsIFile
> targetFile
;
349 nsCOMPtr
<nsIFile
> codebaseFile
;
352 // Make sure targetFile is not a directory (bug 209234)
353 // and that it exists w/out unescaping (bug 395343)
355 if (!codebaseFileURL
|| !fileURL
||
356 NS_FAILED(fileURL
->GetFile(getter_AddRefs(targetFile
))) ||
357 NS_FAILED(codebaseFileURL
->GetFile(getter_AddRefs(codebaseFile
))) ||
358 !targetFile
|| !codebaseFile
||
359 NS_FAILED(targetFile
->Normalize()) ||
360 NS_FAILED(codebaseFile
->Normalize()) ||
361 NS_FAILED(targetFile
->IsDirectory(&targetIsDir
)) ||
364 nsScriptSecurityManager::ReportError(
365 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
368 return NS_ERROR_DOM_BAD_URI
;
372 // If the file to be loaded is in a subdirectory of the codebase
373 // (or same-dir if codebase is not a directory) then it will
374 // inherit its codebase principal and be scriptable by that codebase.
376 PRBool codebaseIsDir
;
377 PRBool contained
= PR_FALSE
;
378 nsresult rv
= codebaseFile
->IsDirectory(&codebaseIsDir
);
379 if (NS_SUCCEEDED(rv
) && codebaseIsDir
) {
380 rv
= codebaseFile
->Contains(targetFile
, PR_TRUE
, &contained
);
383 nsCOMPtr
<nsIFile
> codebaseParent
;
384 rv
= codebaseFile
->GetParent(getter_AddRefs(codebaseParent
));
385 if (NS_SUCCEEDED(rv
) && codebaseParent
) {
386 rv
= codebaseParent
->Contains(targetFile
, PR_TRUE
, &contained
);
390 if (NS_SUCCEEDED(rv
) && contained
) {
396 nsScriptSecurityManager::ReportError(
397 nsnull
, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase
, aURI
);
400 return NS_ERROR_DOM_BAD_URI
;
407 nsPrincipal::CanEnableCapability(const char *capability
, PRInt16
*result
)
409 // If this principal is marked invalid, can't enable any capabilities
411 nsCStringKey
invalidKey(sInvalid
);
412 if (mCapabilities
->Exists(&invalidKey
)) {
413 *result
= nsIPrincipal::ENABLE_DENIED
;
419 if (!mCert
&& !mTrusted
) {
420 NS_ASSERTION(mInitialized
, "Trying to enable a capability on an "
421 "uninitialized principal");
423 // If we are a non-trusted codebase principal, capabilities can not
424 // be enabled if the user has not set the pref allowing scripts to
425 // request enhanced capabilities; however, the file: and resource:
426 // schemes are special and may be able to get extra capabilities
427 // even with the pref disabled.
429 static const char pref
[] = "signed.applets.codebase_principal_support";
430 nsCOMPtr
<nsIPrefBranch
> prefBranch
=
431 do_GetService(NS_PREFSERVICE_CONTRACTID
);
434 nsresult rv
= prefBranch
->GetBoolPref(pref
, &mightEnable
);
435 if (NS_FAILED(rv
) || !mightEnable
) {
436 rv
= mCodebase
->SchemeIs("file", &mightEnable
);
437 if (NS_FAILED(rv
) || !mightEnable
) {
438 rv
= mCodebase
->SchemeIs("resource", &mightEnable
);
439 if (NS_FAILED(rv
) || !mightEnable
) {
440 *result
= nsIPrincipal::ENABLE_DENIED
;
449 const char *start
= capability
;
450 *result
= nsIPrincipal::ENABLE_GRANTED
;
452 const char *space
= PL_strchr(start
, ' ');
453 PRInt32 len
= space
? space
- start
: strlen(start
);
454 nsCAutoString
capString(start
, len
);
455 nsCStringKey
key(capString
);
457 mCapabilities
? (PRInt16
)NS_PTR_TO_INT32(mCapabilities
->Get(&key
)) : 0;
458 if (value
== 0 || value
== nsIPrincipal::ENABLE_UNKNOWN
) {
459 // We don't know whether we can enable this capability,
460 // so we should ask the user.
461 value
= nsIPrincipal::ENABLE_WITH_USER_PERMISSION
;
464 if (value
< *result
) {
479 nsPrincipal::SetCanEnableCapability(const char *capability
,
482 // If this principal is marked invalid, can't enable any capabilities
483 if (!mCapabilities
) {
484 mCapabilities
= new nsHashtable(7); // XXXbz gets bumped up to 16 anyway
485 NS_ENSURE_TRUE(mCapabilities
, NS_ERROR_OUT_OF_MEMORY
);
488 nsCStringKey
invalidKey(sInvalid
);
489 if (mCapabilities
->Exists(&invalidKey
)) {
493 if (PL_strcmp(capability
, sInvalid
) == 0) {
494 mCapabilities
->Reset();
497 const char *start
= capability
;
499 const char *space
= PL_strchr(start
, ' ');
500 int len
= space
? space
- start
: strlen(start
);
501 nsCAutoString
capString(start
, len
);
502 nsCStringKey
key(capString
);
503 mCapabilities
->Put(&key
, NS_INT32_TO_PTR(canEnable
));
515 nsPrincipal::IsCapabilityEnabled(const char *capability
, void *annotation
,
519 nsHashtable
*ht
= (nsHashtable
*) annotation
;
523 const char *start
= capability
;
525 const char *space
= PL_strchr(start
, ' ');
526 int len
= space
? space
- start
: strlen(start
);
527 nsCAutoString
capString(start
, len
);
528 nsCStringKey
key(capString
);
529 *result
= (ht
->Get(&key
) == (void *) AnnotationEnabled
);
531 // If any single capability is not enabled, then return false.
546 nsPrincipal::EnableCapability(const char *capability
, void **annotation
)
548 return SetCapability(capability
, annotation
, AnnotationEnabled
);
552 nsPrincipal::DisableCapability(const char *capability
, void **annotation
)
554 return SetCapability(capability
, annotation
, AnnotationDisabled
);
558 nsPrincipal::RevertCapability(const char *capability
, void **annotation
)
561 nsHashtable
*ht
= (nsHashtable
*) *annotation
;
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
);
580 nsPrincipal::SetCapability(const char *capability
, void **annotation
,
581 AnnotationValue value
)
583 if (*annotation
== nsnull
) {
584 nsHashtable
* ht
= new nsHashtable(5);
587 return NS_ERROR_OUT_OF_MEMORY
;
590 // This object owns its annotations. Save them so we can release
591 // them when we destroy this object.
592 if (!mAnnotations
.AppendElement(ht
)) {
594 return NS_ERROR_OUT_OF_MEMORY
;
600 const char *start
= capability
;
602 const char *space
= PL_strchr(start
, ' ');
603 int len
= space
? space
- start
: strlen(start
);
604 nsCAutoString
capString(start
, len
);
605 nsCStringKey
key(capString
);
606 nsHashtable
*ht
= static_cast<nsHashtable
*>(*annotation
);
607 ht
->Put(&key
, (void *) value
);
619 nsPrincipal::GetHasCertificate(PRBool
* aResult
)
621 *aResult
= (mCert
!= nsnull
);
627 nsPrincipal::GetURI(nsIURI
** aURI
)
629 if (mCodebaseImmutable
) {
630 NS_ADDREF(*aURI
= mCodebase
);
639 return NS_EnsureSafeToReturn(mCodebase
, aURI
);
643 nsPrincipal::SetURI(nsIURI
* aURI
)
645 mCodebase
= NS_TryToMakeImmutable(aURI
);
646 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
651 nsPrincipal::SetCertificate(const nsACString
& aFingerprint
,
652 const nsACString
& aSubjectName
,
653 const nsACString
& aPrettyName
,
656 NS_ENSURE_STATE(!mCert
);
658 if (aFingerprint
.IsEmpty()) {
659 return NS_ERROR_INVALID_ARG
;
662 mCert
= new Certificate(aFingerprint
, aSubjectName
, aPrettyName
, aCert
);
664 return NS_ERROR_OUT_OF_MEMORY
;
671 nsPrincipal::GetFingerprint(nsACString
& aFingerprint
)
673 NS_ENSURE_STATE(mCert
);
675 aFingerprint
= mCert
->fingerprint
;
681 nsPrincipal::GetPrettyName(nsACString
& aName
)
683 NS_ENSURE_STATE(mCert
);
685 aName
= mCert
->prettyName
;
691 nsPrincipal::GetSubjectName(nsACString
& aName
)
693 NS_ENSURE_STATE(mCert
);
695 aName
= mCert
->subjectName
;
701 nsPrincipal::GetCertificate(nsISupports
** aCertificate
)
704 NS_IF_ADDREF(*aCertificate
= mCert
->cert
);
707 *aCertificate
= nsnull
;
713 nsPrincipal::GetHashValue(PRUint32
* aValue
)
715 NS_PRECONDITION(mCert
|| mCodebase
, "Need a cert or codebase");
717 // If there is a certificate, it takes precendence over the codebase.
719 *aValue
= nsCRT::HashCode(mCert
->fingerprint
.get());
722 *aValue
= nsScriptSecurityManager::HashPrincipalByOrigin(this);
729 nsPrincipal::GetDomain(nsIURI
** aDomain
)
736 if (mDomainImmutable
) {
737 NS_ADDREF(*aDomain
= mDomain
);
741 return NS_EnsureSafeToReturn(mDomain
, aDomain
);
745 nsPrincipal::SetDomain(nsIURI
* aDomain
)
747 mDomain
= NS_TryToMakeImmutable(aDomain
);
748 mDomainImmutable
= URIIsImmutable(mDomain
);
750 // Domain has changed, forget cached security policy
751 SetSecurityPolicy(nsnull
);
757 nsPrincipal::InitFromPersistent(const char* aPrefName
,
758 const nsCString
& aToken
,
759 const nsCString
& aSubjectName
,
760 const nsACString
& aPrettyName
,
761 const char* aGrantedList
,
762 const char* aDeniedList
,
767 NS_PRECONDITION(!mCapabilities
|| mCapabilities
->Count() == 0,
768 "mCapabilities was already initialized?");
769 NS_PRECONDITION(mAnnotations
.Length() == 0,
770 "mAnnotations was already initialized?");
771 NS_PRECONDITION(!mInitialized
, "We were already initialized?");
773 mInitialized
= PR_TRUE
;
777 rv
= SetCertificate(aToken
, aSubjectName
, aPrettyName
, aCert
);
784 rv
= NS_NewURI(getter_AddRefs(mCodebase
), aToken
, nsnull
);
786 NS_ERROR("Malformed URI in capability.principal preference.");
790 NS_TryToSetImmutable(mCodebase
);
791 mCodebaseImmutable
= URIIsImmutable(mCodebase
);
796 rv
= mJSPrincipals
.Init(this, aToken
);
797 NS_ENSURE_SUCCESS(rv
, rv
);
799 //-- Save the preference name
800 mPrefName
= aPrefName
;
802 const char* ordinalBegin
= PL_strpbrk(aPrefName
, "1234567890");
804 PRIntn n
= atoi(ordinalBegin
);
805 if (sCapabilitiesOrdinal
<= n
) {
806 sCapabilitiesOrdinal
= n
+ 1;
810 //-- Store the capabilities
813 rv
= SetCanEnableCapability(aGrantedList
, nsIPrincipal::ENABLE_GRANTED
);
816 if (NS_SUCCEEDED(rv
) && aDeniedList
) {
817 rv
= SetCanEnableCapability(aDeniedList
, nsIPrincipal::ENABLE_DENIED
);
824 nsPrincipal::EnsureCertData(const nsACString
& aSubjectName
,
825 const nsACString
& aPrettyName
,
828 NS_ENSURE_STATE(mCert
);
830 if (!mCert
->subjectName
.IsEmpty() &&
831 !mCert
->subjectName
.Equals(aSubjectName
)) {
832 return NS_ERROR_INVALID_ARG
;
835 mCert
->subjectName
= aSubjectName
;
836 mCert
->prettyName
= aPrettyName
;
841 struct CapabilityList
848 AppendCapability(nsHashKey
*aKey
, void *aData
, void *capListPtr
)
850 CapabilityList
* capList
= (CapabilityList
*)capListPtr
;
851 PRInt16 value
= (PRInt16
)NS_PTR_TO_INT32(aData
);
852 nsCStringKey
* key
= (nsCStringKey
*)aKey
;
853 if (value
== nsIPrincipal::ENABLE_GRANTED
) {
854 capList
->granted
->Append(key
->GetString(), key
->GetStringLength());
855 capList
->granted
->Append(' ');
857 else if (value
== nsIPrincipal::ENABLE_DENIED
) {
858 capList
->denied
->Append(key
->GetString(), key
->GetStringLength());
859 capList
->denied
->Append(' ');
866 nsPrincipal::GetPreferences(char** aPrefName
, char** aID
,
868 char** aGrantedList
, char** aDeniedList
,
871 if (mPrefName
.IsEmpty()) {
873 mPrefName
.Assign("capability.principal.certificate.p");
876 mPrefName
.Assign("capability.principal.codebase.p");
879 mPrefName
.AppendInt(sCapabilitiesOrdinal
++);
880 mPrefName
.Append(".id");
885 *aSubjectName
= nsnull
;
886 *aGrantedList
= nsnull
;
887 *aDeniedList
= nsnull
;
888 *aIsTrusted
= mTrusted
;
890 char *prefName
= nsnull
;
892 char *subjectName
= nsnull
;
893 char *granted
= nsnull
;
894 char *denied
= nsnull
;
897 prefName
= ToNewCString(mPrefName
);
899 return NS_ERROR_OUT_OF_MEMORY
;
905 id
= ToNewCString(mCert
->fingerprint
);
907 rv
= NS_ERROR_OUT_OF_MEMORY
;
915 nsMemory::Free(prefName
);
920 subjectName
= ToNewCString(mCert
->subjectName
);
922 subjectName
= ToNewCString(EmptyCString());
926 nsMemory::Free(prefName
);
928 return NS_ERROR_OUT_OF_MEMORY
;
932 nsCAutoString grantedListStr
, deniedListStr
;
934 CapabilityList capList
= CapabilityList();
935 capList
.granted
= &grantedListStr
;
936 capList
.denied
= &deniedListStr
;
937 mCapabilities
->Enumerate(AppendCapability
, (void*)&capList
);
940 if (!grantedListStr
.IsEmpty()) {
941 grantedListStr
.Truncate(grantedListStr
.Length() - 1);
942 granted
= ToNewCString(grantedListStr
);
944 nsMemory::Free(prefName
);
946 nsMemory::Free(subjectName
);
947 return NS_ERROR_OUT_OF_MEMORY
;
951 if (!deniedListStr
.IsEmpty()) {
952 deniedListStr
.Truncate(deniedListStr
.Length() - 1);
953 denied
= ToNewCString(deniedListStr
);
955 nsMemory::Free(prefName
);
957 nsMemory::Free(subjectName
);
959 nsMemory::Free(granted
);
961 return NS_ERROR_OUT_OF_MEMORY
;
965 *aPrefName
= prefName
;
967 *aSubjectName
= subjectName
;
968 *aGrantedList
= granted
;
969 *aDeniedList
= denied
;
975 ReadAnnotationEntry(nsIObjectInputStream
* aStream
, nsHashKey
** aKey
,
979 nsCStringKey
* key
= new nsCStringKey(aStream
, &rv
);
985 rv
= aStream
->Read32(&value
);
992 *aData
= (void*) value
;
997 FreeAnnotationEntry(nsIObjectInputStream
* aStream
, nsHashKey
* aKey
,
1004 nsPrincipal::Read(nsIObjectInputStream
* aStream
)
1006 PRBool hasCapabilities
;
1007 nsresult rv
= aStream
->ReadBoolean(&hasCapabilities
);
1008 if (NS_SUCCEEDED(rv
) && hasCapabilities
) {
1009 mCapabilities
= new nsHashtable(aStream
, ReadAnnotationEntry
,
1010 FreeAnnotationEntry
, &rv
);
1011 NS_ENSURE_TRUE(mCapabilities
, NS_ERROR_OUT_OF_MEMORY
);
1014 if (NS_FAILED(rv
)) {
1018 rv
= NS_ReadOptionalCString(aStream
, mPrefName
);
1019 if (NS_FAILED(rv
)) {
1023 const char* ordinalBegin
= PL_strpbrk(mPrefName
.get(), "1234567890");
1025 PRIntn n
= atoi(ordinalBegin
);
1026 if (sCapabilitiesOrdinal
<= n
) {
1027 sCapabilitiesOrdinal
= n
+ 1;
1032 rv
= aStream
->ReadBoolean(&haveCert
);
1033 if (NS_FAILED(rv
)) {
1037 nsCString fingerprint
;
1038 nsCString subjectName
;
1039 nsCString prettyName
;
1040 nsCOMPtr
<nsISupports
> cert
;
1042 rv
= NS_ReadOptionalCString(aStream
, fingerprint
);
1043 if (NS_FAILED(rv
)) {
1047 rv
= NS_ReadOptionalCString(aStream
, subjectName
);
1048 if (NS_FAILED(rv
)) {
1052 rv
= NS_ReadOptionalCString(aStream
, prettyName
);
1053 if (NS_FAILED(rv
)) {
1057 rv
= aStream
->ReadObject(PR_TRUE
, getter_AddRefs(cert
));
1058 if (NS_FAILED(rv
)) {
1063 nsCOMPtr
<nsIURI
> codebase
;
1064 rv
= NS_ReadOptionalObject(aStream
, PR_TRUE
, getter_AddRefs(codebase
));
1065 if (NS_FAILED(rv
)) {
1069 rv
= Init(fingerprint
, subjectName
, prettyName
, cert
, codebase
);
1070 NS_ENSURE_SUCCESS(rv
, rv
);
1072 nsCOMPtr
<nsIURI
> domain
;
1073 rv
= NS_ReadOptionalObject(aStream
, PR_TRUE
, getter_AddRefs(domain
));
1074 if (NS_FAILED(rv
)) {
1080 rv
= aStream
->Read8(&mTrusted
);
1081 if (NS_FAILED(rv
)) {
1089 WriteScalarValue(nsIObjectOutputStream
* aStream
, void* aData
)
1091 PRUint32 value
= NS_PTR_TO_INT32(aData
);
1093 return aStream
->Write32(value
);
1097 nsPrincipal::Write(nsIObjectOutputStream
* aStream
)
1099 NS_ENSURE_STATE(mCert
|| mCodebase
);
1101 // mAnnotations is transient data associated to specific JS stack frames. We
1102 // don't want to serialize that.
1104 PRBool hasCapabilities
= (mCapabilities
&& mCapabilities
->Count() > 0);
1105 nsresult rv
= aStream
->WriteBoolean(hasCapabilities
);
1106 if (NS_SUCCEEDED(rv
) && hasCapabilities
) {
1107 rv
= mCapabilities
->Write(aStream
, WriteScalarValue
);
1110 if (NS_FAILED(rv
)) {
1114 rv
= NS_WriteOptionalStringZ(aStream
, mPrefName
.get());
1115 if (NS_FAILED(rv
)) {
1119 rv
= aStream
->WriteBoolean(mCert
!= nsnull
);
1120 if (NS_FAILED(rv
)) {
1125 NS_ENSURE_STATE(mCert
->cert
);
1127 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->fingerprint
.get());
1128 if (NS_FAILED(rv
)) {
1132 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->subjectName
.get());
1133 if (NS_FAILED(rv
)) {
1137 rv
= NS_WriteOptionalStringZ(aStream
, mCert
->prettyName
.get());
1138 if (NS_FAILED(rv
)) {
1142 rv
= aStream
->WriteCompoundObject(mCert
->cert
, NS_GET_IID(nsISupports
),
1144 if (NS_FAILED(rv
)) {
1149 // mSecurityPolicy is an optimization; it'll get looked up again as needed.
1150 // Don't bother saving and restoring it, esp. since it might change if
1151 // preferences change.
1153 rv
= NS_WriteOptionalCompoundObject(aStream
, mCodebase
, NS_GET_IID(nsIURI
),
1155 if (NS_FAILED(rv
)) {
1159 rv
= NS_WriteOptionalCompoundObject(aStream
, mDomain
, NS_GET_IID(nsIURI
),
1161 if (NS_FAILED(rv
)) {
1165 rv
= aStream
->Write8(mTrusted
);
1166 if (NS_FAILED(rv
)) {
1170 // mCodebaseImmutable and mDomainImmutable will be recomputed based
1171 // on the deserialized URIs in Read().