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 "xpcprivate.h"
44 #include "nsScriptSecurityManager.h"
45 #include "nsIServiceManager.h"
46 #include "nsIScriptObjectPrincipal.h"
47 #include "nsIScriptContext.h"
49 #include "nsINestedURI.h"
51 #include "nsJSPrincipals.h"
52 #include "nsSystemPrincipal.h"
53 #include "nsPrincipal.h"
54 #include "nsNullPrincipal.h"
55 #include "nsXPIDLString.h"
57 #include "nsCRTGlue.h"
58 #include "nsIJSContextStack.h"
59 #include "nsDOMError.h"
65 #include "nsIXPConnect.h"
66 #include "nsIXPCSecurityManager.h"
67 #include "nsTextFormatter.h"
68 #include "nsIStringBundle.h"
69 #include "nsNetUtil.h"
70 #include "nsIProperties.h"
71 #include "nsDirectoryServiceDefs.h"
73 #include "nsIFileURL.h"
74 #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"
96 #include "nsPrintfCString.h"
97 #include "nsIContentSecurityPolicy.h"
98 #include "nsIAsyncVerifyRedirectCallback.h"
100 static NS_DEFINE_CID(kZipReaderCID
, NS_ZIPREADER_CID
);
102 nsIIOService
*nsScriptSecurityManager::sIOService
= nsnull
;
103 nsIXPConnect
*nsScriptSecurityManager::sXPConnect
= nsnull
;
104 nsIThreadJSContextStack
*nsScriptSecurityManager::sJSContextStack
= nsnull
;
105 nsIStringBundle
*nsScriptSecurityManager::sStrBundle
= nsnull
;
106 JSRuntime
*nsScriptSecurityManager::sRuntime
= 0;
107 PRBool
nsScriptSecurityManager::sStrictFileOriginPolicy
= PR_TRUE
;
109 ///////////////////////////
110 // Convenience Functions //
111 ///////////////////////////
112 // Result of this function should not be freed.
113 static inline const PRUnichar
*
114 IDToString(JSContext
*cx
, jsid id
)
116 if (JSID_IS_STRING(id
))
117 return JS_GetInternedStringChars(JSID_TO_STRING(id
));
119 JSAutoRequest
ar(cx
);
121 if (!JS_IdToValue(cx
, id
, &idval
))
123 JSString
*str
= JS_ValueToString(cx
, idval
);
126 return JS_GetStringCharsZ(cx
, str
);
129 class nsAutoInPrincipalDomainOriginSetter
{
131 nsAutoInPrincipalDomainOriginSetter() {
132 ++sInPrincipalDomainOrigin
;
134 ~nsAutoInPrincipalDomainOriginSetter() {
135 --sInPrincipalDomainOrigin
;
137 static PRUint32 sInPrincipalDomainOrigin
;
139 PRUint32
nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
;
143 GetOriginFromURI(nsIURI
* aURI
, nsACString
& aOrigin
)
145 if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
> 1) {
146 // Allow a single recursive call to GetPrincipalDomainOrigin, since that
147 // might be happening on a different principal from the first call. But
148 // after that, cut off the recursion; it just indicates that something
149 // we're doing in this method causes us to reenter a security check here.
150 return NS_ERROR_NOT_AVAILABLE
;
153 nsAutoInPrincipalDomainOriginSetter autoSetter
;
155 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
156 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
158 nsCAutoString hostPort
;
160 nsresult rv
= uri
->GetHostPort(hostPort
);
161 if (NS_SUCCEEDED(rv
)) {
162 nsCAutoString scheme
;
163 rv
= uri
->GetScheme(scheme
);
164 NS_ENSURE_SUCCESS(rv
, rv
);
165 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + hostPort
;
168 // Some URIs (e.g., nsSimpleURI) don't support host. Just
169 // get the full spec.
170 rv
= uri
->GetSpec(aOrigin
);
171 NS_ENSURE_SUCCESS(rv
, rv
);
179 GetPrincipalDomainOrigin(nsIPrincipal
* aPrincipal
,
183 nsCOMPtr
<nsIURI
> uri
;
184 aPrincipal
->GetDomain(getter_AddRefs(uri
));
186 aPrincipal
->GetURI(getter_AddRefs(uri
));
188 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
190 return GetOriginFromURI(uri
, aOrigin
);
193 static nsIScriptContext
*
194 GetScriptContext(JSContext
*cx
)
196 return GetScriptContextFromJSContext(cx
);
199 inline void SetPendingException(JSContext
*cx
, const char *aMsg
)
201 JSAutoRequest
ar(cx
);
202 JS_ReportError(cx
, "%s", aMsg
);
205 inline void SetPendingException(JSContext
*cx
, const PRUnichar
*aMsg
)
207 JSAutoRequest
ar(cx
);
208 JS_ReportError(cx
, "%hs", aMsg
);
211 // DomainPolicy members
212 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
213 PRUint32
DomainPolicy::sObjects
=0;
214 void DomainPolicy::_printPopulationInfo()
216 printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n",
217 sGeneration
, sObjects
);
220 PRUint32
DomainPolicy::sGeneration
= 0;
222 // Helper class to get stuff from the ClassInfo and not waste extra time with
223 // virtual method calls for things it has already gotten
227 ClassInfoData(nsIClassInfo
*aClassInfo
, const char *aName
)
228 : mClassInfo(aClassInfo
),
229 mName(const_cast<char *>(aName
)),
230 mDidGetFlags(PR_FALSE
),
231 mMustFreeName(PR_FALSE
)
238 nsMemory::Free(mName
);
245 nsresult rv
= mClassInfo
->GetFlags(&mFlags
);
253 mDidGetFlags
= PR_TRUE
;
261 return !!(GetFlags() & nsIClassInfo::DOM_OBJECT
);
264 const char* GetName()
268 mClassInfo
->GetClassDescription(&mName
);
272 mMustFreeName
= PR_TRUE
;
274 mName
= const_cast<char *>("UnnamedClass");
282 nsIClassInfo
*mClassInfo
; // WEAK
285 PRPackedBool mDidGetFlags
;
286 PRPackedBool mMustFreeName
;
291 AutoCxPusher(nsIJSContextStack
*aStack
, JSContext
*cx
)
292 : mStack(aStack
), mContext(cx
)
294 if (NS_FAILED(mStack
->Push(mContext
))) {
307 nsCOMPtr
<nsIJSContextStack
> mStack
;
312 nsScriptSecurityManager::GetCurrentJSContext()
314 // Get JSContext from stack.
316 if (NS_FAILED(sJSContextStack
->Peek(&cx
)))
322 nsScriptSecurityManager::GetSafeJSContext()
324 // Get JSContext from stack.
326 if (NS_FAILED(sJSContextStack
->GetSafeJSContext(&cx
)))
333 nsScriptSecurityManager::SecurityCompareURIs(nsIURI
* aSourceURI
,
336 return NS_SecurityCompareURIs(aSourceURI
, aTargetURI
, sStrictFileOriginPolicy
);
339 // SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI
340 // is consistent with NS_SecurityCompareURIs. See nsNetUtil.h.
342 nsScriptSecurityManager::SecurityHashURI(nsIURI
* aURI
)
344 return NS_SecurityHashURI(aURI
);
348 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel
* aChannel
,
349 nsIPrincipal
** aPrincipal
)
351 NS_PRECONDITION(aChannel
, "Must have channel!");
352 nsCOMPtr
<nsISupports
> owner
;
353 aChannel
->GetOwner(getter_AddRefs(owner
));
355 CallQueryInterface(owner
, aPrincipal
);
361 // OK, get the principal from the URI. Make sure this does the same thing
362 // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
363 nsCOMPtr
<nsIURI
> uri
;
364 nsresult rv
= NS_GetFinalChannelURI(aChannel
, getter_AddRefs(uri
));
365 NS_ENSURE_SUCCESS(rv
, rv
);
367 return GetCodebasePrincipal(uri
, aPrincipal
);
371 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal
* aPrincipal
,
374 *aIsSystem
= (aPrincipal
== mSystemPrincipal
);
378 NS_IMETHODIMP_(nsIPrincipal
*)
379 nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext
*cx
)
381 NS_ASSERTION(cx
== GetCurrentJSContext(),
382 "Uh, cx is not the current JS context!");
384 nsresult rv
= NS_ERROR_FAILURE
;
385 nsIPrincipal
*principal
= GetSubjectPrincipal(cx
, &rv
);
392 NS_IMETHODIMP_(nsIPrincipal
*)
393 nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext
*cx
, JSStackFrame
**fp
)
395 NS_ASSERTION(cx
== GetCurrentJSContext(),
396 "Uh, cx is not the current JS context!");
398 nsresult rv
= NS_ERROR_FAILURE
;
399 nsIPrincipal
*principal
= GetPrincipalAndFrame(cx
, fp
, &rv
);
407 nsScriptSecurityManager::PushContextPrincipal(JSContext
*cx
,
409 nsIPrincipal
*principal
)
411 ContextPrincipal
*cp
= new ContextPrincipal(mContextPrincipals
, cx
, fp
,
414 return NS_ERROR_OUT_OF_MEMORY
;
416 mContextPrincipals
= cp
;
421 nsScriptSecurityManager::PopContextPrincipal(JSContext
*cx
)
423 NS_ASSERTION(mContextPrincipals
->mCx
== cx
, "Mismatched push/pop");
425 ContextPrincipal
*next
= mContextPrincipals
->mNext
;
426 delete mContextPrincipals
;
427 mContextPrincipals
= next
;
436 // Table of security levels
438 DeleteCapability(nsHashKey
*aKey
, void *aData
, void* closure
)
444 //-- Per-Domain Policy - applies to one or more protocols or hosts
447 DomainEntry(const char* aOrigin
,
448 DomainPolicy
* aDomainPolicy
) : mOrigin(aOrigin
),
449 mDomainPolicy(aDomainPolicy
),
452 mDomainPolicy
->Hold();
457 mDomainPolicy
->Drop();
460 PRBool
Matches(const char *anOrigin
)
462 int len
= strlen(anOrigin
);
463 int thisLen
= mOrigin
.Length();
466 if (mOrigin
.RFindChar(':', thisLen
-1, 1) != -1)
467 //-- Policy applies to all URLs of this scheme, compare scheme only
468 return mOrigin
.EqualsIgnoreCase(anOrigin
, thisLen
);
470 //-- Policy applies to a particular host; compare domains
471 if (!mOrigin
.Equals(anOrigin
+ (len
- thisLen
)))
475 char charBefore
= anOrigin
[len
-thisLen
-1];
476 return (charBefore
== '.' || charBefore
== ':' || charBefore
== '/');
480 DomainPolicy
* mDomainPolicy
;
482 #if defined(DEBUG) || defined(DEBUG_CAPS_HACKER)
483 nsCString mPolicyName_DEBUG
;
488 DeleteDomainEntry(nsHashKey
*aKey
, void *aData
, void* closure
)
490 DomainEntry
*entry
= (DomainEntry
*) aData
;
493 DomainEntry
*next
= entry
->mNext
;
500 /////////////////////////////
501 // nsScriptSecurityManager //
502 /////////////////////////////
504 ////////////////////////////////////
505 // Methods implementing ISupports //
506 ////////////////////////////////////
507 NS_IMPL_ISUPPORTS4(nsScriptSecurityManager
,
508 nsIScriptSecurityManager
,
509 nsIXPCSecurityManager
,
513 ///////////////////////////////////////////////////
514 // Methods implementing nsIScriptSecurityManager //
515 ///////////////////////////////////////////////////
517 ///////////////// Security Checks /////////////////
519 nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext
*cx
)
521 // Get the security manager
522 nsScriptSecurityManager
*ssm
=
523 nsScriptSecurityManager::GetScriptSecurityManager();
525 NS_ASSERTION(ssm
, "Failed to get security manager service");
530 nsIPrincipal
* subjectPrincipal
= ssm
->GetSubjectPrincipal(cx
, &rv
);
532 NS_ASSERTION(NS_SUCCEEDED(rv
), "CSP: Failed to get nsIPrincipal from js context");
534 return JS_FALSE
; // Not just absence of principal, but failure.
536 if (!subjectPrincipal
) {
537 // See bug 553448 for discussion of this case.
538 NS_ASSERTION(!JS_GetSecurityCallbacks(cx
)->findObjectPrincipals
,
539 "CSP: Should have been able to find subject principal. "
540 "Reluctantly granting access.");
544 nsCOMPtr
<nsIContentSecurityPolicy
> csp
;
545 rv
= subjectPrincipal
->GetCsp(getter_AddRefs(csp
));
546 NS_ASSERTION(NS_SUCCEEDED(rv
), "CSP: Failed to get CSP from principal.");
548 // don't do anything unless there's a CSP
552 PRBool evalOK
= PR_TRUE
;
553 // this call will send violation reports as warranted (and return true if
554 // reportOnly is set).
555 rv
= csp
->GetAllowsEval(&evalOK
);
559 NS_WARNING("CSP: failed to get allowsEval");
560 return JS_TRUE
; // fail open to not break sites.
568 nsScriptSecurityManager::CheckObjectAccess(JSContext
*cx
, JSObject
*obj
,
569 jsid id
, JSAccessMode mode
,
572 // Get the security manager
573 nsScriptSecurityManager
*ssm
=
574 nsScriptSecurityManager::GetScriptSecurityManager();
576 NS_ASSERTION(ssm
, "Failed to get security manager service");
580 // Get the object being accessed. We protect these cases:
581 // 1. The Function.prototype.caller property's value, which might lead
582 // an attacker up a call-stack to a function or another object from
583 // a different trust domain.
584 // 2. A user-defined getter or setter function accessible on another
585 // trust domain's window or document object.
586 // *vp can be a primitive, in that case, we use obj as the target
588 JSObject
* target
= JSVAL_IS_PRIMITIVE(*vp
) ? obj
: JSVAL_TO_OBJECT(*vp
);
590 // Do the same-origin check -- this sets a JS exception if the check fails.
591 // Pass the parent object's class name, as we have no class-info for it.
593 ssm
->CheckPropertyAccess(cx
, target
, obj
->getClass()->name
, id
,
594 (mode
& JSACC_WRITE
) ?
595 (PRInt32
)nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
596 (PRInt32
)nsIXPCSecurityManager::ACCESS_GET_PROPERTY
);
599 return JS_FALSE
; // Security check failed (XXX was an error reported?)
605 nsScriptSecurityManager::CheckPropertyAccess(JSContext
* cx
,
607 const char* aClassName
,
611 return CheckPropertyAccessImpl(aAction
, nsnull
, cx
, aJSObject
,
612 nsnull
, nsnull
, nsnull
,
613 aClassName
, aProperty
, nsnull
);
617 nsScriptSecurityManager::CheckSameOrigin(JSContext
* cx
,
622 // Get a context if necessary
625 cx
= GetCurrentJSContext();
627 return NS_OK
; // No JS context, so allow access
630 // Get a principal from the context
631 nsIPrincipal
* sourcePrincipal
= GetSubjectPrincipal(cx
, &rv
);
635 if (!sourcePrincipal
)
637 NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
641 if (sourcePrincipal
== mSystemPrincipal
)
643 // This is a system (chrome) script, so allow access
647 // Get the original URI from the source principal.
648 // This has the effect of ignoring any change to document.domain
649 // which must be done to avoid DNS spoofing (bug 154930)
650 nsCOMPtr
<nsIURI
> sourceURI
;
651 sourcePrincipal
->GetDomain(getter_AddRefs(sourceURI
));
653 sourcePrincipal
->GetURI(getter_AddRefs(sourceURI
));
654 NS_ENSURE_TRUE(sourceURI
, NS_ERROR_FAILURE
);
658 if (!SecurityCompareURIs(sourceURI
, aTargetURI
))
660 ReportError(cx
, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI
, aTargetURI
);
661 return NS_ERROR_DOM_BAD_URI
;
667 nsScriptSecurityManager::CheckSameOriginURI(nsIURI
* aSourceURI
,
671 if (!SecurityCompareURIs(aSourceURI
, aTargetURI
))
674 ReportError(nsnull
, NS_LITERAL_STRING("CheckSameOriginError"),
675 aSourceURI
, aTargetURI
);
677 return NS_ERROR_DOM_BAD_URI
;
683 nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction
,
684 nsAXPCNativeCallContext
* aCallContext
,
685 JSContext
* cx
, JSObject
* aJSObject
,
686 nsISupports
* aObj
, nsIURI
* aTargetURI
,
687 nsIClassInfo
* aClassInfo
,
688 const char* aClassName
, jsid aProperty
,
689 void** aCachedClassPolicy
)
692 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
696 if (!subjectPrincipal
|| subjectPrincipal
== mSystemPrincipal
)
697 // We have native code or the system principal: just allow access
700 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
702 // Hold the class info data here so we don't have to go back to virtual
703 // methods all the time
704 ClassInfoData
classInfoData(aClassInfo
, aClassName
);
705 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
706 nsCAutoString propertyName
;
707 propertyName
.AssignWithConversion((PRUnichar
*)IDToString(cx
, aProperty
));
708 printf("### CanAccess(%s.%s, %i) ", classInfoData
.GetName(),
709 propertyName
.get(), aAction
);
712 //-- Look up the security policy for this class and subject domain
713 SecurityLevel securityLevel
;
714 rv
= LookupPolicy(subjectPrincipal
, classInfoData
, aProperty
, aAction
,
715 (ClassPolicy
**)aCachedClassPolicy
, &securityLevel
);
719 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
721 // No policy found for this property so use the default of last resort.
722 // If we were called from somewhere other than XPConnect
723 // (no XPC call context), assume this is a DOM class. Otherwise,
724 // ask the ClassInfo.
725 if (!aCallContext
|| classInfoData
.IsDOMClass())
726 securityLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
728 securityLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
731 if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel
))
732 // This flag means securityLevel is allAccess, noAccess, or sameOrigin
734 switch (securityLevel
.level
)
736 case SCRIPT_SECURITY_NO_ACCESS
:
737 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
740 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
743 case SCRIPT_SECURITY_ALL_ACCESS
:
744 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
745 printf("allAccess ");
750 case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
:
752 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
753 printf("sameOrigin ");
755 nsCOMPtr
<nsIPrincipal
> principalHolder
;
758 objectPrincipal
= doGetObjectPrincipal(aJSObject
);
759 if (!objectPrincipal
)
760 rv
= NS_ERROR_DOM_SECURITY_ERR
;
764 if (NS_FAILED(GetCodebasePrincipal(
765 aTargetURI
, getter_AddRefs(objectPrincipal
))))
766 return NS_ERROR_FAILURE
;
770 NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
771 return NS_ERROR_FAILURE
;
774 rv
= CheckSameOriginDOMProp(subjectPrincipal
, objectPrincipal
,
779 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
782 NS_ERROR("Bad Security Level Value");
783 return NS_ERROR_FAILURE
;
786 else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
788 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
789 printf("Cap:%s ", securityLevel
.capability
);
791 PRBool capabilityEnabled
= PR_FALSE
;
792 rv
= IsCapabilityEnabled(securityLevel
.capability
, &capabilityEnabled
);
793 if (NS_FAILED(rv
) || !capabilityEnabled
)
794 rv
= NS_ERROR_DOM_SECURITY_ERR
;
799 if (NS_SUCCEEDED(rv
))
801 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
802 printf(" GRANTED.\n");
807 //--See if the object advertises a non-default level of access
808 // using nsISecurityCheckedComponent
809 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
810 do_QueryInterface(aObj
);
812 nsXPIDLCString objectSecurityLevel
;
813 if (checkedComponent
)
815 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
816 nsCOMPtr
<nsIInterfaceInfo
> interfaceInfo
;
817 const nsIID
* objIID
= nsnull
;
818 rv
= aCallContext
->GetCalleeWrapper(getter_AddRefs(wrapper
));
819 if (NS_SUCCEEDED(rv
) && wrapper
)
820 rv
= wrapper
->FindInterfaceWithMember(aProperty
, getter_AddRefs(interfaceInfo
));
821 if (NS_SUCCEEDED(rv
) && interfaceInfo
)
822 rv
= interfaceInfo
->GetIIDShared(&objIID
);
823 if (NS_SUCCEEDED(rv
) && objIID
)
827 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
828 checkedComponent
->CanGetProperty(objIID
,
829 IDToString(cx
, aProperty
),
830 getter_Copies(objectSecurityLevel
));
832 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
833 checkedComponent
->CanSetProperty(objIID
,
834 IDToString(cx
, aProperty
),
835 getter_Copies(objectSecurityLevel
));
837 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
838 checkedComponent
->CanCallMethod(objIID
,
839 IDToString(cx
, aProperty
),
840 getter_Copies(objectSecurityLevel
));
844 rv
= CheckXPCPermissions(cx
, aObj
, aJSObject
, subjectPrincipal
,
845 objectSecurityLevel
);
846 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
848 printf("CheckXPCPerms GRANTED.\n");
850 printf("CheckXPCPerms DENIED.\n");
853 if (NS_FAILED(rv
)) //-- Security tests failed, access is denied, report error
855 nsAutoString stringName
;
858 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
859 stringName
.AssignLiteral("GetPropertyDeniedOrigins");
861 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
862 stringName
.AssignLiteral("SetPropertyDeniedOrigins");
864 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
865 stringName
.AssignLiteral("CallMethodDeniedOrigins");
868 // Null out objectPrincipal for now, so we don't leak information about
869 // it. Whenever we can report different error strings to content and
870 // the UI we can take this out again.
871 objectPrincipal
= nsnull
;
873 NS_ConvertUTF8toUTF16
className(classInfoData
.GetName());
874 nsCAutoString subjectOrigin
;
875 nsCAutoString subjectDomain
;
876 if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
) {
877 nsCOMPtr
<nsIURI
> uri
, domain
;
878 subjectPrincipal
->GetURI(getter_AddRefs(uri
));
879 // Subject can't be system if we failed the security
880 // check, so |uri| is non-null.
881 NS_ASSERTION(uri
, "How did that happen?");
882 GetOriginFromURI(uri
, subjectOrigin
);
883 subjectPrincipal
->GetDomain(getter_AddRefs(domain
));
885 GetOriginFromURI(domain
, subjectDomain
);
888 subjectOrigin
.AssignLiteral("the security manager");
890 NS_ConvertUTF8toUTF16
subjectOriginUnicode(subjectOrigin
);
891 NS_ConvertUTF8toUTF16
subjectDomainUnicode(subjectDomain
);
893 nsCAutoString objectOrigin
;
894 nsCAutoString objectDomain
;
895 if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
&&
897 nsCOMPtr
<nsIURI
> uri
, domain
;
898 objectPrincipal
->GetURI(getter_AddRefs(uri
));
899 if (uri
) { // Object principal might be system
900 GetOriginFromURI(uri
, objectOrigin
);
902 objectPrincipal
->GetDomain(getter_AddRefs(domain
));
904 GetOriginFromURI(domain
, objectDomain
);
907 NS_ConvertUTF8toUTF16
objectOriginUnicode(objectOrigin
);
908 NS_ConvertUTF8toUTF16
objectDomainUnicode(objectDomain
);
910 nsXPIDLString errorMsg
;
911 const PRUnichar
*formatStrings
[] =
913 subjectOriginUnicode
.get(),
915 IDToString(cx
, aProperty
),
916 objectOriginUnicode
.get(),
917 subjectDomainUnicode
.get(),
918 objectDomainUnicode
.get()
921 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
923 // XXXbz Our localization system is stupid and can't handle not showing
924 // some strings that get passed in. Which means that we have to get
925 // our length precisely right: it has to be exactly the number of
926 // strings our format string wants. This means we'll have to move
927 // strings in the array as needed, sadly...
928 if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
||
930 stringName
.AppendLiteral("OnlySubject");
933 // default to a length that doesn't include the domains, then
934 // increase it as needed.
936 if (!subjectDomainUnicode
.IsEmpty()) {
937 stringName
.AppendLiteral("SubjectDomain");
940 if (!objectDomainUnicode
.IsEmpty()) {
941 stringName
.AppendLiteral("ObjectDomain");
943 if (length
!= NS_ARRAY_LENGTH(formatStrings
)) {
944 // We have an object domain but not a subject domain.
945 // Scoot our string over one slot. See the XXX comment
946 // above for why we need to do this.
947 formatStrings
[length
-1] = formatStrings
[length
];
952 // We need to keep our existing failure rv and not override it
953 // with a likely success code from the following string bundle
954 // call in order to throw the correct security exception later.
955 nsresult rv2
= sStrBundle
->FormatStringFromName(stringName
.get(),
958 getter_Copies(errorMsg
));
959 if (NS_FAILED(rv2
)) {
960 // Might just be missing the string... Do our best
961 errorMsg
= stringName
;
964 SetPendingException(cx
, errorMsg
.get());
972 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
973 nsIPrincipal
* aObject
)
976 ** Get origin of subject and object and compare.
978 if (aSubject
== aObject
)
981 // Default to false, and change if that turns out wrong.
982 PRBool subjectSetDomain
= PR_FALSE
;
983 PRBool objectSetDomain
= PR_FALSE
;
985 nsCOMPtr
<nsIURI
> subjectURI
;
986 nsCOMPtr
<nsIURI
> objectURI
;
988 aSubject
->GetDomain(getter_AddRefs(subjectURI
));
990 aSubject
->GetURI(getter_AddRefs(subjectURI
));
992 subjectSetDomain
= PR_TRUE
;
995 aObject
->GetDomain(getter_AddRefs(objectURI
));
997 aObject
->GetURI(getter_AddRefs(objectURI
));
999 objectSetDomain
= PR_TRUE
;
1002 if (SecurityCompareURIs(subjectURI
, objectURI
))
1003 { // If either the subject or the object has changed its principal by
1004 // explicitly setting document.domain then the other must also have
1005 // done so in order to be considered the same origin. This prevents
1006 // DNS spoofing based on document.domain (154930)
1008 // If both or neither explicitly set their domain, allow the access
1009 if (subjectSetDomain
== objectSetDomain
)
1014 ** Access tests failed, so now report error.
1016 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1019 // It's important that
1021 // CheckSameOriginPrincipal(A, B) == NS_OK
1025 // HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
1027 // if principals A and B could ever be used as keys in a hashtable.
1028 // Violation of this invariant leads to spurious failures of hashtable
1029 // lookups. See bug 454850.
1032 nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal
* aPrincipal
)
1034 nsCOMPtr
<nsIURI
> uri
;
1035 aPrincipal
->GetDomain(getter_AddRefs(uri
));
1037 aPrincipal
->GetURI(getter_AddRefs(uri
));
1038 return SecurityHashURI(uri
);
1042 nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
1043 nsIPrincipal
* aObject
,
1048 rv
= aSubject
->Subsumes(aObject
, &subsumes
);
1049 if (NS_SUCCEEDED(rv
) && !subsumes
) {
1050 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1053 if (NS_SUCCEEDED(rv
))
1057 * Content can't ever touch chrome (we check for UniversalXPConnect later)
1059 if (aObject
== mSystemPrincipal
)
1060 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1063 * If we failed the origin tests it still might be the case that we
1064 * are a signed script and have permissions to do this operation.
1065 * Check for that here.
1067 PRBool capabilityEnabled
= PR_FALSE
;
1068 const char* cap
= aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
?
1069 "UniversalBrowserWrite" : "UniversalBrowserRead";
1070 rv
= IsCapabilityEnabled(cap
, &capabilityEnabled
);
1071 NS_ENSURE_SUCCESS(rv
, rv
);
1072 if (capabilityEnabled
)
1076 ** Access tests failed, so now report error.
1078 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1082 nsScriptSecurityManager::LookupPolicy(nsIPrincipal
* aPrincipal
,
1083 ClassInfoData
& aClassData
,
1086 ClassPolicy
** aCachedClassPolicy
,
1087 SecurityLevel
* result
)
1090 result
->level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
1092 DomainPolicy
* dpolicy
= nsnull
;
1093 //-- Initialize policies if necessary
1094 if (mPolicyPrefsChanged
)
1098 NS_ENSURE_SUCCESS(rv
, rv
);
1100 rv
= InitPolicies();
1106 aPrincipal
->GetSecurityPolicy((void**)&dpolicy
);
1109 if (!dpolicy
&& mOriginToPolicyMap
)
1111 //-- Look up the relevant domain policy, if any
1112 #ifdef DEBUG_CAPS_LookupPolicy
1113 printf("DomainLookup ");
1116 nsCAutoString origin
;
1117 rv
= GetPrincipalDomainOrigin(aPrincipal
, origin
);
1118 NS_ENSURE_SUCCESS(rv
, rv
);
1120 char *start
= origin
.BeginWriting();
1121 const char *nextToLastDot
= nsnull
;
1122 const char *lastDot
= nsnull
;
1123 const char *colon
= nsnull
;
1126 //-- search domain (stop at the end of the string or at the 3rd slash)
1127 for (PRUint32 slashes
=0; *p
; p
++)
1129 if (*p
== '/' && ++slashes
== 3)
1131 *p
= '\0'; // truncate at 3rd slash
1136 nextToLastDot
= lastDot
;
1139 else if (!colon
&& *p
== ':')
1143 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : start
);
1144 DomainEntry
*de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&key
);
1147 nsCAutoString
scheme(start
, colon
-start
+1);
1148 nsCStringKey
schemeKey(scheme
);
1149 de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&schemeKey
);
1154 if (de
->Matches(start
))
1156 dpolicy
= de
->mDomainPolicy
;
1163 dpolicy
= mDefaultPolicy
;
1165 aPrincipal
->SetSecurityPolicy((void*)dpolicy
);
1168 ClassPolicy
* cpolicy
= nsnull
;
1170 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1172 // No per-domain policy for this principal (the more common case)
1173 // so look for a cached class policy from the object wrapper
1174 cpolicy
= *aCachedClassPolicy
;
1178 { //-- No cached policy for this class, need to look it up
1179 #ifdef DEBUG_CAPS_LookupPolicy
1180 printf("ClassLookup ");
1183 cpolicy
= static_cast<ClassPolicy
*>
1184 (PL_DHashTableOperate(dpolicy
,
1185 aClassData
.GetName(),
1188 if (PL_DHASH_ENTRY_IS_FREE(cpolicy
))
1189 cpolicy
= NO_POLICY_FOR_CLASS
;
1191 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1192 *aCachedClassPolicy
= cpolicy
;
1195 NS_ASSERTION(JSID_IS_INT(aProperty
) || JSID_IS_OBJECT(aProperty
) ||
1196 JSID_IS_STRING(aProperty
), "Property must be a valid id");
1198 // Only atomized strings are stored in the policies' hash tables.
1199 if (!JSID_IS_STRING(aProperty
))
1202 JSString
*propertyKey
= JSID_TO_STRING(aProperty
);
1204 // We look for a PropertyPolicy in the following places:
1205 // 1) The ClassPolicy for our class we got from our DomainPolicy
1206 // 2) The mWildcardPolicy of our DomainPolicy
1207 // 3) The ClassPolicy for our class we got from mDefaultPolicy
1208 // 4) The mWildcardPolicy of our mDefaultPolicy
1209 PropertyPolicy
* ppolicy
= nsnull
;
1210 if (cpolicy
!= NO_POLICY_FOR_CLASS
)
1212 ppolicy
= static_cast<PropertyPolicy
*>
1213 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1218 // If there is no class policy for this property, and we have a wildcard
1219 // policy, try that.
1220 if (dpolicy
->mWildcardPolicy
&&
1221 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1224 static_cast<PropertyPolicy
*>
1225 (PL_DHashTableOperate(dpolicy
->mWildcardPolicy
->mPolicy
,
1230 // If dpolicy is not the defauly policy and there's no class or wildcard
1231 // policy for this property, check the default policy for this class and
1232 // the default wildcard policy
1233 if (dpolicy
!= mDefaultPolicy
&&
1234 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1236 cpolicy
= static_cast<ClassPolicy
*>
1237 (PL_DHashTableOperate(mDefaultPolicy
,
1238 aClassData
.GetName(),
1241 if (PL_DHASH_ENTRY_IS_BUSY(cpolicy
))
1244 static_cast<PropertyPolicy
*>
1245 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1250 if ((!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)) &&
1251 mDefaultPolicy
->mWildcardPolicy
)
1254 static_cast<PropertyPolicy
*>
1255 (PL_DHashTableOperate(mDefaultPolicy
->mWildcardPolicy
->mPolicy
,
1261 if (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
))
1264 // Get the correct security level from the property policy
1265 if (aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
)
1266 *result
= ppolicy
->mSet
;
1268 *result
= ppolicy
->mGet
;
1275 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext
*cx
, nsIURI
*aURI
)
1277 // Get principal of currently executing script.
1279 nsIPrincipal
* principal
= GetSubjectPrincipal(cx
, &rv
);
1283 // Native code can load all URIs.
1287 rv
= CheckLoadURIWithPrincipal(principal
, aURI
,
1288 nsIScriptSecurityManager::STANDARD
);
1289 if (NS_SUCCEEDED(rv
)) {
1294 // See if we're attempting to load a file: URI. If so, let a
1295 // UniversalFileRead capability trump the above check.
1296 PRBool isFile
= PR_FALSE
;
1297 PRBool isRes
= PR_FALSE
;
1298 if (NS_FAILED(aURI
->SchemeIs("file", &isFile
)) ||
1299 NS_FAILED(aURI
->SchemeIs("resource", &isRes
)))
1300 return NS_ERROR_FAILURE
;
1301 if (isFile
|| isRes
)
1304 if (NS_FAILED(IsCapabilityEnabled("UniversalFileRead", &enabled
)))
1305 return NS_ERROR_FAILURE
;
1312 if (NS_FAILED(aURI
->GetAsciiSpec(spec
)))
1313 return NS_ERROR_FAILURE
;
1314 nsCAutoString
msg("Access to '");
1316 msg
.AppendLiteral("' from script denied");
1317 SetPendingException(cx
, msg
.get());
1318 return NS_ERROR_DOM_BAD_URI
;
1322 nsScriptSecurityManager::CheckLoadURI(nsIURI
*aSourceURI
, nsIURI
*aTargetURI
,
1325 // FIXME: bug 327244 -- this function should really die... Really truly.
1326 NS_PRECONDITION(aSourceURI
, "CheckLoadURI called with null source URI");
1327 NS_ENSURE_ARG_POINTER(aSourceURI
);
1329 // Note: this is not _quite_ right if aSourceURI has
1330 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1331 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1332 // really needs to go away....
1333 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1334 nsresult rv
= CreateCodebasePrincipal(aSourceURI
,
1335 getter_AddRefs(sourcePrincipal
));
1336 NS_ENSURE_SUCCESS(rv
, rv
);
1337 return CheckLoadURIWithPrincipal(sourcePrincipal
, aTargetURI
, aFlags
);
1341 * Helper method to handle cases where a flag passed to
1342 * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
1343 * nsIProtocolHandler flags set.
1344 * @return if success, access is allowed. Otherwise, deny access
1347 DenyAccessIfURIHasFlags(nsIURI
* aURI
, PRUint32 aURIFlags
)
1349 NS_PRECONDITION(aURI
, "Must have URI!");
1353 NS_URIChainHasFlags(aURI
, aURIFlags
, &uriHasFlags
);
1354 NS_ENSURE_SUCCESS(rv
, rv
);
1357 return NS_ERROR_DOM_BAD_URI
;
1364 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal
* aPrincipal
,
1368 NS_PRECONDITION(aPrincipal
, "CheckLoadURIWithPrincipal must have a principal");
1369 // If someone passes a flag that we don't understand, we should
1370 // fail, because they may need a security check that we don't
1372 NS_ENSURE_FALSE(aFlags
& ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
1373 nsIScriptSecurityManager::ALLOW_CHROME
|
1374 nsIScriptSecurityManager::DISALLOW_SCRIPT
|
1375 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
),
1376 NS_ERROR_UNEXPECTED
);
1377 NS_ENSURE_ARG_POINTER(aPrincipal
);
1378 NS_ENSURE_ARG_POINTER(aTargetURI
);
1380 if (aPrincipal
== mSystemPrincipal
) {
1385 nsCOMPtr
<nsIURI
> sourceURI
;
1386 aPrincipal
->GetURI(getter_AddRefs(sourceURI
));
1388 NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
1389 "must have a URI!");
1390 return NS_ERROR_UNEXPECTED
;
1393 // Automatic loads are not allowed from certain protocols.
1394 if (aFlags
& nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
) {
1396 DenyAccessIfURIHasFlags(sourceURI
,
1397 nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT
);
1398 NS_ENSURE_SUCCESS(rv
, rv
);
1401 // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
1402 // would do such inheriting. That would be URIs that do not have their own
1403 // security context.
1404 if (aFlags
& nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
) {
1406 DenyAccessIfURIHasFlags(aTargetURI
,
1407 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
);
1408 NS_ENSURE_SUCCESS(rv
, rv
);
1411 // If either URI is a nested URI, get the base URI
1412 nsCOMPtr
<nsIURI
> sourceBaseURI
= NS_GetInnermostURI(sourceURI
);
1413 nsCOMPtr
<nsIURI
> targetBaseURI
= NS_GetInnermostURI(aTargetURI
);
1415 //-- get the target scheme
1416 nsCAutoString targetScheme
;
1417 nsresult rv
= targetBaseURI
->GetScheme(targetScheme
);
1418 if (NS_FAILED(rv
)) return rv
;
1420 //-- Some callers do not allow loading javascript:
1421 if ((aFlags
& nsIScriptSecurityManager::DISALLOW_SCRIPT
) &&
1422 targetScheme
.EqualsLiteral("javascript"))
1424 return NS_ERROR_DOM_BAD_URI
;
1427 NS_NAMED_LITERAL_STRING(errorTag
, "CheckLoadURIError");
1429 // Check for uris that are only loadable by principals that subsume them
1431 rv
= NS_URIChainHasFlags(targetBaseURI
,
1432 nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS
,
1434 NS_ENSURE_SUCCESS(rv
, rv
);
1437 return aPrincipal
->CheckMayLoad(targetBaseURI
, PR_TRUE
);
1440 //-- get the source scheme
1441 nsCAutoString sourceScheme
;
1442 rv
= sourceBaseURI
->GetScheme(sourceScheme
);
1443 if (NS_FAILED(rv
)) return rv
;
1445 if (sourceScheme
.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME
)) {
1446 // A null principal can target its own URI.
1447 if (sourceURI
== aTargetURI
) {
1451 else if (targetScheme
.Equals(sourceScheme
,
1452 nsCaseInsensitiveCStringComparator()))
1454 // every scheme can access another URI from the same scheme,
1455 // as long as they don't represent null principals.
1459 // If the schemes don't match, the policy is specified by the protocol
1460 // flags on the target URI. Note that the order of policy checks here is
1461 // very important! We start from most restrictive and work our way down.
1462 // Note that since we're working with the innermost URI, we can just use
1463 // the methods that work on chains of nested URIs and they will only look
1464 // at the flags for our one URI.
1466 // Check for system target URI
1467 rv
= DenyAccessIfURIHasFlags(targetBaseURI
,
1468 nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
);
1469 if (NS_FAILED(rv
)) {
1470 // Deny access, since the origin principal is not system
1471 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1475 // Check for chrome target URI
1476 rv
= NS_URIChainHasFlags(targetBaseURI
,
1477 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1479 NS_ENSURE_SUCCESS(rv
, rv
);
1481 if (aFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) {
1482 if (!targetScheme
.EqualsLiteral("chrome")) {
1483 // for now don't change behavior for resource: or moz-icon:
1487 // allow load only if chrome package is whitelisted
1488 nsCOMPtr
<nsIXULChromeRegistry
> reg(do_GetService(
1489 NS_CHROMEREGISTRY_CONTRACTID
));
1491 PRBool accessAllowed
= PR_FALSE
;
1492 reg
->AllowContentToAccess(targetBaseURI
, &accessAllowed
);
1493 if (accessAllowed
) {
1499 // resource: and chrome: are equivalent, securitywise
1500 // That's bogus!! Fix this. But watch out for
1501 // the view-source stylesheet?
1502 PRBool sourceIsChrome
;
1503 rv
= NS_URIChainHasFlags(sourceBaseURI
,
1504 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1506 NS_ENSURE_SUCCESS(rv
, rv
);
1507 if (sourceIsChrome
) {
1510 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1511 return NS_ERROR_DOM_BAD_URI
;
1514 // Check for target URI pointing to a file
1515 rv
= NS_URIChainHasFlags(targetBaseURI
,
1516 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
1518 NS_ENSURE_SUCCESS(rv
, rv
);
1520 // resource: and chrome: are equivalent, securitywise
1521 // That's bogus!! Fix this. But watch out for
1522 // the view-source stylesheet?
1523 PRBool sourceIsChrome
;
1524 rv
= NS_URIChainHasFlags(sourceURI
,
1525 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1527 NS_ENSURE_SUCCESS(rv
, rv
);
1528 if (sourceIsChrome
) {
1532 // Now check capability policies
1533 static const char loadURIPrefGroup
[] = "checkloaduri";
1534 ClassInfoData
nameData(nsnull
, loadURIPrefGroup
);
1536 SecurityLevel secLevel
;
1537 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1538 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1540 if (NS_SUCCEEDED(rv
) && secLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
1542 // OK for this site!
1546 ReportError(nsnull
, errorTag
, sourceURI
, aTargetURI
);
1547 return NS_ERROR_DOM_BAD_URI
;
1550 // OK, everyone is allowed to load this, since unflagged handlers are
1551 // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
1552 // need to warn. At some point we'll want to make this warning into an
1553 // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
1554 rv
= NS_URIChainHasFlags(targetBaseURI
,
1555 nsIProtocolHandler::URI_LOADABLE_BY_ANYONE
,
1557 NS_ENSURE_SUCCESS(rv
, rv
);
1559 nsXPIDLString message
;
1560 NS_ConvertASCIItoUTF16
ucsTargetScheme(targetScheme
);
1561 const PRUnichar
* formatStrings
[] = { ucsTargetScheme
.get() };
1563 FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
1565 NS_ARRAY_LENGTH(formatStrings
),
1566 getter_Copies(message
));
1567 if (NS_SUCCEEDED(rv
)) {
1568 nsCOMPtr
<nsIConsoleService
> console(
1569 do_GetService("@mozilla.org/consoleservice;1"));
1570 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1572 console
->LogStringMessage(message
.get());
1574 fprintf(stderr
, "%s\n", NS_ConvertUTF16toUTF8(message
).get());
1583 nsScriptSecurityManager::ReportError(JSContext
* cx
, const nsAString
& messageTag
,
1584 nsIURI
* aSource
, nsIURI
* aTarget
)
1587 NS_ENSURE_TRUE(aSource
&& aTarget
, NS_ERROR_NULL_POINTER
);
1589 // Get the source URL spec
1590 nsCAutoString sourceSpec
;
1591 rv
= aSource
->GetAsciiSpec(sourceSpec
);
1592 NS_ENSURE_SUCCESS(rv
, rv
);
1594 // Get the target URL spec
1595 nsCAutoString targetSpec
;
1596 rv
= aTarget
->GetAsciiSpec(targetSpec
);
1597 NS_ENSURE_SUCCESS(rv
, rv
);
1599 // Localize the error message
1600 nsXPIDLString message
;
1601 NS_ConvertASCIItoUTF16
ucsSourceSpec(sourceSpec
);
1602 NS_ConvertASCIItoUTF16
ucsTargetSpec(targetSpec
);
1603 const PRUnichar
*formatStrings
[] = { ucsSourceSpec
.get(), ucsTargetSpec
.get() };
1604 rv
= sStrBundle
->FormatStringFromName(PromiseFlatString(messageTag
).get(),
1606 NS_ARRAY_LENGTH(formatStrings
),
1607 getter_Copies(message
));
1608 NS_ENSURE_SUCCESS(rv
, rv
);
1610 // If a JS context was passed in, set a JS exception.
1611 // Otherwise, print the error message directly to the JS console
1612 // and to standard output
1615 SetPendingException(cx
, message
.get());
1617 else // Print directly to the console
1619 nsCOMPtr
<nsIConsoleService
> console(
1620 do_GetService("@mozilla.org/consoleservice;1"));
1621 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1623 console
->LogStringMessage(message
.get());
1625 fprintf(stderr
, "%s\n", NS_LossyConvertUTF16toASCII(message
).get());
1632 nsScriptSecurityManager::CheckLoadURIStr(const nsACString
& aSourceURIStr
,
1633 const nsACString
& aTargetURIStr
,
1636 // FIXME: bug 327244 -- this function should really die... Really truly.
1637 nsCOMPtr
<nsIURI
> source
;
1638 nsresult rv
= NS_NewURI(getter_AddRefs(source
), aSourceURIStr
,
1639 nsnull
, nsnull
, sIOService
);
1640 NS_ENSURE_SUCCESS(rv
, rv
);
1642 // Note: this is not _quite_ right if aSourceURI has
1643 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1644 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1645 // really needs to go away....
1646 nsCOMPtr
<nsIPrincipal
> sourcePrincipal
;
1647 rv
= CreateCodebasePrincipal(source
,
1648 getter_AddRefs(sourcePrincipal
));
1649 NS_ENSURE_SUCCESS(rv
, rv
);
1651 return CheckLoadURIStrWithPrincipal(sourcePrincipal
, aTargetURIStr
,
1656 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal
* aPrincipal
,
1657 const nsACString
& aTargetURIStr
,
1661 nsCOMPtr
<nsIURI
> target
;
1662 rv
= NS_NewURI(getter_AddRefs(target
), aTargetURIStr
,
1663 nsnull
, nsnull
, sIOService
);
1664 NS_ENSURE_SUCCESS(rv
, rv
);
1666 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1667 NS_ENSURE_SUCCESS(rv
, rv
);
1669 // Now start testing fixup -- since aTargetURIStr is a string, not
1670 // an nsIURI, we may well end up fixing it up before loading.
1671 // Note: This needs to stay in sync with the nsIURIFixup api.
1672 nsCOMPtr
<nsIURIFixup
> fixup
= do_GetService(NS_URIFIXUP_CONTRACTID
);
1677 PRUint32 flags
[] = {
1678 nsIURIFixup::FIXUP_FLAG_NONE
,
1679 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
,
1680 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
,
1681 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
|
1682 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
1685 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(flags
); ++i
) {
1686 rv
= fixup
->CreateFixupURI(aTargetURIStr
, flags
[i
],
1687 getter_AddRefs(target
));
1688 NS_ENSURE_SUCCESS(rv
, rv
);
1690 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1691 NS_ENSURE_SUCCESS(rv
, rv
);
1698 nsScriptSecurityManager::CheckFunctionAccess(JSContext
*aCx
, void *aFunObj
,
1701 // This check is called for event handlers
1703 nsIPrincipal
* subject
=
1704 GetFunctionObjectPrincipal(aCx
, (JSObject
*)aFunObj
, nsnull
, &rv
);
1706 // If subject is null, get a principal from the function object's scope.
1707 if (NS_SUCCEEDED(rv
) && !subject
)
1711 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, (JSObject
*)aFunObj
);
1712 JSScript
*script
= JS_GetFunctionScript(aCx
, fun
);
1714 NS_ASSERTION(!script
, "Null principal for non-native function!");
1718 subject
= doGetObjectPrincipal((JSObject
*)aFunObj
);
1722 return NS_ERROR_FAILURE
;
1724 if (subject
== mSystemPrincipal
)
1725 // This is the system principal: just allow access
1728 // Check if the principal the function was compiled under is
1729 // allowed to execute scripts.
1732 rv
= CanExecuteScripts(aCx
, subject
, &result
);
1737 return NS_ERROR_DOM_SECURITY_ERR
;
1740 ** Get origin of subject and object and compare.
1742 JSObject
* obj
= (JSObject
*)aTargetObj
;
1743 nsIPrincipal
* object
= doGetObjectPrincipal(obj
);
1746 return NS_ERROR_FAILURE
;
1749 rv
= subject
->Subsumes(object
, &subsumes
);
1750 if (NS_SUCCEEDED(rv
) && !subsumes
) {
1751 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1757 nsScriptSecurityManager::CanExecuteScripts(JSContext
* cx
,
1758 nsIPrincipal
*aPrincipal
,
1763 if (aPrincipal
== mSystemPrincipal
)
1765 // Even if JavaScript is disabled, we must still execute system scripts
1770 //-- See if the current window allows JS execution
1771 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
1772 if (!scriptContext
) return NS_ERROR_FAILURE
;
1774 if (!scriptContext
->GetScriptsEnabled()) {
1775 // No scripting on this context, folks
1780 nsIScriptGlobalObject
*sgo
= scriptContext
->GetGlobalObject();
1783 return NS_ERROR_FAILURE
;
1786 // window can be null here if we're running with a non-DOM window
1787 // as the script global (i.e. a XUL prototype document).
1788 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(sgo
);
1789 nsCOMPtr
<nsIDocShell
> docshell
;
1793 docshell
= window
->GetDocShell();
1797 rv
= docshell
->GetCanExecuteScripts(result
);
1798 if (NS_FAILED(rv
)) return rv
;
1799 if (!*result
) return NS_OK
;
1802 // OK, the docshell doesn't have script execution explicitly disabled.
1803 // Check whether our URI is an "about:" URI that allows scripts. If it is,
1804 // we need to allow JS to run. In this case, don't apply the JS enabled
1805 // pref or policies. On failures, just press on and don't do this special
1807 nsCOMPtr
<nsIURI
> principalURI
;
1808 aPrincipal
->GetURI(getter_AddRefs(principalURI
));
1809 if (!principalURI
) {
1810 // Broken principal of some sort. Disallow.
1812 return NS_ERROR_UNEXPECTED
;
1816 rv
= principalURI
->SchemeIs("about", &isAbout
);
1817 if (NS_SUCCEEDED(rv
) && isAbout
) {
1818 nsCOMPtr
<nsIAboutModule
> module
;
1819 rv
= NS_GetAboutModule(principalURI
, getter_AddRefs(module
));
1820 if (NS_SUCCEEDED(rv
)) {
1822 rv
= module
->GetURIFlags(principalURI
, &flags
);
1823 if (NS_SUCCEEDED(rv
) &&
1824 (flags
& nsIAboutModule::ALLOW_SCRIPT
)) {
1831 *result
= mIsJavaScriptEnabled
;
1833 return NS_OK
; // Do not run scripts
1835 //-- Check for a per-site policy
1836 static const char jsPrefGroupName
[] = "javascript";
1837 ClassInfoData
nameData(nsnull
, jsPrefGroupName
);
1839 SecurityLevel secLevel
;
1840 rv
= LookupPolicy(aPrincipal
, nameData
, sEnabledID
,
1841 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1843 if (NS_FAILED(rv
) || secLevel
.level
== SCRIPT_SECURITY_NO_ACCESS
)
1849 //-- Nobody vetoed, so allow the JS to run.
1854 ///////////////// Principals ///////////////////////
1856 nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal
**aSubjectPrincipal
)
1859 *aSubjectPrincipal
= doGetSubjectPrincipal(&rv
);
1860 if (NS_SUCCEEDED(rv
))
1861 NS_IF_ADDREF(*aSubjectPrincipal
);
1866 nsScriptSecurityManager::doGetSubjectPrincipal(nsresult
* rv
)
1868 NS_PRECONDITION(rv
, "Null out param");
1869 JSContext
*cx
= GetCurrentJSContext();
1875 return GetSubjectPrincipal(cx
, rv
);
1879 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal
**result
)
1881 NS_ADDREF(*result
= mSystemPrincipal
);
1887 nsScriptSecurityManager::SubjectPrincipalIsSystem(PRBool
* aIsSystem
)
1889 NS_ENSURE_ARG_POINTER(aIsSystem
);
1890 *aIsSystem
= PR_FALSE
;
1892 if (!mSystemPrincipal
)
1895 nsCOMPtr
<nsIPrincipal
> subject
;
1896 nsresult rv
= GetSubjectPrincipal(getter_AddRefs(subject
));
1902 // No subject principal means no JS is running;
1903 // this is the equivalent of system principal code
1904 *aIsSystem
= PR_TRUE
;
1908 return mSystemPrincipal
->Equals(subject
, aIsSystem
);
1912 nsScriptSecurityManager::GetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1913 const nsACString
& aSubjectName
,
1914 const nsACString
& aPrettyName
,
1915 nsISupports
* aCertificate
,
1917 nsIPrincipal
**result
)
1921 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty() &&
1922 !aSubjectName
.IsEmpty() &&
1925 return DoGetCertificatePrincipal(aCertFingerprint
, aSubjectName
,
1926 aPrettyName
, aCertificate
, aURI
, PR_TRUE
,
1931 nsScriptSecurityManager::DoGetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1932 const nsACString
& aSubjectName
,
1933 const nsACString
& aPrettyName
,
1934 nsISupports
* aCertificate
,
1936 PRBool aModifyTable
,
1937 nsIPrincipal
**result
)
1939 NS_ENSURE_ARG(!aCertFingerprint
.IsEmpty());
1941 // Create a certificate principal out of the certificate ID
1942 // and URI given to us. We will use this principal to test
1943 // equality when doing our hashtable lookups below.
1944 nsRefPtr
<nsPrincipal
> certificate
= new nsPrincipal();
1946 return NS_ERROR_OUT_OF_MEMORY
;
1948 nsresult rv
= certificate
->Init(aCertFingerprint
, aSubjectName
,
1949 aPrettyName
, aCertificate
, aURI
);
1950 NS_ENSURE_SUCCESS(rv
, rv
);
1952 // Check to see if we already have this principal.
1953 nsCOMPtr
<nsIPrincipal
> fromTable
;
1954 mPrincipals
.Get(certificate
, getter_AddRefs(fromTable
));
1956 // Bingo. We found the certificate in the table, which means
1957 // that it has escalated privileges.
1960 // Make sure this principal has names, so if we ever go to save it
1961 // we'll save them. If we get a name mismatch here we'll throw,
1962 // but that's desirable.
1963 rv
= static_cast<nsPrincipal
*>
1964 (static_cast<nsIPrincipal
*>(fromTable
))
1965 ->EnsureCertData(aSubjectName
, aPrettyName
, aCertificate
);
1966 if (NS_FAILED(rv
)) {
1967 // We have a subject name mismatch for the same cert id.
1968 // Hand back the |certificate| object we created and don't give
1969 // it any rights from the table.
1970 NS_ADDREF(*result
= certificate
);
1976 // We were asked to just get the base certificate, so output
1977 // what we have in the table.
1978 certificate
= static_cast<nsPrincipal
*>
1979 (static_cast<nsIPrincipal
*>
1982 // We found a certificate and now need to install a codebase
1983 // on it. We don't want to modify the principal in the hash
1984 // table, so create a new principal and clone the pertinent
1986 nsXPIDLCString prefName
;
1988 nsXPIDLCString subjectName
;
1989 nsXPIDLCString granted
;
1990 nsXPIDLCString denied
;
1992 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
1994 getter_Copies(subjectName
),
1995 getter_Copies(granted
),
1996 getter_Copies(denied
),
1998 // XXXbz assert something about subjectName and aSubjectName here?
1999 if (NS_SUCCEEDED(rv
)) {
2000 NS_ASSERTION(!isTrusted
, "Shouldn't have isTrusted true here");
2002 certificate
= new nsPrincipal();
2004 return NS_ERROR_OUT_OF_MEMORY
;
2006 rv
= certificate
->InitFromPersistent(prefName
, id
,
2007 subjectName
, aPrettyName
,
2014 certificate
->SetURI(aURI
);
2019 NS_ADDREF(*result
= certificate
);
2025 nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI
* aURI
, nsIPrincipal
**result
)
2027 // I _think_ it's safe to not create null principals here based on aURI.
2028 // At least all the callers would do the right thing in those cases, as far
2029 // as I can tell. --bz
2031 nsCOMPtr
<nsIURIWithPrincipal
> uriPrinc
= do_QueryInterface(aURI
);
2033 nsCOMPtr
<nsIPrincipal
> principal
;
2034 uriPrinc
->GetPrincipal(getter_AddRefs(principal
));
2035 if (!principal
|| principal
== mSystemPrincipal
) {
2036 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
2039 principal
.forget(result
);
2044 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
2046 return NS_ERROR_OUT_OF_MEMORY
;
2048 nsresult rv
= codebase
->Init(EmptyCString(), EmptyCString(),
2049 EmptyCString(), nsnull
, aURI
);
2053 NS_ADDREF(*result
= codebase
);
2059 nsScriptSecurityManager::GetCodebasePrincipal(nsIURI
*aURI
,
2060 nsIPrincipal
**result
)
2062 NS_ENSURE_ARG(aURI
);
2064 PRBool inheritsPrincipal
;
2066 NS_URIChainHasFlags(aURI
,
2067 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
2068 &inheritsPrincipal
);
2069 if (NS_FAILED(rv
) || inheritsPrincipal
) {
2070 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
2073 nsCOMPtr
<nsIPrincipal
> principal
;
2074 rv
= CreateCodebasePrincipal(aURI
, getter_AddRefs(principal
));
2075 if (NS_FAILED(rv
)) return rv
;
2077 if (mPrincipals
.Count() > 0)
2079 //-- Check to see if we already have this principal.
2080 nsCOMPtr
<nsIPrincipal
> fromTable
;
2081 mPrincipals
.Get(principal
, getter_AddRefs(fromTable
));
2083 // We found an existing codebase principal. But it might have a
2084 // generic codebase for this origin on it. Install our particular
2086 // XXXbz this is kinda similar to the code in
2087 // GetCertificatePrincipal, but just ever so slightly different.
2089 nsXPIDLCString prefName
;
2091 nsXPIDLCString subjectName
;
2092 nsXPIDLCString granted
;
2093 nsXPIDLCString denied
;
2095 rv
= fromTable
->GetPreferences(getter_Copies(prefName
),
2097 getter_Copies(subjectName
),
2098 getter_Copies(granted
),
2099 getter_Copies(denied
),
2101 if (NS_SUCCEEDED(rv
)) {
2102 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
2104 return NS_ERROR_OUT_OF_MEMORY
;
2106 rv
= codebase
->InitFromPersistent(prefName
, id
,
2107 subjectName
, EmptyCString(),
2114 codebase
->SetURI(aURI
);
2115 principal
= codebase
;
2121 NS_IF_ADDREF(*result
= principal
);
2127 nsScriptSecurityManager::GetPrincipalFromContext(JSContext
*cx
,
2128 nsIPrincipal
**result
)
2132 nsIScriptContextPrincipal
* scp
=
2133 GetScriptContextPrincipalFromJSContext(cx
);
2137 return NS_ERROR_FAILURE
;
2140 nsIScriptObjectPrincipal
* globalData
= scp
->GetObjectPrincipal();
2142 NS_IF_ADDREF(*result
= globalData
->GetPrincipal());
2149 nsScriptSecurityManager::GetScriptPrincipal(JSContext
*cx
,
2153 NS_PRECONDITION(rv
, "Null out param");
2159 JSPrincipals
*jsp
= JS_GetScriptPrincipals(cx
, script
);
2161 *rv
= NS_ERROR_FAILURE
;
2162 NS_ERROR("Script compiled without principals!");
2165 nsJSPrincipals
*nsJSPrin
= static_cast<nsJSPrincipals
*>(jsp
);
2166 nsIPrincipal
* result
= nsJSPrin
->nsIPrincipalPtr
;
2168 *rv
= NS_ERROR_FAILURE
;
2174 nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext
*cx
,
2179 NS_PRECONDITION(rv
, "Null out param");
2183 if (!JS_ObjectIsFunction(cx
, obj
))
2185 // Protect against pseudo-functions (like SJOWs).
2186 nsIPrincipal
*result
= doGetObjectPrincipal(obj
);
2188 *rv
= NS_ERROR_FAILURE
;
2192 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, obj
);
2193 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2197 // A native function: skip it in order to find its scripted caller.
2201 JSScript
*frameScript
= fp
? JS_GetFrameScript(cx
, fp
) : nsnull
;
2203 if (frameScript
&& frameScript
!= script
)
2205 // There is a frame script, and it's different from the
2206 // function script. In this case we're dealing with either
2207 // an eval or a Script object, and in these cases the
2208 // principal we want is in the frame's script, not in the
2209 // function's script. The function's script is where the
2210 // eval-calling code came from, not where the eval or new
2211 // Script object came from, and we want the principal of
2212 // the eval function object or new Script object.
2214 script
= frameScript
;
2216 else if (JS_GetFunctionObject(fun
) != obj
)
2218 // Here, obj is a cloned function object. In this case, the
2219 // clone's prototype may have been precompiled from brutally
2220 // shared chrome, or else it is a lambda or nested function.
2221 // The general case here is a function compiled against a
2222 // different scope than the one it is parented by at runtime,
2223 // hence the creation of a clone to carry the correct scope
2226 // Since principals follow scope, we must get the object
2227 // principal from the clone's scope chain. There are no
2228 // reliable principals compiled into the function itself.
2230 nsIPrincipal
*result
= doGetObjectPrincipal(obj
);
2232 *rv
= NS_ERROR_FAILURE
;
2236 return GetScriptPrincipal(cx
, script
, rv
);
2240 nsScriptSecurityManager::GetFramePrincipal(JSContext
*cx
,
2244 NS_PRECONDITION(rv
, "Null out param");
2245 JSObject
*obj
= JS_GetFrameFunctionObject(cx
, fp
);
2248 // Must be in a top-level script. Get principal from the script.
2249 JSScript
*script
= JS_GetFrameScript(cx
, fp
);
2250 return GetScriptPrincipal(cx
, script
, rv
);
2253 nsIPrincipal
* result
= GetFunctionObjectPrincipal(cx
, obj
, fp
, rv
);
2256 if (NS_SUCCEEDED(*rv
) && !result
)
2258 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, obj
);
2259 JSScript
*script
= JS_GetFunctionScript(cx
, fun
);
2261 NS_ASSERTION(!script
, "Null principal for non-native function!");
2269 nsScriptSecurityManager::GetPrincipalAndFrame(JSContext
*cx
,
2270 JSStackFrame
**frameResult
,
2273 NS_PRECONDITION(rv
, "Null out param");
2274 //-- If there's no principal on the stack, look at the global object
2275 // and return the innermost frame for annotations.
2280 JSStackFrame
*target
= nsnull
;
2281 nsIPrincipal
*targetPrincipal
= nsnull
;
2282 for (ContextPrincipal
*cp
= mContextPrincipals
; cp
; cp
= cp
->mNext
)
2287 targetPrincipal
= cp
->mPrincipal
;
2292 // Get principals from innermost JavaScript frame.
2293 JSStackFrame
*fp
= nsnull
; // tell JS_FrameIterator to start at innermost
2294 for (fp
= JS_FrameIterator(cx
, &fp
); fp
; fp
= JS_FrameIterator(cx
, &fp
))
2298 nsIPrincipal
* result
= GetFramePrincipal(cx
, fp
, rv
);
2301 NS_ASSERTION(NS_SUCCEEDED(*rv
), "Weird return");
2307 // If targetPrincipal is non-null, then it means that someone wants to
2308 // clamp the principals on this context to this principal. Note that
2309 // fp might not equal target here (fp might be null) because someone
2310 // could have set aside the frame chain in the meantime.
2311 if (targetPrincipal
)
2313 if (fp
&& fp
== target
)
2319 JSStackFrame
*inner
= nsnull
;
2320 *frameResult
= JS_FrameIterator(cx
, &inner
);
2323 return targetPrincipal
;
2326 nsIScriptContextPrincipal
* scp
=
2327 GetScriptContextPrincipalFromJSContext(cx
);
2330 nsIScriptObjectPrincipal
* globalData
= scp
->GetObjectPrincipal();
2333 *rv
= NS_ERROR_FAILURE
;
2337 // Note that we're not in a loop or anything, and nothing comes
2338 // after this point in the function, so we can just return here.
2339 nsIPrincipal
* result
= globalData
->GetPrincipal();
2342 JSStackFrame
*inner
= nsnull
;
2343 *frameResult
= JS_FrameIterator(cx
, &inner
);
2353 nsScriptSecurityManager::GetSubjectPrincipal(JSContext
*cx
,
2356 NS_PRECONDITION(rv
, "Null out param");
2358 return GetPrincipalAndFrame(cx
, &fp
, rv
);
2362 nsScriptSecurityManager::GetObjectPrincipal(JSContext
*aCx
, JSObject
*aObj
,
2363 nsIPrincipal
**result
)
2365 *result
= doGetObjectPrincipal(aObj
);
2367 return NS_ERROR_FAILURE
;
2374 nsScriptSecurityManager::doGetObjectPrincipal(JSObject
*aObj
2376 , PRBool aAllowShortCircuit
2380 NS_ASSERTION(aObj
, "Bad call to doGetObjectPrincipal()!");
2381 nsIPrincipal
* result
= nsnull
;
2384 JSObject
* origObj
= aObj
;
2387 js::Class
*jsClass
= aObj
->getClass();
2389 // A common case seen in this code is that we enter this function
2390 // with aObj being a Function object, whose parent is a Call
2391 // object. Neither of those have object principals, so we can skip
2392 // those objects here before we enter the below loop. That way we
2393 // avoid wasting time checking properties of their classes etc in
2396 if (jsClass
== &js_FunctionClass
) {
2397 aObj
= aObj
->getParent();
2402 jsClass
= aObj
->getClass();
2404 if (jsClass
== &js_CallClass
) {
2405 aObj
= aObj
->getParent();
2410 jsClass
= aObj
->getClass();
2415 // Note: jsClass is set before this loop, and also at the
2416 // *end* of this loop.
2418 if (IS_WRAPPER_CLASS(jsClass
)) {
2419 result
= sXPConnect
->GetPrincipal(aObj
,
2429 } else if (!(~jsClass
->flags
& (JSCLASS_HAS_PRIVATE
|
2430 JSCLASS_PRIVATE_IS_NSISUPPORTS
))) {
2431 nsISupports
*priv
= (nsISupports
*) aObj
->getPrivate();
2434 if (aAllowShortCircuit
) {
2435 nsCOMPtr
<nsIXPConnectWrappedNative
> xpcWrapper
=
2436 do_QueryInterface(priv
);
2438 NS_ASSERTION(!xpcWrapper
||
2439 !strcmp(jsClass
->name
, "XPCNativeWrapper"),
2440 "Uh, an nsIXPConnectWrappedNative with the "
2441 "wrong JSClass or getObjectOps hooks!");
2445 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrin
=
2446 do_QueryInterface(priv
);
2449 result
= objPrin
->GetPrincipal();
2457 aObj
= aObj
->getParent();
2462 jsClass
= aObj
->getClass();
2466 if (aAllowShortCircuit
) {
2467 nsIPrincipal
*principal
= doGetObjectPrincipal(origObj
, PR_FALSE
);
2469 // Location is always wrapped (even for same-compartment), so we can
2470 // loosen the check to same-origin instead of same-principal.
2471 NS_ASSERTION(strcmp(jsClass
->name
, "Location") == 0 ?
2472 NS_SUCCEEDED(CheckSameOriginPrincipal(result
, principal
)) :
2473 result
== principal
,
2474 "Principal mismatch. Not good");
2482 nsScriptSecurityManager::SavePrincipal(nsIPrincipal
* aToSave
)
2484 //-- Save to mPrincipals
2485 mPrincipals
.Put(aToSave
, aToSave
);
2488 nsXPIDLCString idPrefName
;
2490 nsXPIDLCString subjectName
;
2491 nsXPIDLCString grantedList
;
2492 nsXPIDLCString deniedList
;
2494 nsresult rv
= aToSave
->GetPreferences(getter_Copies(idPrefName
),
2496 getter_Copies(subjectName
),
2497 getter_Copies(grantedList
),
2498 getter_Copies(deniedList
),
2500 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2502 nsCAutoString grantedPrefName
;
2503 nsCAutoString deniedPrefName
;
2504 nsCAutoString subjectNamePrefName
;
2505 rv
= GetPrincipalPrefNames( idPrefName
,
2508 subjectNamePrefName
);
2509 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2511 mIsWritingPrefs
= PR_TRUE
;
2513 mPrefBranch
->SetCharPref(grantedPrefName
.get(), grantedList
);
2515 mPrefBranch
->ClearUserPref(grantedPrefName
.get());
2518 mPrefBranch
->SetCharPref(deniedPrefName
.get(), deniedList
);
2520 mPrefBranch
->ClearUserPref(deniedPrefName
.get());
2522 if (grantedList
|| deniedList
) {
2523 mPrefBranch
->SetCharPref(idPrefName
, id
);
2524 mPrefBranch
->SetCharPref(subjectNamePrefName
.get(),
2528 mPrefBranch
->ClearUserPref(idPrefName
);
2529 mPrefBranch
->ClearUserPref(subjectNamePrefName
.get());
2532 mIsWritingPrefs
= PR_FALSE
;
2534 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
2535 NS_ENSURE_SUCCESS(rv
, rv
);
2536 return prefService
->SavePrefFile(nsnull
);
2539 ///////////////// Capabilities API /////////////////////
2541 nsScriptSecurityManager::IsCapabilityEnabled(const char *capability
,
2545 JSStackFrame
*fp
= nsnull
;
2546 JSContext
*cx
= GetCurrentJSContext();
2547 fp
= cx
? JS_FrameIterator(cx
, &fp
) : nsnull
;
2550 // No script code on stack. Allow execution.
2555 nsIPrincipal
* previousPrincipal
= nsnull
;
2558 nsIPrincipal
* principal
= GetFramePrincipal(cx
, fp
, &rv
);
2563 // If caller has a different principal, stop looking up the stack.
2564 if(previousPrincipal
)
2566 PRBool isEqual
= PR_FALSE
;
2567 if(NS_FAILED(previousPrincipal
->Equals(principal
, &isEqual
)) || !isEqual
)
2571 previousPrincipal
= principal
;
2573 // First check if the principal is even able to enable the
2574 // given capability. If not, don't look any further.
2576 rv
= principal
->CanEnableCapability(capability
, &canEnable
);
2577 if (NS_FAILED(rv
)) return rv
;
2578 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
&&
2579 canEnable
!= nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2582 // Now see if the capability is enabled.
2583 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2584 rv
= principal
->IsCapabilityEnabled(capability
, annotation
, result
);
2585 if (NS_FAILED(rv
)) return rv
;
2588 } while ((fp
= JS_FrameIterator(cx
, &fp
)) != nsnull
);
2590 if (!previousPrincipal
)
2592 // No principals on the stack, all native code. Allow
2593 // execution if the subject principal is the system principal.
2595 return SubjectPrincipalIsSystem(result
);
2602 nsScriptSecurityManager::FormatCapabilityString(nsAString
& aCapability
)
2604 nsAutoString newcaps
;
2605 nsAutoString rawcap
;
2606 NS_NAMED_LITERAL_STRING(capdesc
, "capdesc.");
2608 PRInt32 index
= kNotFound
;
2611 NS_ASSERTION(kNotFound
== -1, "Basic constant changed, algorithm broken!");
2615 index
= aCapability
.FindChar(' ', pos
);
2616 rawcap
= Substring(aCapability
, pos
,
2617 (index
== kNotFound
) ? index
: index
- pos
);
2619 nsXPIDLString capstr
;
2620 rv
= sStrBundle
->GetStringFromName(
2621 nsPromiseFlatString(capdesc
+rawcap
).get(),
2622 getter_Copies(capstr
));
2623 if (NS_SUCCEEDED(rv
))
2627 nsXPIDLString extensionCap
;
2628 const PRUnichar
* formatArgs
[] = { rawcap
.get() };
2629 rv
= sStrBundle
->FormatStringFromName(
2630 NS_LITERAL_STRING("ExtensionCapability").get(),
2632 NS_ARRAY_LENGTH(formatArgs
),
2633 getter_Copies(extensionCap
));
2634 if (NS_SUCCEEDED(rv
))
2635 newcaps
+= extensionCap
;
2640 newcaps
+= NS_LITERAL_STRING("\n");
2641 } while (index
!= kNotFound
);
2643 aCapability
= newcaps
;
2647 nsScriptSecurityManager::CheckConfirmDialog(JSContext
* cx
, nsIPrincipal
* aPrincipal
,
2648 const char* aCapability
, PRBool
*checkValue
)
2651 *checkValue
= PR_FALSE
;
2653 //-- Get a prompter for the current window.
2654 nsCOMPtr
<nsIPrompt
> prompter
;
2657 nsIScriptContext
*scriptContext
= GetScriptContext(cx
);
2660 nsCOMPtr
<nsIDOMWindowInternal
> domWin
=
2661 do_QueryInterface(scriptContext
->GetGlobalObject());
2663 domWin
->GetPrompter(getter_AddRefs(prompter
));
2669 //-- Couldn't get prompter from the current window, so get the prompt service.
2670 nsCOMPtr
<nsIWindowWatcher
> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
2672 wwatch
->GetNewPrompter(0, getter_AddRefs(prompter
));
2677 //-- Localize the dialog text
2678 nsXPIDLString check
;
2679 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("CheckMessage").get(),
2680 getter_Copies(check
));
2684 nsXPIDLString title
;
2685 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Titleline").get(),
2686 getter_Copies(title
));
2690 nsXPIDLString yesStr
;
2691 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("Yes").get(),
2692 getter_Copies(yesStr
));
2696 nsXPIDLString noStr
;
2697 rv
= sStrBundle
->GetStringFromName(NS_LITERAL_STRING("No").get(),
2698 getter_Copies(noStr
));
2704 aPrincipal
->GetHasCertificate(&hasCert
);
2706 rv
= aPrincipal
->GetPrettyName(val
);
2708 rv
= GetPrincipalDomainOrigin(aPrincipal
, val
);
2713 NS_ConvertUTF8toUTF16
location(val
);
2714 NS_ConvertASCIItoUTF16
capability(aCapability
);
2715 FormatCapabilityString(capability
);
2716 const PRUnichar
*formatStrings
[] = { location
.get(), capability
.get() };
2718 nsXPIDLString message
;
2719 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityQuery").get(),
2721 NS_ARRAY_LENGTH(formatStrings
),
2722 getter_Copies(message
));
2726 PRInt32 buttonPressed
= 1; // If the user exits by clicking the close box, assume No (button 1)
2727 rv
= prompter
->ConfirmEx(title
.get(), message
.get(),
2728 (nsIPrompt::BUTTON_DELAY_ENABLE
) +
2729 (nsIPrompt::BUTTON_POS_1_DEFAULT
) +
2730 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_0
) +
2731 (nsIPrompt::BUTTON_TITLE_IS_STRING
* nsIPrompt::BUTTON_POS_1
),
2732 yesStr
.get(), noStr
.get(), nsnull
, check
.get(), checkValue
, &buttonPressed
);
2735 *checkValue
= PR_FALSE
;
2736 return (buttonPressed
== 0);
2740 nsScriptSecurityManager::RequestCapability(nsIPrincipal
* aPrincipal
,
2741 const char *capability
, PRInt16
* canEnable
)
2743 if (NS_FAILED(aPrincipal
->CanEnableCapability(capability
, canEnable
)))
2744 return NS_ERROR_FAILURE
;
2745 if (*canEnable
== nsIPrincipal::ENABLE_WITH_USER_PERMISSION
)
2747 // Prompt user for permission to enable capability.
2748 JSContext
* cx
= GetCurrentJSContext();
2750 if (CheckConfirmDialog(cx
, aPrincipal
, capability
, &remember
))
2751 *canEnable
= nsIPrincipal::ENABLE_GRANTED
;
2753 *canEnable
= nsIPrincipal::ENABLE_DENIED
;
2756 //-- Save principal to prefs and to mPrincipals
2757 if (NS_FAILED(aPrincipal
->SetCanEnableCapability(capability
, *canEnable
)))
2758 return NS_ERROR_FAILURE
;
2759 if (NS_FAILED(SavePrincipal(aPrincipal
)))
2760 return NS_ERROR_FAILURE
;
2767 nsScriptSecurityManager::EnableCapability(const char *capability
)
2769 JSContext
*cx
= GetCurrentJSContext();
2772 //-- Error checks for capability string length (200)
2773 if(PL_strlen(capability
)>200)
2775 static const char msg
[] = "Capability name too long";
2776 SetPendingException(cx
, msg
);
2777 return NS_ERROR_FAILURE
;
2780 //-- Check capability string for valid characters
2782 // Logically we might have wanted this in nsPrincipal, but performance
2783 // worries dictate it can't go in IsCapabilityEnabled() and we may have
2784 // to show the capability on a dialog before we call the principal's
2785 // EnableCapability().
2787 // We don't need to validate the capability string on the other APIs
2788 // available to web content. Without the ability to enable junk then
2789 // isPrivilegeEnabled, disablePrivilege, and revertPrivilege all do
2790 // the right thing (effectively nothing) when passed unallowed chars.
2791 for (const char *ch
= capability
; *ch
; ++ch
)
2793 if (!NS_IS_ALPHA(*ch
) && *ch
!= ' ' && !NS_IS_DIGIT(*ch
)
2794 && *ch
!= '_' && *ch
!= '-' && *ch
!= '.')
2796 static const char msg
[] = "Invalid character in capability name";
2797 SetPendingException(cx
, msg
);
2798 return NS_ERROR_FAILURE
;
2803 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2807 return NS_ERROR_NOT_AVAILABLE
;
2809 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2811 if (NS_FAILED(principal
->IsCapabilityEnabled(capability
, annotation
,
2813 return NS_ERROR_FAILURE
;
2818 if (NS_FAILED(RequestCapability(principal
, capability
, &canEnable
)))
2819 return NS_ERROR_FAILURE
;
2821 if (canEnable
!= nsIPrincipal::ENABLE_GRANTED
)
2826 principal
->GetHasCertificate(&hasCert
);
2828 rv
= principal
->GetPrettyName(val
);
2830 rv
= GetPrincipalDomainOrigin(principal
, val
);
2835 NS_ConvertUTF8toUTF16
location(val
);
2836 NS_ConvertUTF8toUTF16
cap(capability
);
2837 const PRUnichar
*formatStrings
[] = { location
.get(), cap
.get() };
2839 nsXPIDLString message
;
2840 rv
= sStrBundle
->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityDenied").get(),
2842 NS_ARRAY_LENGTH(formatStrings
),
2843 getter_Copies(message
));
2847 SetPendingException(cx
, message
.get());
2849 return NS_ERROR_FAILURE
; // XXX better error code?
2851 if (NS_FAILED(principal
->EnableCapability(capability
, &annotation
)))
2852 return NS_ERROR_FAILURE
;
2853 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2858 nsScriptSecurityManager::RevertCapability(const char *capability
)
2860 JSContext
*cx
= GetCurrentJSContext();
2863 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2867 return NS_ERROR_NOT_AVAILABLE
;
2868 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2869 principal
->RevertCapability(capability
, &annotation
);
2870 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2875 nsScriptSecurityManager::DisableCapability(const char *capability
)
2877 JSContext
*cx
= GetCurrentJSContext();
2880 nsIPrincipal
* principal
= GetPrincipalAndFrame(cx
, &fp
, &rv
);
2884 return NS_ERROR_NOT_AVAILABLE
;
2885 void *annotation
= JS_GetFrameAnnotation(cx
, fp
);
2886 principal
->DisableCapability(capability
, &annotation
);
2887 JS_SetFrameAnnotation(cx
, fp
, annotation
);
2891 //////////////// Master Certificate Functions ///////////////////////////////////////
2893 nsScriptSecurityManager::SetCanEnableCapability(const nsACString
& certFingerprint
,
2894 const char* capability
,
2897 NS_ENSURE_ARG(!certFingerprint
.IsEmpty());
2900 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv
);
2904 //-- Get the system certificate
2905 if (!mSystemCertificate
)
2907 nsCOMPtr
<nsIFile
> systemCertFile
;
2908 nsCOMPtr
<nsIProperties
> directoryService
=
2909 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
2910 if (!directoryService
) return NS_ERROR_FAILURE
;
2911 rv
= directoryService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
, NS_GET_IID(nsIFile
),
2912 getter_AddRefs(systemCertFile
));
2913 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2914 systemCertFile
->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
2915 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2916 nsCOMPtr
<nsIZipReader
> systemCertZip
= do_CreateInstance(kZipReaderCID
, &rv
);
2917 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2918 rv
= systemCertZip
->Open(systemCertFile
);
2919 if (NS_SUCCEEDED(rv
))
2921 rv
= systemCertZip
->GetCertificatePrincipal(nsnull
,
2922 getter_AddRefs(mSystemCertificate
));
2923 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2927 //-- Make sure the caller's principal is the system certificate
2928 PRBool isEqual
= PR_FALSE
;
2929 if (mSystemCertificate
)
2931 rv
= mSystemCertificate
->Equals(subjectPrincipal
, &isEqual
);
2932 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2936 JSContext
* cx
= GetCurrentJSContext();
2937 if (!cx
) return NS_ERROR_FAILURE
;
2938 static const char msg1
[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate";
2939 static const char msg2
[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established";
2940 SetPendingException(cx
, mSystemCertificate
? msg1
: msg2
);
2941 return NS_ERROR_FAILURE
;
2944 //-- Get the target principal
2945 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
2946 rv
= DoGetCertificatePrincipal(certFingerprint
, EmptyCString(),
2947 EmptyCString(), nsnull
,
2949 getter_AddRefs(objectPrincipal
));
2950 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2951 rv
= objectPrincipal
->SetCanEnableCapability(capability
, canEnable
);
2952 if (NS_FAILED(rv
)) return NS_ERROR_FAILURE
;
2953 return SavePrincipal(objectPrincipal
);
2956 ////////////////////////////////////////////////
2957 // Methods implementing nsIXPCSecurityManager //
2958 ////////////////////////////////////////////////
2961 nsScriptSecurityManager::CanCreateWrapper(JSContext
*cx
,
2964 nsIClassInfo
*aClassInfo
,
2967 #ifdef DEBUG_CAPS_CanCreateWrapper
2968 char* iidStr
= aIID
.ToString();
2969 printf("### CanCreateWrapper(%s) ", iidStr
);
2972 // XXX Special case for nsIXPCException ?
2973 ClassInfoData objClassInfo
= ClassInfoData(aClassInfo
, nsnull
);
2974 if (objClassInfo
.IsDOMClass())
2976 #ifdef DEBUG_CAPS_CanCreateWrapper
2977 printf("DOM class - GRANTED.\n");
2982 //--See if the object advertises a non-default level of access
2983 // using nsISecurityCheckedComponent
2984 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
2985 do_QueryInterface(aObj
);
2987 nsXPIDLCString objectSecurityLevel
;
2988 if (checkedComponent
)
2989 checkedComponent
->CanCreateWrapper((nsIID
*)&aIID
, getter_Copies(objectSecurityLevel
));
2991 nsresult rv
= CheckXPCPermissions(cx
, aObj
, nsnull
, nsnull
, objectSecurityLevel
);
2994 //-- Access denied, report an error
2995 NS_ConvertUTF8toUTF16
strName("CreateWrapperDenied");
2996 nsCAutoString origin
;
2998 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv2
);
2999 if (NS_SUCCEEDED(rv2
) && subjectPrincipal
) {
3000 GetPrincipalDomainOrigin(subjectPrincipal
, origin
);
3002 NS_ConvertUTF8toUTF16
originUnicode(origin
);
3003 NS_ConvertUTF8toUTF16
className(objClassInfo
.GetName());
3004 const PRUnichar
* formatStrings
[] = {
3008 PRUint32 length
= NS_ARRAY_LENGTH(formatStrings
);
3009 if (originUnicode
.IsEmpty()) {
3012 strName
.AppendLiteral("ForOrigin");
3014 nsXPIDLString errorMsg
;
3015 // We need to keep our existing failure rv and not override it
3016 // with a likely success code from the following string bundle
3017 // call in order to throw the correct security exception later.
3018 rv2
= sStrBundle
->FormatStringFromName(strName
.get(),
3021 getter_Copies(errorMsg
));
3022 NS_ENSURE_SUCCESS(rv2
, rv2
);
3024 SetPendingException(cx
, errorMsg
.get());
3026 #ifdef DEBUG_CAPS_CanCreateWrapper
3027 printf("DENIED.\n");
3031 printf("GRANTED.\n");
3038 #ifdef XPC_IDISPATCH_SUPPORT
3040 nsScriptSecurityManager::CheckComponentPermissions(JSContext
*cx
,
3044 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
3048 // Reformat the CID string so it's suitable for prefs
3049 nsXPIDLCString cidTemp
;
3050 cidTemp
.Adopt(aCID
.ToString());
3051 nsCAutoString
cid(NS_LITERAL_CSTRING("CID") +
3052 Substring(cidTemp
, 1, cidTemp
.Length() - 2));
3055 #ifdef DEBUG_CAPS_CheckComponentPermissions
3056 printf("### CheckComponentPermissions(ClassID.%s) ",cid
.get());
3059 // Look up the policy for this class.
3060 // while this isn't a property we'll treat it as such, using ACCESS_CALL_METHOD
3061 JSAutoRequest
ar(cx
);
3062 jsid cidId
= INTERNED_STRING_TO_JSID(::JS_InternString(cx
, cid
.get()));
3064 ClassInfoData
nameData(nsnull
, "ClassID");
3065 SecurityLevel securityLevel
;
3066 rv
= LookupPolicy(subjectPrincipal
, nameData
, cidId
,
3067 nsIXPCSecurityManager::ACCESS_CALL_METHOD
,
3068 nsnull
, &securityLevel
);
3072 // If there's no policy stored, use the "security.classID.allowByDefault" pref
3073 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3074 securityLevel
.level
= mXPCDefaultGrantAll
? SCRIPT_SECURITY_ALL_ACCESS
:
3075 SCRIPT_SECURITY_NO_ACCESS
;
3077 if (securityLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
3079 #ifdef DEBUG_CAPS_CheckComponentPermissions
3080 printf(" GRANTED.\n");
3085 #ifdef DEBUG_CAPS_CheckComponentPermissions
3086 printf(" DENIED.\n");
3088 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
3093 nsScriptSecurityManager::CanCreateInstance(JSContext
*cx
,
3096 #ifdef DEBUG_CAPS_CanCreateInstance
3097 char* cidStr
= aCID
.ToString();
3098 printf("### CanCreateInstance(%s) ", cidStr
);
3102 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
, nsnull
, nsnull
, nsnull
);
3104 #ifdef XPC_IDISPATCH_SUPPORT
3106 rv
= CheckComponentPermissions(cx
, aCID
);
3111 //-- Access denied, report an error
3112 nsCAutoString
errorMsg("Permission denied to create instance of class. CID=");
3113 char cidStr
[NSID_LENGTH
];
3114 aCID
.ToProvidedString(cidStr
);
3115 errorMsg
.Append(cidStr
);
3116 SetPendingException(cx
, errorMsg
.get());
3118 #ifdef DEBUG_CAPS_CanCreateInstance
3123 printf("GRANTED\n");
3130 nsScriptSecurityManager::CanGetService(JSContext
*cx
,
3133 #ifdef DEBUG_CAPS_CanGetService
3134 char* cidStr
= aCID
.ToString();
3135 printf("### CanGetService(%s) ", cidStr
);
3139 nsresult rv
= CheckXPCPermissions(nsnull
, nsnull
, nsnull
, nsnull
, nsnull
);
3142 //-- Access denied, report an error
3143 nsCAutoString
errorMsg("Permission denied to get service. CID=");
3144 char cidStr
[NSID_LENGTH
];
3145 aCID
.ToProvidedString(cidStr
);
3146 errorMsg
.Append(cidStr
);
3147 SetPendingException(cx
, errorMsg
.get());
3149 #ifdef DEBUG_CAPS_CanGetService
3154 printf("GRANTED\n");
3163 nsScriptSecurityManager::CanAccess(PRUint32 aAction
,
3164 nsAXPCNativeCallContext
* aCallContext
,
3166 JSObject
* aJSObject
,
3168 nsIClassInfo
* aClassInfo
,
3172 return CheckPropertyAccessImpl(aAction
, aCallContext
, cx
,
3173 aJSObject
, aObj
, nsnull
, aClassInfo
,
3174 nsnull
, aPropertyName
, aPolicy
);
3178 nsScriptSecurityManager::CheckXPCPermissions(JSContext
* cx
,
3179 nsISupports
* aObj
, JSObject
* aJSObject
,
3180 nsIPrincipal
* aSubjectPrincipal
,
3181 const char* aObjectSecurityLevel
)
3183 //-- Check for the all-powerful UniversalXPConnect privilege
3184 PRBool ok
= PR_FALSE
;
3185 if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalXPConnect", &ok
)) && ok
)
3188 //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
3189 if (aObjectSecurityLevel
)
3191 if (PL_strcasecmp(aObjectSecurityLevel
, "allAccess") == 0)
3193 if (cx
&& PL_strcasecmp(aObjectSecurityLevel
, "sameOrigin") == 0)
3198 nsCOMPtr
<nsIXPConnectWrappedJS
> xpcwrappedjs
=
3199 do_QueryInterface(aObj
);
3202 rv
= xpcwrappedjs
->GetJSObject(&aJSObject
);
3203 NS_ENSURE_SUCCESS(rv
, rv
);
3207 if (!aSubjectPrincipal
)
3209 // No subject principal passed in. Compute it.
3210 aSubjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
3211 NS_ENSURE_SUCCESS(rv
, rv
);
3213 if (aSubjectPrincipal
&& aJSObject
)
3215 nsIPrincipal
* objectPrincipal
= doGetObjectPrincipal(aJSObject
);
3217 // Only do anything if we have both a subject and object
3219 if (objectPrincipal
)
3222 rv
= aSubjectPrincipal
->Subsumes(objectPrincipal
, &subsumes
);
3223 NS_ENSURE_SUCCESS(rv
, rv
);
3229 else if (PL_strcasecmp(aObjectSecurityLevel
, "noAccess") != 0)
3231 PRBool canAccess
= PR_FALSE
;
3232 if (NS_SUCCEEDED(IsCapabilityEnabled(aObjectSecurityLevel
, &canAccess
)) &&
3238 //-- If user allows scripting of plugins by untrusted scripts,
3239 // and the target object is a plugin, allow the access.
3243 nsCOMPtr
<nsIPluginInstance
> plugin(do_QueryInterface(aObj
, &rv
));
3244 if (NS_SUCCEEDED(rv
))
3246 static PRBool prefSet
= PR_FALSE
;
3247 static PRBool allowPluginAccess
= PR_FALSE
;
3250 rv
= mPrefBranch
->GetBoolPref("security.xpconnect.plugin.unrestricted",
3251 &allowPluginAccess
);
3254 if (allowPluginAccess
)
3259 //-- Access tests failed
3260 return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED
;
3263 /////////////////////////////////////////////
3264 // Method implementing nsIChannelEventSink //
3265 /////////////////////////////////////////////
3267 nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel
* oldChannel
,
3268 nsIChannel
* newChannel
,
3269 PRUint32 redirFlags
,
3270 nsIAsyncVerifyRedirectCallback
*cb
)
3272 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
3273 GetChannelPrincipal(oldChannel
, getter_AddRefs(oldPrincipal
));
3275 nsCOMPtr
<nsIURI
> newURI
;
3276 newChannel
->GetURI(getter_AddRefs(newURI
));
3277 nsCOMPtr
<nsIURI
> newOriginalURI
;
3278 newChannel
->GetOriginalURI(getter_AddRefs(newOriginalURI
));
3280 NS_ENSURE_STATE(oldPrincipal
&& newURI
&& newOriginalURI
);
3282 const PRUint32 flags
=
3283 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
3284 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
3285 nsresult rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newURI
, flags
);
3286 if (NS_SUCCEEDED(rv
) && newOriginalURI
!= newURI
) {
3287 rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newOriginalURI
, flags
);
3293 cb
->OnRedirectVerifyCallback(NS_OK
);
3298 /////////////////////////////////////
3299 // Method implementing nsIObserver //
3300 /////////////////////////////////////
3301 static const char sPrincipalPrefix
[] = "capability.principal";
3302 static const char sPolicyPrefix
[] = "capability.policy.";
3305 nsScriptSecurityManager::Observe(nsISupports
* aObject
, const char* aTopic
,
3306 const PRUnichar
* aMessage
)
3308 nsresult rv
= NS_OK
;
3309 NS_ConvertUTF16toUTF8
messageStr(aMessage
);
3310 const char *message
= messageStr
.get();
3312 static const char jsPrefix
[] = "javascript.";
3313 static const char securityPrefix
[] = "security.";
3314 if ((PL_strncmp(message
, jsPrefix
, sizeof(jsPrefix
)-1) == 0) ||
3315 (PL_strncmp(message
, securityPrefix
, sizeof(securityPrefix
)-1) == 0) )
3317 ScriptSecurityPrefChanged();
3319 else if (PL_strncmp(message
, sPolicyPrefix
, sizeof(sPolicyPrefix
)-1) == 0)
3321 // This will force re-initialization of the pref table
3322 mPolicyPrefsChanged
= PR_TRUE
;
3324 else if ((PL_strncmp(message
, sPrincipalPrefix
, sizeof(sPrincipalPrefix
)-1) == 0) &&
3327 static const char id
[] = "id";
3328 char* lastDot
= PL_strrchr(message
, '.');
3329 //-- This check makes sure the string copy below doesn't overwrite its bounds
3330 if(PL_strlen(lastDot
) >= sizeof(id
))
3332 PL_strcpy(lastDot
+ 1, id
);
3333 const char** idPrefArray
= (const char**)&message
;
3334 rv
= InitPrincipals(1, idPrefArray
);
3340 /////////////////////////////////////////////
3341 // Constructor, Destructor, Initialization //
3342 /////////////////////////////////////////////
3343 nsScriptSecurityManager::nsScriptSecurityManager(void)
3344 : mOriginToPolicyMap(nsnull
),
3345 mDefaultPolicy(nsnull
),
3346 mCapabilities(nsnull
),
3347 mContextPrincipals(nsnull
),
3348 mIsJavaScriptEnabled(PR_FALSE
),
3349 mIsWritingPrefs(PR_FALSE
),
3350 mPolicyPrefsChanged(PR_TRUE
)
3351 #ifdef XPC_IDISPATCH_SUPPORT
3352 , mXPCDefaultGrantAll(PR_FALSE
)
3355 NS_ASSERTION(sizeof(PRWord
) == sizeof(void*),
3356 "PRWord and void* have different lengths on this platform. "
3357 "This may cause a security failure with the SecurityLevel union.");
3358 mPrincipals
.Init(31);
3362 nsresult
nsScriptSecurityManager::Init()
3364 nsXPConnect
* xpconnect
= nsXPConnect::GetXPConnect();
3366 return NS_ERROR_FAILURE
;
3368 NS_ADDREF(sXPConnect
= xpconnect
);
3369 NS_ADDREF(sJSContextStack
= xpconnect
);
3371 JSContext
* cx
= GetSafeJSContext();
3372 if (!cx
) return NS_ERROR_FAILURE
; // this can happen of xpt loading fails
3374 ::JS_BeginRequest(cx
);
3375 if (sEnabledID
== JSID_VOID
)
3376 sEnabledID
= INTERNED_STRING_TO_JSID(::JS_InternString(cx
, "enabled"));
3377 ::JS_EndRequest(cx
);
3381 nsresult rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
3382 NS_ENSURE_SUCCESS(rv
, rv
);
3384 nsCOMPtr
<nsIStringBundleService
> bundleService
=
3385 mozilla::services::GetStringBundleService();
3387 return NS_ERROR_FAILURE
;
3389 rv
= bundleService
->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle
);
3390 NS_ENSURE_SUCCESS(rv
, rv
);
3392 // Create our system principal singleton
3393 nsRefPtr
<nsSystemPrincipal
> system
= new nsSystemPrincipal();
3394 NS_ENSURE_TRUE(system
, NS_ERROR_OUT_OF_MEMORY
);
3396 rv
= system
->Init();
3397 NS_ENSURE_SUCCESS(rv
, rv
);
3399 mSystemPrincipal
= system
;
3401 //-- Register security check callback in the JS engine
3402 // Currently this is used to control access to function.caller
3403 nsCOMPtr
<nsIJSRuntimeService
> runtimeService
=
3404 do_QueryInterface(sXPConnect
, &rv
);
3405 NS_ENSURE_SUCCESS(rv
, rv
);
3407 rv
= runtimeService
->GetRuntime(&sRuntime
);
3408 NS_ENSURE_SUCCESS(rv
, rv
);
3410 static JSSecurityCallbacks securityCallbacks
= {
3414 ContentSecurityPolicyPermitsJSAction
3418 JSSecurityCallbacks
*oldcallbacks
=
3420 JS_SetRuntimeSecurityCallbacks(sRuntime
, &securityCallbacks
);
3421 NS_ASSERTION(!oldcallbacks
, "Someone else set security callbacks!");
3426 static nsScriptSecurityManager
*gScriptSecMan
= nsnull
;
3428 jsid
nsScriptSecurityManager::sEnabledID
= JSID_VOID
;
3430 nsScriptSecurityManager::~nsScriptSecurityManager(void)
3432 NS_ASSERTION(!mContextPrincipals
, "Leaking mContextPrincipals");
3433 delete mOriginToPolicyMap
;
3435 mDefaultPolicy
->Drop();
3436 delete mCapabilities
;
3437 gScriptSecMan
= nsnull
;
3441 nsScriptSecurityManager::Shutdown()
3444 JS_SetRuntimeSecurityCallbacks(sRuntime
, NULL
);
3447 sEnabledID
= JSID_VOID
;
3449 NS_IF_RELEASE(sIOService
);
3450 NS_IF_RELEASE(sXPConnect
);
3451 NS_IF_RELEASE(sJSContextStack
);
3452 NS_IF_RELEASE(sStrBundle
);
3455 nsScriptSecurityManager
*
3456 nsScriptSecurityManager::GetScriptSecurityManager()
3460 nsScriptSecurityManager
* ssManager
= new nsScriptSecurityManager();
3464 rv
= ssManager
->Init();
3465 NS_ASSERTION(NS_SUCCEEDED(rv
), "Failed to initialize nsScriptSecurityManager");
3466 if (NS_FAILED(rv
)) {
3471 rv
= nsJSPrincipals::Startup();
3472 if (NS_FAILED(rv
)) {
3473 NS_WARNING("can't initialize JS engine security protocol glue!");
3478 rv
= sXPConnect
->SetDefaultSecurityManager(ssManager
,
3479 nsIXPCSecurityManager::HOOK_ALL
);
3480 if (NS_FAILED(rv
)) {
3481 NS_WARNING("Failed to install xpconnect security manager!");
3486 gScriptSecMan
= ssManager
;
3488 return gScriptSecMan
;
3491 // Currently this nsGenericFactory constructor is used only from FastLoad
3492 // (XPCOM object deserialization) code, when "creating" the system principal
3495 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
3497 nsIPrincipal
*sysprin
= nsnull
;
3499 NS_ADDREF(sysprin
= gScriptSecMan
->mSystemPrincipal
);
3500 return static_cast<nsSystemPrincipal
*>(sysprin
);
3504 nsScriptSecurityManager::InitPolicies()
3506 // Clear any policies cached on XPConnect wrappers
3507 NS_ENSURE_STATE(sXPConnect
);
3508 nsresult rv
= sXPConnect
->ClearAllWrappedNativeSecurityPolicies();
3509 if (NS_FAILED(rv
)) return rv
;
3511 //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
3512 //-- whose dtor decrements refcount of stored DomainPolicy object
3513 delete mOriginToPolicyMap
;
3515 //-- Marks all the survivor DomainPolicy objects (those cached
3516 //-- by nsPrincipal objects) as invalid: they will be released
3517 //-- on first nsPrincipal::GetSecurityPolicy() attempt.
3518 DomainPolicy::InvalidateAll();
3520 //-- Release old default policy
3521 if(mDefaultPolicy
) {
3522 mDefaultPolicy
->Drop();
3523 mDefaultPolicy
= nsnull
;
3526 //-- Initialize a new mOriginToPolicyMap
3527 mOriginToPolicyMap
=
3528 new nsObjectHashtable(nsnull
, nsnull
, DeleteDomainEntry
, nsnull
);
3529 if (!mOriginToPolicyMap
)
3530 return NS_ERROR_OUT_OF_MEMORY
;
3532 //-- Create, refcount and initialize a new default policy
3533 mDefaultPolicy
= new DomainPolicy();
3534 if (!mDefaultPolicy
)
3535 return NS_ERROR_OUT_OF_MEMORY
;
3537 mDefaultPolicy
->Hold();
3538 if (!mDefaultPolicy
->Init())
3539 return NS_ERROR_UNEXPECTED
;
3541 //-- Initialize the table of security levels
3545 new nsObjectHashtable(nsnull
, nsnull
, DeleteCapability
, nsnull
);
3547 return NS_ERROR_OUT_OF_MEMORY
;
3550 // Get a JS context - we need it to create internalized strings later.
3551 JSContext
* cx
= GetSafeJSContext();
3552 NS_ASSERTION(cx
, "failed to get JS context");
3553 AutoCxPusher
autoPusher(sJSContextStack
, cx
);
3554 rv
= InitDomainPolicy(cx
, "default", mDefaultPolicy
);
3555 NS_ENSURE_SUCCESS(rv
, rv
);
3557 nsXPIDLCString policyNames
;
3558 rv
= mPrefBranch
->GetCharPref("capability.policy.policynames",
3559 getter_Copies(policyNames
));
3561 nsXPIDLCString defaultPolicyNames
;
3562 rv
= mPrefBranch
->GetCharPref("capability.policy.default_policynames",
3563 getter_Copies(defaultPolicyNames
));
3564 policyNames
+= NS_LITERAL_CSTRING(" ") + defaultPolicyNames
;
3566 //-- Initialize domain policies
3567 char* policyCurrent
= policyNames
.BeginWriting();
3568 PRBool morePolicies
= PR_TRUE
;
3569 while (morePolicies
)
3571 while(*policyCurrent
== ' ' || *policyCurrent
== ',')
3573 if (*policyCurrent
== '\0')
3575 char* nameBegin
= policyCurrent
;
3577 while(*policyCurrent
!= '\0' && *policyCurrent
!= ' ' && *policyCurrent
!= ',')
3580 morePolicies
= (*policyCurrent
!= '\0');
3581 *policyCurrent
= '\0';
3584 nsCAutoString
sitesPrefName(
3585 NS_LITERAL_CSTRING(sPolicyPrefix
) +
3586 nsDependentCString(nameBegin
) +
3587 NS_LITERAL_CSTRING(".sites"));
3588 nsXPIDLCString domainList
;
3589 rv
= mPrefBranch
->GetCharPref(sitesPrefName
.get(),
3590 getter_Copies(domainList
));
3594 DomainPolicy
* domainPolicy
= new DomainPolicy();
3596 return NS_ERROR_OUT_OF_MEMORY
;
3598 if (!domainPolicy
->Init())
3600 delete domainPolicy
;
3601 return NS_ERROR_UNEXPECTED
;
3603 domainPolicy
->Hold();
3604 //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
3605 char* domainStart
= domainList
.BeginWriting();
3606 char* domainCurrent
= domainStart
;
3607 char* lastDot
= nsnull
;
3608 char* nextToLastDot
= nsnull
;
3609 PRBool moreDomains
= PR_TRUE
;
3612 if (*domainCurrent
== ' ' || *domainCurrent
== '\0')
3614 moreDomains
= (*domainCurrent
!= '\0');
3615 *domainCurrent
= '\0';
3616 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : domainStart
);
3617 DomainEntry
*newEntry
= new DomainEntry(domainStart
, domainPolicy
);
3620 domainPolicy
->Drop();
3621 return NS_ERROR_OUT_OF_MEMORY
;
3624 newEntry
->mPolicyName_DEBUG
= nameBegin
;
3626 DomainEntry
*existingEntry
= (DomainEntry
*)
3627 mOriginToPolicyMap
->Get(&key
);
3629 mOriginToPolicyMap
->Put(&key
, newEntry
);
3632 if (existingEntry
->Matches(domainStart
))
3634 newEntry
->mNext
= existingEntry
;
3635 mOriginToPolicyMap
->Put(&key
, newEntry
);
3639 while (existingEntry
->mNext
)
3641 if (existingEntry
->mNext
->Matches(domainStart
))
3643 newEntry
->mNext
= existingEntry
->mNext
;
3644 existingEntry
->mNext
= newEntry
;
3647 existingEntry
= existingEntry
->mNext
;
3649 if (!existingEntry
->mNext
)
3650 existingEntry
->mNext
= newEntry
;
3653 domainStart
= domainCurrent
+ 1;
3654 lastDot
= nextToLastDot
= nsnull
;
3656 else if (*domainCurrent
== '.')
3658 nextToLastDot
= lastDot
;
3659 lastDot
= domainCurrent
;
3664 rv
= InitDomainPolicy(cx
, nameBegin
, domainPolicy
);
3665 domainPolicy
->Drop();
3670 // Reset the "dirty" flag
3671 mPolicyPrefsChanged
= PR_FALSE
;
3673 #ifdef DEBUG_CAPS_HACKER
3681 nsScriptSecurityManager::InitDomainPolicy(JSContext
* cx
,
3682 const char* aPolicyName
,
3683 DomainPolicy
* aDomainPolicy
)
3686 nsCAutoString
policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix
) +
3687 nsDependentCString(aPolicyName
) +
3688 NS_LITERAL_CSTRING("."));
3689 PRUint32 prefixLength
= policyPrefix
.Length() - 1; // subtract the '.'
3693 rv
= mPrefBranch
->GetChildList(policyPrefix
.get(),
3694 &prefCount
, &prefNames
);
3695 if (NS_FAILED(rv
)) return rv
;
3699 //-- Populate the policy
3700 PRUint32 currentPref
= 0;
3701 for (; currentPref
< prefCount
; currentPref
++)
3703 // Get the class name
3704 const char* start
= prefNames
[currentPref
] + prefixLength
+ 1;
3705 char* end
= PL_strchr(start
, '.');
3706 if (!end
) // malformed pref, bail on this one
3708 static const char sitesStr
[] = "sites";
3710 // We dealt with "sites" in InitPolicies(), so no need to do
3712 if (PL_strncmp(start
, sitesStr
, sizeof(sitesStr
)-1) == 0)
3715 // Get the pref value
3716 nsXPIDLCString prefValue
;
3717 rv
= mPrefBranch
->GetCharPref(prefNames
[currentPref
],
3718 getter_Copies(prefValue
));
3719 if (NS_FAILED(rv
) || !prefValue
)
3722 SecurityLevel secLevel
;
3723 if (PL_strcasecmp(prefValue
, "noAccess") == 0)
3724 secLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
3725 else if (PL_strcasecmp(prefValue
, "allAccess") == 0)
3726 secLevel
.level
= SCRIPT_SECURITY_ALL_ACCESS
;
3727 else if (PL_strcasecmp(prefValue
, "sameOrigin") == 0)
3728 secLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
3730 { //-- pref value is the name of a capability
3731 nsCStringKey
secLevelKey(prefValue
);
3732 secLevel
.capability
=
3733 reinterpret_cast<char*>(mCapabilities
->Get(&secLevelKey
));
3734 if (!secLevel
.capability
)
3736 secLevel
.capability
= NS_strdup(prefValue
);
3737 if (!secLevel
.capability
)
3739 mCapabilities
->Put(&secLevelKey
,
3740 secLevel
.capability
);
3745 // Find or store this class in the classes table
3746 ClassPolicy
* cpolicy
=
3747 static_cast<ClassPolicy
*>
3748 (PL_DHashTableOperate(aDomainPolicy
, start
,
3753 // If this is the wildcard class (class '*'), save it in mWildcardPolicy
3754 // (we leave it stored in the hashtable too to take care of the cleanup)
3755 if ((*start
== '*') && (end
== start
+ 1)) {
3756 aDomainPolicy
->mWildcardPolicy
= cpolicy
;
3758 // Make sure that cpolicy knows about aDomainPolicy so it can reset
3759 // the mWildcardPolicy pointer as needed if it gets moved in the
3761 cpolicy
->mDomainWeAreWildcardFor
= aDomainPolicy
;
3764 // Get the property name
3766 end
= PL_strchr(start
, '.');
3770 JSAutoRequest
ar(cx
);
3772 JSString
* propertyKey
= ::JS_InternString(cx
, start
);
3774 return NS_ERROR_OUT_OF_MEMORY
;
3776 // Store this property in the class policy
3777 PropertyPolicy
* ppolicy
=
3778 static_cast<PropertyPolicy
*>
3779 (PL_DHashTableOperate(cpolicy
->mPolicy
, propertyKey
,
3784 if (end
) // The pref specifies an access mode
3787 if (PL_strcasecmp(start
, "set") == 0)
3788 ppolicy
->mSet
= secLevel
;
3790 ppolicy
->mGet
= secLevel
;
3794 if (ppolicy
->mGet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3795 ppolicy
->mGet
= secLevel
;
3796 if (ppolicy
->mSet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
3797 ppolicy
->mSet
= secLevel
;
3801 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
3802 if (currentPref
< prefCount
) // Loop exited early because of out-of-memory error
3803 return NS_ERROR_OUT_OF_MEMORY
;
3808 // XXXbz We should really just get a prefbranch to handle this...
3810 nsScriptSecurityManager::GetPrincipalPrefNames(const char* prefBase
,
3811 nsCString
& grantedPref
,
3812 nsCString
& deniedPref
,
3813 nsCString
& subjectNamePref
)
3815 char* lastDot
= PL_strrchr(prefBase
, '.');
3816 if (!lastDot
) return NS_ERROR_FAILURE
;
3817 PRInt32 prefLen
= lastDot
- prefBase
+ 1;
3819 grantedPref
.Assign(prefBase
, prefLen
);
3820 deniedPref
.Assign(prefBase
, prefLen
);
3821 subjectNamePref
.Assign(prefBase
, prefLen
);
3823 #define GRANTED "granted"
3824 #define DENIED "denied"
3825 #define SUBJECTNAME "subjectName"
3827 grantedPref
.AppendLiteral(GRANTED
);
3828 if (grantedPref
.Length() != prefLen
+ sizeof(GRANTED
) - 1) {
3829 return NS_ERROR_OUT_OF_MEMORY
;
3832 deniedPref
.AppendLiteral(DENIED
);
3833 if (deniedPref
.Length() != prefLen
+ sizeof(DENIED
) - 1) {
3834 return NS_ERROR_OUT_OF_MEMORY
;
3837 subjectNamePref
.AppendLiteral(SUBJECTNAME
);
3838 if (subjectNamePref
.Length() != prefLen
+ sizeof(SUBJECTNAME
) - 1) {
3839 return NS_ERROR_OUT_OF_MEMORY
;
3850 nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount
, const char** aPrefNames
)
3852 /* This is the principal preference syntax:
3853 * capability.principal.[codebase|codebaseTrusted|certificate].<name>.[id|granted|denied]
3855 * user_pref("capability.principal.certificate.p1.id","12:34:AB:CD");
3856 * user_pref("capability.principal.certificate.p1.granted","Capability1 Capability2");
3857 * user_pref("capability.principal.certificate.p1.denied","Capability3");
3860 /* codebaseTrusted means a codebase principal that can enable capabilities even if
3861 * codebase principals are disabled. Don't use trustedCodebase except with unspoofable
3862 * URLs such as HTTPS URLs.
3865 static const char idSuffix
[] = ".id";
3866 for (PRUint32 c
= 0; c
< aPrefCount
; c
++)
3868 PRInt32 prefNameLen
= PL_strlen(aPrefNames
[c
]) -
3869 (NS_ARRAY_LENGTH(idSuffix
) - 1);
3870 if (PL_strcasecmp(aPrefNames
[c
] + prefNameLen
, idSuffix
) != 0)
3874 if (NS_FAILED(mPrefBranch
->GetCharPref(aPrefNames
[c
], getter_Copies(id
))))
3875 return NS_ERROR_FAILURE
;
3877 nsCAutoString grantedPrefName
;
3878 nsCAutoString deniedPrefName
;
3879 nsCAutoString subjectNamePrefName
;
3880 nsresult rv
= GetPrincipalPrefNames(aPrefNames
[c
],
3883 subjectNamePrefName
);
3884 if (rv
== NS_ERROR_OUT_OF_MEMORY
)
3889 nsXPIDLCString grantedList
;
3890 mPrefBranch
->GetCharPref(grantedPrefName
.get(),
3891 getter_Copies(grantedList
));
3892 nsXPIDLCString deniedList
;
3893 mPrefBranch
->GetCharPref(deniedPrefName
.get(),
3894 getter_Copies(deniedList
));
3895 nsXPIDLCString subjectName
;
3896 mPrefBranch
->GetCharPref(subjectNamePrefName
.get(),
3897 getter_Copies(subjectName
));
3899 //-- Delete prefs if their value is the empty string
3900 if (id
.IsEmpty() || (grantedList
.IsEmpty() && deniedList
.IsEmpty()))
3902 mPrefBranch
->ClearUserPref(aPrefNames
[c
]);
3903 mPrefBranch
->ClearUserPref(grantedPrefName
.get());
3904 mPrefBranch
->ClearUserPref(deniedPrefName
.get());
3905 mPrefBranch
->ClearUserPref(subjectNamePrefName
.get());
3909 //-- Create a principal based on the prefs
3910 static const char certificateName
[] = "capability.principal.certificate";
3911 static const char codebaseName
[] = "capability.principal.codebase";
3912 static const char codebaseTrustedName
[] = "capability.principal.codebaseTrusted";
3914 PRBool isCert
= PR_FALSE
;
3915 PRBool isTrusted
= PR_FALSE
;
3917 if (PL_strncmp(aPrefNames
[c
], certificateName
,
3918 sizeof(certificateName
) - 1) == 0)
3922 else if (PL_strncmp(aPrefNames
[c
], codebaseName
,
3923 sizeof(codebaseName
) - 1) == 0)
3925 isTrusted
= (PL_strncmp(aPrefNames
[c
], codebaseTrustedName
,
3926 sizeof(codebaseTrustedName
) - 1) == 0);
3930 NS_ERROR("Not a codebase or a certificate?!");
3933 nsRefPtr
<nsPrincipal
> newPrincipal
= new nsPrincipal();
3935 return NS_ERROR_OUT_OF_MEMORY
;
3937 rv
= newPrincipal
->InitFromPersistent(aPrefNames
[c
], id
, subjectName
,
3939 grantedList
, deniedList
, nsnull
,
3941 if (NS_SUCCEEDED(rv
))
3942 mPrincipals
.Put(newPrincipal
, newPrincipal
);
3947 const char nsScriptSecurityManager::sJSEnabledPrefName
[] =
3948 "javascript.enabled";
3949 const char nsScriptSecurityManager::sFileOriginPolicyPrefName
[] =
3950 "security.fileuri.strict_origin_policy";
3951 #ifdef XPC_IDISPATCH_SUPPORT
3952 const char nsScriptSecurityManager::sXPCDefaultGrantAllName
[] =
3953 "security.classID.allowByDefault";
3957 nsScriptSecurityManager::ScriptSecurityPrefChanged()
3959 // JavaScript defaults to enabled in failure cases.
3960 mIsJavaScriptEnabled
= PR_TRUE
;
3962 sStrictFileOriginPolicy
= PR_TRUE
;
3964 #ifdef XPC_IDISPATCH_SUPPORT
3965 // Granting XPC Priveleges defaults to disabled in failure cases.
3966 mXPCDefaultGrantAll
= PR_FALSE
;
3977 rv
= mPrefBranch
->GetBoolPref(sJSEnabledPrefName
, &temp
);
3978 if (NS_SUCCEEDED(rv
))
3979 mIsJavaScriptEnabled
= temp
;
3981 rv
= mPrefBranch
->GetBoolPref(sFileOriginPolicyPrefName
, &temp
);
3982 if (NS_SUCCEEDED(rv
))
3983 sStrictFileOriginPolicy
= NS_SUCCEEDED(rv
) && temp
;
3985 #ifdef XPC_IDISPATCH_SUPPORT
3986 rv
= mPrefBranch
->GetBoolPref(sXPCDefaultGrantAllName
, &temp
);
3987 if (NS_SUCCEEDED(rv
))
3988 mXPCDefaultGrantAll
= temp
;
3993 nsScriptSecurityManager::InitPrefs()
3996 nsCOMPtr
<nsIPrefService
> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
3997 NS_ENSURE_SUCCESS(rv
, rv
);
3998 rv
= prefService
->GetBranch(nsnull
, getter_AddRefs(mPrefBranch
));
3999 NS_ENSURE_SUCCESS(rv
, rv
);
4000 nsCOMPtr
<nsIPrefBranch2
> prefBranchInternal(do_QueryInterface(mPrefBranch
, &rv
));
4001 NS_ENSURE_SUCCESS(rv
, rv
);
4003 // Set the initial value of the "javascript.enabled" prefs
4004 ScriptSecurityPrefChanged();
4005 // set observer callbacks in case the value of the prefs change
4006 prefBranchInternal
->AddObserver(sJSEnabledPrefName
, this, PR_FALSE
);
4007 prefBranchInternal
->AddObserver(sFileOriginPolicyPrefName
, this, PR_FALSE
);
4008 #ifdef XPC_IDISPATCH_SUPPORT
4009 prefBranchInternal
->AddObserver(sXPCDefaultGrantAllName
, this, PR_FALSE
);
4014 // Set a callback for policy pref changes
4015 prefBranchInternal
->AddObserver(sPolicyPrefix
, this, PR_FALSE
);
4017 //-- Initialize the principals database from prefs
4018 rv
= mPrefBranch
->GetChildList(sPrincipalPrefix
, &prefCount
, &prefNames
);
4019 if (NS_SUCCEEDED(rv
) && prefCount
> 0)
4021 rv
= InitPrincipals(prefCount
, (const char**)prefNames
);
4022 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
4023 NS_ENSURE_SUCCESS(rv
, rv
);
4025 //-- Set a callback for principal changes
4026 prefBranchInternal
->AddObserver(sPrincipalPrefix
, this, PR_FALSE
);
4031 ///////////////////////////////////////////////////////////////////////////////
4032 // The following code prints the contents of the policy DB to the console.
4033 #ifdef DEBUG_CAPS_HACKER
4035 //typedef PLDHashOperator
4036 //(* PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
4037 // PRUint32 number, void *arg);
4038 static PLDHashOperator
4039 PrintPropertyPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
4040 PRUint32 number
, void *arg
)
4042 PropertyPolicy
* pp
= (PropertyPolicy
*)entry
;
4043 nsCAutoString
prop(" ");
4044 JSContext
* cx
= (JSContext
*)arg
;
4045 prop
.AppendInt((PRUint32
)pp
->key
);
4047 prop
.AppendWithConversion((PRUnichar
*)JS_GetStringChars(pp
->key
));
4049 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mGet
))
4050 prop
.AppendInt(pp
->mGet
.level
);
4052 prop
+= pp
->mGet
.capability
;
4055 if (SECURITY_ACCESS_LEVEL_FLAG(pp
->mSet
))
4056 prop
.AppendInt(pp
->mSet
.level
);
4058 prop
+= pp
->mSet
.capability
;
4060 printf("%s.\n", prop
.get());
4061 return PL_DHASH_NEXT
;
4064 static PLDHashOperator
4065 PrintClassPolicy(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
4066 PRUint32 number
, void *arg
)
4068 ClassPolicy
* cp
= (ClassPolicy
*)entry
;
4069 printf(" %s\n", cp
->key
);
4071 PL_DHashTableEnumerate(cp
->mPolicy
, PrintPropertyPolicy
, arg
);
4072 return PL_DHASH_NEXT
;
4076 // (* nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
4078 PrintDomainPolicy(nsHashKey
*aKey
, void *aData
, void* aClosure
)
4080 DomainEntry
* de
= (DomainEntry
*)aData
;
4081 printf("----------------------------\n");
4082 printf("Domain: %s Policy Name: %s.\n", de
->mOrigin
.get(),
4083 de
->mPolicyName_DEBUG
.get());
4084 PL_DHashTableEnumerate(de
->mDomainPolicy
, PrintClassPolicy
, aClosure
);
4089 PrintCapability(nsHashKey
*aKey
, void *aData
, void* aClosure
)
4091 char* cap
= (char*)aData
;
4092 printf(" %s.\n", cap
);
4097 nsScriptSecurityManager::PrintPolicyDB()
4099 printf("############## Security Policies ###############\n");
4100 if(mOriginToPolicyMap
)
4102 JSContext
* cx
= GetCurrentJSContext();
4104 cx
= GetSafeJSContext();
4105 printf("----------------------------\n");
4106 printf("Domain: Default.\n");
4107 PL_DHashTableEnumerate(mDefaultPolicy
, PrintClassPolicy
, (void*)cx
);
4108 mOriginToPolicyMap
->Enumerate(PrintDomainPolicy
, (void*)cx
);
4110 printf("############ End Security Policies #############\n\n");
4111 printf("############## Capabilities ###############\n");
4112 mCapabilities
->Enumerate(PrintCapability
);
4113 printf("############## End Capabilities ###############\n");