1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
26 * Christopher A. Aillon
30 * Alternatively, the contents of this file may be used under the terms of
31 * either of the GNU General Public License Version 2 or later (the "GPL"),
32 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
43 #include "nsScriptSecurityManager.h"
44 #include "nsIServiceManager.h"
45 #include "nsIScriptObjectPrincipal.h"
46 #include "nsIScriptContext.h"
48 #include "nsINestedURI.h"
50 #include "nsJSPrincipals.h"
51 #include "nsSystemPrincipal.h"
52 #include "nsPrincipal.h"
53 #include "nsNullPrincipal.h"
54 #include "nsXPIDLString.h"
56 #include "nsCRTGlue.h"
57 #include "nsIJSContextStack.h"
58 #include "nsDOMError.h"
64 #include "nsIXPConnect.h"
65 #include "nsIXPCSecurityManager.h"
66 #include "nsTextFormatter.h"
67 #include "nsIStringBundle.h"
68 #include "nsNetUtil.h"
69 #include "nsIProperties.h"
70 #include "nsDirectoryServiceDefs.h"
72 #include "nsIFileURL.h"
73 #include "nsIZipReader.h"
75 #include "nsIPluginInstance.h"
76 #include "nsIXPConnect.h"
77 #include "nsIScriptGlobalObject.h"
78 #include "nsPIDOMWindow.h"
79 #include "nsIDocShell.h"
80 #include "nsIDocShellTreeItem.h"
81 #include "nsIPrompt.h"
82 #include "nsIWindowWatcher.h"
83 #include "nsIConsoleService.h"
84 #include "nsISecurityCheckedComponent.h"
85 #include "nsIPrefBranch2.h"
86 #include "nsIJSRuntimeService.h"
87 #include "nsIObserverService.h"
88 #include "nsIContent.h"
89 #include "nsAutoPtr.h"
90 #include "nsDOMJSUtils.h"
91 #include "nsAboutProtocolUtils.h"
92 #include "nsIClassInfo.h"
93 #include "nsIURIFixup.h"
94 #include "nsCDefaultURIFixup.h"
95 #include "nsIChromeRegistry.h"
97 static NS_DEFINE_CID(kZipReaderCID
, NS_ZIPREADER_CID
);
99 nsIIOService
*nsScriptSecurityManager::sIOService
= nsnull
;
100 nsIXPConnect
*nsScriptSecurityManager::sXPConnect
= nsnull
;
101 nsIThreadJSContextStack
*nsScriptSecurityManager::sJSContextStack
= nsnull
;
102 nsIStringBundle
*nsScriptSecurityManager::sStrBundle
= nsnull
;
103 JSRuntime
*nsScriptSecurityManager::sRuntime
= 0;
104 PRBool
nsScriptSecurityManager::sStrictFileOriginPolicy
= PR_TRUE
;
106 // Info we need about the JSClasses used by XPConnects wrapped
107 // natives, to avoid having to QI to nsIXPConnectWrappedNative all the
108 // time when doing security checks.
109 static const JSClass
*sXPCWrappedNativeJSClass
;
110 static JSGetObjectOps sXPCWrappedNativeGetObjOps1
;
111 static JSGetObjectOps sXPCWrappedNativeGetObjOps2
;
114 ///////////////////////////
115 // Convenience Functions //
116 ///////////////////////////
117 // Result of this function should not be freed.
118 static inline const PRUnichar
*
119 JSValIDToString(JSContext
*cx
, const jsval idval
)
121 JSAutoRequest
ar(cx
);
122 JSString
*str
= JS_ValueToString(cx
, idval
);
125 return reinterpret_cast<PRUnichar
*>(JS_GetStringChars(str
));
130 GetPrincipalDomainOrigin(nsIPrincipal
* aPrincipal
,
135 nsCOMPtr
<nsIURI
> uri
;
136 aPrincipal
->GetDomain(getter_AddRefs(uri
));
138 aPrincipal
->GetURI(getter_AddRefs(uri
));
140 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
142 uri
= NS_GetInnermostURI(uri
);
143 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
145 nsCAutoString hostPort
;
147 nsresult rv
= uri
->GetHostPort(hostPort
);
148 if (NS_SUCCEEDED(rv
)) {
149 nsCAutoString scheme
;
150 rv
= uri
->GetScheme(scheme
);
151 NS_ENSURE_SUCCESS(rv
, rv
);
152 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + hostPort
;
155 // Some URIs (e.g., nsSimpleURI) don't support host. Just
156 // get the full spec.
157 rv
= uri
->GetSpec(aOrigin
);
158 NS_ENSURE_SUCCESS(rv
, rv
);
164 // Inline copy of JS_GetPrivate() for better inlining and optimization
165 // possibilities. Also doesn't take a cx argument as it's not
166 // needed. We access the private data only on objects whose private
167 // data is not expected to change during the lifetime of the object,
168 // so thus we won't worry about locking and holding on to slot values
169 // etc while referencing private data.
171 caps_GetJSPrivate(JSObject
*obj
)
175 JS_ASSERT(STOBJ_GET_CLASS(obj
)->flags
& JSCLASS_HAS_PRIVATE
);
176 v
= obj
->fslots
[JSSLOT_PRIVATE
];
177 if (!JSVAL_IS_INT(v
))
179 return JSVAL_TO_PRIVATE(v
);
182 static nsIScriptContext
*
183 GetScriptContext(JSContext
*cx
)
185 return GetScriptContextFromJSContext(cx
);
188 inline void SetPendingException(JSContext
*cx
, const char *aMsg
)
190 JSAutoRequest
ar(cx
);
191 JS_ReportError(cx
, "%s", aMsg
);
194 inline void SetPendingException(JSContext
*cx
, const PRUnichar
*aMsg
)
196 JSAutoRequest
ar(cx
);
197 JS_ReportError(cx
, "%hs", aMsg
);
200 // DomainPolicy members
201 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
202 PRUint32
DomainPolicy::sObjects
=0;
203 void DomainPolicy::_printPopulationInfo()
205 printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n",
206 sGeneration
, sObjects
);
209 PRUint32
DomainPolicy::sGeneration
= 0;
211 // Helper class to get stuff from the ClassInfo and not waste extra time with
212 // virtual method calls for things it has already gotten
216 ClassInfoData(nsIClassInfo
*aClassInfo
, const char *aName
)
217 : mClassInfo(aClassInfo
),
218 mName(const_cast<char *>(aName
)),
219 mDidGetFlags(PR_FALSE
),
220 mMustFreeName(PR_FALSE
)
227 nsMemory::Free(mName
);
234 nsresult rv
= mClassInfo
->GetFlags(&mFlags
);
242 mDidGetFlags
= PR_TRUE
;
250 return !!(GetFlags() & nsIClassInfo::DOM_OBJECT
);
253 PRBool
IsContentNode()
255 return !!(GetFlags() & nsIClassInfo::CONTENT_NODE
);
258 const char* GetName()
262 mClassInfo
->GetClassDescription(&mName
);
266 mMustFreeName
= PR_TRUE
;
268 mName
= const_cast<char *>("UnnamedClass");
276 nsIClassInfo
*mClassInfo
; // WEAK
279 PRPackedBool mDidGetFlags
;
280 PRPackedBool mMustFreeName
;
285 AutoCxPusher(nsIJSContextStack
*aStack
, JSContext
*cx
)
286 : mStack(aStack
), mContext(cx
)
288 if (NS_FAILED(mStack
->Push(mContext
))) {
301 nsCOMPtr
<nsIJSContextStack
> mStack
;
306 nsScriptSecurityManager::GetCurrentJSContext()
308 // Get JSContext from stack.
310 if (NS_FAILED(sJSContextStack
->Peek(&cx
)))
316 nsScriptSecurityManager::GetSafeJSContext()
318 // Get JSContext from stack.
320 if (NS_FAILED(sJSContextStack
->GetSafeJSContext(&cx
)))
327 nsScriptSecurityManager::SecurityCompareURIs(nsIURI
* aSourceURI
,
330 return NS_SecurityCompareURIs(aSourceURI
, aTargetURI
, sStrictFileOriginPolicy
);
333 // SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI
334 // is consistent with NS_SecurityCompareURIs. See nsNetUtil.h.
336 nsScriptSecurityManager::SecurityHashURI(nsIURI
* aURI
)
338 return NS_SecurityHashURI(aURI
);
342 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel
* aChannel
,
343 nsIPrincipal
** aPrincipal
)
345 NS_PRECONDITION(aChannel
, "Must have channel!");
346 nsCOMPtr
<nsISupports
> owner
;
347 aChannel
->GetOwner(getter_AddRefs(owner
));
349 CallQueryInterface(owner
, aPrincipal
);
355 // OK, get the principal from the URI. Make sure this does the same thing
356 // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
357 nsCOMPtr
<nsIURI
> uri
;
358 nsresult rv
= NS_GetFinalChannelURI(aChannel
, getter_AddRefs(uri
));
359 NS_ENSURE_SUCCESS(rv
, rv
);
361 return GetCodebasePrincipal(uri
, aPrincipal
);
365 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal
* aPrincipal
,
368 *aIsSystem
= (aPrincipal
== mSystemPrincipal
);
372 NS_IMETHODIMP_(nsIPrincipal
*)
373 nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext
*cx
)
375 NS_ASSERTION(cx
== GetCurrentJSContext(),
376 "Uh, cx is not the current JS context!");
378 nsresult rv
= NS_ERROR_FAILURE
;
379 nsIPrincipal
*principal
= GetSubjectPrincipal(cx
, &rv
);
386 NS_IMETHODIMP_(nsIPrincipal
*)
387 nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext
*cx
, JSStackFrame
**fp
)
389 NS_ASSERTION(cx
== GetCurrentJSContext(),
390 "Uh, cx is not the current JS context!");
392 nsresult rv
= NS_ERROR_FAILURE
;
393 nsIPrincipal
*principal
= GetPrincipalAndFrame(cx
, fp
, &rv
);
404 // Table of security levels
406 DeleteCapability(nsHashKey
*aKey
, void *aData
, void* closure
)
412 //-- Per-Domain Policy - applies to one or more protocols or hosts
415 DomainEntry(const char* aOrigin
,
416 DomainPolicy
* aDomainPolicy
) : mOrigin(aOrigin
),
417 mDomainPolicy(aDomainPolicy
),
420 mDomainPolicy
->Hold();
425 mDomainPolicy
->Drop();
428 PRBool
Matches(const char *anOrigin
)
430 int len
= strlen(anOrigin
);
431 int thisLen
= mOrigin
.Length();
434 if (mOrigin
.RFindChar(':', thisLen
-1, 1) != -1)
435 //-- Policy applies to all URLs of this scheme, compare scheme only
436 return mOrigin
.EqualsIgnoreCase(anOrigin
, thisLen
);
438 //-- Policy applies to a particular host; compare domains
439 if (!mOrigin
.Equals(anOrigin
+ (len
- thisLen
)))
443 char charBefore
= anOrigin
[len
-thisLen
-1];
444 return (charBefore
== '.' || charBefore
== ':' || charBefore
== '/');
448 DomainPolicy
* mDomainPolicy
;
450 #if defined(DEBUG) || defined(DEBUG_CAPS_HACKER)
451 nsCString mPolicyName_DEBUG
;
456 DeleteDomainEntry(nsHashKey
*aKey
, void *aData
, void* closure
)
458 DomainEntry
*entry
= (DomainEntry
*) aData
;
461 DomainEntry
*next
= entry
->mNext
;
468 /////////////////////////////
469 // nsScriptSecurityManager //
470 /////////////////////////////
472 ////////////////////////////////////
473 // Methods implementing ISupports //
474 ////////////////////////////////////
475 NS_IMPL_ISUPPORTS5(nsScriptSecurityManager
,
476 nsIScriptSecurityManager
,
477 nsIXPCSecurityManager
,
478 nsIPrefSecurityCheck
,
482 ///////////////////////////////////////////////////
483 // Methods implementing nsIScriptSecurityManager //
484 ///////////////////////////////////////////////////
486 ///////////////// Security Checks /////////////////
488 nsScriptSecurityManager::CheckObjectAccess(JSContext
*cx
, JSObject
*obj
,
489 jsval id
, JSAccessMode mode
,
492 // Get the security manager
493 nsScriptSecurityManager
*ssm
=
494 nsScriptSecurityManager::GetScriptSecurityManager();
496 NS_ASSERTION(ssm
, "Failed to get security manager service");
500 // Get the object being accessed. We protect these cases:
501 // 1. The Function.prototype.caller property's value, which might lead
502 // an attacker up a call-stack to a function or another object from
503 // a different trust domain.
504 // 2. A user-defined getter or setter function accessible on another
505 // trust domain's window or document object.
506 // *vp can be a primitive, in that case, we use obj as the target
508 JSObject
* target
= JSVAL_IS_PRIMITIVE(*vp
) ? obj
: JSVAL_TO_OBJECT(*vp
);
510 // Do the same-origin check -- this sets a JS exception if the check fails.
511 // Pass the parent object's class name, as we have no class-info for it.
513 ssm
->CheckPropertyAccess(cx
, target
, STOBJ_GET_CLASS(obj
)->name
, id
,
514 (mode
& JSACC_WRITE
) ?
515 (PRInt32
)nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
516 (PRInt32
)nsIXPCSecurityManager::ACCESS_GET_PROPERTY
);
519 return JS_FALSE
; // Security check failed (XXX was an error reported?)
525 nsScriptSecurityManager::CheckPropertyAccess(JSContext
* cx
,
527 const char* aClassName
,
531 return CheckPropertyAccessImpl(aAction
, nsnull
, cx
, aJSObject
,
532 nsnull
, nsnull
, nsnull
,
533 aClassName
, aProperty
, nsnull
);
537 nsScriptSecurityManager::CheckConnect(JSContext
* cx
,
539 const char* aClassName
,
540 const char* aPropertyName
)
542 // Get a context if necessary
545 cx
= GetCurrentJSContext();
547 return NS_OK
; // No JS context, so allow the load
550 nsresult rv
= CheckLoadURIFromScript(cx
, aTargetURI
);
551 if (NS_FAILED(rv
)) return rv
;
553 JSAutoRequest
ar(cx
);
555 JSString
* propertyName
= ::JS_InternString(cx
, aPropertyName
);
557 return NS_ERROR_OUT_OF_MEMORY
;
559 return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD
, nsnull
,
560 cx
, nsnull
, nsnull
, aTargetURI
,
561 nsnull
, aClassName
, STRING_TO_JSVAL(propertyName
), nsnull
);
565 nsScriptSecurityManager::CheckSameOrigin(JSContext
* cx
,
570 // Get a context if necessary
573 cx
= GetCurrentJSContext();
575 return NS_OK
; // No JS context, so allow access
578 // Get a principal from the context
579 nsIPrincipal
* sourcePrincipal
= GetSubjectPrincipal(cx
, &rv
);
583 if (!sourcePrincipal
)
585 NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
589 if (sourcePrincipal
== mSystemPrincipal
)
591 // This is a system (chrome) script, so allow access
595 // Get the original URI from the source principal.
596 // This has the effect of ignoring any change to document.domain
597 // which must be done to avoid DNS spoofing (bug 154930)
598 nsCOMPtr
<nsIURI
> sourceURI
;
599 sourcePrincipal
->GetDomain(getter_AddRefs(sourceURI
));
601 sourcePrincipal
->GetURI(getter_AddRefs(sourceURI
));
602 NS_ENSURE_TRUE(sourceURI
, NS_ERROR_FAILURE
);
606 if (!SecurityCompareURIs(sourceURI
, aTargetURI
))
608 ReportError(cx
, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI
, aTargetURI
);
609 return NS_ERROR_DOM_BAD_URI
;
615 nsScriptSecurityManager::CheckSameOriginURI(nsIURI
* aSourceURI
,
619 if (!SecurityCompareURIs(aSourceURI
, aTargetURI
))
622 ReportError(nsnull
, NS_LITERAL_STRING("CheckSameOriginError"),
623 aSourceURI
, aTargetURI
);
625 return NS_ERROR_DOM_BAD_URI
;
631 nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction
,
632 nsAXPCNativeCallContext
* aCallContext
,
633 JSContext
* cx
, JSObject
* aJSObject
,
634 nsISupports
* aObj
, nsIURI
* aTargetURI
,
635 nsIClassInfo
* aClassInfo
,
636 const char* aClassName
, jsval aProperty
,
637 void** aCachedClassPolicy
)
640 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
644 if (!subjectPrincipal
|| subjectPrincipal
== mSystemPrincipal
)
645 // We have native code or the system principal: just allow access
648 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
650 // Hold the class info data here so we don't have to go back to virtual
651 // methods all the time
652 ClassInfoData
classInfoData(aClassInfo
, aClassName
);
653 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
654 nsCAutoString propertyName
;
655 propertyName
.AssignWithConversion((PRUnichar
*)JSValIDToString(cx
, aProperty
));
656 printf("### CanAccess(%s.%s, %i) ", classInfoData
.GetName(),
657 propertyName
.get(), aAction
);
660 //-- Look up the security policy for this class and subject domain
661 SecurityLevel securityLevel
;
662 rv
= LookupPolicy(subjectPrincipal
, classInfoData
, aProperty
, aAction
,
663 (ClassPolicy
**)aCachedClassPolicy
, &securityLevel
);
667 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
669 // No policy found for this property so use the default of last resort.
670 // If we were called from somewhere other than XPConnect
671 // (no XPC call context), assume this is a DOM class. Otherwise,
672 // ask the ClassInfo.
673 if (!aCallContext
|| classInfoData
.IsDOMClass())
674 securityLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
676 securityLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
679 if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel
))
680 // This flag means securityLevel is allAccess, noAccess, or sameOrigin
682 switch (securityLevel
.level
)
684 case SCRIPT_SECURITY_NO_ACCESS
:
685 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
688 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
691 case SCRIPT_SECURITY_ALL_ACCESS
:
692 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
693 printf("allAccess ");
698 case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
:
700 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
701 printf("sameOrigin ");
703 nsCOMPtr
<nsIPrincipal
> principalHolder
;
706 objectPrincipal
= doGetObjectPrincipal(aJSObject
);
707 if (!objectPrincipal
)
708 rv
= NS_ERROR_DOM_SECURITY_ERR
;
712 if (NS_FAILED(GetCodebasePrincipal(
713 aTargetURI
, getter_AddRefs(objectPrincipal
))))
714 return NS_ERROR_FAILURE
;
718 NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
719 return NS_ERROR_FAILURE
;
722 rv
= CheckSameOriginDOMProp(subjectPrincipal
, objectPrincipal
,
723 aAction
, aTargetURI
!= nsnull
);
727 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
730 NS_ERROR("Bad Security Level Value");
731 return NS_ERROR_FAILURE
;
734 else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
736 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
737 printf("Cap:%s ", securityLevel
.capability
);
739 PRBool capabilityEnabled
= PR_FALSE
;
740 rv
= IsCapabilityEnabled(securityLevel
.capability
, &capabilityEnabled
);
741 if (NS_FAILED(rv
) || !capabilityEnabled
)
742 rv
= NS_ERROR_DOM_SECURITY_ERR
;
747 if (NS_SUCCEEDED(rv
) && classInfoData
.IsContentNode())
749 // No access to anonymous content from the web! (bug 164086)
750 nsIContent
*content
= static_cast<nsIContent
*>(aObj
);
751 if (content
->IsInNativeAnonymousSubtree()) {
752 rv
= NS_ERROR_DOM_SECURITY_ERR
;
756 if (NS_SUCCEEDED(rv
))
758 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
759 printf(" GRANTED.\n");
764 //--See if the object advertises a non-default level of access
765 // using nsISecurityCheckedComponent
766 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
767 do_QueryInterface(aObj
);
769 nsXPIDLCString objectSecurityLevel
;
770 if (checkedComponent
)
772 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
773 nsCOMPtr
<nsIInterfaceInfo
> interfaceInfo
;
775 rv
= aCallContext
->GetCalleeWrapper(getter_AddRefs(wrapper
));
776 if (NS_SUCCEEDED(rv
))
777 rv
= wrapper
->FindInterfaceWithMember(aProperty
, getter_AddRefs(interfaceInfo
));
778 if (NS_SUCCEEDED(rv
))
779 rv
= interfaceInfo
->GetIIDShared(&objIID
);
780 if (NS_SUCCEEDED(rv
))
784 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
785 checkedComponent
->CanGetProperty(objIID
,
786 JSValIDToString(cx
, aProperty
),
787 getter_Copies(objectSecurityLevel
));
789 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
790 checkedComponent
->CanSetProperty(objIID
,
791 JSValIDToString(cx
, aProperty
),
792 getter_Copies(objectSecurityLevel
));
794 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
795 checkedComponent
->CanCallMethod(objIID
,
796 JSValIDToString(cx
, aProperty
),
797 getter_Copies(objectSecurityLevel
));
801 rv
= CheckXPCPermissions(aObj
, objectSecurityLevel
);
802 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
804 printf("CheckXPCPerms GRANTED.\n");
806 printf("CheckXPCPerms DENIED.\n");
809 if (NS_FAILED(rv
)) //-- Security tests failed, access is denied, report error
811 nsAutoString stringName
;
814 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
815 stringName
.AssignLiteral("GetPropertyDeniedOrigins");
817 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
818 stringName
.AssignLiteral("SetPropertyDeniedOrigins");
820 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
821 stringName
.AssignLiteral("CallMethodDeniedOrigins");
824 NS_ConvertUTF8toUTF16
className(classInfoData
.GetName());
825 nsCAutoString subjectOrigin
;
826 GetPrincipalDomainOrigin(subjectPrincipal
, subjectOrigin
);
827 NS_ConvertUTF8toUTF16
subjectOriginUnicode(subjectOrigin
);
829 nsCAutoString objectOrigin
;
830 if (objectPrincipal
) {
831 GetPrincipalDomainOrigin(objectPrincipal
, objectOrigin
);
833 NS_ConvertUTF8toUTF16
objectOriginUnicode(objectOrigin
);
835 nsXPIDLString errorMsg
;
836 const PRUnichar
*formatStrings
[] =
838 subjectOriginUnicode
.get(),
840 JSValIDToString(cx
, aProperty
),
841 objectOriginUnicode
.get()
844 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
846 if (!objectPrincipal
) {
847 stringName
.AppendLiteral("OnlySubject");
851 // We need to keep our existing failure rv and not override it
852 // with a likely success code from the following string bundle
853 // call in order to throw the correct security exception later.
854 nsresult rv2
= sStrBundle
->FormatStringFromName(stringName
.get(),
857 getter_Copies(errorMsg
));
858 if (NS_FAILED(rv2
)) {
859 // Might just be missing the string... Do our best
860 errorMsg
= stringName
;
863 SetPendingException(cx
, errorMsg
.get());
871 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
872 nsIPrincipal
* aObject
,
873 PRBool aIsCheckConnect
)
876 ** Get origin of subject and object and compare.
878 if (aSubject
== aObject
)
881 // These booleans are only used when !aIsCheckConnect. Default
882 // them to false, and change if that turns out wrong.
883 PRBool subjectSetDomain
= PR_FALSE
;
884 PRBool objectSetDomain
= PR_FALSE
;
886 nsCOMPtr
<nsIURI
> subjectURI
;
887 nsCOMPtr
<nsIURI
> objectURI
;
891 // Don't use domain for CheckConnect calls, since that's called for
892 // data-only load checks like XMLHTTPRequest (bug 290100).
893 aSubject
->GetURI(getter_AddRefs(subjectURI
));
894 aObject
->GetURI(getter_AddRefs(objectURI
));
898 aSubject
->GetDomain(getter_AddRefs(subjectURI
));
900 aSubject
->GetURI(getter_AddRefs(subjectURI
));
902 subjectSetDomain
= PR_TRUE
;
905 aObject
->GetDomain(getter_AddRefs(objectURI
));
907 aObject
->GetURI(getter_AddRefs(objectURI
));
909 objectSetDomain
= PR_TRUE
;
913 if (SecurityCompareURIs(subjectURI
, objectURI
))
914 { // If either the subject or the object has changed its principal by
915 // explicitly setting document.domain then the other must also have
916 // done so in order to be considered the same origin. This prevents
917 // DNS spoofing based on document.domain (154930)
919 // But this restriction does not apply to CheckConnect calls, since
920 // that's called for data-only load checks like XMLHTTPRequest where
921 // we ignore domain (bug 290100).
925 // If both or neither explicitly set their domain, allow the access
926 if (subjectSetDomain
== objectSetDomain
)
931 ** Access tests failed, so now report error.
933 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
936 // It's important that
938 // CheckSameOriginPrincipal(A, B, PR_FALSE) == NS_OK
942 // HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
944 // if principals A and B could ever be used as keys in a hashtable.
945 // Violation of this invariant leads to spurious failures of hashtable
946 // lookups. See bug 454850.
949 nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal
* aPrincipal
)
951 nsCOMPtr
<nsIURI
> uri
;
952 aPrincipal
->GetDomain(getter_AddRefs(uri
));
954 aPrincipal
->GetURI(getter_AddRefs(uri
));
955 return SecurityHashURI(uri
);
959 nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
960 nsIPrincipal
* aObject
,
962 PRBool aIsCheckConnect
)
965 if (aIsCheckConnect
) {
966 // Don't do equality compares, just do a same-origin compare,
967 // since the object principal isn't a real principal, just a
968 // GetCodebasePrincipal() on whatever URI we started with.
969 rv
= CheckSameOriginPrincipal(aSubject
, aObject
, aIsCheckConnect
);
972 rv
= aSubject
->Subsumes(aObject
, &subsumes
);
973 if (NS_SUCCEEDED(rv
) && !subsumes
) {
974 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
978 if (NS_SUCCEEDED(rv
))
982 * Content can't ever touch chrome (we check for UniversalXPConnect later)
984 if (aObject
== mSystemPrincipal
)
985 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
988 * If we failed the origin tests it still might be the case that we
989 * are a signed script and have permissions to do this operation.
990 * Check for that here.
992 PRBool capabilityEnabled
= PR_FALSE
;
993 const char* cap
= aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
?
994 "UniversalBrowserWrite" : "UniversalBrowserRead";
995 rv
= IsCapabilityEnabled(cap
, &capabilityEnabled
);
996 NS_ENSURE_SUCCESS(rv
, rv
);
997 if (capabilityEnabled
)
1001 ** Access tests failed, so now report error.
1003 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1007 nsScriptSecurityManager::LookupPolicy(nsIPrincipal
* aPrincipal
,
1008 ClassInfoData
& aClassData
,
1011 ClassPolicy
** aCachedClassPolicy
,
1012 SecurityLevel
* result
)
1015 result
->level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
1017 DomainPolicy
* dpolicy
= nsnull
;
1018 //-- Initialize policies if necessary
1019 if (mPolicyPrefsChanged
)
1021 rv
= InitPolicies();
1027 aPrincipal
->GetSecurityPolicy((void**)&dpolicy
);
1030 if (!dpolicy
&& mOriginToPolicyMap
)
1032 //-- Look up the relevant domain policy, if any
1033 #ifdef DEBUG_CAPS_LookupPolicy
1034 printf("DomainLookup ");
1037 nsCAutoString origin
;
1038 rv
= GetPrincipalDomainOrigin(aPrincipal
, origin
);
1039 NS_ENSURE_SUCCESS(rv
, rv
);
1041 char *start
= origin
.BeginWriting();
1042 const char *nextToLastDot
= nsnull
;
1043 const char *lastDot
= nsnull
;
1044 const char *colon
= nsnull
;
1047 //-- search domain (stop at the end of the string or at the 3rd slash)
1048 for (PRUint32 slashes
=0; *p
; p
++)
1050 if (*p
== '/' && ++slashes
== 3)
1052 *p
= '\0'; // truncate at 3rd slash
1057 nextToLastDot
= lastDot
;
1060 else if (!colon
&& *p
== ':')
1064 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : start
);
1065 DomainEntry
*de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&key
);
1068 nsCAutoString
scheme(start
, colon
-start
+1);
1069 nsCStringKey
schemeKey(scheme
);
1070 de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&schemeKey
);
1075 if (de
->Matches(start
))
1077 dpolicy
= de
->mDomainPolicy
;
1084 dpolicy
= mDefaultPolicy
;
1086 aPrincipal
->SetSecurityPolicy((void*)dpolicy
);
1089 ClassPolicy
* cpolicy
= nsnull
;
1091 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1093 // No per-domain policy for this principal (the more common case)
1094 // so look for a cached class policy from the object wrapper
1095 cpolicy
= *aCachedClassPolicy
;
1099 { //-- No cached policy for this class, need to look it up
1100 #ifdef DEBUG_CAPS_LookupPolicy
1101 printf("ClassLookup ");
1104 cpolicy
= static_cast<ClassPolicy
*>
1105 (PL_DHashTableOperate(dpolicy
,
1106 aClassData
.GetName(),
1109 if (PL_DHASH_ENTRY_IS_FREE(cpolicy
))
1110 cpolicy
= NO_POLICY_FOR_CLASS
;
1112 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1113 *aCachedClassPolicy
= cpolicy
;
1116 // We look for a PropertyPolicy in the following places:
1117 // 1) The ClassPolicy for our class we got from our DomainPolicy
1118 // 2) The mWildcardPolicy of our DomainPolicy
1119 // 3) The ClassPolicy for our class we got from mDefaultPolicy
1120 // 4) The mWildcardPolicy of our mDefaultPolicy
1121 PropertyPolicy
* ppolicy
= nsnull
;
1122 if (cpolicy
!= NO_POLICY_FOR_CLASS
)
1124 ppolicy
= static_cast<PropertyPolicy
*>
1125 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1130 // If there is no class policy for this property, and we have a wildcard
1131 // policy, try that.
1132 if (dpolicy
->mWildcardPolicy
&&
1133 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1136 static_cast<PropertyPolicy
*>
1137 (PL_DHashTableOperate(dpolicy
->mWildcardPolicy
->mPolicy
,
1142 // If dpolicy is not the defauly policy and there's no class or wildcard
1143 // policy for this property, check the default policy for this class and
1144 // the default wildcard policy
1145 if (dpolicy
!= mDefaultPolicy
&&
1146 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1148 cpolicy
= static_cast<ClassPolicy
*>
1149 (PL_DHashTableOperate(mDefaultPolicy
,
1150 aClassData
.GetName(),
1153 if (PL_DHASH_ENTRY_IS_BUSY(cpolicy
))
1156 static_cast<PropertyPolicy
*>
1157 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1162 if ((!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)) &&
1163 mDefaultPolicy
->mWildcardPolicy
)
1166 static_cast<PropertyPolicy
*>
1167 (PL_DHashTableOperate(mDefaultPolicy
->mWildcardPolicy
->mPolicy
,
1173 if (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
))
1176 // Get the correct security level from the property policy
1177 if (aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
)
1178 *result
= ppolicy
->mSet
;
1180 *result
= ppolicy
->mGet
;
1187 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext
*cx
, nsIURI
*aURI
)
1189 // Get principal of currently executing script.
1191 nsIPrincipal
* principal
= GetSubjectPrincipal(cx
, &rv
);
1195 // Native code can load all URIs.
1199 rv
= CheckLoadURIWithPrincipal(principal
, aURI
,
1200 nsIScriptSecurityManager::STANDARD
);
1201 if (NS_SUCCEEDED(rv
)) {
1206 // See if we're attempting to load a file: URI. If so, let a
1207 // UniversalFileRead capability trump the above check.
1208 PRBool isFile
= PR_FALSE
;
1209 PRBool isRes
= PR_FALSE
;
1210 if (NS_FAILED(aURI
->SchemeIs("file", &isFile
)) ||
1211 NS_FAILED(aURI
->SchemeIs("resource", &isRes
)))
1212 return NS_ERROR_FAILURE
;
1213 if (isFile
|| isRes
)
1216 if (NS_FAILED(IsCapabilityEnabled("UniversalFileRead", &enabled
)))
1217 return NS_ERROR_FAILURE
;
1224 if (NS_FAILED(aURI
->GetAsciiSpec(spec
)))
1225 return NS_ERROR_FAILURE
;
1226 JS_ReportError(cx
, "Access to '%s' from script denied", spec
.get());
1227 return NS_ERROR_DOM_BAD_URI
;
1231 nsScriptSecurityManager::CheckLoadURI(nsIURI
*aSourceURI
, nsIURI
*aTargetURI
,
1234 // FIXME: bug 327244 -- this function should really die... Really truly.
1235 NS_PRECONDITION(aSourceURI
, "CheckLoadURI called with null source URI");
1236 NS_ENSURE_ARG_POINTER(aSourceURI
);
1238 // Note: this is not _quite_ right if aSourceURI has
1239 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1240 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1241 // really needs to go away....
1242 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1243 nsresult rv
= CreateCodebasePrincipal(aSourceURI
,
1244 getter_AddRefs(sourcePrincipal
));
1245 NS_ENSURE_SUCCESS(rv
, rv
);
1246 return CheckLoadURIWithPrincipal(sourcePrincipal
, aTargetURI
, aFlags
);
1250 * Helper method to handle cases where a flag passed to
1251 * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
1252 * nsIProtocolHandler flags set.
1253 * @return if success, access is allowed. Otherwise, deny access
1256 DenyAccessIfURIHasFlags(nsIURI
* aURI
, PRUint32 aURIFlags
)
1258 NS_PRECONDITION(aURI
, "Must have URI!");
1262 NS_URIChainHasFlags(aURI
, aURIFlags
, &uriHasFlags
);
1263 NS_ENSURE_SUCCESS(rv
, rv
);
1266 return NS_ERROR_DOM_BAD_URI
;
1273 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal
* aPrincipal
,
1277 NS_PRECONDITION(aPrincipal
, "CheckLoadURIWithPrincipal must have a principal");
1278 // If someone passes a flag that we don't understand, we should
1279 // fail, because they may need a security check that we don't
1281 NS_ENSURE_FALSE(aFlags
& ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
1282 nsIScriptSecurityManager::ALLOW_CHROME
|
1283 nsIScriptSecurityManager::DISALLOW_SCRIPT
|
1284 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
),
1285 NS_ERROR_UNEXPECTED
);
1286 NS_ENSURE_ARG_POINTER(aPrincipal
);
1288 if (aPrincipal
== mSystemPrincipal
) {
1293 nsCOMPtr
<nsIURI
> sourceURI
;
1294 aPrincipal
->GetURI(getter_AddRefs(sourceURI
));
1296 NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
1297 "must have a URI!");
1298 return NS_ERROR_UNEXPECTED
;
1301 // Automatic loads are not allowed from certain protocols.
1302 if (aFlags
& nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
) {
1304 DenyAccessIfURIHasFlags(sourceURI
,
1305 nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT
);
1306 NS_ENSURE_SUCCESS(rv
, rv
);
1309 // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
1310 // would do such inheriting. That would be URIs that do not have their own
1311 // security context.
1312 if (aFlags
& nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
) {
1314 DenyAccessIfURIHasFlags(aTargetURI
,
1315 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
);
1316 NS_ENSURE_SUCCESS(rv
, rv
);
1319 // If either URI is a nested URI, get the base URI
1320 nsCOMPtr
<nsIURI
> sourceBaseURI
= NS_GetInnermostURI(sourceURI
);
1321 nsCOMPtr
<nsIURI
> targetBaseURI
= NS_GetInnermostURI(aTargetURI
);
1323 //-- get the target scheme
1324 nsCAutoString targetScheme
;
1325 nsresult rv
= targetBaseURI
->GetScheme(targetScheme
);
1326 if (NS_FAILED(rv
)) return rv
;
1328 //-- Some callers do not allow loading javascript:
1329 if ((aFlags
& nsIScriptSecurityManager::DISALLOW_SCRIPT
) &&
1330 targetScheme
.EqualsLiteral("javascript"))
1332 return NS_ERROR_DOM_BAD_URI
;
1335 //-- get the source scheme
1336 nsCAutoString sourceScheme
;
1337 rv
= sourceBaseURI
->GetScheme(sourceScheme
);
1338 if (NS_FAILED(rv
)) return rv
;
1340 if (sourceScheme
.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME
)) {
1341 // A null principal can target its own URI.
1342 if (sourceURI
== aTargetURI
) {
1346 else if (targetScheme
.Equals(sourceScheme
,
1347 nsCaseInsensitiveCStringComparator()))
1349 // every scheme can access another URI from the same scheme,
1350 // as long as they don't represent null principals.
1354 NS_NAMED_LITERAL_STRING(errorTag
, "CheckLoadURIError");
1356 // If the schemes don't match, the policy is specified by the protocol
1357 // flags on the target URI. Note that the order of policy checks here is
1358 // very important! We start from most restrictive and work our way down.
1359 // Note that since we're working with the innermost URI, we can just use
1360 // the methods that work on chains of nested URIs and they will only look
1361 // at the flags for our one URI.
1363 // Check for system target URI
1364 rv
= DenyAccessIfURIHasFlags(targetBaseURI
,
1365 nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
);
1366 if (NS_FAILED(rv
)) {
1367 // Deny access, since the origin principal is not system
1368 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1372 // Check for chrome target URI
1374 rv
= NS_URIChainHasFlags(targetBaseURI
,
1375 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1377 NS_ENSURE_SUCCESS(rv
, rv
);
1379 if (aFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) {
1380 if (!targetScheme
.EqualsLiteral("chrome")) {
1381 // for now don't change behavior for resource: or moz-icon:
1385 // allow load only if chrome package is whitelisted
1386 nsCOMPtr
<nsIXULChromeRegistry
> reg(do_GetService(
1387 NS_CHROMEREGISTRY_CONTRACTID
));
1389 PRBool accessAllowed
= PR_FALSE
;
1390 reg
->AllowContentToAccess(targetBaseURI
, &accessAllowed
);
1391 if (accessAllowed
) {
1397 // resource: and chrome: are equivalent, securitywise
1398 // That's bogus!! Fix this. But watch out for
1399 // the view-source stylesheet?
1400 PRBool sourceIsChrome
;
1401 rv
= NS_URIChainHasFlags(sourceBaseURI
,
1402 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1404 NS_ENSURE_SUCCESS(rv
, rv
);
1405 if (sourceIsChrome
) {
1408 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1409 return NS_ERROR_DOM_BAD_URI
;
1412 // Check for target URI pointing to a file
1413 rv
= NS_URIChainHasFlags(targetBaseURI
,
1414 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
1416 NS_ENSURE_SUCCESS(rv
, rv
);
1418 // resource: and chrome: are equivalent, securitywise
1419 // That's bogus!! Fix this. But watch out for
1420 // the view-source stylesheet?
1421 PRBool sourceIsChrome
;
1422 rv
= NS_URIChainHasFlags(sourceURI
,
1423 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1425 NS_ENSURE_SUCCESS(rv
, rv
);
1426 if (sourceIsChrome
) {
1430 // Now check capability policies
1431 static const char loadURIPrefGroup
[] = "checkloaduri";
1432 ClassInfoData
nameData(nsnull
, loadURIPrefGroup
);
1434 SecurityLevel secLevel
;
1435 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1436 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1438 if (NS_SUCCEEDED(rv
) && secLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
1440 // OK for this site!
1444 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1445 return NS_ERROR_DOM_BAD_URI
;
1448 // OK, everyone is allowed to load this, since unflagged handlers are
1449 // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
1450 // need to warn. At some point we'll want to make this warning into an
1451 // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
1452 rv
= NS_URIChainHasFlags(targetBaseURI
,
1453 nsIProtocolHandler::URI_LOADABLE_BY_ANYONE
,
1455 NS_ENSURE_SUCCESS(rv
, rv
);
1457 nsXPIDLString message
;
1458 NS_ConvertASCIItoUTF16
ucsTargetScheme(targetScheme
);
1459 const PRUnichar
* formatStrings
[] = { ucsTargetScheme
.get() };
1461 FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
1463 NS_ARRAY_LENGTH(formatStrings
),
1464 getter_Copies(message
));
1465 if (NS_SUCCEEDED(rv
)) {
1466 nsCOMPtr
<nsIConsoleService
> console(
1467 do_GetService("@mozilla.org/consoleservice;1"));
1468 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1470 console
->LogStringMessage(message
.get());
1472 fprintf(stderr
, "%s\n", NS_ConvertUTF16toUTF8(message
).get());
1481 nsScriptSecurityManager::ReportError(JSContext
* cx
, const nsAString
& messageTag
,
1482 nsIURI
* aSource
, nsIURI
* aTarget
)
1485 NS_ENSURE_TRUE(aSource
&& aTarget
, NS_ERROR_NULL_POINTER
);
1487 // Get the source URL spec
1488 nsCAutoString sourceSpec
;
1489 rv
= aSource
->GetAsciiSpec(sourceSpec
);
1490 NS_ENSURE_SUCCESS(rv
, rv
);
1492 // Get the target URL spec
1493 nsCAutoString targetSpec
;
1494 rv
= aTarget
->GetAsciiSpec(targetSpec
);
1495 NS_ENSURE_SUCCESS(rv
, rv
);
1497 // Localize the error message
1498 nsXPIDLString message
;
1499 NS_ConvertASCIItoUTF16
ucsSourceSpec(sourceSpec
);
1500 NS_ConvertASCIItoUTF16
ucsTargetSpec(targetSpec
);
1501 const PRUnichar
*formatStrings
[] = { ucsSourceSpec
.get(), ucsTargetSpec
.get() };
1502 rv
= sStrBundle
->FormatStringFromName(PromiseFlatString(messageTag
).get(),
1504 NS_ARRAY_LENGTH(formatStrings
),
1505 getter_Copies(message
));
1506 NS_ENSURE_SUCCESS(rv
, rv
);
1508 // If a JS context was passed in, set a JS exception.
1509 // Otherwise, print the error message directly to the JS console
1510 // and to standard output
1513 SetPendingException(cx
, message
.get());
1515 else // Print directly to the console
1517 nsCOMPtr
<nsIConsoleService
> console(
1518 do_GetService("@mozilla.org/consoleservice;1"));
1519 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1521 console
->LogStringMessage(message
.get());
1523 fprintf(stderr
, "%s\n", NS_LossyConvertUTF16toASCII(message
).get());
1530 nsScriptSecurityManager::CheckLoadURIStr(const nsACString
& aSourceURIStr
,
1531 const nsACString
& aTargetURIStr
,
1534 // FIXME: bug 327244 -- this function should really die... Really truly.
1535 nsCOMPtr
<nsIURI
> source
;
1536 nsresult rv
= NS_NewURI(getter_AddRefs(source
), aSourceURIStr
,
1537 nsnull
, nsnull
, sIOService
);
1538 NS_ENSURE_SUCCESS(rv
, rv
);
1540 // Note: this is not _quite_ right if aSourceURI has
1541 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1542 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1543 // really needs to go away....
1544 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1545 rv
= CreateCodebasePrincipal(source
,
1546 getter_AddRefs(sourcePrincipal
));
1547 NS_ENSURE_SUCCESS(rv
, rv
);
1549 return CheckLoadURIStrWithPrincipal(sourcePrincipal
, aTargetURIStr
,
1554 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal
* aPrincipal
,
1555 const nsACString
& aTargetURIStr
,
1559 nsCOMPtr
<nsIURI
> target
;
1560 rv
= NS_NewURI(getter_AddRefs(target
), aTargetURIStr
,
1561 nsnull
, nsnull
, sIOService
);
1562 NS_ENSURE_SUCCESS(rv
, rv
);
1564 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1565 NS_ENSURE_SUCCESS(rv
, rv
);
1567 // Now start testing fixup -- since aTargetURIStr is a string, not
1568 // an nsIURI, we may well end up fixing it up before loading.
1569 // Note: This needs to stay in sync with the nsIURIFixup api.
1570 nsCOMPtr
<nsIURIFixup
> fixup
= do_GetService(NS_URIFIXUP_CONTRACTID
);
1575 PRUint32 flags
[] = {
1576 nsIURIFixup::FIXUP_FLAG_NONE
,
1577 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
,
1578 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
,
1579 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
|
1580 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
1583 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(flags
); ++i
) {
1584 rv
= fixup
->CreateFixupURI(aTargetURIStr
, flags
[i
],
1585 getter_AddRefs(target
));
1586 NS_ENSURE_SUCCESS(rv
, rv
);
1588 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1589 NS_ENSURE_SUCCESS(rv
, rv
);
1596 nsScriptSecurityManager::CheckFunctionAccess(JSContext
*aCx
, void *aFunObj
,
1599 // This check is called for event handlers
1601 nsIPrincipal
* subject
=
1602 GetFunctionObjectPrincipal(aCx
, (JSObject
*)aFunObj
, nsnull
, &rv
);
1604 // If subject is null, get a principal from the function object's scope.
1605 if (NS_SUCCEEDED(rv
) && !subject
)
1610 (JSFunction
*)caps_GetJSPrivate((JSObject
*)aFunObj
);
1611 JSScript
*script
= JS_GetFunctionScript(aCx
, fun
);
1613 NS_ASSERTION(!script
, "Null principal for non-native function!");
1617 subject
= doGetObjectPrincipal((JSObject
*)aFunObj
);
1621 return NS_ERROR_FAILURE
;
1623 if (subject
== mSystemPrincipal
)
1624 // This is the system principal: just allow access
1627 // Check if the principal the function was compiled under is
1628 // allowed to execute scripts.
1631 rv
= CanExecuteScripts(aCx
, subject
, &result
);
1636 return NS_ERROR_DOM_SECURITY_ERR
;
1639 ** Get origin of subject and object and compare.
1641 JSObject
* obj
= (JSObject
*)aTargetObj
;
1642 nsIPrincipal
* object
= doGetObjectPrincipal(obj
);
1645 return NS_ERROR_FAILURE
;
1648 rv
= subject
->Subsumes(object
, &subsumes
);
1649 if (NS_SUCCEEDED(rv
) && !subsumes
) {
1650 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1656 nsScriptSecurityManager::CanExecuteScripts(JSContext
* cx
,
1657 nsIPrincipal
*aPrincipal
,
1662 if (aPrincipal
== mSystemPrincipal
)
1664 // Even if JavaScript is disabled, we must still execute system scripts
1669 //-- See if the current window allows JS execution
1670 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
1671 if (!scriptContext
) return NS_ERROR_FAILURE
;
1673 if (!scriptContext
->GetScriptsEnabled()) {
1674 // No scripting on this context, folks
1679 nsIScriptGlobalObject
*sgo
= scriptContext
->GetGlobalObject();
1682 return NS_ERROR_FAILURE
;
1685 // window can be null here if we're running with a non-DOM window
1686 // as the script global (i.e. a XUL prototype document).
1687 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(sgo
);
1688 nsCOMPtr
<nsIDocShell
> docshell
;
1692 docshell
= window
->GetDocShell();
1695 nsCOMPtr
<nsIDocShellTreeItem
> globalObjTreeItem
=
1696 do_QueryInterface(docshell
);
1698 if (globalObjTreeItem
)
1700 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(globalObjTreeItem
);
1701 nsCOMPtr
<nsIDocShellTreeItem
> parentItem
;
1703 // Walk up the docshell tree to see if any containing docshell disallows scripts
1706 rv
= docshell
->GetAllowJavascript(result
);
1707 if (NS_FAILED(rv
)) return rv
;
1709 return NS_OK
; // Do not run scripts
1710 treeItem
->GetParent(getter_AddRefs(parentItem
));
1711 treeItem
.swap(parentItem
);
1712 docshell
= do_QueryInterface(treeItem
);
1714 if (treeItem
&& !docshell
) {
1715 NS_ERROR("cannot get a docshell from a treeItem!");
1718 } while (treeItem
&& docshell
);
1721 // OK, the docshell doesn't have script execution explicitly disabled.
1722 // Check whether our URI is an "about:" URI that allows scripts. If it is,
1723 // we need to allow JS to run. In this case, don't apply the JS enabled
1724 // pref or policies. On failures, just press on and don't do this special
1726 nsCOMPtr
<nsIURI
> principalURI
;
1727 aPrincipal
->GetURI(getter_AddRefs(principalURI
));
1728 if (!principalURI
) {
1729 // Broken principal of some sort. Disallow.
1731 return NS_ERROR_UNEXPECTED
;
1735 rv
= principalURI
->SchemeIs("about", &isAbout
);
1736 if (NS_SUCCEEDED(rv
) && isAbout
) {
1737 nsCOMPtr
<nsIAboutModule
> module
;
1738 rv
= NS_GetAboutModule(principalURI
, getter_AddRefs(module
));
1739 if (NS_SUCCEEDED(rv
)) {
1741 rv
= module
->GetURIFlags(principalURI
, &flags
);
1742 if (NS_SUCCEEDED(rv
) &&
1743 (flags
& nsIAboutModule::ALLOW_SCRIPT
)) {
1750 //-- See if JS is disabled globally (via prefs)
1751 *result
= mIsJavaScriptEnabled
;
1752 if (mIsJavaScriptEnabled
!= mIsMailJavaScriptEnabled
&& globalObjTreeItem
)
1754 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
1755 globalObjTreeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
1756 docshell
= do_QueryInterface(rootItem
);
1759 // Is this script running from mail?
1761 rv
= docshell
->GetAppType(&appType
);
1762 if (NS_FAILED(rv
)) return rv
;
1763 if (appType
== nsIDocShell::APP_TYPE_MAIL
)
1765 *result
= mIsMailJavaScriptEnabled
;
1771 return NS_OK
; // Do not run scripts
1773 //-- Check for a per-site policy
1774 static const char jsPrefGroupName
[] = "javascript";
1775 ClassInfoData
nameData(nsnull
, jsPrefGroupName
);
1777 SecurityLevel secLevel
;
1778 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1779 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1781 if (NS_FAILED(rv
) || secLevel
.level
== SCRIPT_SECURITY_NO_ACCESS
)
1787 //-- Nobody vetoed, so allow the JS to run.
1792 ///////////////// Principals ///////////////////////
1794 nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal
**aSubjectPrincipal
)
1797 *aSubjectPrincipal
= doGetSubjectPrincipal(&rv
);
1798 if (NS_SUCCEEDED(rv
))
1799 NS_IF_ADDREF(*aSubjectPrincipal
);
1804 nsScriptSecurityManager::doGetSubjectPrincipal(nsresult
* rv
)
1806 NS_PRECONDITION(rv
, "Null out param");
1807 JSContext
*cx
= GetCurrentJSContext();
1813 return GetSubjectPrincipal(cx
, rv
);
1817 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal
**result
)
1819 NS_ADDREF(*result
= mSystemPrincipal
);
1825 nsScriptSecurityManager::SubjectPrincipalIsSystem(PRBool
* aIsSystem
)
1827 NS_ENSURE_ARG_POINTER(aIsSystem
);
1828 *aIsSystem
= PR_FALSE
;
1830 if (!mSystemPrincipal
)
1833 nsCOMPtr
<nsIPrincipal
> subject
;
1834 nsresult rv
= GetSubjectPrincipal(getter_AddRefs(subject
));
1840 // No subject principal means no JS is running;
1841 // this is the equivalent of system principal code
1842 *aIsSystem
= PR_TRUE
;
1846 return mSystemPrincipal
->Equals(subject
, aIsSystem
);
1850 nsScriptSecurityManager::GetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1851 const nsACString
& aSubjectName
,
1852 const nsACString
& aPrettyName
,
1853 nsISupports
* aCertificate
,
1855 nsIPrincipal
**result
)
1859 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty() &&
1860 !aSubjectName
.IsEmpty() &&
1863 return DoGetCertificatePrincipal(aCertFingerprint
, aSubjectName
,
1864 aPrettyName
, aCertificate
, aURI
, PR_TRUE
,
1869 nsScriptSecurityManager::DoGetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1870 const nsACString
& aSubjectName
,
1871 const nsACString
& aPrettyName
,
1872 nsISupports
* aCertificate
,
1874 PRBool aModifyTable
,
1875 nsIPrincipal
**result
)
1877 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty());
1879 // Create a certificate principal out of the certificate ID
1880 // and URI given to us. We will use this principal to test
1881 // equality when doing our hashtable lookups below.
1882 nsRefPtr
<nsPrincipal
> certificate
= new nsPrincipal();
1884 return NS_ERROR_OUT_OF_MEMORY
;
1886 nsresult rv
= certificate
->Init(aCertFingerprint
, aSubjectName
,
1887 aPrettyName
, aCertificate
, aURI
);
1888 NS_ENSURE_SUCCESS(rv
, rv
);
1890 // Check to see if we already have this principal.
1891 nsCOMPtr
<nsIPrincipal
> fromTable
;
1892 mPrincipals
.Get(certificate
, getter_AddRefs(fromTable
));
1894 // Bingo. We found the certificate in the table, which means
1895 // that it has escalated privileges.
1898 // Make sure this principal has names, so if we ever go to save it
1899 // we'll save them. If we get a name mismatch here we'll throw,
1900 // but that's desirable.
1901 rv
= static_cast<nsPrincipal
*>
1902 (static_cast<nsIPrincipal
*>(fromTable
))
1903 ->EnsureCertData(aSubjectName
, aPrettyName
, aCertificate
);
1904 if (NS_FAILED(rv
)) {
1905 // We have a subject name mismatch for the same cert id.
1906 // Hand back the |certificate| object we created and don't give
1907 // it any rights from the table.
1908 NS_ADDREF(*result
= certificate
);
1914 // We were asked to just get the base certificate, so output
1915 // what we have in the table.
1916 certificate
= static_cast<nsPrincipal
*>
1917 (static_cast<nsIPrincipal
*>
1920 // We found a certificate and now need to install a codebase
1921 // on it. We don't want to modify the principal in the hash
1922 // table, so create a new principal and clone the pertinent
1924 nsXPIDLCString prefName
;
1926 nsXPIDLCString subjectName
;
1927 nsXPIDLCString granted
;
1928 nsXPIDLCString denied
;
1930 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
1932 getter_Copies(subjectName
),
1933 getter_Copies(granted
),
1934 getter_Copies(denied
),
1936 // XXXbz assert something about subjectName and aSubjectName here?
1937 if (NS_SUCCEEDED(rv
)) {
1938 NS_ASSERTION(!isTrusted
, "Shouldn't have isTrusted true here");
1940 certificate
= new nsPrincipal();
1942 return NS_ERROR_OUT_OF_MEMORY
;
1944 rv
= certificate
->InitFromPersistent(prefName
, id
,
1945 subjectName
, aPrettyName
,
1952 certificate
->SetURI(aURI
);
1957 NS_ADDREF(*result
= certificate
);
1963 nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI
* aURI
, nsIPrincipal
**result
)
1965 // I _think_ it's safe to not create null principals here based on aURI.
1966 // At least all the callers would do the right thing in those cases, as far
1967 // as I can tell. --bz
1968 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
1970 return NS_ERROR_OUT_OF_MEMORY
;
1972 nsresult rv
= codebase
->Init(EmptyCString(), EmptyCString(),
1973 EmptyCString(), nsnull
, aURI
);
1977 NS_ADDREF(*result
= codebase
);
1983 nsScriptSecurityManager::GetCodebasePrincipal(nsIURI
*aURI
,
1984 nsIPrincipal
**result
)
1986 NS_ENSURE_ARG(aURI
);
1988 PRBool inheritsPrincipal
;
1990 NS_URIChainHasFlags(aURI
,
1991 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
1992 &inheritsPrincipal
);
1993 if (NS_FAILED(rv
) || inheritsPrincipal
) {
1994 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
1997 nsCOMPtr
<nsIPrincipal
> principal
;
1998 rv
= CreateCodebasePrincipal(aURI
, getter_AddRefs(principal
));
1999 if (NS_FAILED(rv
)) return rv
;
2001 if (mPrincipals
.Count() > 0)
2003 //-- Check to see if we already have this principal.
2004 nsCOMPtr
<nsIPrincipal
> fromTable
;
2005 mPrincipals
.Get(principal
, getter_AddRefs(fromTable
));
2007 // We found an existing codebase principal. But it might have a
2008 // generic codebase for this origin on it. Install our particular
2010 // XXXbz this is kinda similar to the code in
2011 // GetCertificatePrincipal, but just ever so slightly different.
2013 nsXPIDLCString prefName
;
2015 nsXPIDLCString subjectName
;
2016 nsXPIDLCString granted
;
2017 nsXPIDLCString denied
;
2019 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
2021 getter_Copies(subjectName
),
2022 getter_Copies(granted
),
2023 getter_Copies(denied
),
2025 if (NS_SUCCEEDED(rv
)) {
2026 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
2028 return NS_ERROR_OUT_OF_MEMORY
;
2030 rv
= codebase
->InitFromPersistent(prefName
, id
,
2031 subjectName
, EmptyCString(),
2038 codebase
->SetURI(aURI
);
2039 principal
= codebase
;
2045 NS_IF_ADDREF(*result
= principal
);
2051 nsScriptSecurityManager::GetPrincipalFromContext(JSContext
*cx
,
2052 nsIPrincipal
**result
)
2056 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2060 return NS_ERROR_FAILURE
;
2063 nsCOMPtr
<nsIScriptObjectPrincipal
> globalData
=
2064 do_QueryInterface(scriptContext
->GetGlobalObject());
2066 NS_IF_ADDREF(*result
= globalData
->GetPrincipal());
2073 nsScriptSecurityManager::GetScriptPrincipal(JSContext
*cx
,
2077 NS_PRECONDITION(rv
, "Null out param");
2083 JSPrincipals
*jsp
= JS_GetScriptPrincipals(cx
, script
);
2085 *rv
= NS_ERROR_FAILURE
;
2086 NS_ERROR("Script compiled without principals!");
2089 nsJSPrincipals
*nsJSPrin
= static_cast<nsJSPrincipals
*>(jsp
);
2090 nsIPrincipal
* result
= nsJSPrin
->nsIPrincipalPtr
;
2092 *rv
= NS_ERROR_FAILURE
;
2098 nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext
*cx
,
2103 NS_PRECONDITION(rv
, "Null out param");
2104 JSFunction
*fun
= (JSFunction
*) caps_GetJSPrivate(obj
);
2105 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2111 // A native function: skip it in order to find its scripted caller.
2115 JSScript
*frameScript
= fp
? JS_GetFrameScript(cx
, fp
) : nsnull
;
2117 if (frameScript
&& frameScript
!= script
)
2119 // There is a frame script, and it's different from the
2120 // function script. In this case we're dealing with either
2121 // an eval or a Script object, and in these cases the
2122 // principal we want is in the frame's script, not in the
2123 // function's script. The function's script is where the
2124 // eval-calling code came from, not where the eval or new
2125 // Script object came from, and we want the principal of
2126 // the eval function object or new Script object.
2128 script
= frameScript
;
2130 else if (JS_GetFunctionObject(fun
) != obj
)
2132 // Here, obj is a cloned function object. In this case, the
2133 // clone's prototype may have been precompiled from brutally
2134 // shared chrome, or else it is a lambda or nested function.
2135 // The general case here is a function compiled against a
2136 // different scope than the one it is parented by at runtime,
2137 // hence the creation of a clone to carry the correct scope
2140 // Since principals follow scope, we must get the object
2141 // principal from the clone's scope chain. There are no
2142 // reliable principals compiled into the function itself.
2144 nsIPrincipal
*result
= doGetObjectPrincipal(obj
);
2146 *rv
= NS_ERROR_FAILURE
;
2150 return GetScriptPrincipal(cx
, script
, rv
);
2155 nsScriptSecurityManager::GetFramePrincipal(JSContext
*cx
,
2159 NS_PRECONDITION(rv
, "Null out param");
2160 JSObject
*obj
= JS_GetFrameFunctionObject(cx
, fp
);
2163 // Must be in a top-level script. Get principal from the script.
2164 JSScript
*script
= JS_GetFrameScript(cx
, fp
);
2165 return GetScriptPrincipal(cx
, script
, rv
);
2168 nsIPrincipal
* result
= GetFunctionObjectPrincipal(cx
, obj
, fp
, rv
);
2171 if (NS_SUCCEEDED(*rv
) && !result
)
2173 JSFunction
*fun
= (JSFunction
*)caps_GetJSPrivate(obj
);
2174 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2176 NS_ASSERTION(!script
, "Null principal for non-native function!");
2185 nsScriptSecurityManager::GetPrincipalAndFrame(JSContext
*cx
,
2186 JSStackFrame
**frameResult
,
2189 NS_PRECONDITION(rv
, "Null out param");
2190 //-- If there's no principal on the stack, look at the global object
2191 // and return the innermost frame for annotations.
2195 // Get principals from innermost frame of JavaScript or Java.
2196 JSStackFrame
*fp
= nsnull
; // tell JS_FrameIterator to start at innermost
2197 for (fp
= JS_FrameIterator(cx
, &fp
); fp
; fp
= JS_FrameIterator(cx
, &fp
))
2199 nsIPrincipal
* result
= GetFramePrincipal(cx
, fp
, rv
);
2202 NS_ASSERTION(NS_SUCCEEDED(*rv
), "Weird return");
2208 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2211 nsCOMPtr
<nsIScriptObjectPrincipal
> globalData
=
2212 do_QueryInterface(scriptContext
->GetGlobalObject());
2215 *rv
= NS_ERROR_FAILURE
;
2219 // Note that we're not in a loop or anything, and nothing comes
2220 // after this point in the function, so we can just return here.
2221 nsIPrincipal
* result
= globalData
->GetPrincipal();
2224 JSStackFrame
*inner
= nsnull
;
2225 *frameResult
= JS_FrameIterator(cx
, &inner
);
2236 nsScriptSecurityManager::GetSubjectPrincipal(JSContext
*cx
,
2239 NS_PRECONDITION(rv
, "Null out param");
2241 return GetPrincipalAndFrame(cx
, &fp
, rv
);
2245 nsScriptSecurityManager::GetObjectPrincipal(JSContext
*aCx
, JSObject
*aObj
,
2246 nsIPrincipal
**result
)
2248 *result
= doGetObjectPrincipal(aObj
);
2250 return NS_ERROR_FAILURE
;
2257 nsScriptSecurityManager::doGetObjectPrincipal(JSObject
*aObj
2259 , PRBool aAllowShortCircuit
2263 NS_ASSERTION(aObj
, "Bad call to doGetObjectPrincipal()!");
2264 nsIPrincipal
* result
= nsnull
;
2267 JSObject
* origObj
= aObj
;
2270 const JSClass
*jsClass
= STOBJ_GET_CLASS(aObj
);
2272 // A common case seen in this code is that we enter this function
2273 // with aObj being a Function object, whose parent is a Call
2274 // object. Neither of those have object principals, so we can skip
2275 // those objects here before we enter the below loop. That way we
2276 // avoid wasting time checking properties of their classes etc in
2279 if (jsClass
== &js_FunctionClass
) {
2280 aObj
= STOBJ_GET_PARENT(aObj
);
2285 jsClass
= STOBJ_GET_CLASS(aObj
);
2287 if (jsClass
== &js_CallClass
) {
2288 aObj
= STOBJ_GET_PARENT(aObj
);
2293 jsClass
= STOBJ_GET_CLASS(aObj
);
2298 // Note: jsClass is set before this loop, and also at the
2299 // *end* of this loop.
2301 // NOTE: These class and getObjectOps hook checks better match
2302 // what IS_WRAPPER_CLASS() does in xpconnect!
2303 if (jsClass
== sXPCWrappedNativeJSClass
||
2304 jsClass
->getObjectOps
== sXPCWrappedNativeGetObjOps1
||
2305 jsClass
->getObjectOps
== sXPCWrappedNativeGetObjOps2
) {
2306 nsIXPConnectWrappedNative
*xpcWrapper
=
2307 (nsIXPConnectWrappedNative
*)caps_GetJSPrivate(aObj
);
2311 if (aAllowShortCircuit
) {
2313 result
= xpcWrapper
->GetObjectPrincipal();
2322 // If not, check if it points to an
2323 // nsIScriptObjectPrincipal
2324 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrin
=
2325 do_QueryWrappedNative(xpcWrapper
);
2327 result
= objPrin
->GetPrincipal();
2334 } else if (!(~jsClass
->flags
& (JSCLASS_HAS_PRIVATE
|
2335 JSCLASS_PRIVATE_IS_NSISUPPORTS
))) {
2336 nsISupports
*priv
= (nsISupports
*)caps_GetJSPrivate(aObj
);
2339 if (aAllowShortCircuit
) {
2340 nsCOMPtr
<nsIXPConnectWrappedNative
> xpcWrapper
=
2341 do_QueryInterface(priv
);
2343 NS_ASSERTION(!xpcWrapper
||
2344 !strcmp(jsClass
->name
, "XPCNativeWrapper"),
2345 "Uh, an nsIXPConnectWrappedNative with the "
2346 "wrong JSClass or getObjectOps hooks!");
2350 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrin
=
2351 do_QueryInterface(priv
);
2354 result
= objPrin
->GetPrincipal();
2362 aObj
= STOBJ_GET_PARENT(aObj
);
2367 jsClass
= STOBJ_GET_CLASS(aObj
);
2370 NS_ASSERTION(!aAllowShortCircuit
||
2371 result
== doGetObjectPrincipal(origObj
, PR_FALSE
),
2372 "Principal mismatch. Not good");
2378 nsScriptSecurityManager::SavePrincipal(nsIPrincipal
* aToSave
)
2380 //-- Save to mPrincipals
2381 mPrincipals
.Put(aToSave
, aToSave
);
2384 nsXPIDLCString idPrefName
;
2386 nsXPIDLCString subjectName
;
2387 nsXPIDLCString grantedList
;
2388 nsXPIDLCString deniedList
;
2390 nsresult rv
= aToSave
->GetPreferences(getter_Copies(idPrefName
),
2392 getter_Copies(subjectName
),
2393 getter_Copies(grantedList
),
2394 getter_Copies(deniedList
),
2396 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2398 nsCAutoString grantedPrefName
;
2399 nsCAutoString deniedPrefName
;
2400 nsCAutoString subjectNamePrefName
;
2401 rv
= GetPrincipalPrefNames( idPrefName
,
2404 subjectNamePrefName
);
2405 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2407 mIsWritingPrefs
= PR_TRUE
;
2409 mSecurityPref
->SecuritySetCharPref(grantedPrefName
.get(), grantedList
);
2411 mSecurityPref
->SecurityClearUserPref(grantedPrefName
.get());
2414 mSecurityPref
->SecuritySetCharPref(deniedPrefName
.get(), deniedList
);
2416 mSecurityPref
->SecurityClearUserPref(deniedPrefName
.get());
2418 if (grantedList
|| deniedList
) {
2419 mSecurityPref
->SecuritySetCharPref(idPrefName
, id
);
2420 mSecurityPref
->SecuritySetCharPref(subjectNamePrefName
.get(),
2424 mSecurityPref
->SecurityClearUserPref(idPrefName
);
2425 mSecurityPref
->SecurityClearUserPref(subjectNamePrefName
.get());
2428 mIsWritingPrefs
= PR_FALSE
;
2430 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
2431 NS_ENSURE_SUCCESS(rv
, rv
);
2432 return prefService
->SavePrefFile(nsnull
);
2435 ///////////////// Capabilities API /////////////////////
2437 nsScriptSecurityManager::IsCapabilityEnabled(const char *capability
,
2441 JSStackFrame
*fp
= nsnull
;
2442 JSContext
*cx
= GetCurrentJSContext();
2443 fp
= cx
? JS_FrameIterator(cx
, &fp
) : nsnull
;
2446 // No script code on stack. Allow execution.
2451 nsIPrincipal
* previousPrincipal
= nsnull
;
2454 nsIPrincipal
* principal
= GetFramePrincipal(cx
, fp
, &rv
);
2459 // If caller has a different principal, stop looking up the stack.
2460 if(previousPrincipal
)
2462 PRBool isEqual
= PR_FALSE
;
2463 if(NS_FAILED(previousPrincipal
->Equals(principal
, &isEqual
)) || !isEqual
)
2467 previousPrincipal
= principal
;
2469 // First check if the principal is even able to enable the
2470 // given capability. If not, don't look any further.
2472 rv
= principal
->CanEnableCapability(capability
, &canEnable
);
2473 if (NS_FAILED(rv
)) return rv
;
2474 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
&&
2475 canEnable
!= nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2478 // Now see if the capability is enabled.
2479 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2480 rv
= principal
->IsCapabilityEnabled(capability
, annotation
, result
);
2481 if (NS_FAILED(rv
)) return rv
;
2484 } while ((fp
= JS_FrameIterator(cx
, &fp
)) != nsnull
);
2486 if (!previousPrincipal
)
2488 // No principals on the stack, all native code. Allow
2489 // execution if the subject principal is the system principal.
2491 return SubjectPrincipalIsSystem(result
);
2498 nsScriptSecurityManager::FormatCapabilityString(nsAString
& aCapability
)
2500 nsAutoString newcaps
;
2501 nsAutoString rawcap
;
2502 NS_NAMED_LITERAL_STRING(capdesc
, "capdesc.");
2504 PRInt32 index
= kNotFound
;
2507 NS_ASSERTION(kNotFound
== -1, "Basic constant changed, algorithm broken!");
2511 index
= aCapability
.FindChar(' ', pos
);
2512 rawcap
= Substring(aCapability
, pos
,
2513 (index
== kNotFound
) ? index
: index
- pos
);
2515 nsXPIDLString capstr
;
2516 rv
= sStrBundle
->GetStringFromName(
2517 nsPromiseFlatString(capdesc
+rawcap
).get(),
2518 getter_Copies(capstr
));
2519 if (NS_SUCCEEDED(rv
))
2523 nsXPIDLString extensionCap
;
2524 const PRUnichar
* formatArgs
[] = { rawcap
.get() };
2525 rv
= sStrBundle
->FormatStringFromName(
2526 NS_LITERAL_STRING("ExtensionCapability").get(),
2528 NS_ARRAY_LENGTH(formatArgs
),
2529 getter_Copies(extensionCap
));
2530 if (NS_SUCCEEDED(rv
))
2531 newcaps
+= extensionCap
;
2536 newcaps
+= NS_LITERAL_STRING("\n");
2537 } while (index
!= kNotFound
);
2539 aCapability
= newcaps
;
2543 nsScriptSecurityManager::CheckConfirmDialog(JSContext
* cx
, nsIPrincipal
* aPrincipal
,
2544 const char* aCapability
, PRBool
*checkValue
)
2547 *checkValue
= PR_FALSE
;
2549 //-- Get a prompter for the current window.
2550 nsCOMPtr
<nsIPrompt
> prompter
;
2553 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2556 nsCOMPtr
<nsIDOMWindowInternal
> domWin
=
2557 do_QueryInterface(scriptContext
->GetGlobalObject());
2559 domWin
->GetPrompter(getter_AddRefs(prompter
));
2565 //-- Couldn't get prompter from the current window, so get the prompt service.
2566 nsCOMPtr
<nsIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
2568 wwatch
->GetNewPrompter(0, getter_AddRefs(prompter
));
2573 //-- Localize the dialog text
2574 nsXPIDLString check
;
2575 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("CheckMessage").get(),
2576 getter_Copies(check
));
2580 nsXPIDLString title
;
2581 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Titleline").get(),
2582 getter_Copies(title
));
2586 nsXPIDLString yesStr
;
2587 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Yes").get(),
2588 getter_Copies(yesStr
));
2592 nsXPIDLString noStr
;
2593 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("No").get(),
2594 getter_Copies(noStr
));
2600 aPrincipal
->GetHasCertificate(&hasCert
);
2602 rv
= aPrincipal
->GetPrettyName(val
);
2604 rv
= GetPrincipalDomainOrigin(aPrincipal
, val
);
2609 NS_ConvertUTF8toUTF16
location(val
);
2610 NS_ConvertASCIItoUTF16
capability(aCapability
);
2611 FormatCapabilityString(capability
);
2612 const PRUnichar
*formatStrings
[] = { location
.get(), capability
.get() };
2614 nsXPIDLString message
;
2615 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityQuery").get(),
2617 NS_ARRAY_LENGTH(formatStrings
),
2618 getter_Copies(message
));
2622 PRInt32 buttonPressed
= 1; // If the user exits by clicking the close box, assume No (button 1)
2623 rv
= prompter
->ConfirmEx(title
.get(), message
.get(),
2624 (nsIPrompt::BUTTON_DELAY_ENABLE
) +
2625 (nsIPrompt::BUTTON_POS_1_DEFAULT
) +
2626 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_0
) +
2627 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_1
),
2628 yesStr
.get(), noStr
.get(), nsnull
, check
.get(), checkValue
, &buttonPressed
);
2631 *checkValue
= PR_FALSE
;
2632 return (buttonPressed
== 0);
2636 nsScriptSecurityManager::RequestCapability(nsIPrincipal
* aPrincipal
,
2637 const char *capability
, PRInt16
* canEnable
)
2639 if (NS_FAILED(aPrincipal
->CanEnableCapability(capability
, canEnable
)))
2640 return NS_ERROR_FAILURE
;
2641 if (*canEnable
== nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2643 // Prompt user for permission to enable capability.
2644 JSContext
* cx
= GetCurrentJSContext();
2646 if (CheckConfirmDialog(cx
, aPrincipal
, capability
, &remember
))
2647 *canEnable
= nsIPrincipal::ENABLE_GRANTED
;
2649 *canEnable
= nsIPrincipal::ENABLE_DENIED
;
2652 //-- Save principal to prefs and to mPrincipals
2653 if (NS_FAILED(aPrincipal
->SetCanEnableCapability(capability
, *canEnable
)))
2654 return NS_ERROR_FAILURE
;
2655 if (NS_FAILED(SavePrincipal(aPrincipal
)))
2656 return NS_ERROR_FAILURE
;
2663 nsScriptSecurityManager::EnableCapability(const char *capability
)
2665 JSContext
*cx
= GetCurrentJSContext();
2668 //-- Error checks for capability string length (200)
2669 if(PL_strlen(capability
)>200)
2671 static const char msg
[] = "Capability name too long";
2672 SetPendingException(cx
, msg
);
2673 return NS_ERROR_FAILURE
;
2676 //-- Check capability string for valid characters
2678 // Logically we might have wanted this in nsPrincipal, but performance
2679 // worries dictate it can't go in IsCapabilityEnabled() and we may have
2680 // to show the capability on a dialog before we call the principal's
2681 // EnableCapability().
2683 // We don't need to validate the capability string on the other APIs
2684 // available to web content. Without the ability to enable junk then
2685 // isPrivilegeEnabled, disablePrivilege, and revertPrivilege all do
2686 // the right thing (effectively nothing) when passed unallowed chars.
2687 for (const char *ch
= capability
; *ch
; ++ch
)
2689 if (!NS_IS_ALPHA(*ch
) && *ch
!= ' ' && !NS_IS_DIGIT(*ch
)
2690 && *ch
!= '_' && *ch
!= '-' && *ch
!= '.')
2692 static const char msg
[] = "Invalid character in capability name";
2693 SetPendingException(cx
, msg
);
2694 return NS_ERROR_FAILURE
;
2699 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2703 return NS_ERROR_NOT_AVAILABLE
;
2705 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2707 if (NS_FAILED(principal
->IsCapabilityEnabled(capability
, annotation
,
2709 return NS_ERROR_FAILURE
;
2714 if (NS_FAILED(RequestCapability(principal
, capability
, &canEnable
)))
2715 return NS_ERROR_FAILURE
;
2717 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
)
2722 principal
->GetHasCertificate(&hasCert
);
2724 rv
= principal
->GetPrettyName(val
);
2726 rv
= GetPrincipalDomainOrigin(principal
, val
);
2731 NS_ConvertUTF8toUTF16
location(val
);
2732 NS_ConvertUTF8toUTF16
cap(capability
);
2733 const PRUnichar
*formatStrings
[] = { location
.get(), cap
.get() };
2735 nsXPIDLString message
;
2736 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityDenied").get(),
2738 NS_ARRAY_LENGTH(formatStrings
),
2739 getter_Copies(message
));
2743 SetPendingException(cx
, message
.get());
2745 return NS_ERROR_FAILURE
; // XXX better error code?
2747 if (NS_FAILED(principal
->EnableCapability(capability
, &annotation
)))
2748 return NS_ERROR_FAILURE
;
2749 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2754 nsScriptSecurityManager::RevertCapability(const char *capability
)
2756 JSContext
*cx
= GetCurrentJSContext();
2759 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2763 return NS_ERROR_NOT_AVAILABLE
;
2764 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2765 principal
->RevertCapability(capability
, &annotation
);
2766 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2771 nsScriptSecurityManager::DisableCapability(const char *capability
)
2773 JSContext
*cx
= GetCurrentJSContext();
2776 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2780 return NS_ERROR_NOT_AVAILABLE
;
2781 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2782 principal
->DisableCapability(capability
, &annotation
);
2783 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2787 //////////////// Master Certificate Functions ///////////////////////////////////////
2789 nsScriptSecurityManager::SetCanEnableCapability(const nsACString
& certFingerprint
,
2790 const char* capability
,
2793 NS_ENSURE_ARG(!certFingerprint
.IsEmpty());
2796 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv
);
2800 //-- Get the system certificate
2801 if (!mSystemCertificate
)
2803 nsCOMPtr
<nsIFile
> systemCertFile
;
2804 nsCOMPtr
<nsIProperties
> directoryService
=
2805 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
2806 if (!directoryService
) return NS_ERROR_FAILURE
;
2807 rv
= directoryService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
, NS_GET_IID(nsIFile
),
2808 getter_AddRefs(systemCertFile
));
2809 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2810 systemCertFile
->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
2811 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2812 nsCOMPtr
<nsIZipReader
> systemCertZip
= do_CreateInstance(kZipReaderCID
, &rv
);
2813 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2814 rv
= systemCertZip
->Open(systemCertFile
);
2815 if (NS_SUCCEEDED(rv
))
2817 nsCOMPtr
<nsIJAR
> systemCertJar(do_QueryInterface(systemCertZip
, &rv
));
2818 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2819 rv
= systemCertJar
->GetCertificatePrincipal(nsnull
,
2820 getter_AddRefs(mSystemCertificate
));
2821 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2825 //-- Make sure the caller's principal is the system certificate
2826 PRBool isEqual
= PR_FALSE
;
2827 if (mSystemCertificate
)
2829 rv
= mSystemCertificate
->Equals(subjectPrincipal
, &isEqual
);
2830 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2834 JSContext
* cx
= GetCurrentJSContext();
2835 if (!cx
) return NS_ERROR_FAILURE
;
2836 static const char msg1
[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate";
2837 static const char msg2
[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established";
2838 SetPendingException(cx
, mSystemCertificate
? msg1
: msg2
);
2839 return NS_ERROR_FAILURE
;
2842 //-- Get the target principal
2843 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
2844 rv
= DoGetCertificatePrincipal(certFingerprint
, EmptyCString(),
2845 EmptyCString(), nsnull
,
2847 getter_AddRefs(objectPrincipal
));
2848 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2849 rv
= objectPrincipal
->SetCanEnableCapability(capability
, canEnable
);
2850 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2851 return SavePrincipal(objectPrincipal
);
2854 ////////////////////////////////////////////////
2855 // Methods implementing nsIXPCSecurityManager //
2856 ////////////////////////////////////////////////
2859 nsScriptSecurityManager::CanCreateWrapper(JSContext
*cx
,
2862 nsIClassInfo
*aClassInfo
,
2865 #ifdef DEBUG_CAPS_CanCreateWrapper
2866 char* iidStr
= aIID
.ToString();
2867 printf("### CanCreateWrapper(%s) ", iidStr
);
2868 nsCRT::free(iidStr
);
2870 // XXX Special case for nsIXPCException ?
2871 ClassInfoData objClassInfo
= ClassInfoData(aClassInfo
, nsnull
);
2872 if (objClassInfo
.IsDOMClass())
2874 #ifdef DEBUG_CAPS_CanCreateWrapper
2875 printf("DOM class - GRANTED.\n");
2880 //--See if the object advertises a non-default level of access
2881 // using nsISecurityCheckedComponent
2882 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
2883 do_QueryInterface(aObj
);
2885 nsXPIDLCString objectSecurityLevel
;
2886 if (checkedComponent
)
2887 checkedComponent
->CanCreateWrapper((nsIID
*)&aIID
, getter_Copies(objectSecurityLevel
));
2889 nsresult rv
= CheckXPCPermissions(aObj
, objectSecurityLevel
);
2892 //-- Access denied, report an error
2893 NS_ConvertUTF8toUTF16
strName("CreateWrapperDenied");
2894 nsCAutoString origin
;
2896 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv2
);
2897 if (NS_SUCCEEDED(rv2
) && subjectPrincipal
) {
2898 GetPrincipalDomainOrigin(subjectPrincipal
, origin
);
2900 NS_ConvertUTF8toUTF16
originUnicode(origin
);
2901 NS_ConvertUTF8toUTF16
className(objClassInfo
.GetName());
2902 const PRUnichar
* formatStrings
[] = {
2906 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
2907 if (originUnicode
.IsEmpty()) {
2910 strName
.AppendLiteral("ForOrigin");
2912 nsXPIDLString errorMsg
;
2913 // We need to keep our existing failure rv and not override it
2914 // with a likely success code from the following string bundle
2915 // call in order to throw the correct security exception later.
2916 rv2
= sStrBundle
->FormatStringFromName(strName
.get(),
2919 getter_Copies(errorMsg
));
2920 NS_ENSURE_SUCCESS(rv2
, rv2
);
2922 SetPendingException(cx
, errorMsg
.get());
2924 #ifdef DEBUG_CAPS_CanCreateWrapper
2925 printf("DENIED.\n");
2929 printf("GRANTED.\n");
2936 #ifdef XPC_IDISPATCH_SUPPORT
2938 nsScriptSecurityManager::CheckComponentPermissions(JSContext
*cx
,
2942 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
2946 // Reformat the CID string so it's suitable for prefs
2947 nsXPIDLCString cidTemp
;
2948 cidTemp
.Adopt(aCID
.ToString());
2949 nsCAutoString
cid(NS_LITERAL_CSTRING("CID") +
2950 Substring(cidTemp
, 1, cidTemp
.Length() - 2));
2953 #ifdef DEBUG_CAPS_CheckComponentPermissions
2954 printf("### CheckComponentPermissions(ClassID.%s) ",cid
.get());
2957 // Look up the policy for this class.
2958 // while this isn't a property we'll treat it as such, using ACCESS_CALL_METHOD
2959 JSAutoRequest
ar(cx
);
2960 jsval cidVal
= STRING_TO_JSVAL(::JS_InternString(cx
, cid
.get()));
2962 ClassInfoData
nameData(nsnull
, "ClassID");
2963 SecurityLevel securityLevel
;
2964 rv
= LookupPolicy(subjectPrincipal
, nameData
, cidVal
,
2965 nsIXPCSecurityManager::ACCESS_CALL_METHOD
,
2966 nsnull
, &securityLevel
);
2970 // If there's no policy stored, use the "security.classID.allowByDefault" pref
2971 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
2972 securityLevel
.level
= mXPCDefaultGrantAll
? SCRIPT_SECURITY_ALL_ACCESS
:
2973 SCRIPT_SECURITY_NO_ACCESS
;
2975 if (securityLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
2977 #ifdef DEBUG_CAPS_CheckComponentPermissions
2978 printf(" GRANTED.\n");
2983 #ifdef DEBUG_CAPS_CheckComponentPermissions
2984 printf(" DENIED.\n");
2986 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
2991 nsScriptSecurityManager::CanCreateInstance(JSContext
*cx
,
2994 #ifdef DEBUG_CAPS_CanCreateInstance
2995 char* cidStr
= aCID
.ToString();
2996 printf("### CanCreateInstance(%s) ", cidStr
);
2997 nsCRT::free(cidStr
);
3000 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
);
3002 #ifdef XPC_IDISPATCH_SUPPORT
3004 rv
= CheckComponentPermissions(cx
, aCID
);
3009 //-- Access denied, report an error
3010 nsCAutoString
errorMsg("Permission denied to create instance of class. CID=");
3011 char cidStr
[NSID_LENGTH
];
3012 aCID
.ToProvidedString(cidStr
);
3013 errorMsg
.Append(cidStr
);
3014 SetPendingException(cx
, errorMsg
.get());
3016 #ifdef DEBUG_CAPS_CanCreateInstance
3021 printf("GRANTED\n");
3028 nsScriptSecurityManager::CanGetService(JSContext
*cx
,
3031 #ifdef DEBUG_CAPS_CanGetService
3032 char* cidStr
= aCID
.ToString();
3033 printf("### CanGetService(%s) ", cidStr
);
3034 nsCRT::free(cidStr
);
3037 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
);
3040 //-- Access denied, report an error
3041 nsCAutoString
errorMsg("Permission denied to get service. CID=");
3042 char cidStr
[NSID_LENGTH
];
3043 aCID
.ToProvidedString(cidStr
);
3044 errorMsg
.Append(cidStr
);
3045 SetPendingException(cx
, errorMsg
.get());
3047 #ifdef DEBUG_CAPS_CanGetService
3052 printf("GRANTED\n");
3061 nsScriptSecurityManager::CanAccess(PRUint32 aAction
,
3062 nsAXPCNativeCallContext
* aCallContext
,
3064 JSObject
* aJSObject
,
3066 nsIClassInfo
* aClassInfo
,
3067 jsval aPropertyName
,
3070 return CheckPropertyAccessImpl(aAction
, aCallContext
, cx
,
3071 aJSObject
, aObj
, nsnull
, aClassInfo
,
3072 nsnull
, aPropertyName
, aPolicy
);
3076 nsScriptSecurityManager::CheckXPCPermissions(nsISupports
* aObj
,
3077 const char* aObjectSecurityLevel
)
3079 //-- Check for the all-powerful UniversalXPConnect privilege
3080 PRBool ok
= PR_FALSE
;
3081 if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalXPConnect", &ok
)) && ok
)
3084 //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
3085 if (aObjectSecurityLevel
)
3087 if (PL_strcasecmp(aObjectSecurityLevel
, "allAccess") == 0)
3089 else if (PL_strcasecmp(aObjectSecurityLevel
, "noAccess") != 0)
3091 PRBool canAccess
= PR_FALSE
;
3092 if (NS_SUCCEEDED(IsCapabilityEnabled(aObjectSecurityLevel
, &canAccess
)) &&
3098 //-- If user allows scripting of plugins by untrusted scripts,
3099 // and the target object is a plugin, allow the access.
3103 nsCOMPtr
<nsIPluginInstance
> plugin(do_QueryInterface(aObj
, &rv
));
3104 if (NS_SUCCEEDED(rv
))
3106 static PRBool prefSet
= PR_FALSE
;
3107 static PRBool allowPluginAccess
= PR_FALSE
;
3110 rv
= mSecurityPref
->SecurityGetBoolPref("security.xpconnect.plugin.unrestricted",
3111 &allowPluginAccess
);
3114 if (allowPluginAccess
)
3119 //-- Access tests failed
3120 return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED
;
3123 //////////////////////////////////////////////
3124 // Method implementing nsIPrefSecurityCheck //
3125 //////////////////////////////////////////////
3128 nsScriptSecurityManager::CanAccessSecurityPreferences(PRBool
* _retval
)
3130 return IsCapabilityEnabled("CapabilityPreferencesAccess", _retval
);
3133 /////////////////////////////////////////////
3134 // Method implementing nsIChannelEventSink //
3135 /////////////////////////////////////////////
3137 nsScriptSecurityManager::OnChannelRedirect(nsIChannel
* oldChannel
,
3138 nsIChannel
* newChannel
,
3139 PRUint32 redirFlags
)
3141 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
3142 GetChannelPrincipal(oldChannel
, getter_AddRefs(oldPrincipal
));
3144 nsCOMPtr
<nsIURI
> newURI
;
3145 newChannel
->GetURI(getter_AddRefs(newURI
));
3146 nsCOMPtr
<nsIURI
> newOriginalURI
;
3147 newChannel
->GetOriginalURI(getter_AddRefs(newOriginalURI
));
3149 NS_ENSURE_STATE(oldPrincipal
&& newURI
&& newOriginalURI
);
3151 const PRUint32 flags
=
3152 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
3153 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
3154 nsresult rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newURI
, flags
);
3155 if (NS_SUCCEEDED(rv
) && newOriginalURI
!= newURI
) {
3156 rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newOriginalURI
, flags
);
3162 /////////////////////////////////////
3163 // Method implementing nsIObserver //
3164 /////////////////////////////////////
3165 static const char sPrincipalPrefix
[] = "capability.principal";
3166 static const char sPolicyPrefix
[] = "capability.policy.";
3169 nsScriptSecurityManager::Observe(nsISupports
* aObject
, const char* aTopic
,
3170 const PRUnichar
* aMessage
)
3172 nsresult rv
= NS_OK
;
3173 NS_ConvertUTF16toUTF8
messageStr(aMessage
);
3174 const char *message
= messageStr
.get();
3176 static const char jsPrefix
[] = "javascript.";
3177 static const char securityPrefix
[] = "security.";
3178 if ((PL_strncmp(message
, jsPrefix
, sizeof(jsPrefix
)-1) == 0) ||
3179 (PL_strncmp(message
, securityPrefix
, sizeof(securityPrefix
)-1) == 0) )
3181 ScriptSecurityPrefChanged();
3183 else if (PL_strncmp(message
, sPolicyPrefix
, sizeof(sPolicyPrefix
)-1) == 0)
3185 // This will force re-initialization of the pref table
3186 mPolicyPrefsChanged
= PR_TRUE
;
3188 else if ((PL_strncmp(message
, sPrincipalPrefix
, sizeof(sPrincipalPrefix
)-1) == 0) &&
3191 static const char id
[] = "id";
3192 char* lastDot
= PL_strrchr(message
, '.');
3193 //-- This check makes sure the string copy below doesn't overwrite its bounds
3194 if(PL_strlen(lastDot
) >= sizeof(id
))
3196 PL_strcpy(lastDot
+ 1, id
);
3197 const char** idPrefArray
= (const char**)&message
;
3198 rv
= InitPrincipals(1, idPrefArray
, mSecurityPref
);
3204 /////////////////////////////////////////////
3205 // Constructor, Destructor, Initialization //
3206 /////////////////////////////////////////////
3207 nsScriptSecurityManager::nsScriptSecurityManager(void)
3208 : mOriginToPolicyMap(nsnull
),
3209 mDefaultPolicy(nsnull
),
3210 mCapabilities(nsnull
),
3211 mIsJavaScriptEnabled(PR_FALSE
),
3212 mIsMailJavaScriptEnabled(PR_FALSE
),
3213 mIsWritingPrefs(PR_FALSE
),
3214 mPolicyPrefsChanged(PR_TRUE
)
3215 #ifdef XPC_IDISPATCH_SUPPORT
3216 , mXPCDefaultGrantAll(PR_FALSE
)
3219 NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure.");
3220 mPrincipals
.Init(31);
3224 nsresult
nsScriptSecurityManager::Init()
3226 nsresult rv
= CallGetService(nsIXPConnect::GetCID(), &sXPConnect
);
3227 NS_ENSURE_SUCCESS(rv
, rv
);
3229 rv
= CallGetService("@mozilla.org/js/xpc/ContextStack;1", &sJSContextStack
);
3230 NS_ENSURE_SUCCESS(rv
, rv
);
3232 JSContext
* cx
= GetSafeJSContext();
3233 if (!cx
) return NS_ERROR_FAILURE
; // this can happen of xpt loading fails
3235 ::JS_BeginRequest(cx
);
3236 if (sEnabledID
== JSVAL_VOID
)
3237 sEnabledID
= STRING_TO_JSVAL(::JS_InternString(cx
, "enabled"));
3238 ::JS_EndRequest(cx
);
3241 NS_ENSURE_SUCCESS(rv
, rv
);
3243 rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
3244 NS_ENSURE_SUCCESS(rv
, rv
);
3246 nsCOMPtr
<nsIStringBundleService
> bundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
3247 NS_ENSURE_SUCCESS(rv
, rv
);
3249 rv
= bundleService
->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle
);
3250 NS_ENSURE_SUCCESS(rv
, rv
);
3252 // Create our system principal singleton
3253 nsRefPtr
<nsSystemPrincipal
> system
= new nsSystemPrincipal();
3254 NS_ENSURE_TRUE(system
, NS_ERROR_OUT_OF_MEMORY
);
3256 rv
= system
->Init();
3257 NS_ENSURE_SUCCESS(rv
, rv
);
3259 mSystemPrincipal
= system
;
3261 //-- Register security check callback in the JS engine
3262 // Currently this is used to control access to function.caller
3263 nsCOMPtr
<nsIJSRuntimeService
> runtimeService
=
3264 do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv
);
3265 NS_ENSURE_SUCCESS(rv
, rv
);
3267 rv
= runtimeService
->GetRuntime(&sRuntime
);
3268 NS_ENSURE_SUCCESS(rv
, rv
);
3270 static JSSecurityCallbacks securityCallbacks
= {
3277 JSSecurityCallbacks
*oldcallbacks
=
3279 JS_SetRuntimeSecurityCallbacks(sRuntime
, &securityCallbacks
);
3280 NS_ASSERTION(!oldcallbacks
, "Someone else set security callbacks!");
3282 sXPConnect
->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeJSClass
,
3283 &sXPCWrappedNativeGetObjOps1
,
3284 &sXPCWrappedNativeGetObjOps2
);
3288 static nsScriptSecurityManager
*gScriptSecMan
= nsnull
;
3290 jsval
nsScriptSecurityManager::sEnabledID
= JSVAL_VOID
;
3292 nsScriptSecurityManager::~nsScriptSecurityManager(void)
3294 delete mOriginToPolicyMap
;
3296 mDefaultPolicy
->Drop();
3297 delete mCapabilities
;
3298 gScriptSecMan
= nsnull
;
3302 nsScriptSecurityManager::Shutdown()
3305 JS_SetRuntimeSecurityCallbacks(sRuntime
, NULL
);
3308 sEnabledID
= JSVAL_VOID
;
3310 NS_IF_RELEASE(sIOService
);
3311 NS_IF_RELEASE(sXPConnect
);
3312 NS_IF_RELEASE(sJSContextStack
);
3313 NS_IF_RELEASE(sStrBundle
);
3316 nsScriptSecurityManager
*
3317 nsScriptSecurityManager::GetScriptSecurityManager()
3321 nsScriptSecurityManager
* ssManager
= new nsScriptSecurityManager();
3325 rv
= ssManager
->Init();
3326 NS_ASSERTION(NS_SUCCEEDED(rv
), "Failed to initialize nsScriptSecurityManager");
3327 if (NS_FAILED(rv
)) {
3332 rv
= nsJSPrincipals::Startup();
3333 if (NS_FAILED(rv
)) {
3334 NS_WARNING("can't initialize JS engine security protocol glue!");
3339 rv
= sXPConnect
->SetDefaultSecurityManager(ssManager
,
3340 nsIXPCSecurityManager::HOOK_ALL
);
3341 if (NS_FAILED(rv
)) {
3342 NS_WARNING("Failed to install xpconnect security manager!");
3347 gScriptSecMan
= ssManager
;
3349 return gScriptSecMan
;
3352 // Currently this nsGenericFactory constructor is used only from FastLoad
3353 // (XPCOM object deserialization) code, when "creating" the system principal
3356 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
3358 nsIPrincipal
*sysprin
= nsnull
;
3360 NS_ADDREF(sysprin
= gScriptSecMan
->mSystemPrincipal
);
3361 return static_cast<nsSystemPrincipal
*>(sysprin
);
3365 nsScriptSecurityManager::InitPolicies()
3367 // Clear any policies cached on XPConnect wrappers
3368 NS_ENSURE_STATE(sXPConnect
);
3369 nsresult rv
= sXPConnect
->ClearAllWrappedNativeSecurityPolicies();
3370 if (NS_FAILED(rv
)) return rv
;
3372 //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
3373 //-- whose dtor decrements refcount of stored DomainPolicy object
3374 delete mOriginToPolicyMap
;
3376 //-- Marks all the survivor DomainPolicy objects (those cached
3377 //-- by nsPrincipal objects) as invalid: they will be released
3378 //-- on first nsPrincipal::GetSecurityPolicy() attempt.
3379 DomainPolicy::InvalidateAll();
3381 //-- Release old default policy
3382 if(mDefaultPolicy
) {
3383 mDefaultPolicy
->Drop();
3384 mDefaultPolicy
= nsnull
;
3387 //-- Initialize a new mOriginToPolicyMap
3388 mOriginToPolicyMap
=
3389 new nsObjectHashtable(nsnull
, nsnull
, DeleteDomainEntry
, nsnull
);
3390 if (!mOriginToPolicyMap
)
3391 return NS_ERROR_OUT_OF_MEMORY
;
3393 //-- Create, refcount and initialize a new default policy
3394 mDefaultPolicy
= new DomainPolicy();
3395 if (!mDefaultPolicy
)
3396 return NS_ERROR_OUT_OF_MEMORY
;
3398 mDefaultPolicy
->Hold();
3399 if (!mDefaultPolicy
->Init())
3400 return NS_ERROR_UNEXPECTED
;
3402 //-- Initialize the table of security levels
3406 new nsObjectHashtable(nsnull
, nsnull
, DeleteCapability
, nsnull
);
3408 return NS_ERROR_OUT_OF_MEMORY
;
3411 // Get a JS context - we need it to create internalized strings later.
3412 JSContext
* cx
= GetSafeJSContext();
3413 NS_ASSERTION(cx
, "failed to get JS context");
3414 AutoCxPusher
autoPusher(sJSContextStack
, cx
);
3415 rv
= InitDomainPolicy(cx
, "default", mDefaultPolicy
);
3416 NS_ENSURE_SUCCESS(rv
, rv
);
3418 nsXPIDLCString policyNames
;
3419 rv
= mSecurityPref
->SecurityGetCharPref("capability.policy.policynames",
3420 getter_Copies(policyNames
));
3422 nsXPIDLCString defaultPolicyNames
;
3423 rv
= mSecurityPref
->SecurityGetCharPref("capability.policy.default_policynames",
3424 getter_Copies(defaultPolicyNames
));
3425 policyNames
+= NS_LITERAL_CSTRING(" ") + defaultPolicyNames
;
3427 //-- Initialize domain policies
3428 char* policyCurrent
= policyNames
.BeginWriting();
3429 PRBool morePolicies
= PR_TRUE
;
3430 while (morePolicies
)
3432 while(*policyCurrent
== ' ' || *policyCurrent
== ',')
3434 if (*policyCurrent
== '\0')
3436 char* nameBegin
= policyCurrent
;
3438 while(*policyCurrent
!= '\0' && *policyCurrent
!= ' ' && *policyCurrent
!= ',')
3441 morePolicies
= (*policyCurrent
!= '\0');
3442 *policyCurrent
= '\0';
3445 nsCAutoString
sitesPrefName(
3446 NS_LITERAL_CSTRING(sPolicyPrefix
) +
3447 nsDependentCString(nameBegin
) +
3448 NS_LITERAL_CSTRING(".sites"));
3449 nsXPIDLCString domainList
;
3450 rv
= mSecurityPref
->SecurityGetCharPref(sitesPrefName
.get(),
3451 getter_Copies(domainList
));
3455 DomainPolicy
* domainPolicy
= new DomainPolicy();
3457 return NS_ERROR_OUT_OF_MEMORY
;
3459 if (!domainPolicy
->Init())
3461 delete domainPolicy
;
3462 return NS_ERROR_UNEXPECTED
;
3464 domainPolicy
->Hold();
3465 //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
3466 char* domainStart
= domainList
.BeginWriting();
3467 char* domainCurrent
= domainStart
;
3468 char* lastDot
= nsnull
;
3469 char* nextToLastDot
= nsnull
;
3470 PRBool moreDomains
= PR_TRUE
;
3473 if (*domainCurrent
== ' ' || *domainCurrent
== '\0')
3475 moreDomains
= (*domainCurrent
!= '\0');
3476 *domainCurrent
= '\0';
3477 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : domainStart
);
3478 DomainEntry
*newEntry
= new DomainEntry(domainStart
, domainPolicy
);
3481 domainPolicy
->Drop();
3482 return NS_ERROR_OUT_OF_MEMORY
;
3485 newEntry
->mPolicyName_DEBUG
= nameBegin
;
3487 DomainEntry
*existingEntry
= (DomainEntry
*)
3488 mOriginToPolicyMap
->Get(&key
);
3490 mOriginToPolicyMap
->Put(&key
, newEntry
);
3493 if (existingEntry
->Matches(domainStart
))
3495 newEntry
->mNext
= existingEntry
;
3496 mOriginToPolicyMap
->Put(&key
, newEntry
);
3500 while (existingEntry
->mNext
)
3502 if (existingEntry
->mNext
->Matches(domainStart
))
3504 newEntry
->mNext
= existingEntry
->mNext
;
3505 existingEntry
->mNext
= newEntry
;
3508 existingEntry
= existingEntry
->mNext
;
3510 if (!existingEntry
->mNext
)
3511 existingEntry
->mNext
= newEntry
;
3514 domainStart
= domainCurrent
+ 1;
3515 lastDot
= nextToLastDot
= nsnull
;
3517 else if (*domainCurrent
== '.')
3519 nextToLastDot
= lastDot
;
3520 lastDot
= domainCurrent
;
3525 rv
= InitDomainPolicy(cx
, nameBegin
, domainPolicy
);
3526 domainPolicy
->Drop();
3531 // Reset the "dirty" flag
3532 mPolicyPrefsChanged
= PR_FALSE
;
3534 #ifdef DEBUG_CAPS_HACKER
3542 nsScriptSecurityManager::InitDomainPolicy(JSContext
* cx
,
3543 const char* aPolicyName
,
3544 DomainPolicy
* aDomainPolicy
)
3547 nsCAutoString
policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix
) +
3548 nsDependentCString(aPolicyName
) +
3549 NS_LITERAL_CSTRING("."));
3550 PRUint32 prefixLength
= policyPrefix
.Length() - 1; // subtract the '.'
3554 rv
= mPrefBranch
->GetChildList(policyPrefix
.get(),
3555 &prefCount
, &prefNames
);
3556 if (NS_FAILED(rv
)) return rv
;
3560 //-- Populate the policy
3561 PRUint32 currentPref
= 0;
3562 for (; currentPref
< prefCount
; currentPref
++)
3564 // Get the class name
3565 const char* start
= prefNames
[currentPref
] + prefixLength
+ 1;
3566 char* end
= PL_strchr(start
, '.');
3567 if (!end
) // malformed pref, bail on this one
3569 static const char sitesStr
[] = "sites";
3571 // We dealt with "sites" in InitPolicies(), so no need to do
3573 if (PL_strncmp(start
, sitesStr
, sizeof(sitesStr
)-1) == 0)
3576 // Get the pref value
3577 nsXPIDLCString prefValue
;
3578 rv
= mSecurityPref
->SecurityGetCharPref(prefNames
[currentPref
],
3579 getter_Copies(prefValue
));
3580 if (NS_FAILED(rv
) || !prefValue
)
3583 SecurityLevel secLevel
;
3584 if (PL_strcasecmp(prefValue
, "noAccess") == 0)
3585 secLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
3586 else if (PL_strcasecmp(prefValue
, "allAccess") == 0)
3587 secLevel
.level
= SCRIPT_SECURITY_ALL_ACCESS
;
3588 else if (PL_strcasecmp(prefValue
, "sameOrigin") == 0)
3589 secLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
3591 { //-- pref value is the name of a capability
3592 nsCStringKey
secLevelKey(prefValue
);
3593 secLevel
.capability
=
3594 reinterpret_cast<char*>(mCapabilities
->Get(&secLevelKey
));
3595 if (!secLevel
.capability
)
3597 secLevel
.capability
= NS_strdup(prefValue
);
3598 if (!secLevel
.capability
)
3600 mCapabilities
->Put(&secLevelKey
,
3601 secLevel
.capability
);
3606 // Find or store this class in the classes table
3607 ClassPolicy
* cpolicy
=
3608 static_cast<ClassPolicy
*>
3609 (PL_DHashTableOperate(aDomainPolicy
, start
,
3614 // If this is the wildcard class (class '*'), save it in mWildcardPolicy
3615 // (we leave it stored in the hashtable too to take care of the cleanup)
3616 if ((*start
== '*') && (end
== start
+ 1)) {
3617 aDomainPolicy
->mWildcardPolicy
= cpolicy
;
3619 // Make sure that cpolicy knows about aDomainPolicy so it can reset
3620 // the mWildcardPolicy pointer as needed if it gets moved in the
3622 cpolicy
->mDomainWeAreWildcardFor
= aDomainPolicy
;
3625 // Get the property name
3627 end
= PL_strchr(start
, '.');
3631 JSAutoRequest
ar(cx
);
3633 JSString
* propertyKey
= ::JS_InternString(cx
, start
);
3635 return NS_ERROR_OUT_OF_MEMORY
;
3637 // Store this property in the class policy
3639 reinterpret_cast<const void*>(STRING_TO_JSVAL(propertyKey
));
3640 PropertyPolicy
* ppolicy
=
3641 static_cast<PropertyPolicy
*>
3642 (PL_DHashTableOperate(cpolicy
->mPolicy
, ppkey
,
3647 if (end
) // The pref specifies an access mode
3650 if (PL_strcasecmp(start
, "set") == 0)
3651 ppolicy
->mSet
= secLevel
;
3653 ppolicy
->mGet
= secLevel
;
3657 if (ppolicy
->mGet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3658 ppolicy
->mGet
= secLevel
;
3659 if (ppolicy
->mSet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3660 ppolicy
->mSet
= secLevel
;
3664 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
3665 if (currentPref
< prefCount
) // Loop exited early because of out-of-memory error
3666 return NS_ERROR_OUT_OF_MEMORY
;
3671 // XXXbz We should really just get a prefbranch to handle this...
3673 nsScriptSecurityManager::GetPrincipalPrefNames(const char* prefBase
,
3674 nsCString
& grantedPref
,
3675 nsCString
& deniedPref
,
3676 nsCString
& subjectNamePref
)
3678 char* lastDot
= PL_strrchr(prefBase
, '.');
3679 if (!lastDot
) return NS_ERROR_FAILURE
;
3680 PRInt32 prefLen
= lastDot
- prefBase
+ 1;
3682 grantedPref
.Assign(prefBase
, prefLen
);
3683 deniedPref
.Assign(prefBase
, prefLen
);
3684 subjectNamePref
.Assign(prefBase
, prefLen
);
3686 #define GRANTED "granted"
3687 #define DENIED "denied"
3688 #define SUBJECTNAME "subjectName"
3690 grantedPref
.AppendLiteral(GRANTED
);
3691 if (grantedPref
.Length() != prefLen
+ sizeof(GRANTED
) - 1) {
3692 return NS_ERROR_OUT_OF_MEMORY
;
3695 deniedPref
.AppendLiteral(DENIED
);
3696 if (deniedPref
.Length() != prefLen
+ sizeof(DENIED
) - 1) {
3697 return NS_ERROR_OUT_OF_MEMORY
;
3700 subjectNamePref
.AppendLiteral(SUBJECTNAME
);
3701 if (subjectNamePref
.Length() != prefLen
+ sizeof(SUBJECTNAME
) - 1) {
3702 return NS_ERROR_OUT_OF_MEMORY
;
3713 nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount
, const char** aPrefNames
,
3714 nsISecurityPref
* aSecurityPref
)
3716 /* This is the principal preference syntax:
3717 * capability.principal.[codebase|codebaseTrusted|certificate].<name>.[id|granted|denied]
3719 * user_pref("capability.principal.certificate.p1.id","12:34:AB:CD");
3720 * user_pref("capability.principal.certificate.p1.granted","Capability1 Capability2");
3721 * user_pref("capability.principal.certificate.p1.denied","Capability3");
3724 /* codebaseTrusted means a codebase principal that can enable capabilities even if
3725 * codebase principals are disabled. Don't use trustedCodebase except with unspoofable
3726 * URLs such as HTTPS URLs.
3729 static const char idSuffix
[] = ".id";
3730 for (PRUint32 c
= 0; c
< aPrefCount
; c
++)
3732 PRInt32 prefNameLen
= PL_strlen(aPrefNames
[c
]) -
3733 (NS_ARRAY_LENGTH(idSuffix
) - 1);
3734 if (PL_strcasecmp(aPrefNames
[c
] + prefNameLen
, idSuffix
) != 0)
3738 if (NS_FAILED(mSecurityPref
->SecurityGetCharPref(aPrefNames
[c
], getter_Copies(id
))))
3739 return NS_ERROR_FAILURE
;
3741 nsCAutoString grantedPrefName
;
3742 nsCAutoString deniedPrefName
;
3743 nsCAutoString subjectNamePrefName
;
3744 nsresult rv
= GetPrincipalPrefNames(aPrefNames
[c
],
3747 subjectNamePrefName
);
3748 if (rv
== NS_ERROR_OUT_OF_MEMORY
)
3753 nsXPIDLCString grantedList
;
3754 mSecurityPref
->SecurityGetCharPref(grantedPrefName
.get(),
3755 getter_Copies(grantedList
));
3756 nsXPIDLCString deniedList
;
3757 mSecurityPref
->SecurityGetCharPref(deniedPrefName
.get(),
3758 getter_Copies(deniedList
));
3759 nsXPIDLCString subjectName
;
3760 mSecurityPref
->SecurityGetCharPref(subjectNamePrefName
.get(),
3761 getter_Copies(subjectName
));
3763 //-- Delete prefs if their value is the empty string
3764 if (id
.IsEmpty() || (grantedList
.IsEmpty() && deniedList
.IsEmpty()))
3766 mSecurityPref
->SecurityClearUserPref(aPrefNames
[c
]);
3767 mSecurityPref
->SecurityClearUserPref(grantedPrefName
.get());
3768 mSecurityPref
->SecurityClearUserPref(deniedPrefName
.get());
3769 mSecurityPref
->SecurityClearUserPref(subjectNamePrefName
.get());
3773 //-- Create a principal based on the prefs
3774 static const char certificateName
[] = "capability.principal.certificate";
3775 static const char codebaseName
[] = "capability.principal.codebase";
3776 static const char codebaseTrustedName
[] = "capability.principal.codebaseTrusted";
3778 PRBool isCert
= PR_FALSE
;
3779 PRBool isTrusted
= PR_FALSE
;
3781 if (PL_strncmp(aPrefNames
[c
], certificateName
,
3782 sizeof(certificateName
) - 1) == 0)
3786 else if (PL_strncmp(aPrefNames
[c
], codebaseName
,
3787 sizeof(codebaseName
) - 1) == 0)
3789 isTrusted
= (PL_strncmp(aPrefNames
[c
], codebaseTrustedName
,
3790 sizeof(codebaseTrustedName
) - 1) == 0);
3794 NS_ERROR("Not a codebase or a certificate?!");
3797 nsRefPtr
<nsPrincipal
> newPrincipal
= new nsPrincipal();
3799 return NS_ERROR_OUT_OF_MEMORY
;
3801 rv
= newPrincipal
->InitFromPersistent(aPrefNames
[c
], id
, subjectName
,
3803 grantedList
, deniedList
, nsnull
,
3805 if (NS_SUCCEEDED(rv
))
3806 mPrincipals
.Put(newPrincipal
, newPrincipal
);
3811 const char nsScriptSecurityManager::sJSEnabledPrefName
[] =
3812 "javascript.enabled";
3813 const char nsScriptSecurityManager::sJSMailEnabledPrefName
[] =
3814 "javascript.allow.mailnews";
3815 const char nsScriptSecurityManager::sFileOriginPolicyPrefName
[] =
3816 "security.fileuri.strict_origin_policy";
3817 #ifdef XPC_IDISPATCH_SUPPORT
3818 const char nsScriptSecurityManager::sXPCDefaultGrantAllName
[] =
3819 "security.classID.allowByDefault";
3823 nsScriptSecurityManager::ScriptSecurityPrefChanged()
3826 nsresult rv
= mSecurityPref
->SecurityGetBoolPref(sJSEnabledPrefName
, &temp
);
3827 // JavaScript defaults to enabled in failure cases.
3828 mIsJavaScriptEnabled
= NS_FAILED(rv
) || temp
;
3830 rv
= mSecurityPref
->SecurityGetBoolPref(sJSMailEnabledPrefName
, &temp
);
3831 // JavaScript in Mail defaults to disabled in failure cases.
3832 // disable javascript in mailnews for TB 3.0 beta1
3833 mIsMailJavaScriptEnabled
= PR_FALSE
; // NS_SUCCEEDED(rv) && temp;
3835 rv
= mSecurityPref
->SecurityGetBoolPref(sFileOriginPolicyPrefName
, &temp
);
3836 sStrictFileOriginPolicy
= NS_SUCCEEDED(rv
) && temp
;
3838 #ifdef XPC_IDISPATCH_SUPPORT
3839 rv
= mSecurityPref
->SecurityGetBoolPref(sXPCDefaultGrantAllName
, &temp
);
3840 // Granting XPC Priveleges defaults to disabled in failure cases.
3841 mXPCDefaultGrantAll
= NS_SUCCEEDED(rv
) && temp
;
3846 nsScriptSecurityManager::InitPrefs()
3849 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
3850 NS_ENSURE_SUCCESS(rv
, rv
);
3851 rv
= prefService
->GetBranch(nsnull
, getter_AddRefs(mPrefBranch
));
3852 NS_ENSURE_SUCCESS(rv
, rv
);
3853 nsCOMPtr
<nsIPrefBranch2
> prefBranchInternal(do_QueryInterface(mPrefBranch
, &rv
));
3854 NS_ENSURE_SUCCESS(rv
, rv
);
3855 mSecurityPref
= do_QueryInterface(mPrefBranch
, &rv
);
3856 NS_ENSURE_SUCCESS(rv
, rv
);
3858 // Set the initial value of the "javascript.enabled" prefs
3859 ScriptSecurityPrefChanged();
3860 // set observer callbacks in case the value of the prefs change
3861 prefBranchInternal
->AddObserver(sJSEnabledPrefName
, this, PR_FALSE
);
3862 prefBranchInternal
->AddObserver(sJSMailEnabledPrefName
, this, PR_FALSE
);
3863 prefBranchInternal
->AddObserver(sFileOriginPolicyPrefName
, this, PR_FALSE
);
3864 #ifdef XPC_IDISPATCH_SUPPORT
3865 prefBranchInternal
->AddObserver(sXPCDefaultGrantAllName
, this, PR_FALSE
);
3870 // Set a callback for policy pref changes
3871 prefBranchInternal
->AddObserver(sPolicyPrefix
, this, PR_FALSE
);
3873 //-- Initialize the principals database from prefs
3874 rv
= mPrefBranch
->GetChildList(sPrincipalPrefix
, &prefCount
, &prefNames
);
3875 if (NS_SUCCEEDED(rv
) && prefCount
> 0)
3877 rv
= InitPrincipals(prefCount
, (const char**)prefNames
, mSecurityPref
);
3878 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
3879 NS_ENSURE_SUCCESS(rv
, rv
);
3881 //-- Set a callback for principal changes
3882 prefBranchInternal
->AddObserver(sPrincipalPrefix
, this, PR_FALSE
);
3887 ///////////////////////////////////////////////////////////////////////////////
3888 // The following code prints the contents of the policy DB to the console.
3889 #ifdef DEBUG_CAPS_HACKER
3891 //typedef PLDHashOperator
3892 //(* PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
3893 // PRUint32 number, void *arg);
3894 static PLDHashOperator
3895 PrintPropertyPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
3896 PRUint32 number
, void *arg
)
3898 PropertyPolicy
* pp
= (PropertyPolicy
*)entry
;
3899 nsCAutoString
prop(" ");
3900 JSContext
* cx
= (JSContext
*)arg
;
3901 prop
.AppendInt((PRUint32
)pp
->key
);
3903 prop
.AppendWithConversion((PRUnichar
*)JSValIDToString(cx
, pp
->key
));
3905 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mGet
))
3906 prop
.AppendInt(pp
->mGet
.level
);
3908 prop
+= pp
->mGet
.capability
;
3911 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mSet
))
3912 prop
.AppendInt(pp
->mSet
.level
);
3914 prop
+= pp
->mSet
.capability
;
3916 printf("%s.\n", prop
.get());
3917 return PL_DHASH_NEXT
;
3920 static PLDHashOperator
3921 PrintClassPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
3922 PRUint32 number
, void *arg
)
3924 ClassPolicy
* cp
= (ClassPolicy
*)entry
;
3925 printf(" %s\n", cp
->key
);
3927 PL_DHashTableEnumerate(cp
->mPolicy
, PrintPropertyPolicy
, arg
);
3928 return PL_DHASH_NEXT
;
3932 // (* nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
3934 PrintDomainPolicy(nsHashKey
*aKey
, void *aData
, void* aClosure
)
3936 DomainEntry
* de
= (DomainEntry
*)aData
;
3937 printf("----------------------------\n");
3938 printf("Domain: %s Policy Name: %s.\n", de
->mOrigin
.get(),
3939 de
->mPolicyName_DEBUG
.get());
3940 PL_DHashTableEnumerate(de
->mDomainPolicy
, PrintClassPolicy
, aClosure
);
3945 PrintCapability(nsHashKey
*aKey
, void *aData
, void* aClosure
)
3947 char* cap
= (char*)aData
;
3948 printf(" %s.\n", cap
);
3953 nsScriptSecurityManager::PrintPolicyDB()
3955 printf("############## Security Policies ###############\n");
3956 if(mOriginToPolicyMap
)
3958 JSContext
* cx
= GetCurrentJSContext();
3960 cx
= GetSafeJSContext();
3961 printf("----------------------------\n");
3962 printf("Domain: Default.\n");
3963 PL_DHashTableEnumerate(mDefaultPolicy
, PrintClassPolicy
, (void*)cx
);
3964 mOriginToPolicyMap
->Enumerate(PrintDomainPolicy
, (void*)cx
);
3966 printf("############ End Security Policies #############\n\n");
3967 printf("############## Capabilities ###############\n");
3968 mCapabilities
->Enumerate(PrintCapability
);
3969 printf("############## End Capabilities ###############\n");