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 nsIStringBundle
*nsScriptSecurityManager::sStrBundle
= nsnull
;
102 JSRuntime
*nsScriptSecurityManager::sRuntime
= 0;
103 PRBool
nsScriptSecurityManager::sStrictFileOriginPolicy
= PR_TRUE
;
105 // Info we need about the JSClasses used by XPConnects wrapped
106 // natives, to avoid having to QI to nsIXPConnectWrappedNative all the
107 // time when doing security checks.
108 static const JSClass
*sXPCWrappedNativeJSClass
;
109 static JSGetObjectOps sXPCWrappedNativeGetObjOps1
;
110 static JSGetObjectOps sXPCWrappedNativeGetObjOps2
;
113 ///////////////////////////
114 // Convenience Functions //
115 ///////////////////////////
116 // Result of this function should not be freed.
117 static inline const PRUnichar
*
118 JSValIDToString(JSContext
*cx
, const jsval idval
)
120 JSAutoRequest
ar(cx
);
121 JSString
*str
= JS_ValueToString(cx
, idval
);
124 return reinterpret_cast<PRUnichar
*>(JS_GetStringChars(str
));
129 GetPrincipalDomainOrigin(nsIPrincipal
* aPrincipal
,
134 nsCOMPtr
<nsIURI
> uri
;
135 aPrincipal
->GetDomain(getter_AddRefs(uri
));
137 aPrincipal
->GetURI(getter_AddRefs(uri
));
139 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
141 uri
= NS_GetInnermostURI(uri
);
142 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
144 nsCAutoString hostPort
;
146 nsresult rv
= uri
->GetHostPort(hostPort
);
147 if (NS_SUCCEEDED(rv
)) {
148 nsCAutoString scheme
;
149 rv
= uri
->GetScheme(scheme
);
150 NS_ENSURE_SUCCESS(rv
, rv
);
151 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + hostPort
;
154 // Some URIs (e.g., nsSimpleURI) don't support host. Just
155 // get the full spec.
156 rv
= uri
->GetSpec(aOrigin
);
157 NS_ENSURE_SUCCESS(rv
, rv
);
163 // Inline copy of JS_GetPrivate() for better inlining and optimization
164 // possibilities. Also doesn't take a cx argument as it's not
165 // needed. We access the private data only on objects whose private
166 // data is not expected to change during the lifetime of the object,
167 // so thus we won't worry about locking and holding on to slot values
168 // etc while referencing private data.
170 caps_GetJSPrivate(JSObject
*obj
)
174 JS_ASSERT(STOBJ_GET_CLASS(obj
)->flags
& JSCLASS_HAS_PRIVATE
);
175 v
= obj
->fslots
[JSSLOT_PRIVATE
];
176 if (!JSVAL_IS_INT(v
))
178 return JSVAL_TO_PRIVATE(v
);
181 static nsIScriptContext
*
182 GetScriptContext(JSContext
*cx
)
184 return GetScriptContextFromJSContext(cx
);
187 inline void SetPendingException(JSContext
*cx
, const char *aMsg
)
189 JSAutoRequest
ar(cx
);
190 JS_ReportError(cx
, "%s", aMsg
);
193 inline void SetPendingException(JSContext
*cx
, const PRUnichar
*aMsg
)
195 JSAutoRequest
ar(cx
);
196 JS_ReportError(cx
, "%hs", aMsg
);
199 // DomainPolicy members
200 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
201 PRUint32
DomainPolicy::sObjects
=0;
202 void DomainPolicy::_printPopulationInfo()
204 printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n",
205 sGeneration
, sObjects
);
208 PRUint32
DomainPolicy::sGeneration
= 0;
210 // Helper class to get stuff from the ClassInfo and not waste extra time with
211 // virtual method calls for things it has already gotten
215 ClassInfoData(nsIClassInfo
*aClassInfo
, const char *aName
)
216 : mClassInfo(aClassInfo
),
217 mName(const_cast<char *>(aName
)),
218 mDidGetFlags(PR_FALSE
),
219 mMustFreeName(PR_FALSE
)
226 nsMemory::Free(mName
);
233 nsresult rv
= mClassInfo
->GetFlags(&mFlags
);
241 mDidGetFlags
= PR_TRUE
;
249 return !!(GetFlags() & nsIClassInfo::DOM_OBJECT
);
252 PRBool
IsContentNode()
254 return !!(GetFlags() & nsIClassInfo::CONTENT_NODE
);
257 const char* GetName()
261 mClassInfo
->GetClassDescription(&mName
);
265 mMustFreeName
= PR_TRUE
;
267 mName
= const_cast<char *>("UnnamedClass");
275 nsIClassInfo
*mClassInfo
; // WEAK
278 PRPackedBool mDidGetFlags
;
279 PRPackedBool mMustFreeName
;
283 nsScriptSecurityManager::GetCurrentJSContext()
285 // Get JSContext from stack.
286 if (!mJSContextStack
)
288 mJSContextStack
= do_GetService("@mozilla.org/js/xpc/ContextStack;1");
289 if (!mJSContextStack
)
293 if (NS_FAILED(mJSContextStack
->Peek(&cx
)))
299 nsScriptSecurityManager::GetSafeJSContext()
301 // Get JSContext from stack.
302 if (!mJSContextStack
) {
303 mJSContextStack
= do_GetService("@mozilla.org/js/xpc/ContextStack;1");
304 if (!mJSContextStack
)
309 if (NS_FAILED(mJSContextStack
->GetSafeJSContext(&cx
)))
316 nsScriptSecurityManager::SecurityCompareURIs(nsIURI
* aSourceURI
,
319 return NS_SecurityCompareURIs(aSourceURI
, aTargetURI
, sStrictFileOriginPolicy
);
323 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel
* aChannel
,
324 nsIPrincipal
** aPrincipal
)
326 NS_PRECONDITION(aChannel
, "Must have channel!");
327 nsCOMPtr
<nsISupports
> owner
;
328 aChannel
->GetOwner(getter_AddRefs(owner
));
330 CallQueryInterface(owner
, aPrincipal
);
336 // OK, get the principal from the URI. Make sure this does the same thing
337 // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
338 nsCOMPtr
<nsIURI
> uri
;
339 nsresult rv
= NS_GetFinalChannelURI(aChannel
, getter_AddRefs(uri
));
340 NS_ENSURE_SUCCESS(rv
, rv
);
342 return GetCodebasePrincipal(uri
, aPrincipal
);
346 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal
* aPrincipal
,
349 *aIsSystem
= (aPrincipal
== mSystemPrincipal
);
353 NS_IMETHODIMP_(nsIPrincipal
*)
354 nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext
*cx
)
356 NS_ASSERTION(cx
== GetCurrentJSContext(),
357 "Uh, cx is not the current JS context!");
359 nsresult rv
= NS_ERROR_FAILURE
;
360 nsIPrincipal
*principal
= GetSubjectPrincipal(cx
, &rv
);
371 // Table of security levels
372 PR_STATIC_CALLBACK(PRBool
)
373 DeleteCapability(nsHashKey
*aKey
, void *aData
, void* closure
)
379 //-- Per-Domain Policy - applies to one or more protocols or hosts
382 DomainEntry(const char* aOrigin
,
383 DomainPolicy
* aDomainPolicy
) : mOrigin(aOrigin
),
384 mDomainPolicy(aDomainPolicy
),
387 mDomainPolicy
->Hold();
392 mDomainPolicy
->Drop();
395 PRBool
Matches(const char *anOrigin
)
397 int len
= strlen(anOrigin
);
398 int thisLen
= mOrigin
.Length();
401 if (mOrigin
.RFindChar(':', thisLen
-1, 1) != -1)
402 //-- Policy applies to all URLs of this scheme, compare scheme only
403 return mOrigin
.EqualsIgnoreCase(anOrigin
, thisLen
);
405 //-- Policy applies to a particular host; compare domains
406 if (!mOrigin
.Equals(anOrigin
+ (len
- thisLen
)))
410 char charBefore
= anOrigin
[len
-thisLen
-1];
411 return (charBefore
== '.' || charBefore
== ':' || charBefore
== '/');
415 DomainPolicy
* mDomainPolicy
;
417 #if defined(DEBUG) || defined(DEBUG_CAPS_HACKER)
418 nsCString mPolicyName_DEBUG
;
422 PR_STATIC_CALLBACK(PRBool
)
423 DeleteDomainEntry(nsHashKey
*aKey
, void *aData
, void* closure
)
425 DomainEntry
*entry
= (DomainEntry
*) aData
;
428 DomainEntry
*next
= entry
->mNext
;
435 /////////////////////////////
436 // nsScriptSecurityManager //
437 /////////////////////////////
439 ////////////////////////////////////
440 // Methods implementing ISupports //
441 ////////////////////////////////////
442 NS_IMPL_ISUPPORTS5(nsScriptSecurityManager
,
443 nsIScriptSecurityManager
,
444 nsIXPCSecurityManager
,
445 nsIPrefSecurityCheck
,
449 ///////////////////////////////////////////////////
450 // Methods implementing nsIScriptSecurityManager //
451 ///////////////////////////////////////////////////
453 ///////////////// Security Checks /////////////////
455 nsScriptSecurityManager::CheckObjectAccess(JSContext
*cx
, JSObject
*obj
,
456 jsval id
, JSAccessMode mode
,
459 // Get the security manager
460 nsScriptSecurityManager
*ssm
=
461 nsScriptSecurityManager::GetScriptSecurityManager();
463 NS_ASSERTION(ssm
, "Failed to get security manager service");
467 // Get the object being accessed. We protect these cases:
468 // 1. The Function.prototype.caller property's value, which might lead
469 // an attacker up a call-stack to a function or another object from
470 // a different trust domain.
471 // 2. A user-defined getter or setter function accessible on another
472 // trust domain's window or document object.
473 // *vp can be a primitive, in that case, we use obj as the target
475 JSObject
* target
= JSVAL_IS_PRIMITIVE(*vp
) ? obj
: JSVAL_TO_OBJECT(*vp
);
477 // Do the same-origin check -- this sets a JS exception if the check fails.
478 // Pass the parent object's class name, as we have no class-info for it.
480 ssm
->CheckPropertyAccess(cx
, target
, STOBJ_GET_CLASS(obj
)->name
, id
,
481 (mode
& JSACC_WRITE
) ?
482 nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
483 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
);
486 return JS_FALSE
; // Security check failed (XXX was an error reported?)
492 nsScriptSecurityManager::CheckPropertyAccess(JSContext
* cx
,
494 const char* aClassName
,
498 return CheckPropertyAccessImpl(aAction
, nsnull
, cx
, aJSObject
,
499 nsnull
, nsnull
, nsnull
,
500 aClassName
, aProperty
, nsnull
);
504 nsScriptSecurityManager::CheckConnect(JSContext
* cx
,
506 const char* aClassName
,
507 const char* aPropertyName
)
509 // Get a context if necessary
512 cx
= GetCurrentJSContext();
514 return NS_OK
; // No JS context, so allow the load
517 nsresult rv
= CheckLoadURIFromScript(cx
, aTargetURI
);
518 if (NS_FAILED(rv
)) return rv
;
520 JSAutoRequest
ar(cx
);
522 JSString
* propertyName
= ::JS_InternString(cx
, aPropertyName
);
524 return NS_ERROR_OUT_OF_MEMORY
;
526 return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD
, nsnull
,
527 cx
, nsnull
, nsnull
, aTargetURI
,
528 nsnull
, aClassName
, STRING_TO_JSVAL(propertyName
), nsnull
);
532 nsScriptSecurityManager::CheckSameOrigin(JSContext
* cx
,
537 // Get a context if necessary
540 cx
= GetCurrentJSContext();
542 return NS_OK
; // No JS context, so allow access
545 // Get a principal from the context
546 nsIPrincipal
* sourcePrincipal
= GetSubjectPrincipal(cx
, &rv
);
550 if (!sourcePrincipal
)
552 NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
556 if (sourcePrincipal
== mSystemPrincipal
)
558 // This is a system (chrome) script, so allow access
562 // Get the original URI from the source principal.
563 // This has the effect of ignoring any change to document.domain
564 // which must be done to avoid DNS spoofing (bug 154930)
565 nsCOMPtr
<nsIURI
> sourceURI
;
566 sourcePrincipal
->GetDomain(getter_AddRefs(sourceURI
));
568 sourcePrincipal
->GetURI(getter_AddRefs(sourceURI
));
569 NS_ENSURE_TRUE(sourceURI
, NS_ERROR_FAILURE
);
573 if (!SecurityCompareURIs(sourceURI
, aTargetURI
))
575 ReportError(cx
, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI
, aTargetURI
);
576 return NS_ERROR_DOM_BAD_URI
;
582 nsScriptSecurityManager::CheckSameOriginURI(nsIURI
* aSourceURI
,
586 if (!SecurityCompareURIs(aSourceURI
, aTargetURI
))
589 ReportError(nsnull
, NS_LITERAL_STRING("CheckSameOriginError"),
590 aSourceURI
, aTargetURI
);
592 return NS_ERROR_DOM_BAD_URI
;
598 nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction
,
599 nsAXPCNativeCallContext
* aCallContext
,
600 JSContext
* cx
, JSObject
* aJSObject
,
601 nsISupports
* aObj
, nsIURI
* aTargetURI
,
602 nsIClassInfo
* aClassInfo
,
603 const char* aClassName
, jsval aProperty
,
604 void** aCachedClassPolicy
)
607 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
611 if (!subjectPrincipal
|| subjectPrincipal
== mSystemPrincipal
)
612 // We have native code or the system principal: just allow access
615 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
617 // Hold the class info data here so we don't have to go back to virtual
618 // methods all the time
619 ClassInfoData
classInfoData(aClassInfo
, aClassName
);
620 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
621 nsCAutoString propertyName
;
622 propertyName
.AssignWithConversion((PRUnichar
*)JSValIDToString(cx
, aProperty
));
623 printf("### CanAccess(%s.%s, %i) ", classInfoData
.GetName(),
624 propertyName
.get(), aAction
);
627 //-- Look up the security policy for this class and subject domain
628 SecurityLevel securityLevel
;
629 rv
= LookupPolicy(subjectPrincipal
, classInfoData
, aProperty
, aAction
,
630 (ClassPolicy
**)aCachedClassPolicy
, &securityLevel
);
634 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
636 // No policy found for this property so use the default of last resort.
637 // If we were called from somewhere other than XPConnect
638 // (no XPC call context), assume this is a DOM class. Otherwise,
639 // ask the ClassInfo.
640 if (!aCallContext
|| classInfoData
.IsDOMClass())
641 securityLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
643 securityLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
646 if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel
))
647 // This flag means securityLevel is allAccess, noAccess, or sameOrigin
649 switch (securityLevel
.level
)
651 case SCRIPT_SECURITY_NO_ACCESS
:
652 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
655 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
658 case SCRIPT_SECURITY_ALL_ACCESS
:
659 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
660 printf("allAccess ");
665 case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
:
667 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
668 printf("sameOrigin ");
670 nsCOMPtr
<nsIPrincipal
> principalHolder
;
673 objectPrincipal
= doGetObjectPrincipal(aJSObject
);
674 if (!objectPrincipal
)
675 rv
= NS_ERROR_DOM_SECURITY_ERR
;
679 if (NS_FAILED(GetCodebasePrincipal(
680 aTargetURI
, getter_AddRefs(objectPrincipal
))))
681 return NS_ERROR_FAILURE
;
685 NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
686 return NS_ERROR_FAILURE
;
689 rv
= CheckSameOriginDOMProp(subjectPrincipal
, objectPrincipal
,
690 aAction
, aTargetURI
!= nsnull
);
694 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
697 NS_ERROR("Bad Security Level Value");
698 return NS_ERROR_FAILURE
;
701 else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
703 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
704 printf("Cap:%s ", securityLevel
.capability
);
706 PRBool capabilityEnabled
= PR_FALSE
;
707 rv
= IsCapabilityEnabled(securityLevel
.capability
, &capabilityEnabled
);
708 if (NS_FAILED(rv
) || !capabilityEnabled
)
709 rv
= NS_ERROR_DOM_SECURITY_ERR
;
714 if (NS_SUCCEEDED(rv
) && classInfoData
.IsContentNode())
716 // No access to anonymous content from the web! (bug 164086)
717 nsIContent
*content
= static_cast<nsIContent
*>(aObj
);
718 if (content
->IsInNativeAnonymousSubtree()) {
719 rv
= NS_ERROR_DOM_SECURITY_ERR
;
723 if (NS_SUCCEEDED(rv
))
725 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
726 printf(" GRANTED.\n");
731 //--See if the object advertises a non-default level of access
732 // using nsISecurityCheckedComponent
733 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
734 do_QueryInterface(aObj
);
736 nsXPIDLCString objectSecurityLevel
;
737 if (checkedComponent
)
739 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
740 nsCOMPtr
<nsIInterfaceInfo
> interfaceInfo
;
742 rv
= aCallContext
->GetCalleeWrapper(getter_AddRefs(wrapper
));
743 if (NS_SUCCEEDED(rv
))
744 rv
= wrapper
->FindInterfaceWithMember(aProperty
, getter_AddRefs(interfaceInfo
));
745 if (NS_SUCCEEDED(rv
))
746 rv
= interfaceInfo
->GetIIDShared(&objIID
);
747 if (NS_SUCCEEDED(rv
))
751 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
752 checkedComponent
->CanGetProperty(objIID
,
753 JSValIDToString(cx
, aProperty
),
754 getter_Copies(objectSecurityLevel
));
756 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
757 checkedComponent
->CanSetProperty(objIID
,
758 JSValIDToString(cx
, aProperty
),
759 getter_Copies(objectSecurityLevel
));
761 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
762 checkedComponent
->CanCallMethod(objIID
,
763 JSValIDToString(cx
, aProperty
),
764 getter_Copies(objectSecurityLevel
));
768 rv
= CheckXPCPermissions(aObj
, objectSecurityLevel
);
769 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
771 printf("CheckXPCPerms GRANTED.\n");
773 printf("CheckXPCPerms DENIED.\n");
776 if (NS_FAILED(rv
)) //-- Security tests failed, access is denied, report error
778 nsAutoString stringName
;
781 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
782 stringName
.AssignLiteral("GetPropertyDeniedOrigins");
784 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
785 stringName
.AssignLiteral("SetPropertyDeniedOrigins");
787 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
788 stringName
.AssignLiteral("CallMethodDeniedOrigins");
791 NS_ConvertUTF8toUTF16
className(classInfoData
.GetName());
792 nsCAutoString subjectOrigin
;
793 GetPrincipalDomainOrigin(subjectPrincipal
, subjectOrigin
);
794 NS_ConvertUTF8toUTF16
subjectOriginUnicode(subjectOrigin
);
796 nsCAutoString objectOrigin
;
797 if (objectPrincipal
) {
798 GetPrincipalDomainOrigin(objectPrincipal
, objectOrigin
);
800 NS_ConvertUTF8toUTF16
objectOriginUnicode(objectOrigin
);
802 nsXPIDLString errorMsg
;
803 const PRUnichar
*formatStrings
[] =
805 subjectOriginUnicode
.get(),
807 JSValIDToString(cx
, aProperty
),
808 objectOriginUnicode
.get()
811 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
813 if (!objectPrincipal
) {
814 stringName
.AppendLiteral("OnlySubject");
818 // We need to keep our existing failure rv and not override it
819 // with a likely success code from the following string bundle
820 // call in order to throw the correct security exception later.
821 nsresult rv2
= sStrBundle
->FormatStringFromName(stringName
.get(),
824 getter_Copies(errorMsg
));
825 if (NS_FAILED(rv2
)) {
826 // Might just be missing the string... Do our best
827 errorMsg
= stringName
;
830 SetPendingException(cx
, errorMsg
.get());
838 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
839 nsIPrincipal
* aObject
,
840 PRBool aIsCheckConnect
)
843 ** Get origin of subject and object and compare.
845 if (aSubject
== aObject
)
848 // These booleans are only used when !aIsCheckConnect. Default
849 // them to false, and change if that turns out wrong.
850 PRBool subjectSetDomain
= PR_FALSE
;
851 PRBool objectSetDomain
= PR_FALSE
;
853 nsCOMPtr
<nsIURI
> subjectURI
;
854 nsCOMPtr
<nsIURI
> objectURI
;
858 // Don't use domain for CheckConnect calls, since that's called for
859 // data-only load checks like XMLHTTPRequest (bug 290100).
860 aSubject
->GetURI(getter_AddRefs(subjectURI
));
861 aObject
->GetURI(getter_AddRefs(objectURI
));
865 aSubject
->GetDomain(getter_AddRefs(subjectURI
));
867 aSubject
->GetURI(getter_AddRefs(subjectURI
));
869 subjectSetDomain
= PR_TRUE
;
872 aObject
->GetDomain(getter_AddRefs(objectURI
));
874 aObject
->GetURI(getter_AddRefs(objectURI
));
876 objectSetDomain
= PR_TRUE
;
880 if (SecurityCompareURIs(subjectURI
, objectURI
))
881 { // If either the subject or the object has changed its principal by
882 // explicitly setting document.domain then the other must also have
883 // done so in order to be considered the same origin. This prevents
884 // DNS spoofing based on document.domain (154930)
886 // But this restriction does not apply to CheckConnect calls, since
887 // that's called for data-only load checks like XMLHTTPRequest where
888 // we ignore domain (bug 290100).
892 // If both or neither explicitly set their domain, allow the access
893 if (subjectSetDomain
== objectSetDomain
)
898 ** Access tests failed, so now report error.
900 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
905 nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
906 nsIPrincipal
* aObject
,
908 PRBool aIsCheckConnect
)
911 if (aIsCheckConnect
) {
912 // Don't do equality compares, just do a same-origin compare,
913 // since the object principal isn't a real principal, just a
914 // GetCodebasePrincipal() on whatever URI we started with.
915 rv
= CheckSameOriginPrincipal(aSubject
, aObject
, aIsCheckConnect
);
918 rv
= aSubject
->Subsumes(aObject
, &subsumes
);
919 if (NS_SUCCEEDED(rv
) && !subsumes
) {
920 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
924 if (NS_SUCCEEDED(rv
))
928 * Content can't ever touch chrome (we check for UniversalXPConnect later)
930 if (aObject
== mSystemPrincipal
)
931 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
934 * If we failed the origin tests it still might be the case that we
935 * are a signed script and have permissions to do this operation.
936 * Check for that here.
938 PRBool capabilityEnabled
= PR_FALSE
;
939 const char* cap
= aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
?
940 "UniversalBrowserWrite" : "UniversalBrowserRead";
941 rv
= IsCapabilityEnabled(cap
, &capabilityEnabled
);
942 NS_ENSURE_SUCCESS(rv
, rv
);
943 if (capabilityEnabled
)
947 ** Access tests failed, so now report error.
949 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
953 nsScriptSecurityManager::LookupPolicy(nsIPrincipal
* aPrincipal
,
954 ClassInfoData
& aClassData
,
957 ClassPolicy
** aCachedClassPolicy
,
958 SecurityLevel
* result
)
961 result
->level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
963 DomainPolicy
* dpolicy
= nsnull
;
964 //-- Initialize policies if necessary
965 if (mPolicyPrefsChanged
)
973 aPrincipal
->GetSecurityPolicy((void**)&dpolicy
);
976 if (!dpolicy
&& mOriginToPolicyMap
)
978 //-- Look up the relevant domain policy, if any
979 #ifdef DEBUG_CAPS_LookupPolicy
980 printf("DomainLookup ");
983 nsCAutoString origin
;
984 rv
= GetPrincipalDomainOrigin(aPrincipal
, origin
);
985 NS_ENSURE_SUCCESS(rv
, rv
);
987 char *start
= origin
.BeginWriting();
988 const char *nextToLastDot
= nsnull
;
989 const char *lastDot
= nsnull
;
990 const char *colon
= nsnull
;
993 //-- search domain (stop at the end of the string or at the 3rd slash)
994 for (PRUint32 slashes
=0; *p
; p
++)
996 if (*p
== '/' && ++slashes
== 3)
998 *p
= '\0'; // truncate at 3rd slash
1003 nextToLastDot
= lastDot
;
1006 else if (!colon
&& *p
== ':')
1010 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : start
);
1011 DomainEntry
*de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&key
);
1014 nsCAutoString
scheme(start
, colon
-start
+1);
1015 nsCStringKey
schemeKey(scheme
);
1016 de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&schemeKey
);
1021 if (de
->Matches(start
))
1023 dpolicy
= de
->mDomainPolicy
;
1030 dpolicy
= mDefaultPolicy
;
1032 aPrincipal
->SetSecurityPolicy((void*)dpolicy
);
1035 ClassPolicy
* cpolicy
= nsnull
;
1037 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1039 // No per-domain policy for this principal (the more common case)
1040 // so look for a cached class policy from the object wrapper
1041 cpolicy
= *aCachedClassPolicy
;
1045 { //-- No cached policy for this class, need to look it up
1046 #ifdef DEBUG_CAPS_LookupPolicy
1047 printf("ClassLookup ");
1050 cpolicy
= static_cast<ClassPolicy
*>
1051 (PL_DHashTableOperate(dpolicy
,
1052 aClassData
.GetName(),
1055 if (PL_DHASH_ENTRY_IS_FREE(cpolicy
))
1056 cpolicy
= NO_POLICY_FOR_CLASS
;
1058 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1059 *aCachedClassPolicy
= cpolicy
;
1062 // We look for a PropertyPolicy in the following places:
1063 // 1) The ClassPolicy for our class we got from our DomainPolicy
1064 // 2) The mWildcardPolicy of our DomainPolicy
1065 // 3) The ClassPolicy for our class we got from mDefaultPolicy
1066 // 4) The mWildcardPolicy of our mDefaultPolicy
1067 PropertyPolicy
* ppolicy
= nsnull
;
1068 if (cpolicy
!= NO_POLICY_FOR_CLASS
)
1070 ppolicy
= static_cast<PropertyPolicy
*>
1071 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1076 // If there is no class policy for this property, and we have a wildcard
1077 // policy, try that.
1078 if (dpolicy
->mWildcardPolicy
&&
1079 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1082 static_cast<PropertyPolicy
*>
1083 (PL_DHashTableOperate(dpolicy
->mWildcardPolicy
->mPolicy
,
1088 // If dpolicy is not the defauly policy and there's no class or wildcard
1089 // policy for this property, check the default policy for this class and
1090 // the default wildcard policy
1091 if (dpolicy
!= mDefaultPolicy
&&
1092 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1094 cpolicy
= static_cast<ClassPolicy
*>
1095 (PL_DHashTableOperate(mDefaultPolicy
,
1096 aClassData
.GetName(),
1099 if (PL_DHASH_ENTRY_IS_BUSY(cpolicy
))
1102 static_cast<PropertyPolicy
*>
1103 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1108 if ((!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)) &&
1109 mDefaultPolicy
->mWildcardPolicy
)
1112 static_cast<PropertyPolicy
*>
1113 (PL_DHashTableOperate(mDefaultPolicy
->mWildcardPolicy
->mPolicy
,
1119 if (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
))
1122 // Get the correct security level from the property policy
1123 if (aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
)
1124 *result
= ppolicy
->mSet
;
1126 *result
= ppolicy
->mGet
;
1133 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext
*cx
, nsIURI
*aURI
)
1135 // Get principal of currently executing script.
1137 nsIPrincipal
* principal
= GetSubjectPrincipal(cx
, &rv
);
1141 // Native code can load all URIs.
1145 rv
= CheckLoadURIWithPrincipal(principal
, aURI
,
1146 nsIScriptSecurityManager::STANDARD
);
1147 if (NS_SUCCEEDED(rv
)) {
1152 // See if we're attempting to load a file: URI. If so, let a
1153 // UniversalFileRead capability trump the above check.
1154 PRBool isFile
= PR_FALSE
;
1155 PRBool isRes
= PR_FALSE
;
1156 if (NS_FAILED(aURI
->SchemeIs("file", &isFile
)) ||
1157 NS_FAILED(aURI
->SchemeIs("resource", &isRes
)))
1158 return NS_ERROR_FAILURE
;
1159 if (isFile
|| isRes
)
1162 if (NS_FAILED(IsCapabilityEnabled("UniversalFileRead", &enabled
)))
1163 return NS_ERROR_FAILURE
;
1170 if (NS_FAILED(aURI
->GetAsciiSpec(spec
)))
1171 return NS_ERROR_FAILURE
;
1172 JS_ReportError(cx
, "Access to '%s' from script denied", spec
.get());
1173 return NS_ERROR_DOM_BAD_URI
;
1177 nsScriptSecurityManager::CheckLoadURI(nsIURI
*aSourceURI
, nsIURI
*aTargetURI
,
1180 // FIXME: bug 327244 -- this function should really die... Really truly.
1181 NS_PRECONDITION(aSourceURI
, "CheckLoadURI called with null source URI");
1182 NS_ENSURE_ARG_POINTER(aSourceURI
);
1184 // Note: this is not _quite_ right if aSourceURI has
1185 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1186 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1187 // really needs to go away....
1188 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1189 nsresult rv
= CreateCodebasePrincipal(aSourceURI
,
1190 getter_AddRefs(sourcePrincipal
));
1191 NS_ENSURE_SUCCESS(rv
, rv
);
1192 return CheckLoadURIWithPrincipal(sourcePrincipal
, aTargetURI
, aFlags
);
1196 * Helper method to handle cases where a flag passed to
1197 * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
1198 * nsIProtocolHandler flags set.
1199 * @return if success, access is allowed. Otherwise, deny access
1202 DenyAccessIfURIHasFlags(nsIURI
* aURI
, PRUint32 aURIFlags
)
1204 NS_PRECONDITION(aURI
, "Must have URI!");
1208 NS_URIChainHasFlags(aURI
, aURIFlags
, &uriHasFlags
);
1209 NS_ENSURE_SUCCESS(rv
, rv
);
1212 return NS_ERROR_DOM_BAD_URI
;
1219 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal
* aPrincipal
,
1223 NS_PRECONDITION(aPrincipal
, "CheckLoadURIWithPrincipal must have a principal");
1224 // If someone passes a flag that we don't understand, we should
1225 // fail, because they may need a security check that we don't
1227 NS_ENSURE_FALSE(aFlags
& ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
1228 nsIScriptSecurityManager::ALLOW_CHROME
|
1229 nsIScriptSecurityManager::DISALLOW_SCRIPT
|
1230 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
),
1231 NS_ERROR_UNEXPECTED
);
1232 NS_ENSURE_ARG_POINTER(aPrincipal
);
1234 if (aPrincipal
== mSystemPrincipal
) {
1239 nsCOMPtr
<nsIURI
> sourceURI
;
1240 aPrincipal
->GetURI(getter_AddRefs(sourceURI
));
1242 NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
1243 "must have a URI!");
1244 return NS_ERROR_UNEXPECTED
;
1247 // Automatic loads are not allowed from certain protocols.
1248 if (aFlags
& nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
) {
1250 DenyAccessIfURIHasFlags(sourceURI
,
1251 nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT
);
1252 NS_ENSURE_SUCCESS(rv
, rv
);
1255 // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
1256 // would do such inheriting. That would be URIs that do not have their own
1257 // security context.
1258 if (aFlags
& nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
) {
1260 DenyAccessIfURIHasFlags(aTargetURI
,
1261 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
);
1262 NS_ENSURE_SUCCESS(rv
, rv
);
1265 // If either URI is a nested URI, get the base URI
1266 nsCOMPtr
<nsIURI
> sourceBaseURI
= NS_GetInnermostURI(sourceURI
);
1267 nsCOMPtr
<nsIURI
> targetBaseURI
= NS_GetInnermostURI(aTargetURI
);
1269 //-- get the target scheme
1270 nsCAutoString targetScheme
;
1271 nsresult rv
= targetBaseURI
->GetScheme(targetScheme
);
1272 if (NS_FAILED(rv
)) return rv
;
1274 //-- Some callers do not allow loading javascript:
1275 if ((aFlags
& nsIScriptSecurityManager::DISALLOW_SCRIPT
) &&
1276 targetScheme
.EqualsLiteral("javascript"))
1278 return NS_ERROR_DOM_BAD_URI
;
1281 //-- get the source scheme
1282 nsCAutoString sourceScheme
;
1283 rv
= sourceBaseURI
->GetScheme(sourceScheme
);
1284 if (NS_FAILED(rv
)) return rv
;
1286 if (sourceScheme
.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME
)) {
1287 // A null principal can target its own URI.
1288 if (sourceURI
== aTargetURI
) {
1292 else if (targetScheme
.Equals(sourceScheme
,
1293 nsCaseInsensitiveCStringComparator()))
1295 // every scheme can access another URI from the same scheme,
1296 // as long as they don't represent null principals.
1300 NS_NAMED_LITERAL_STRING(errorTag
, "CheckLoadURIError");
1302 // If the schemes don't match, the policy is specified by the protocol
1303 // flags on the target URI. Note that the order of policy checks here is
1304 // very important! We start from most restrictive and work our way down.
1305 // Note that since we're working with the innermost URI, we can just use
1306 // the methods that work on chains of nested URIs and they will only look
1307 // at the flags for our one URI.
1309 // Check for system target URI
1310 rv
= DenyAccessIfURIHasFlags(targetBaseURI
,
1311 nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
);
1312 if (NS_FAILED(rv
)) {
1313 // Deny access, since the origin principal is not system
1314 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1318 // Check for chrome target URI
1320 rv
= NS_URIChainHasFlags(targetBaseURI
,
1321 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1323 NS_ENSURE_SUCCESS(rv
, rv
);
1325 if (aFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) {
1326 if (!targetScheme
.EqualsLiteral("chrome")) {
1327 // for now don't change behavior for resource: or moz-icon:
1331 // allow load only if chrome package is whitelisted
1332 nsCOMPtr
<nsIXULChromeRegistry
> reg(do_GetService(
1333 NS_CHROMEREGISTRY_CONTRACTID
));
1335 PRBool accessAllowed
= PR_FALSE
;
1336 reg
->AllowContentToAccess(targetBaseURI
, &accessAllowed
);
1337 if (accessAllowed
) {
1343 // resource: and chrome: are equivalent, securitywise
1344 // That's bogus!! Fix this. But watch out for
1345 // the view-source stylesheet?
1346 PRBool sourceIsChrome
;
1347 rv
= NS_URIChainHasFlags(sourceBaseURI
,
1348 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1350 NS_ENSURE_SUCCESS(rv
, rv
);
1351 if (sourceIsChrome
) {
1354 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1355 return NS_ERROR_DOM_BAD_URI
;
1358 // Check for target URI pointing to a file
1359 rv
= NS_URIChainHasFlags(targetBaseURI
,
1360 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
1362 NS_ENSURE_SUCCESS(rv
, rv
);
1364 // resource: and chrome: are equivalent, securitywise
1365 // That's bogus!! Fix this. But watch out for
1366 // the view-source stylesheet?
1367 PRBool sourceIsChrome
;
1368 rv
= NS_URIChainHasFlags(sourceURI
,
1369 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1371 NS_ENSURE_SUCCESS(rv
, rv
);
1372 if (sourceIsChrome
) {
1376 // Now check capability policies
1377 static const char loadURIPrefGroup
[] = "checkloaduri";
1378 ClassInfoData
nameData(nsnull
, loadURIPrefGroup
);
1380 SecurityLevel secLevel
;
1381 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1382 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1384 if (NS_SUCCEEDED(rv
) && secLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
1386 // OK for this site!
1390 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1391 return NS_ERROR_DOM_BAD_URI
;
1394 // OK, everyone is allowed to load this, since unflagged handlers are
1395 // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
1396 // need to warn. At some point we'll want to make this warning into an
1397 // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
1398 rv
= NS_URIChainHasFlags(targetBaseURI
,
1399 nsIProtocolHandler::URI_LOADABLE_BY_ANYONE
,
1401 NS_ENSURE_SUCCESS(rv
, rv
);
1403 nsXPIDLString message
;
1404 NS_ConvertASCIItoUTF16
ucsTargetScheme(targetScheme
);
1405 const PRUnichar
* formatStrings
[] = { ucsTargetScheme
.get() };
1407 FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
1409 NS_ARRAY_LENGTH(formatStrings
),
1410 getter_Copies(message
));
1411 if (NS_SUCCEEDED(rv
)) {
1412 nsCOMPtr
<nsIConsoleService
> console(
1413 do_GetService("@mozilla.org/consoleservice;1"));
1414 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1416 console
->LogStringMessage(message
.get());
1418 fprintf(stderr
, "%s\n", NS_ConvertUTF16toUTF8(message
).get());
1427 nsScriptSecurityManager::ReportError(JSContext
* cx
, const nsAString
& messageTag
,
1428 nsIURI
* aSource
, nsIURI
* aTarget
)
1431 NS_ENSURE_TRUE(aSource
&& aTarget
, NS_ERROR_NULL_POINTER
);
1433 // Get the source URL spec
1434 nsCAutoString sourceSpec
;
1435 rv
= aSource
->GetAsciiSpec(sourceSpec
);
1436 NS_ENSURE_SUCCESS(rv
, rv
);
1438 // Get the target URL spec
1439 nsCAutoString targetSpec
;
1440 rv
= aTarget
->GetAsciiSpec(targetSpec
);
1441 NS_ENSURE_SUCCESS(rv
, rv
);
1443 // Localize the error message
1444 nsXPIDLString message
;
1445 NS_ConvertASCIItoUTF16
ucsSourceSpec(sourceSpec
);
1446 NS_ConvertASCIItoUTF16
ucsTargetSpec(targetSpec
);
1447 const PRUnichar
*formatStrings
[] = { ucsSourceSpec
.get(), ucsTargetSpec
.get() };
1448 rv
= sStrBundle
->FormatStringFromName(PromiseFlatString(messageTag
).get(),
1450 NS_ARRAY_LENGTH(formatStrings
),
1451 getter_Copies(message
));
1452 NS_ENSURE_SUCCESS(rv
, rv
);
1454 // If a JS context was passed in, set a JS exception.
1455 // Otherwise, print the error message directly to the JS console
1456 // and to standard output
1459 SetPendingException(cx
, message
.get());
1461 else // Print directly to the console
1463 nsCOMPtr
<nsIConsoleService
> console(
1464 do_GetService("@mozilla.org/consoleservice;1"));
1465 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1467 console
->LogStringMessage(message
.get());
1469 fprintf(stderr
, "%s\n", NS_LossyConvertUTF16toASCII(message
).get());
1476 nsScriptSecurityManager::CheckLoadURIStr(const nsACString
& aSourceURIStr
,
1477 const nsACString
& aTargetURIStr
,
1480 // FIXME: bug 327244 -- this function should really die... Really truly.
1481 nsCOMPtr
<nsIURI
> source
;
1482 nsresult rv
= NS_NewURI(getter_AddRefs(source
), aSourceURIStr
,
1483 nsnull
, nsnull
, sIOService
);
1484 NS_ENSURE_SUCCESS(rv
, rv
);
1486 // Note: this is not _quite_ right if aSourceURI has
1487 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1488 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1489 // really needs to go away....
1490 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1491 rv
= CreateCodebasePrincipal(source
,
1492 getter_AddRefs(sourcePrincipal
));
1493 NS_ENSURE_SUCCESS(rv
, rv
);
1495 return CheckLoadURIStrWithPrincipal(sourcePrincipal
, aTargetURIStr
,
1500 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal
* aPrincipal
,
1501 const nsACString
& aTargetURIStr
,
1505 nsCOMPtr
<nsIURI
> target
;
1506 rv
= NS_NewURI(getter_AddRefs(target
), aTargetURIStr
,
1507 nsnull
, nsnull
, sIOService
);
1508 NS_ENSURE_SUCCESS(rv
, rv
);
1510 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1511 NS_ENSURE_SUCCESS(rv
, rv
);
1513 // Now start testing fixup -- since aTargetURIStr is a string, not
1514 // an nsIURI, we may well end up fixing it up before loading.
1515 // Note: This needs to stay in sync with the nsIURIFixup api.
1516 nsCOMPtr
<nsIURIFixup
> fixup
= do_GetService(NS_URIFIXUP_CONTRACTID
);
1521 PRUint32 flags
[] = {
1522 nsIURIFixup::FIXUP_FLAG_NONE
,
1523 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
,
1524 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
,
1525 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
|
1526 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
1529 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(flags
); ++i
) {
1530 rv
= fixup
->CreateFixupURI(aTargetURIStr
, flags
[i
],
1531 getter_AddRefs(target
));
1532 NS_ENSURE_SUCCESS(rv
, rv
);
1534 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1535 NS_ENSURE_SUCCESS(rv
, rv
);
1542 nsScriptSecurityManager::CheckFunctionAccess(JSContext
*aCx
, void *aFunObj
,
1545 // This check is called for event handlers
1547 nsIPrincipal
* subject
=
1548 GetFunctionObjectPrincipal(aCx
, (JSObject
*)aFunObj
, nsnull
, &rv
);
1550 // If subject is null, get a principal from the function object's scope.
1551 if (NS_SUCCEEDED(rv
) && !subject
)
1556 (JSFunction
*)caps_GetJSPrivate((JSObject
*)aFunObj
);
1557 JSScript
*script
= JS_GetFunctionScript(aCx
, fun
);
1559 NS_ASSERTION(!script
, "Null principal for non-native function!");
1563 subject
= doGetObjectPrincipal((JSObject
*)aFunObj
);
1567 return NS_ERROR_FAILURE
;
1569 if (subject
== mSystemPrincipal
)
1570 // This is the system principal: just allow access
1573 // Check if the principal the function was compiled under is
1574 // allowed to execute scripts.
1577 rv
= CanExecuteScripts(aCx
, subject
, &result
);
1582 return NS_ERROR_DOM_SECURITY_ERR
;
1585 ** Get origin of subject and object and compare.
1587 JSObject
* obj
= (JSObject
*)aTargetObj
;
1588 nsIPrincipal
* object
= doGetObjectPrincipal(obj
);
1591 return NS_ERROR_FAILURE
;
1594 rv
= subject
->Subsumes(object
, &subsumes
);
1595 if (NS_SUCCEEDED(rv
) && !subsumes
) {
1596 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1602 nsScriptSecurityManager::CanExecuteScripts(JSContext
* cx
,
1603 nsIPrincipal
*aPrincipal
,
1608 if (aPrincipal
== mSystemPrincipal
)
1610 // Even if JavaScript is disabled, we must still execute system scripts
1615 //-- See if the current window allows JS execution
1616 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
1617 if (!scriptContext
) return NS_ERROR_FAILURE
;
1619 if (!scriptContext
->GetScriptsEnabled()) {
1620 // No scripting on this context, folks
1625 nsIScriptGlobalObject
*sgo
= scriptContext
->GetGlobalObject();
1628 return NS_ERROR_FAILURE
;
1631 // window can be null here if we're running with a non-DOM window
1632 // as the script global (i.e. a XUL prototype document).
1633 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(sgo
);
1634 nsCOMPtr
<nsIDocShell
> docshell
;
1638 docshell
= window
->GetDocShell();
1641 nsCOMPtr
<nsIDocShellTreeItem
> globalObjTreeItem
=
1642 do_QueryInterface(docshell
);
1644 if (globalObjTreeItem
)
1646 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(globalObjTreeItem
);
1647 nsCOMPtr
<nsIDocShellTreeItem
> parentItem
;
1649 // Walk up the docshell tree to see if any containing docshell disallows scripts
1652 rv
= docshell
->GetAllowJavascript(result
);
1653 if (NS_FAILED(rv
)) return rv
;
1655 return NS_OK
; // Do not run scripts
1656 treeItem
->GetParent(getter_AddRefs(parentItem
));
1657 treeItem
.swap(parentItem
);
1658 docshell
= do_QueryInterface(treeItem
);
1660 if (treeItem
&& !docshell
) {
1661 NS_ERROR("cannot get a docshell from a treeItem!");
1664 } while (treeItem
&& docshell
);
1667 // OK, the docshell doesn't have script execution explicitly disabled.
1668 // Check whether our URI is an "about:" URI that allows scripts. If it is,
1669 // we need to allow JS to run. In this case, don't apply the JS enabled
1670 // pref or policies. On failures, just press on and don't do this special
1672 nsCOMPtr
<nsIURI
> principalURI
;
1673 aPrincipal
->GetURI(getter_AddRefs(principalURI
));
1674 if (!principalURI
) {
1675 // Broken principal of some sort. Disallow.
1677 return NS_ERROR_UNEXPECTED
;
1681 rv
= principalURI
->SchemeIs("about", &isAbout
);
1682 if (NS_SUCCEEDED(rv
) && isAbout
) {
1683 nsCOMPtr
<nsIAboutModule
> module
;
1684 rv
= NS_GetAboutModule(principalURI
, getter_AddRefs(module
));
1685 if (NS_SUCCEEDED(rv
)) {
1687 rv
= module
->GetURIFlags(principalURI
, &flags
);
1688 if (NS_SUCCEEDED(rv
) &&
1689 (flags
& nsIAboutModule::ALLOW_SCRIPT
)) {
1696 //-- See if JS is disabled globally (via prefs)
1697 *result
= mIsJavaScriptEnabled
;
1698 if (mIsJavaScriptEnabled
!= mIsMailJavaScriptEnabled
&& globalObjTreeItem
)
1700 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
1701 globalObjTreeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
1702 docshell
= do_QueryInterface(rootItem
);
1705 // Is this script running from mail?
1707 rv
= docshell
->GetAppType(&appType
);
1708 if (NS_FAILED(rv
)) return rv
;
1709 if (appType
== nsIDocShell::APP_TYPE_MAIL
)
1711 *result
= mIsMailJavaScriptEnabled
;
1717 return NS_OK
; // Do not run scripts
1719 //-- Check for a per-site policy
1720 static const char jsPrefGroupName
[] = "javascript";
1721 ClassInfoData
nameData(nsnull
, jsPrefGroupName
);
1723 SecurityLevel secLevel
;
1724 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1725 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1727 if (NS_FAILED(rv
) || secLevel
.level
== SCRIPT_SECURITY_NO_ACCESS
)
1733 //-- Nobody vetoed, so allow the JS to run.
1738 ///////////////// Principals ///////////////////////
1740 nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal
**aSubjectPrincipal
)
1743 *aSubjectPrincipal
= doGetSubjectPrincipal(&rv
);
1744 if (NS_SUCCEEDED(rv
))
1745 NS_IF_ADDREF(*aSubjectPrincipal
);
1750 nsScriptSecurityManager::doGetSubjectPrincipal(nsresult
* rv
)
1752 NS_PRECONDITION(rv
, "Null out param");
1753 JSContext
*cx
= GetCurrentJSContext();
1759 return GetSubjectPrincipal(cx
, rv
);
1763 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal
**result
)
1765 NS_ADDREF(*result
= mSystemPrincipal
);
1771 nsScriptSecurityManager::SubjectPrincipalIsSystem(PRBool
* aIsSystem
)
1773 NS_ENSURE_ARG_POINTER(aIsSystem
);
1774 *aIsSystem
= PR_FALSE
;
1776 if (!mSystemPrincipal
)
1779 nsCOMPtr
<nsIPrincipal
> subject
;
1780 nsresult rv
= GetSubjectPrincipal(getter_AddRefs(subject
));
1786 // No subject principal means no JS is running;
1787 // this is the equivalent of system principal code
1788 *aIsSystem
= PR_TRUE
;
1792 return mSystemPrincipal
->Equals(subject
, aIsSystem
);
1796 nsScriptSecurityManager::GetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1797 const nsACString
& aSubjectName
,
1798 const nsACString
& aPrettyName
,
1799 nsISupports
* aCertificate
,
1801 nsIPrincipal
**result
)
1805 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty() &&
1806 !aSubjectName
.IsEmpty() &&
1809 return DoGetCertificatePrincipal(aCertFingerprint
, aSubjectName
,
1810 aPrettyName
, aCertificate
, aURI
, PR_TRUE
,
1815 nsScriptSecurityManager::DoGetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1816 const nsACString
& aSubjectName
,
1817 const nsACString
& aPrettyName
,
1818 nsISupports
* aCertificate
,
1820 PRBool aModifyTable
,
1821 nsIPrincipal
**result
)
1823 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty());
1825 // Create a certificate principal out of the certificate ID
1826 // and URI given to us. We will use this principal to test
1827 // equality when doing our hashtable lookups below.
1828 nsRefPtr
<nsPrincipal
> certificate
= new nsPrincipal();
1830 return NS_ERROR_OUT_OF_MEMORY
;
1832 nsresult rv
= certificate
->Init(aCertFingerprint
, aSubjectName
,
1833 aPrettyName
, aCertificate
, aURI
);
1834 NS_ENSURE_SUCCESS(rv
, rv
);
1836 // Check to see if we already have this principal.
1837 nsCOMPtr
<nsIPrincipal
> fromTable
;
1838 mPrincipals
.Get(certificate
, getter_AddRefs(fromTable
));
1840 // Bingo. We found the certificate in the table, which means
1841 // that it has escalated privileges.
1844 // Make sure this principal has names, so if we ever go to save it
1845 // we'll save them. If we get a name mismatch here we'll throw,
1846 // but that's desirable.
1847 rv
= static_cast<nsPrincipal
*>
1848 (static_cast<nsIPrincipal
*>(fromTable
))
1849 ->EnsureCertData(aSubjectName
, aPrettyName
, aCertificate
);
1850 if (NS_FAILED(rv
)) {
1851 // We have a subject name mismatch for the same cert id.
1852 // Hand back the |certificate| object we created and don't give
1853 // it any rights from the table.
1854 NS_ADDREF(*result
= certificate
);
1860 // We were asked to just get the base certificate, so output
1861 // what we have in the table.
1862 certificate
= static_cast<nsPrincipal
*>
1863 (static_cast<nsIPrincipal
*>
1866 // We found a certificate and now need to install a codebase
1867 // on it. We don't want to modify the principal in the hash
1868 // table, so create a new principal and clone the pertinent
1870 nsXPIDLCString prefName
;
1872 nsXPIDLCString subjectName
;
1873 nsXPIDLCString granted
;
1874 nsXPIDLCString denied
;
1876 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
1878 getter_Copies(subjectName
),
1879 getter_Copies(granted
),
1880 getter_Copies(denied
),
1882 // XXXbz assert something about subjectName and aSubjectName here?
1883 if (NS_SUCCEEDED(rv
)) {
1884 NS_ASSERTION(!isTrusted
, "Shouldn't have isTrusted true here");
1886 certificate
= new nsPrincipal();
1888 return NS_ERROR_OUT_OF_MEMORY
;
1890 rv
= certificate
->InitFromPersistent(prefName
, id
,
1891 subjectName
, aPrettyName
,
1898 certificate
->SetURI(aURI
);
1903 NS_ADDREF(*result
= certificate
);
1909 nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI
* aURI
, nsIPrincipal
**result
)
1911 // I _think_ it's safe to not create null principals here based on aURI.
1912 // At least all the callers would do the right thing in those cases, as far
1913 // as I can tell. --bz
1914 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
1916 return NS_ERROR_OUT_OF_MEMORY
;
1918 nsresult rv
= codebase
->Init(EmptyCString(), EmptyCString(),
1919 EmptyCString(), nsnull
, aURI
);
1923 NS_ADDREF(*result
= codebase
);
1929 nsScriptSecurityManager::GetCodebasePrincipal(nsIURI
*aURI
,
1930 nsIPrincipal
**result
)
1932 NS_ENSURE_ARG(aURI
);
1934 PRBool inheritsPrincipal
;
1936 NS_URIChainHasFlags(aURI
,
1937 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
1938 &inheritsPrincipal
);
1939 if (NS_FAILED(rv
) || inheritsPrincipal
) {
1940 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
1943 nsCOMPtr
<nsIPrincipal
> principal
;
1944 rv
= CreateCodebasePrincipal(aURI
, getter_AddRefs(principal
));
1945 if (NS_FAILED(rv
)) return rv
;
1947 if (mPrincipals
.Count() > 0)
1949 //-- Check to see if we already have this principal.
1950 nsCOMPtr
<nsIPrincipal
> fromTable
;
1951 mPrincipals
.Get(principal
, getter_AddRefs(fromTable
));
1954 //-- Check to see if we have a more general principal
1956 // XXXbz if only GetOrigin returned a URI! Or better yet if the
1957 // HashKey function on principals were smarter. As it is, we can
1958 // have cases where two principals will have different hashkeys but
1959 // test equal via KeyEquals, which is absolutely silly. That's
1960 // what we're working around here.
1961 nsXPIDLCString originUrl
;
1962 rv
= principal
->GetOrigin(getter_Copies(originUrl
));
1963 if (NS_FAILED(rv
)) return rv
;
1964 nsCOMPtr
<nsIURI
> newURI
;
1965 rv
= NS_NewURI(getter_AddRefs(newURI
), originUrl
, nsnull
, sIOService
);
1966 if (NS_FAILED(rv
)) return rv
;
1967 nsCOMPtr
<nsIPrincipal
> principal2
;
1968 rv
= CreateCodebasePrincipal(newURI
, getter_AddRefs(principal2
));
1969 if (NS_FAILED(rv
)) return rv
;
1970 mPrincipals
.Get(principal2
, getter_AddRefs(fromTable
));
1974 // We found an existing codebase principal. But it might have a
1975 // generic codebase for this origin on it. Install our particular
1977 // XXXbz this is kinda similar to the code in
1978 // GetCertificatePrincipal, but just ever so slightly different.
1980 nsXPIDLCString prefName
;
1982 nsXPIDLCString subjectName
;
1983 nsXPIDLCString granted
;
1984 nsXPIDLCString denied
;
1986 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
1988 getter_Copies(subjectName
),
1989 getter_Copies(granted
),
1990 getter_Copies(denied
),
1992 if (NS_SUCCEEDED(rv
)) {
1993 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
1995 return NS_ERROR_OUT_OF_MEMORY
;
1997 rv
= codebase
->InitFromPersistent(prefName
, id
,
1998 subjectName
, EmptyCString(),
2005 codebase
->SetURI(aURI
);
2006 principal
= codebase
;
2012 NS_IF_ADDREF(*result
= principal
);
2018 nsScriptSecurityManager::GetPrincipalFromContext(JSContext
*cx
,
2019 nsIPrincipal
**result
)
2023 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2027 return NS_ERROR_FAILURE
;
2030 nsCOMPtr
<nsIScriptObjectPrincipal
> globalData
=
2031 do_QueryInterface(scriptContext
->GetGlobalObject());
2033 NS_IF_ADDREF(*result
= globalData
->GetPrincipal());
2040 nsScriptSecurityManager::GetScriptPrincipal(JSContext
*cx
,
2044 NS_PRECONDITION(rv
, "Null out param");
2050 JSPrincipals
*jsp
= JS_GetScriptPrincipals(cx
, script
);
2052 *rv
= NS_ERROR_FAILURE
;
2053 NS_ERROR("Script compiled without principals!");
2056 nsJSPrincipals
*nsJSPrin
= static_cast<nsJSPrincipals
*>(jsp
);
2057 nsIPrincipal
* result
= nsJSPrin
->nsIPrincipalPtr
;
2059 *rv
= NS_ERROR_FAILURE
;
2065 nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext
*cx
,
2070 NS_PRECONDITION(rv
, "Null out param");
2071 JSFunction
*fun
= (JSFunction
*) caps_GetJSPrivate(obj
);
2072 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2078 // A native function: skip it in order to find its scripted caller.
2082 JSScript
*frameScript
= fp
? JS_GetFrameScript(cx
, fp
) : nsnull
;
2084 if (frameScript
&& frameScript
!= script
)
2086 // There is a frame script, and it's different from the
2087 // function script. In this case we're dealing with either
2088 // an eval or a Script object, and in these cases the
2089 // principal we want is in the frame's script, not in the
2090 // function's script. The function's script is where the
2091 // eval-calling code came from, not where the eval or new
2092 // Script object came from, and we want the principal of
2093 // the eval function object or new Script object.
2095 script
= frameScript
;
2097 else if (JS_GetFunctionObject(fun
) != obj
)
2099 // Here, obj is a cloned function object. In this case, the
2100 // clone's prototype may have been precompiled from brutally
2101 // shared chrome, or else it is a lambda or nested function.
2102 // The general case here is a function compiled against a
2103 // different scope than the one it is parented by at runtime,
2104 // hence the creation of a clone to carry the correct scope
2107 // Since principals follow scope, we must get the object
2108 // principal from the clone's scope chain. There are no
2109 // reliable principals compiled into the function itself.
2111 nsIPrincipal
*result
= doGetObjectPrincipal(obj
);
2113 *rv
= NS_ERROR_FAILURE
;
2117 return GetScriptPrincipal(cx
, script
, rv
);
2122 nsScriptSecurityManager::GetFramePrincipal(JSContext
*cx
,
2126 NS_PRECONDITION(rv
, "Null out param");
2127 JSObject
*obj
= JS_GetFrameFunctionObject(cx
, fp
);
2130 // Must be in a top-level script. Get principal from the script.
2131 JSScript
*script
= JS_GetFrameScript(cx
, fp
);
2132 return GetScriptPrincipal(cx
, script
, rv
);
2135 nsIPrincipal
* result
= GetFunctionObjectPrincipal(cx
, obj
, fp
, rv
);
2138 if (NS_SUCCEEDED(*rv
) && !result
)
2140 JSFunction
*fun
= (JSFunction
*)caps_GetJSPrivate(obj
);
2141 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2143 NS_ASSERTION(!script
, "Null principal for non-native function!");
2152 nsScriptSecurityManager::GetPrincipalAndFrame(JSContext
*cx
,
2153 JSStackFrame
**frameResult
,
2156 NS_PRECONDITION(rv
, "Null out param");
2157 //-- If there's no principal on the stack, look at the global object
2158 // and return the innermost frame for annotations.
2162 // Get principals from innermost frame of JavaScript or Java.
2163 JSStackFrame
*fp
= nsnull
; // tell JS_FrameIterator to start at innermost
2164 for (fp
= JS_FrameIterator(cx
, &fp
); fp
; fp
= JS_FrameIterator(cx
, &fp
))
2166 nsIPrincipal
* result
= GetFramePrincipal(cx
, fp
, rv
);
2169 NS_ASSERTION(NS_SUCCEEDED(*rv
), "Weird return");
2175 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2178 nsCOMPtr
<nsIScriptObjectPrincipal
> globalData
=
2179 do_QueryInterface(scriptContext
->GetGlobalObject());
2182 *rv
= NS_ERROR_FAILURE
;
2186 // Note that we're not in a loop or anything, and nothing comes
2187 // after this point in the function, so we can just return here.
2188 nsIPrincipal
* result
= globalData
->GetPrincipal();
2191 JSStackFrame
*inner
= nsnull
;
2192 *frameResult
= JS_FrameIterator(cx
, &inner
);
2203 nsScriptSecurityManager::GetSubjectPrincipal(JSContext
*cx
,
2206 NS_PRECONDITION(rv
, "Null out param");
2208 return GetPrincipalAndFrame(cx
, &fp
, rv
);
2212 nsScriptSecurityManager::GetObjectPrincipal(JSContext
*aCx
, JSObject
*aObj
,
2213 nsIPrincipal
**result
)
2215 *result
= doGetObjectPrincipal(aObj
);
2217 return NS_ERROR_FAILURE
;
2224 nsScriptSecurityManager::doGetObjectPrincipal(JSObject
*aObj
2226 , PRBool aAllowShortCircuit
2230 NS_ASSERTION(aObj
, "Bad call to doGetObjectPrincipal()!");
2231 nsIPrincipal
* result
= nsnull
;
2234 JSObject
* origObj
= aObj
;
2237 const JSClass
*jsClass
= STOBJ_GET_CLASS(aObj
);
2239 // A common case seen in this code is that we enter this function
2240 // with aObj being a Function object, whose parent is a Call
2241 // object. Neither of those have object principals, so we can skip
2242 // those objects here before we enter the below loop. That way we
2243 // avoid wasting time checking properties of their classes etc in
2246 if (jsClass
== &js_FunctionClass
) {
2247 aObj
= STOBJ_GET_PARENT(aObj
);
2252 jsClass
= STOBJ_GET_CLASS(aObj
);
2254 if (jsClass
== &js_CallClass
) {
2255 aObj
= STOBJ_GET_PARENT(aObj
);
2260 jsClass
= STOBJ_GET_CLASS(aObj
);
2265 // Note: jsClass is set before this loop, and also at the
2266 // *end* of this loop.
2268 // NOTE: These class and getObjectOps hook checks better match
2269 // what IS_WRAPPER_CLASS() does in xpconnect!
2270 if (jsClass
== sXPCWrappedNativeJSClass
||
2271 jsClass
->getObjectOps
== sXPCWrappedNativeGetObjOps1
||
2272 jsClass
->getObjectOps
== sXPCWrappedNativeGetObjOps2
) {
2273 nsIXPConnectWrappedNative
*xpcWrapper
=
2274 (nsIXPConnectWrappedNative
*)caps_GetJSPrivate(aObj
);
2278 if (aAllowShortCircuit
) {
2280 result
= xpcWrapper
->GetObjectPrincipal();
2289 // If not, check if it points to an
2290 // nsIScriptObjectPrincipal
2291 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrin
=
2292 do_QueryWrappedNative(xpcWrapper
);
2294 result
= objPrin
->GetPrincipal();
2301 } else if (!(~jsClass
->flags
& (JSCLASS_HAS_PRIVATE
|
2302 JSCLASS_PRIVATE_IS_NSISUPPORTS
))) {
2303 nsISupports
*priv
= (nsISupports
*)caps_GetJSPrivate(aObj
);
2306 if (aAllowShortCircuit
) {
2307 nsCOMPtr
<nsIXPConnectWrappedNative
> xpcWrapper
=
2308 do_QueryInterface(priv
);
2310 NS_ASSERTION(!xpcWrapper
||
2311 !strcmp(jsClass
->name
, "XPCNativeWrapper"),
2312 "Uh, an nsIXPConnectWrappedNative with the "
2313 "wrong JSClass or getObjectOps hooks!");
2317 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrin
=
2318 do_QueryInterface(priv
);
2321 result
= objPrin
->GetPrincipal();
2329 aObj
= STOBJ_GET_PARENT(aObj
);
2334 jsClass
= STOBJ_GET_CLASS(aObj
);
2337 NS_ASSERTION(!aAllowShortCircuit
||
2338 result
== doGetObjectPrincipal(origObj
, PR_FALSE
),
2339 "Principal mismatch. Not good");
2345 nsScriptSecurityManager::SavePrincipal(nsIPrincipal
* aToSave
)
2347 //-- Save to mPrincipals
2348 mPrincipals
.Put(aToSave
, aToSave
);
2351 nsXPIDLCString idPrefName
;
2353 nsXPIDLCString subjectName
;
2354 nsXPIDLCString grantedList
;
2355 nsXPIDLCString deniedList
;
2357 nsresult rv
= aToSave
->GetPreferences(getter_Copies(idPrefName
),
2359 getter_Copies(subjectName
),
2360 getter_Copies(grantedList
),
2361 getter_Copies(deniedList
),
2363 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2365 nsCAutoString grantedPrefName
;
2366 nsCAutoString deniedPrefName
;
2367 nsCAutoString subjectNamePrefName
;
2368 rv
= GetPrincipalPrefNames( idPrefName
,
2371 subjectNamePrefName
);
2372 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2374 mIsWritingPrefs
= PR_TRUE
;
2376 mSecurityPref
->SecuritySetCharPref(grantedPrefName
.get(), grantedList
);
2378 mSecurityPref
->SecurityClearUserPref(grantedPrefName
.get());
2381 mSecurityPref
->SecuritySetCharPref(deniedPrefName
.get(), deniedList
);
2383 mSecurityPref
->SecurityClearUserPref(deniedPrefName
.get());
2385 if (grantedList
|| deniedList
) {
2386 mSecurityPref
->SecuritySetCharPref(idPrefName
, id
);
2387 mSecurityPref
->SecuritySetCharPref(subjectNamePrefName
.get(),
2391 mSecurityPref
->SecurityClearUserPref(idPrefName
);
2392 mSecurityPref
->SecurityClearUserPref(subjectNamePrefName
.get());
2395 mIsWritingPrefs
= PR_FALSE
;
2397 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
2398 NS_ENSURE_SUCCESS(rv
, rv
);
2399 return prefService
->SavePrefFile(nsnull
);
2402 ///////////////// Capabilities API /////////////////////
2404 nsScriptSecurityManager::IsCapabilityEnabled(const char *capability
,
2408 JSStackFrame
*fp
= nsnull
;
2409 JSContext
*cx
= GetCurrentJSContext();
2410 fp
= cx
? JS_FrameIterator(cx
, &fp
) : nsnull
;
2413 // No script code on stack. Allow execution.
2418 nsIPrincipal
* previousPrincipal
= nsnull
;
2421 nsIPrincipal
* principal
= GetFramePrincipal(cx
, fp
, &rv
);
2426 // If caller has a different principal, stop looking up the stack.
2427 if(previousPrincipal
)
2429 PRBool isEqual
= PR_FALSE
;
2430 if(NS_FAILED(previousPrincipal
->Equals(principal
, &isEqual
)) || !isEqual
)
2434 previousPrincipal
= principal
;
2436 // First check if the principal is even able to enable the
2437 // given capability. If not, don't look any further.
2439 rv
= principal
->CanEnableCapability(capability
, &canEnable
);
2440 if (NS_FAILED(rv
)) return rv
;
2441 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
&&
2442 canEnable
!= nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2445 // Now see if the capability is enabled.
2446 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2447 rv
= principal
->IsCapabilityEnabled(capability
, annotation
, result
);
2448 if (NS_FAILED(rv
)) return rv
;
2451 } while ((fp
= JS_FrameIterator(cx
, &fp
)) != nsnull
);
2453 if (!previousPrincipal
)
2455 // No principals on the stack, all native code. Allow
2456 // execution if the subject principal is the system principal.
2458 return SubjectPrincipalIsSystem(result
);
2465 nsScriptSecurityManager::FormatCapabilityString(nsAString
& aCapability
)
2467 nsAutoString newcaps
;
2468 nsAutoString rawcap
;
2469 NS_NAMED_LITERAL_STRING(capdesc
, "capdesc.");
2471 PRInt32 index
= kNotFound
;
2474 NS_ASSERTION(kNotFound
== -1, "Basic constant changed, algorithm broken!");
2478 index
= aCapability
.FindChar(' ', pos
);
2479 rawcap
= Substring(aCapability
, pos
,
2480 (index
== kNotFound
) ? index
: index
- pos
);
2482 nsXPIDLString capstr
;
2483 rv
= sStrBundle
->GetStringFromName(
2484 nsPromiseFlatString(capdesc
+rawcap
).get(),
2485 getter_Copies(capstr
));
2486 if (NS_SUCCEEDED(rv
))
2490 nsXPIDLString extensionCap
;
2491 const PRUnichar
* formatArgs
[] = { rawcap
.get() };
2492 rv
= sStrBundle
->FormatStringFromName(
2493 NS_LITERAL_STRING("ExtensionCapability").get(),
2495 NS_ARRAY_LENGTH(formatArgs
),
2496 getter_Copies(extensionCap
));
2497 if (NS_SUCCEEDED(rv
))
2498 newcaps
+= extensionCap
;
2503 newcaps
+= NS_LITERAL_STRING("\n");
2504 } while (index
!= kNotFound
);
2506 aCapability
= newcaps
;
2510 nsScriptSecurityManager::CheckConfirmDialog(JSContext
* cx
, nsIPrincipal
* aPrincipal
,
2511 const char* aCapability
, PRBool
*checkValue
)
2514 *checkValue
= PR_FALSE
;
2516 //-- Get a prompter for the current window.
2517 nsCOMPtr
<nsIPrompt
> prompter
;
2520 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2523 nsCOMPtr
<nsIDOMWindowInternal
> domWin
=
2524 do_QueryInterface(scriptContext
->GetGlobalObject());
2526 domWin
->GetPrompter(getter_AddRefs(prompter
));
2532 //-- Couldn't get prompter from the current window, so get the prompt service.
2533 nsCOMPtr
<nsIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
2535 wwatch
->GetNewPrompter(0, getter_AddRefs(prompter
));
2540 //-- Localize the dialog text
2541 nsXPIDLString check
;
2542 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("CheckMessage").get(),
2543 getter_Copies(check
));
2547 nsXPIDLString title
;
2548 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Titleline").get(),
2549 getter_Copies(title
));
2553 nsXPIDLString yesStr
;
2554 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Yes").get(),
2555 getter_Copies(yesStr
));
2559 nsXPIDLString noStr
;
2560 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("No").get(),
2561 getter_Copies(noStr
));
2567 aPrincipal
->GetHasCertificate(&hasCert
);
2569 rv
= aPrincipal
->GetPrettyName(val
);
2571 rv
= GetPrincipalDomainOrigin(aPrincipal
, val
);
2576 NS_ConvertUTF8toUTF16
location(val
);
2577 NS_ConvertASCIItoUTF16
capability(aCapability
);
2578 FormatCapabilityString(capability
);
2579 const PRUnichar
*formatStrings
[] = { location
.get(), capability
.get() };
2581 nsXPIDLString message
;
2582 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityQuery").get(),
2584 NS_ARRAY_LENGTH(formatStrings
),
2585 getter_Copies(message
));
2589 PRInt32 buttonPressed
= 1; // If the user exits by clicking the close box, assume No (button 1)
2590 rv
= prompter
->ConfirmEx(title
.get(), message
.get(),
2591 (nsIPrompt::BUTTON_DELAY_ENABLE
) +
2592 (nsIPrompt::BUTTON_POS_1_DEFAULT
) +
2593 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_0
) +
2594 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_1
),
2595 yesStr
.get(), noStr
.get(), nsnull
, check
.get(), checkValue
, &buttonPressed
);
2598 *checkValue
= PR_FALSE
;
2599 return (buttonPressed
== 0);
2603 nsScriptSecurityManager::RequestCapability(nsIPrincipal
* aPrincipal
,
2604 const char *capability
, PRInt16
* canEnable
)
2606 if (NS_FAILED(aPrincipal
->CanEnableCapability(capability
, canEnable
)))
2607 return NS_ERROR_FAILURE
;
2608 if (*canEnable
== nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2610 // Prompt user for permission to enable capability.
2611 JSContext
* cx
= GetCurrentJSContext();
2613 if (CheckConfirmDialog(cx
, aPrincipal
, capability
, &remember
))
2614 *canEnable
= nsIPrincipal::ENABLE_GRANTED
;
2616 *canEnable
= nsIPrincipal::ENABLE_DENIED
;
2619 //-- Save principal to prefs and to mPrincipals
2620 if (NS_FAILED(aPrincipal
->SetCanEnableCapability(capability
, *canEnable
)))
2621 return NS_ERROR_FAILURE
;
2622 if (NS_FAILED(SavePrincipal(aPrincipal
)))
2623 return NS_ERROR_FAILURE
;
2630 nsScriptSecurityManager::EnableCapability(const char *capability
)
2632 JSContext
*cx
= GetCurrentJSContext();
2635 //-- Error checks for capability string length (200)
2636 if(PL_strlen(capability
)>200)
2638 static const char msg
[] = "Capability name too long";
2639 SetPendingException(cx
, msg
);
2640 return NS_ERROR_FAILURE
;
2643 //-- Check capability string for valid characters
2645 // Logically we might have wanted this in nsPrincipal, but performance
2646 // worries dictate it can't go in IsCapabilityEnabled() and we may have
2647 // to show the capability on a dialog before we call the principal's
2648 // EnableCapability().
2650 // We don't need to validate the capability string on the other APIs
2651 // available to web content. Without the ability to enable junk then
2652 // isPrivilegeEnabled, disablePrivilege, and revertPrivilege all do
2653 // the right thing (effectively nothing) when passed unallowed chars.
2654 for (const char *ch
= capability
; *ch
; ++ch
)
2656 if (!NS_IS_ALPHA(*ch
) && *ch
!= ' ' && !NS_IS_DIGIT(*ch
)
2657 && *ch
!= '_' && *ch
!= '-' && *ch
!= '.')
2659 static const char msg
[] = "Invalid character in capability name";
2660 SetPendingException(cx
, msg
);
2661 return NS_ERROR_FAILURE
;
2666 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2670 return NS_ERROR_NOT_AVAILABLE
;
2672 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2674 if (NS_FAILED(principal
->IsCapabilityEnabled(capability
, annotation
,
2676 return NS_ERROR_FAILURE
;
2681 if (NS_FAILED(RequestCapability(principal
, capability
, &canEnable
)))
2682 return NS_ERROR_FAILURE
;
2684 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
)
2689 principal
->GetHasCertificate(&hasCert
);
2691 rv
= principal
->GetPrettyName(val
);
2693 rv
= GetPrincipalDomainOrigin(principal
, val
);
2698 NS_ConvertUTF8toUTF16
location(val
);
2699 NS_ConvertUTF8toUTF16
cap(capability
);
2700 const PRUnichar
*formatStrings
[] = { location
.get(), cap
.get() };
2702 nsXPIDLString message
;
2703 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityDenied").get(),
2705 NS_ARRAY_LENGTH(formatStrings
),
2706 getter_Copies(message
));
2710 SetPendingException(cx
, message
.get());
2712 return NS_ERROR_FAILURE
; // XXX better error code?
2714 if (NS_FAILED(principal
->EnableCapability(capability
, &annotation
)))
2715 return NS_ERROR_FAILURE
;
2716 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2721 nsScriptSecurityManager::RevertCapability(const char *capability
)
2723 JSContext
*cx
= GetCurrentJSContext();
2726 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2730 return NS_ERROR_NOT_AVAILABLE
;
2731 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2732 principal
->RevertCapability(capability
, &annotation
);
2733 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2738 nsScriptSecurityManager::DisableCapability(const char *capability
)
2740 JSContext
*cx
= GetCurrentJSContext();
2743 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2747 return NS_ERROR_NOT_AVAILABLE
;
2748 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2749 principal
->DisableCapability(capability
, &annotation
);
2750 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2754 //////////////// Master Certificate Functions ///////////////////////////////////////
2756 nsScriptSecurityManager::SetCanEnableCapability(const nsACString
& certFingerprint
,
2757 const char* capability
,
2760 NS_ENSURE_ARG(!certFingerprint
.IsEmpty());
2763 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv
);
2767 //-- Get the system certificate
2768 if (!mSystemCertificate
)
2770 nsCOMPtr
<nsIFile
> systemCertFile
;
2771 nsCOMPtr
<nsIProperties
> directoryService
=
2772 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
2773 if (!directoryService
) return NS_ERROR_FAILURE
;
2774 rv
= directoryService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
, NS_GET_IID(nsIFile
),
2775 getter_AddRefs(systemCertFile
));
2776 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2777 systemCertFile
->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
2778 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2779 nsCOMPtr
<nsIZipReader
> systemCertZip
= do_CreateInstance(kZipReaderCID
, &rv
);
2780 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2781 rv
= systemCertZip
->Open(systemCertFile
);
2782 if (NS_SUCCEEDED(rv
))
2784 nsCOMPtr
<nsIJAR
> systemCertJar(do_QueryInterface(systemCertZip
, &rv
));
2785 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2786 rv
= systemCertJar
->GetCertificatePrincipal(nsnull
,
2787 getter_AddRefs(mSystemCertificate
));
2788 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2792 //-- Make sure the caller's principal is the system certificate
2793 PRBool isEqual
= PR_FALSE
;
2794 if (mSystemCertificate
)
2796 rv
= mSystemCertificate
->Equals(subjectPrincipal
, &isEqual
);
2797 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2801 JSContext
* cx
= GetCurrentJSContext();
2802 if (!cx
) return NS_ERROR_FAILURE
;
2803 static const char msg1
[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate";
2804 static const char msg2
[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established";
2805 SetPendingException(cx
, mSystemCertificate
? msg1
: msg2
);
2806 return NS_ERROR_FAILURE
;
2809 //-- Get the target principal
2810 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
2811 rv
= DoGetCertificatePrincipal(certFingerprint
, EmptyCString(),
2812 EmptyCString(), nsnull
,
2814 getter_AddRefs(objectPrincipal
));
2815 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2816 rv
= objectPrincipal
->SetCanEnableCapability(capability
, canEnable
);
2817 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2818 return SavePrincipal(objectPrincipal
);
2821 ////////////////////////////////////////////////
2822 // Methods implementing nsIXPCSecurityManager //
2823 ////////////////////////////////////////////////
2826 nsScriptSecurityManager::CanCreateWrapper(JSContext
*cx
,
2829 nsIClassInfo
*aClassInfo
,
2832 #ifdef DEBUG_CAPS_CanCreateWrapper
2833 char* iidStr
= aIID
.ToString();
2834 printf("### CanCreateWrapper(%s) ", iidStr
);
2835 nsCRT::free(iidStr
);
2837 // XXX Special case for nsIXPCException ?
2838 ClassInfoData objClassInfo
= ClassInfoData(aClassInfo
, nsnull
);
2839 if (objClassInfo
.IsDOMClass())
2841 #ifdef DEBUG_CAPS_CanCreateWrapper
2842 printf("DOM class - GRANTED.\n");
2847 //--See if the object advertises a non-default level of access
2848 // using nsISecurityCheckedComponent
2849 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
2850 do_QueryInterface(aObj
);
2852 nsXPIDLCString objectSecurityLevel
;
2853 if (checkedComponent
)
2854 checkedComponent
->CanCreateWrapper((nsIID
*)&aIID
, getter_Copies(objectSecurityLevel
));
2856 nsresult rv
= CheckXPCPermissions(aObj
, objectSecurityLevel
);
2859 //-- Access denied, report an error
2860 NS_ConvertUTF8toUTF16
strName("CreateWrapperDenied");
2861 nsCAutoString origin
;
2863 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv2
);
2864 if (NS_SUCCEEDED(rv2
) && subjectPrincipal
) {
2865 GetPrincipalDomainOrigin(subjectPrincipal
, origin
);
2867 NS_ConvertUTF8toUTF16
originUnicode(origin
);
2868 NS_ConvertUTF8toUTF16
className(objClassInfo
.GetName());
2869 const PRUnichar
* formatStrings
[] = {
2873 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
2874 if (originUnicode
.IsEmpty()) {
2877 strName
.AppendLiteral("ForOrigin");
2879 nsXPIDLString errorMsg
;
2880 // We need to keep our existing failure rv and not override it
2881 // with a likely success code from the following string bundle
2882 // call in order to throw the correct security exception later.
2883 rv2
= sStrBundle
->FormatStringFromName(strName
.get(),
2886 getter_Copies(errorMsg
));
2887 NS_ENSURE_SUCCESS(rv2
, rv2
);
2889 SetPendingException(cx
, errorMsg
.get());
2891 #ifdef DEBUG_CAPS_CanCreateWrapper
2892 printf("DENIED.\n");
2896 printf("GRANTED.\n");
2903 #ifdef XPC_IDISPATCH_SUPPORT
2905 nsScriptSecurityManager::CheckComponentPermissions(JSContext
*cx
,
2909 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
2913 // Reformat the CID string so it's suitable for prefs
2914 nsXPIDLCString cidTemp
;
2915 cidTemp
.Adopt(aCID
.ToString());
2916 nsCAutoString
cid(NS_LITERAL_CSTRING("CID") +
2917 Substring(cidTemp
, 1, cidTemp
.Length() - 2));
2920 #ifdef DEBUG_CAPS_CheckComponentPermissions
2921 printf("### CheckComponentPermissions(ClassID.%s) ",cid
.get());
2924 // Look up the policy for this class.
2925 // while this isn't a property we'll treat it as such, using ACCESS_CALL_METHOD
2926 JSAutoRequest
ar(cx
);
2927 jsval cidVal
= STRING_TO_JSVAL(::JS_InternString(cx
, cid
.get()));
2929 ClassInfoData
nameData(nsnull
, "ClassID");
2930 SecurityLevel securityLevel
;
2931 rv
= LookupPolicy(subjectPrincipal
, nameData
, cidVal
,
2932 nsIXPCSecurityManager::ACCESS_CALL_METHOD
,
2933 nsnull
, &securityLevel
);
2937 // If there's no policy stored, use the "security.classID.allowByDefault" pref
2938 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
2939 securityLevel
.level
= mXPCDefaultGrantAll
? SCRIPT_SECURITY_ALL_ACCESS
:
2940 SCRIPT_SECURITY_NO_ACCESS
;
2942 if (securityLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
2944 #ifdef DEBUG_CAPS_CheckComponentPermissions
2945 printf(" GRANTED.\n");
2950 #ifdef DEBUG_CAPS_CheckComponentPermissions
2951 printf(" DENIED.\n");
2953 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
2958 nsScriptSecurityManager::CanCreateInstance(JSContext
*cx
,
2961 #ifdef DEBUG_CAPS_CanCreateInstance
2962 char* cidStr
= aCID
.ToString();
2963 printf("### CanCreateInstance(%s) ", cidStr
);
2964 nsCRT::free(cidStr
);
2967 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
);
2969 #ifdef XPC_IDISPATCH_SUPPORT
2971 rv
= CheckComponentPermissions(cx
, aCID
);
2976 //-- Access denied, report an error
2977 nsCAutoString
errorMsg("Permission denied to create instance of class. CID=");
2978 char cidStr
[NSID_LENGTH
];
2979 aCID
.ToProvidedString(cidStr
);
2980 errorMsg
.Append(cidStr
);
2981 SetPendingException(cx
, errorMsg
.get());
2983 #ifdef DEBUG_CAPS_CanCreateInstance
2988 printf("GRANTED\n");
2995 nsScriptSecurityManager::CanGetService(JSContext
*cx
,
2998 #ifdef DEBUG_CAPS_CanGetService
2999 char* cidStr
= aCID
.ToString();
3000 printf("### CanGetService(%s) ", cidStr
);
3001 nsCRT::free(cidStr
);
3004 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
);
3007 //-- Access denied, report an error
3008 nsCAutoString
errorMsg("Permission denied to get service. CID=");
3009 char cidStr
[NSID_LENGTH
];
3010 aCID
.ToProvidedString(cidStr
);
3011 errorMsg
.Append(cidStr
);
3012 SetPendingException(cx
, errorMsg
.get());
3014 #ifdef DEBUG_CAPS_CanGetService
3019 printf("GRANTED\n");
3028 nsScriptSecurityManager::CanAccess(PRUint32 aAction
,
3029 nsAXPCNativeCallContext
* aCallContext
,
3031 JSObject
* aJSObject
,
3033 nsIClassInfo
* aClassInfo
,
3034 jsval aPropertyName
,
3037 return CheckPropertyAccessImpl(aAction
, aCallContext
, cx
,
3038 aJSObject
, aObj
, nsnull
, aClassInfo
,
3039 nsnull
, aPropertyName
, aPolicy
);
3043 nsScriptSecurityManager::CheckXPCPermissions(nsISupports
* aObj
,
3044 const char* aObjectSecurityLevel
)
3046 //-- Check for the all-powerful UniversalXPConnect privilege
3047 PRBool ok
= PR_FALSE
;
3048 if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalXPConnect", &ok
)) && ok
)
3051 //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
3052 if (aObjectSecurityLevel
)
3054 if (PL_strcasecmp(aObjectSecurityLevel
, "allAccess") == 0)
3056 else if (PL_strcasecmp(aObjectSecurityLevel
, "noAccess") != 0)
3058 PRBool canAccess
= PR_FALSE
;
3059 if (NS_SUCCEEDED(IsCapabilityEnabled(aObjectSecurityLevel
, &canAccess
)) &&
3065 //-- If user allows scripting of plugins by untrusted scripts,
3066 // and the target object is a plugin, allow the access.
3070 nsCOMPtr
<nsIPluginInstance
> plugin(do_QueryInterface(aObj
, &rv
));
3071 if (NS_SUCCEEDED(rv
))
3073 static PRBool prefSet
= PR_FALSE
;
3074 static PRBool allowPluginAccess
= PR_FALSE
;
3077 rv
= mSecurityPref
->SecurityGetBoolPref("security.xpconnect.plugin.unrestricted",
3078 &allowPluginAccess
);
3081 if (allowPluginAccess
)
3086 //-- Access tests failed
3087 return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED
;
3090 //////////////////////////////////////////////
3091 // Method implementing nsIPrefSecurityCheck //
3092 //////////////////////////////////////////////
3095 nsScriptSecurityManager::CanAccessSecurityPreferences(PRBool
* _retval
)
3097 return IsCapabilityEnabled("CapabilityPreferencesAccess", _retval
);
3100 /////////////////////////////////////////////
3101 // Method implementing nsIChannelEventSink //
3102 /////////////////////////////////////////////
3104 nsScriptSecurityManager::OnChannelRedirect(nsIChannel
* oldChannel
,
3105 nsIChannel
* newChannel
,
3106 PRUint32 redirFlags
)
3108 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
3109 GetChannelPrincipal(oldChannel
, getter_AddRefs(oldPrincipal
));
3111 nsCOMPtr
<nsIURI
> newURI
;
3112 newChannel
->GetURI(getter_AddRefs(newURI
));
3114 NS_ENSURE_STATE(oldPrincipal
&& newURI
);
3116 const PRUint32 flags
=
3117 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
3118 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
3119 return CheckLoadURIWithPrincipal(oldPrincipal
, newURI
, flags
);
3123 /////////////////////////////////////
3124 // Method implementing nsIObserver //
3125 /////////////////////////////////////
3126 static const char sPrincipalPrefix
[] = "capability.principal";
3127 static const char sPolicyPrefix
[] = "capability.policy.";
3130 nsScriptSecurityManager::Observe(nsISupports
* aObject
, const char* aTopic
,
3131 const PRUnichar
* aMessage
)
3133 nsresult rv
= NS_OK
;
3134 NS_ConvertUTF16toUTF8
messageStr(aMessage
);
3135 const char *message
= messageStr
.get();
3137 static const char jsPrefix
[] = "javascript.";
3138 static const char securityPrefix
[] = "security.";
3139 if ((PL_strncmp(message
, jsPrefix
, sizeof(jsPrefix
)-1) == 0) ||
3140 (PL_strncmp(message
, securityPrefix
, sizeof(securityPrefix
)-1) == 0) )
3142 ScriptSecurityPrefChanged();
3144 else if (PL_strncmp(message
, sPolicyPrefix
, sizeof(sPolicyPrefix
)-1) == 0)
3146 // This will force re-initialization of the pref table
3147 mPolicyPrefsChanged
= PR_TRUE
;
3149 else if ((PL_strncmp(message
, sPrincipalPrefix
, sizeof(sPrincipalPrefix
)-1) == 0) &&
3152 static const char id
[] = "id";
3153 char* lastDot
= PL_strrchr(message
, '.');
3154 //-- This check makes sure the string copy below doesn't overwrite its bounds
3155 if(PL_strlen(lastDot
) >= sizeof(id
))
3157 PL_strcpy(lastDot
+ 1, id
);
3158 const char** idPrefArray
= (const char**)&message
;
3159 rv
= InitPrincipals(1, idPrefArray
, mSecurityPref
);
3165 /////////////////////////////////////////////
3166 // Constructor, Destructor, Initialization //
3167 /////////////////////////////////////////////
3168 nsScriptSecurityManager::nsScriptSecurityManager(void)
3169 : mOriginToPolicyMap(nsnull
),
3170 mDefaultPolicy(nsnull
),
3171 mCapabilities(nsnull
),
3172 mIsJavaScriptEnabled(PR_FALSE
),
3173 mIsMailJavaScriptEnabled(PR_FALSE
),
3174 mIsWritingPrefs(PR_FALSE
),
3175 mPolicyPrefsChanged(PR_TRUE
)
3176 #ifdef XPC_IDISPATCH_SUPPORT
3177 , mXPCDefaultGrantAll(PR_FALSE
)
3180 NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure.");
3181 mPrincipals
.Init(31);
3185 nsresult
nsScriptSecurityManager::Init()
3187 JSContext
* cx
= GetSafeJSContext();
3188 if (!cx
) return NS_ERROR_FAILURE
; // this can happen of xpt loading fails
3190 ::JS_BeginRequest(cx
);
3191 if (sEnabledID
== JSVAL_VOID
)
3192 sEnabledID
= STRING_TO_JSVAL(::JS_InternString(cx
, "enabled"));
3193 ::JS_EndRequest(cx
);
3195 nsresult rv
= InitPrefs();
3196 NS_ENSURE_SUCCESS(rv
, rv
);
3198 rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
3199 NS_ENSURE_SUCCESS(rv
, rv
);
3201 rv
= CallGetService(nsIXPConnect::GetCID(), &sXPConnect
);
3202 NS_ENSURE_SUCCESS(rv
, rv
);
3204 nsCOMPtr
<nsIStringBundleService
> bundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
3205 NS_ENSURE_SUCCESS(rv
, rv
);
3207 rv
= bundleService
->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle
);
3208 NS_ENSURE_SUCCESS(rv
, rv
);
3210 // Create our system principal singleton
3211 nsRefPtr
<nsSystemPrincipal
> system
= new nsSystemPrincipal();
3212 NS_ENSURE_TRUE(system
, NS_ERROR_OUT_OF_MEMORY
);
3214 rv
= system
->Init();
3215 NS_ENSURE_SUCCESS(rv
, rv
);
3217 mSystemPrincipal
= system
;
3219 //-- Register security check callback in the JS engine
3220 // Currently this is used to control access to function.caller
3221 nsCOMPtr
<nsIJSRuntimeService
> runtimeService
=
3222 do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv
);
3223 NS_ENSURE_SUCCESS(rv
, rv
);
3225 rv
= runtimeService
->GetRuntime(&sRuntime
);
3226 NS_ENSURE_SUCCESS(rv
, rv
);
3228 static JSSecurityCallbacks securityCallbacks
= {
3235 JSSecurityCallbacks
*oldcallbacks
=
3237 JS_SetRuntimeSecurityCallbacks(sRuntime
, &securityCallbacks
);
3238 NS_ASSERTION(!oldcallbacks
, "Someone else set security callbacks!");
3240 sXPConnect
->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeJSClass
,
3241 &sXPCWrappedNativeGetObjOps1
,
3242 &sXPCWrappedNativeGetObjOps2
);
3246 static nsScriptSecurityManager
*gScriptSecMan
= nsnull
;
3248 jsval
nsScriptSecurityManager::sEnabledID
= JSVAL_VOID
;
3250 nsScriptSecurityManager::~nsScriptSecurityManager(void)
3252 delete mOriginToPolicyMap
;
3254 mDefaultPolicy
->Drop();
3255 delete mCapabilities
;
3256 gScriptSecMan
= nsnull
;
3260 nsScriptSecurityManager::Shutdown()
3263 JS_SetRuntimeSecurityCallbacks(sRuntime
, NULL
);
3266 sEnabledID
= JSVAL_VOID
;
3268 NS_IF_RELEASE(sIOService
);
3269 NS_IF_RELEASE(sXPConnect
);
3270 NS_IF_RELEASE(sStrBundle
);
3273 nsScriptSecurityManager
*
3274 nsScriptSecurityManager::GetScriptSecurityManager()
3278 nsScriptSecurityManager
* ssManager
= new nsScriptSecurityManager();
3282 rv
= ssManager
->Init();
3283 NS_ASSERTION(NS_SUCCEEDED(rv
), "Failed to initialize nsScriptSecurityManager");
3284 if (NS_FAILED(rv
)) {
3289 rv
= nsJSPrincipals::Startup();
3290 if (NS_FAILED(rv
)) {
3291 NS_WARNING("can't initialize JS engine security protocol glue!");
3296 rv
= sXPConnect
->SetDefaultSecurityManager(ssManager
,
3297 nsIXPCSecurityManager::HOOK_ALL
);
3298 if (NS_FAILED(rv
)) {
3299 NS_WARNING("Failed to install xpconnect security manager!");
3304 gScriptSecMan
= ssManager
;
3306 return gScriptSecMan
;
3309 // Currently this nsGenericFactory constructor is used only from FastLoad
3310 // (XPCOM object deserialization) code, when "creating" the system principal
3313 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
3315 nsIPrincipal
*sysprin
= nsnull
;
3317 NS_ADDREF(sysprin
= gScriptSecMan
->mSystemPrincipal
);
3318 return static_cast<nsSystemPrincipal
*>(sysprin
);
3322 nsScriptSecurityManager::InitPolicies()
3324 // Clear any policies cached on XPConnect wrappers
3325 NS_ENSURE_STATE(sXPConnect
);
3326 nsresult rv
= sXPConnect
->ClearAllWrappedNativeSecurityPolicies();
3327 if (NS_FAILED(rv
)) return rv
;
3329 //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
3330 //-- whose dtor decrements refcount of stored DomainPolicy object
3331 delete mOriginToPolicyMap
;
3333 //-- Marks all the survivor DomainPolicy objects (those cached
3334 //-- by nsPrincipal objects) as invalid: they will be released
3335 //-- on first nsPrincipal::GetSecurityPolicy() attempt.
3336 DomainPolicy::InvalidateAll();
3338 //-- Release old default policy
3339 if(mDefaultPolicy
) {
3340 mDefaultPolicy
->Drop();
3341 mDefaultPolicy
= nsnull
;
3344 //-- Initialize a new mOriginToPolicyMap
3345 mOriginToPolicyMap
=
3346 new nsObjectHashtable(nsnull
, nsnull
, DeleteDomainEntry
, nsnull
);
3347 if (!mOriginToPolicyMap
)
3348 return NS_ERROR_OUT_OF_MEMORY
;
3350 //-- Create, refcount and initialize a new default policy
3351 mDefaultPolicy
= new DomainPolicy();
3352 if (!mDefaultPolicy
)
3353 return NS_ERROR_OUT_OF_MEMORY
;
3355 mDefaultPolicy
->Hold();
3356 if (!mDefaultPolicy
->Init())
3357 return NS_ERROR_UNEXPECTED
;
3359 //-- Initialize the table of security levels
3363 new nsObjectHashtable(nsnull
, nsnull
, DeleteCapability
, nsnull
);
3365 return NS_ERROR_OUT_OF_MEMORY
;
3368 // Get a JS context - we need it to create internalized strings later.
3369 JSContext
* cx
= GetSafeJSContext();
3370 NS_ASSERTION(cx
, "failed to get JS context");
3371 rv
= InitDomainPolicy(cx
, "default", mDefaultPolicy
);
3372 NS_ENSURE_SUCCESS(rv
, rv
);
3374 nsXPIDLCString policyNames
;
3375 rv
= mSecurityPref
->SecurityGetCharPref("capability.policy.policynames",
3376 getter_Copies(policyNames
));
3378 nsXPIDLCString defaultPolicyNames
;
3379 rv
= mSecurityPref
->SecurityGetCharPref("capability.policy.default_policynames",
3380 getter_Copies(defaultPolicyNames
));
3381 policyNames
+= NS_LITERAL_CSTRING(" ") + defaultPolicyNames
;
3383 //-- Initialize domain policies
3384 char* policyCurrent
= policyNames
.BeginWriting();
3385 PRBool morePolicies
= PR_TRUE
;
3386 while (morePolicies
)
3388 while(*policyCurrent
== ' ' || *policyCurrent
== ',')
3390 if (*policyCurrent
== '\0')
3392 char* nameBegin
= policyCurrent
;
3394 while(*policyCurrent
!= '\0' && *policyCurrent
!= ' ' && *policyCurrent
!= ',')
3397 morePolicies
= (*policyCurrent
!= '\0');
3398 *policyCurrent
= '\0';
3401 nsCAutoString
sitesPrefName(
3402 NS_LITERAL_CSTRING(sPolicyPrefix
) +
3403 nsDependentCString(nameBegin
) +
3404 NS_LITERAL_CSTRING(".sites"));
3405 nsXPIDLCString domainList
;
3406 rv
= mSecurityPref
->SecurityGetCharPref(sitesPrefName
.get(),
3407 getter_Copies(domainList
));
3411 DomainPolicy
* domainPolicy
= new DomainPolicy();
3413 return NS_ERROR_OUT_OF_MEMORY
;
3415 if (!domainPolicy
->Init())
3417 delete domainPolicy
;
3418 return NS_ERROR_UNEXPECTED
;
3420 domainPolicy
->Hold();
3421 //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
3422 char* domainStart
= domainList
.BeginWriting();
3423 char* domainCurrent
= domainStart
;
3424 char* lastDot
= nsnull
;
3425 char* nextToLastDot
= nsnull
;
3426 PRBool moreDomains
= PR_TRUE
;
3429 if (*domainCurrent
== ' ' || *domainCurrent
== '\0')
3431 moreDomains
= (*domainCurrent
!= '\0');
3432 *domainCurrent
= '\0';
3433 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : domainStart
);
3434 DomainEntry
*newEntry
= new DomainEntry(domainStart
, domainPolicy
);
3437 domainPolicy
->Drop();
3438 return NS_ERROR_OUT_OF_MEMORY
;
3441 newEntry
->mPolicyName_DEBUG
= nameBegin
;
3443 DomainEntry
*existingEntry
= (DomainEntry
*)
3444 mOriginToPolicyMap
->Get(&key
);
3446 mOriginToPolicyMap
->Put(&key
, newEntry
);
3449 if (existingEntry
->Matches(domainStart
))
3451 newEntry
->mNext
= existingEntry
;
3452 mOriginToPolicyMap
->Put(&key
, newEntry
);
3456 while (existingEntry
->mNext
)
3458 if (existingEntry
->mNext
->Matches(domainStart
))
3460 newEntry
->mNext
= existingEntry
->mNext
;
3461 existingEntry
->mNext
= newEntry
;
3464 existingEntry
= existingEntry
->mNext
;
3466 if (!existingEntry
->mNext
)
3467 existingEntry
->mNext
= newEntry
;
3470 domainStart
= domainCurrent
+ 1;
3471 lastDot
= nextToLastDot
= nsnull
;
3473 else if (*domainCurrent
== '.')
3475 nextToLastDot
= lastDot
;
3476 lastDot
= domainCurrent
;
3481 rv
= InitDomainPolicy(cx
, nameBegin
, domainPolicy
);
3482 domainPolicy
->Drop();
3487 // Reset the "dirty" flag
3488 mPolicyPrefsChanged
= PR_FALSE
;
3490 #ifdef DEBUG_CAPS_HACKER
3498 nsScriptSecurityManager::InitDomainPolicy(JSContext
* cx
,
3499 const char* aPolicyName
,
3500 DomainPolicy
* aDomainPolicy
)
3503 nsCAutoString
policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix
) +
3504 nsDependentCString(aPolicyName
) +
3505 NS_LITERAL_CSTRING("."));
3506 PRUint32 prefixLength
= policyPrefix
.Length() - 1; // subtract the '.'
3510 rv
= mPrefBranch
->GetChildList(policyPrefix
.get(),
3511 &prefCount
, &prefNames
);
3512 if (NS_FAILED(rv
)) return rv
;
3516 //-- Populate the policy
3517 PRUint32 currentPref
= 0;
3518 for (; currentPref
< prefCount
; currentPref
++)
3520 // Get the class name
3521 const char* start
= prefNames
[currentPref
] + prefixLength
+ 1;
3522 char* end
= PL_strchr(start
, '.');
3523 if (!end
) // malformed pref, bail on this one
3525 static const char sitesStr
[] = "sites";
3527 // We dealt with "sites" in InitPolicies(), so no need to do
3529 if (PL_strncmp(start
, sitesStr
, sizeof(sitesStr
)-1) == 0)
3532 // Get the pref value
3533 nsXPIDLCString prefValue
;
3534 rv
= mSecurityPref
->SecurityGetCharPref(prefNames
[currentPref
],
3535 getter_Copies(prefValue
));
3536 if (NS_FAILED(rv
) || !prefValue
)
3539 SecurityLevel secLevel
;
3540 if (PL_strcasecmp(prefValue
, "noAccess") == 0)
3541 secLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
3542 else if (PL_strcasecmp(prefValue
, "allAccess") == 0)
3543 secLevel
.level
= SCRIPT_SECURITY_ALL_ACCESS
;
3544 else if (PL_strcasecmp(prefValue
, "sameOrigin") == 0)
3545 secLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
3547 { //-- pref value is the name of a capability
3548 nsCStringKey
secLevelKey(prefValue
);
3549 secLevel
.capability
=
3550 reinterpret_cast<char*>(mCapabilities
->Get(&secLevelKey
));
3551 if (!secLevel
.capability
)
3553 secLevel
.capability
= NS_strdup(prefValue
);
3554 if (!secLevel
.capability
)
3556 mCapabilities
->Put(&secLevelKey
,
3557 secLevel
.capability
);
3562 // Find or store this class in the classes table
3563 ClassPolicy
* cpolicy
=
3564 static_cast<ClassPolicy
*>
3565 (PL_DHashTableOperate(aDomainPolicy
, start
,
3570 // If this is the wildcard class (class '*'), save it in mWildcardPolicy
3571 // (we leave it stored in the hashtable too to take care of the cleanup)
3572 if ((*start
== '*') && (end
== start
+ 1)) {
3573 aDomainPolicy
->mWildcardPolicy
= cpolicy
;
3575 // Make sure that cpolicy knows about aDomainPolicy so it can reset
3576 // the mWildcardPolicy pointer as needed if it gets moved in the
3578 cpolicy
->mDomainWeAreWildcardFor
= aDomainPolicy
;
3581 // Get the property name
3583 end
= PL_strchr(start
, '.');
3587 JSAutoRequest
ar(cx
);
3589 JSString
* propertyKey
= ::JS_InternString(cx
, start
);
3591 return NS_ERROR_OUT_OF_MEMORY
;
3593 // Store this property in the class policy
3595 reinterpret_cast<const void*>(STRING_TO_JSVAL(propertyKey
));
3596 PropertyPolicy
* ppolicy
=
3597 static_cast<PropertyPolicy
*>
3598 (PL_DHashTableOperate(cpolicy
->mPolicy
, ppkey
,
3603 if (end
) // The pref specifies an access mode
3606 if (PL_strcasecmp(start
, "set") == 0)
3607 ppolicy
->mSet
= secLevel
;
3609 ppolicy
->mGet
= secLevel
;
3613 if (ppolicy
->mGet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3614 ppolicy
->mGet
= secLevel
;
3615 if (ppolicy
->mSet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3616 ppolicy
->mSet
= secLevel
;
3620 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
3621 if (currentPref
< prefCount
) // Loop exited early because of out-of-memory error
3622 return NS_ERROR_OUT_OF_MEMORY
;
3627 // XXXbz We should really just get a prefbranch to handle this...
3629 nsScriptSecurityManager::GetPrincipalPrefNames(const char* prefBase
,
3630 nsCString
& grantedPref
,
3631 nsCString
& deniedPref
,
3632 nsCString
& subjectNamePref
)
3634 char* lastDot
= PL_strrchr(prefBase
, '.');
3635 if (!lastDot
) return NS_ERROR_FAILURE
;
3636 PRInt32 prefLen
= lastDot
- prefBase
+ 1;
3638 grantedPref
.Assign(prefBase
, prefLen
);
3639 deniedPref
.Assign(prefBase
, prefLen
);
3640 subjectNamePref
.Assign(prefBase
, prefLen
);
3642 #define GRANTED "granted"
3643 #define DENIED "denied"
3644 #define SUBJECTNAME "subjectName"
3646 grantedPref
.AppendLiteral(GRANTED
);
3647 if (grantedPref
.Length() != prefLen
+ sizeof(GRANTED
) - 1) {
3648 return NS_ERROR_OUT_OF_MEMORY
;
3651 deniedPref
.AppendLiteral(DENIED
);
3652 if (deniedPref
.Length() != prefLen
+ sizeof(DENIED
) - 1) {
3653 return NS_ERROR_OUT_OF_MEMORY
;
3656 subjectNamePref
.AppendLiteral(SUBJECTNAME
);
3657 if (subjectNamePref
.Length() != prefLen
+ sizeof(SUBJECTNAME
) - 1) {
3658 return NS_ERROR_OUT_OF_MEMORY
;
3669 nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount
, const char** aPrefNames
,
3670 nsISecurityPref
* aSecurityPref
)
3672 /* This is the principal preference syntax:
3673 * capability.principal.[codebase|codebaseTrusted|certificate].<name>.[id|granted|denied]
3675 * user_pref("capability.principal.certificate.p1.id","12:34:AB:CD");
3676 * user_pref("capability.principal.certificate.p1.granted","Capability1 Capability2");
3677 * user_pref("capability.principal.certificate.p1.denied","Capability3");
3680 /* codebaseTrusted means a codebase principal that can enable capabilities even if
3681 * codebase principals are disabled. Don't use trustedCodebase except with unspoofable
3682 * URLs such as HTTPS URLs.
3685 static const char idSuffix
[] = ".id";
3686 for (PRUint32 c
= 0; c
< aPrefCount
; c
++)
3688 PRInt32 prefNameLen
= PL_strlen(aPrefNames
[c
]) -
3689 (NS_ARRAY_LENGTH(idSuffix
) - 1);
3690 if (PL_strcasecmp(aPrefNames
[c
] + prefNameLen
, idSuffix
) != 0)
3694 if (NS_FAILED(mSecurityPref
->SecurityGetCharPref(aPrefNames
[c
], getter_Copies(id
))))
3695 return NS_ERROR_FAILURE
;
3697 nsCAutoString grantedPrefName
;
3698 nsCAutoString deniedPrefName
;
3699 nsCAutoString subjectNamePrefName
;
3700 nsresult rv
= GetPrincipalPrefNames(aPrefNames
[c
],
3703 subjectNamePrefName
);
3704 if (rv
== NS_ERROR_OUT_OF_MEMORY
)
3709 nsXPIDLCString grantedList
;
3710 mSecurityPref
->SecurityGetCharPref(grantedPrefName
.get(),
3711 getter_Copies(grantedList
));
3712 nsXPIDLCString deniedList
;
3713 mSecurityPref
->SecurityGetCharPref(deniedPrefName
.get(),
3714 getter_Copies(deniedList
));
3715 nsXPIDLCString subjectName
;
3716 mSecurityPref
->SecurityGetCharPref(subjectNamePrefName
.get(),
3717 getter_Copies(subjectName
));
3719 //-- Delete prefs if their value is the empty string
3720 if (id
.IsEmpty() || (grantedList
.IsEmpty() && deniedList
.IsEmpty()))
3722 mSecurityPref
->SecurityClearUserPref(aPrefNames
[c
]);
3723 mSecurityPref
->SecurityClearUserPref(grantedPrefName
.get());
3724 mSecurityPref
->SecurityClearUserPref(deniedPrefName
.get());
3725 mSecurityPref
->SecurityClearUserPref(subjectNamePrefName
.get());
3729 //-- Create a principal based on the prefs
3730 static const char certificateName
[] = "capability.principal.certificate";
3731 static const char codebaseName
[] = "capability.principal.codebase";
3732 static const char codebaseTrustedName
[] = "capability.principal.codebaseTrusted";
3734 PRBool isCert
= PR_FALSE
;
3735 PRBool isTrusted
= PR_FALSE
;
3737 if (PL_strncmp(aPrefNames
[c
], certificateName
,
3738 sizeof(certificateName
) - 1) == 0)
3742 else if (PL_strncmp(aPrefNames
[c
], codebaseName
,
3743 sizeof(codebaseName
) - 1) == 0)
3745 isTrusted
= (PL_strncmp(aPrefNames
[c
], codebaseTrustedName
,
3746 sizeof(codebaseTrustedName
) - 1) == 0);
3750 NS_ERROR("Not a codebase or a certificate?!");
3753 nsRefPtr
<nsPrincipal
> newPrincipal
= new nsPrincipal();
3755 return NS_ERROR_OUT_OF_MEMORY
;
3757 rv
= newPrincipal
->InitFromPersistent(aPrefNames
[c
], id
, subjectName
,
3759 grantedList
, deniedList
, nsnull
,
3761 if (NS_SUCCEEDED(rv
))
3762 mPrincipals
.Put(newPrincipal
, newPrincipal
);
3767 const char nsScriptSecurityManager::sJSEnabledPrefName
[] =
3768 "javascript.enabled";
3769 const char nsScriptSecurityManager::sJSMailEnabledPrefName
[] =
3770 "javascript.allow.mailnews";
3771 const char nsScriptSecurityManager::sFileOriginPolicyPrefName
[] =
3772 "security.fileuri.strict_origin_policy";
3773 #ifdef XPC_IDISPATCH_SUPPORT
3774 const char nsScriptSecurityManager::sXPCDefaultGrantAllName
[] =
3775 "security.classID.allowByDefault";
3779 nsScriptSecurityManager::ScriptSecurityPrefChanged()
3782 nsresult rv
= mSecurityPref
->SecurityGetBoolPref(sJSEnabledPrefName
, &temp
);
3783 // JavaScript defaults to enabled in failure cases.
3784 mIsJavaScriptEnabled
= NS_FAILED(rv
) || temp
;
3786 rv
= mSecurityPref
->SecurityGetBoolPref(sJSMailEnabledPrefName
, &temp
);
3787 // JavaScript in Mail defaults to disabled in failure cases.
3788 // disable javascript in mailnews for TB 3.0 beta1
3789 mIsMailJavaScriptEnabled
= PR_FALSE
; // NS_SUCCEEDED(rv) && temp;
3791 rv
= mSecurityPref
->SecurityGetBoolPref(sFileOriginPolicyPrefName
, &temp
);
3792 sStrictFileOriginPolicy
= NS_SUCCEEDED(rv
) && temp
;
3794 #ifdef XPC_IDISPATCH_SUPPORT
3795 rv
= mSecurityPref
->SecurityGetBoolPref(sXPCDefaultGrantAllName
, &temp
);
3796 // Granting XPC Priveleges defaults to disabled in failure cases.
3797 mXPCDefaultGrantAll
= NS_SUCCEEDED(rv
) && temp
;
3802 nsScriptSecurityManager::InitPrefs()
3805 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
3806 NS_ENSURE_SUCCESS(rv
, rv
);
3807 rv
= prefService
->GetBranch(nsnull
, getter_AddRefs(mPrefBranch
));
3808 NS_ENSURE_SUCCESS(rv
, rv
);
3809 nsCOMPtr
<nsIPrefBranch2
> prefBranchInternal(do_QueryInterface(mPrefBranch
, &rv
));
3810 NS_ENSURE_SUCCESS(rv
, rv
);
3811 mSecurityPref
= do_QueryInterface(mPrefBranch
, &rv
);
3812 NS_ENSURE_SUCCESS(rv
, rv
);
3814 // Set the initial value of the "javascript.enabled" prefs
3815 ScriptSecurityPrefChanged();
3816 // set observer callbacks in case the value of the prefs change
3817 prefBranchInternal
->AddObserver(sJSEnabledPrefName
, this, PR_FALSE
);
3818 prefBranchInternal
->AddObserver(sJSMailEnabledPrefName
, this, PR_FALSE
);
3819 prefBranchInternal
->AddObserver(sFileOriginPolicyPrefName
, this, PR_FALSE
);
3820 #ifdef XPC_IDISPATCH_SUPPORT
3821 prefBranchInternal
->AddObserver(sXPCDefaultGrantAllName
, this, PR_FALSE
);
3826 // Set a callback for policy pref changes
3827 prefBranchInternal
->AddObserver(sPolicyPrefix
, this, PR_FALSE
);
3829 //-- Initialize the principals database from prefs
3830 rv
= mPrefBranch
->GetChildList(sPrincipalPrefix
, &prefCount
, &prefNames
);
3831 if (NS_SUCCEEDED(rv
) && prefCount
> 0)
3833 rv
= InitPrincipals(prefCount
, (const char**)prefNames
, mSecurityPref
);
3834 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
3835 NS_ENSURE_SUCCESS(rv
, rv
);
3837 //-- Set a callback for principal changes
3838 prefBranchInternal
->AddObserver(sPrincipalPrefix
, this, PR_FALSE
);
3843 ///////////////////////////////////////////////////////////////////////////////
3844 // The following code prints the contents of the policy DB to the console.
3845 #ifdef DEBUG_CAPS_HACKER
3847 //typedef PLDHashOperator
3848 //(* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
3849 // PRUint32 number, void *arg);
3850 PR_STATIC_CALLBACK(PLDHashOperator
)
3851 PrintPropertyPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
3852 PRUint32 number
, void *arg
)
3854 PropertyPolicy
* pp
= (PropertyPolicy
*)entry
;
3855 nsCAutoString
prop(" ");
3856 JSContext
* cx
= (JSContext
*)arg
;
3857 prop
.AppendInt((PRUint32
)pp
->key
);
3859 prop
.AppendWithConversion((PRUnichar
*)JSValIDToString(cx
, pp
->key
));
3861 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mGet
))
3862 prop
.AppendInt(pp
->mGet
.level
);
3864 prop
+= pp
->mGet
.capability
;
3867 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mSet
))
3868 prop
.AppendInt(pp
->mSet
.level
);
3870 prop
+= pp
->mSet
.capability
;
3872 printf("%s.\n", prop
.get());
3873 return PL_DHASH_NEXT
;
3876 PR_STATIC_CALLBACK(PLDHashOperator
)
3877 PrintClassPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
3878 PRUint32 number
, void *arg
)
3880 ClassPolicy
* cp
= (ClassPolicy
*)entry
;
3881 printf(" %s\n", cp
->key
);
3883 PL_DHashTableEnumerate(cp
->mPolicy
, PrintPropertyPolicy
, arg
);
3884 return PL_DHASH_NEXT
;
3888 // (*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
3889 PR_STATIC_CALLBACK(PRBool
)
3890 PrintDomainPolicy(nsHashKey
*aKey
, void *aData
, void* aClosure
)
3892 DomainEntry
* de
= (DomainEntry
*)aData
;
3893 printf("----------------------------\n");
3894 printf("Domain: %s Policy Name: %s.\n", de
->mOrigin
.get(),
3895 de
->mPolicyName_DEBUG
.get());
3896 PL_DHashTableEnumerate(de
->mDomainPolicy
, PrintClassPolicy
, aClosure
);
3900 PR_STATIC_CALLBACK(PRBool
)
3901 PrintCapability(nsHashKey
*aKey
, void *aData
, void* aClosure
)
3903 char* cap
= (char*)aData
;
3904 printf(" %s.\n", cap
);
3909 nsScriptSecurityManager::PrintPolicyDB()
3911 printf("############## Security Policies ###############\n");
3912 if(mOriginToPolicyMap
)
3914 JSContext
* cx
= GetCurrentJSContext();
3916 cx
= GetSafeJSContext();
3917 printf("----------------------------\n");
3918 printf("Domain: Default.\n");
3919 PL_DHashTableEnumerate(mDefaultPolicy
, PrintClassPolicy
, (void*)cx
);
3920 mOriginToPolicyMap
->Enumerate(PrintDomainPolicy
, (void*)cx
);
3922 printf("############ End Security Policies #############\n\n");
3923 printf("############## Capabilities ###############\n");
3924 mCapabilities
->Enumerate(PrintCapability
);
3925 printf("############## End Capabilities ###############\n");