1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=4 et sw=4 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsScriptSecurityManager.h"
9 #include "mozilla/Util.h"
11 #include "js/OldDebugAPI.h"
12 #include "xpcprivate.h"
13 #include "XPCWrapper.h"
14 #include "nsIServiceManager.h"
15 #include "nsIScriptObjectPrincipal.h"
16 #include "nsIScriptContext.h"
18 #include "nsINestedURI.h"
20 #include "nsJSPrincipals.h"
21 #include "nsSystemPrincipal.h"
22 #include "nsPrincipal.h"
23 #include "nsNullPrincipal.h"
24 #include "DomainPolicy.h"
25 #include "nsXPIDLString.h"
27 #include "nsCRTGlue.h"
30 #include "nsIXPConnect.h"
31 #include "nsIXPCSecurityManager.h"
32 #include "nsTextFormatter.h"
33 #include "nsIStringBundle.h"
34 #include "nsNetUtil.h"
35 #include "nsIProperties.h"
36 #include "nsDirectoryServiceDefs.h"
38 #include "nsIFileURL.h"
39 #include "nsIZipReader.h"
40 #include "nsIXPConnect.h"
41 #include "nsIScriptGlobalObject.h"
42 #include "nsPIDOMWindow.h"
43 #include "nsIDocShell.h"
44 #include "nsIPrompt.h"
45 #include "nsIWindowWatcher.h"
46 #include "nsIConsoleService.h"
47 #include "nsISecurityCheckedComponent.h"
48 #include "nsIJSRuntimeService.h"
49 #include "nsIObserverService.h"
50 #include "nsIContent.h"
51 #include "nsAutoPtr.h"
52 #include "nsDOMJSUtils.h"
53 #include "nsAboutProtocolUtils.h"
54 #include "nsIClassInfo.h"
55 #include "nsIURIFixup.h"
56 #include "nsCDefaultURIFixup.h"
57 #include "nsIChromeRegistry.h"
58 #include "nsIContentSecurityPolicy.h"
59 #include "nsIAsyncVerifyRedirectCallback.h"
60 #include "mozilla/Preferences.h"
61 #include "mozilla/dom/BindingUtils.h"
63 #include "mozilla/ClearOnShutdown.h"
64 #include "mozilla/StaticPtr.h"
65 #include "nsContentUtils.h"
66 #include "nsCxPusher.h"
67 #include "nsJSUtils.h"
69 // This should be probably defined on some other place... but I couldn't find it
70 #define WEBAPPS_PERM_NAME "webapps-manage"
72 using namespace mozilla
;
73 using namespace mozilla::dom
;
75 static NS_DEFINE_CID(kZipReaderCID
, NS_ZIPREADER_CID
);
77 nsIIOService
*nsScriptSecurityManager::sIOService
= nullptr;
78 nsIStringBundle
*nsScriptSecurityManager::sStrBundle
= nullptr;
79 JSRuntime
*nsScriptSecurityManager::sRuntime
= 0;
80 bool nsScriptSecurityManager::sStrictFileOriginPolicy
= true;
82 // Lazily initialized. Use the getter below.
83 static jsid sEnabledID
= JSID_VOID
;
87 if (sEnabledID
!= JSID_VOID
)
88 return JS::HandleId::fromMarkedLocation(&sEnabledID
);
90 sEnabledID
= INTERNED_STRING_TO_JSID(cx
, JS_InternString(cx
, "enabled"));
91 return JS::HandleId::fromMarkedLocation(&sEnabledID
);
95 nsScriptSecurityManager::SubjectIsPrivileged()
97 JSContext
*cx
= GetCurrentJSContext();
98 if (cx
&& xpc::IsUniversalXPConnectEnabled(cx
))
100 bool isSystem
= false;
101 return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem
)) && isSystem
;
104 ///////////////////////////
105 // Convenience Functions //
106 ///////////////////////////
107 // Result of this function should not be freed.
108 static inline const PRUnichar
*
109 IDToString(JSContext
*cx
, jsid id_
)
111 JS::RootedId
id(cx
, id_
);
112 if (JSID_IS_STRING(id
))
113 return JS_GetInternedStringChars(JSID_TO_STRING(id
));
115 JS::Rooted
<JS::Value
> idval(cx
);
116 if (!JS_IdToValue(cx
, id
, idval
.address()))
118 JSString
*str
= JS::ToString(cx
, idval
);
121 return JS_GetStringCharsZ(cx
, str
);
124 class nsAutoInPrincipalDomainOriginSetter
{
126 nsAutoInPrincipalDomainOriginSetter() {
127 ++sInPrincipalDomainOrigin
;
129 ~nsAutoInPrincipalDomainOriginSetter() {
130 --sInPrincipalDomainOrigin
;
132 static uint32_t sInPrincipalDomainOrigin
;
134 uint32_t nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
;
138 GetOriginFromURI(nsIURI
* aURI
, nsACString
& aOrigin
)
140 if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
> 1) {
141 // Allow a single recursive call to GetPrincipalDomainOrigin, since that
142 // might be happening on a different principal from the first call. But
143 // after that, cut off the recursion; it just indicates that something
144 // we're doing in this method causes us to reenter a security check here.
145 return NS_ERROR_NOT_AVAILABLE
;
148 nsAutoInPrincipalDomainOriginSetter autoSetter
;
150 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
151 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
153 nsAutoCString hostPort
;
155 nsresult rv
= uri
->GetHostPort(hostPort
);
156 if (NS_SUCCEEDED(rv
)) {
157 nsAutoCString scheme
;
158 rv
= uri
->GetScheme(scheme
);
159 NS_ENSURE_SUCCESS(rv
, rv
);
160 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + hostPort
;
163 // Some URIs (e.g., nsSimpleURI) don't support host. Just
164 // get the full spec.
165 rv
= uri
->GetSpec(aOrigin
);
166 NS_ENSURE_SUCCESS(rv
, rv
);
174 GetPrincipalDomainOrigin(nsIPrincipal
* aPrincipal
,
178 nsCOMPtr
<nsIURI
> uri
;
179 aPrincipal
->GetDomain(getter_AddRefs(uri
));
181 aPrincipal
->GetURI(getter_AddRefs(uri
));
183 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
185 return GetOriginFromURI(uri
, aOrigin
);
188 inline void SetPendingException(JSContext
*cx
, const char *aMsg
)
190 JS_ReportError(cx
, "%s", aMsg
);
193 inline void SetPendingException(JSContext
*cx
, const PRUnichar
*aMsg
)
195 JS_ReportError(cx
, "%hs", aMsg
);
198 // DomainPolicy members
199 uint32_t DomainPolicy::sGeneration
= 0;
201 // Helper class to get stuff from the ClassInfo and not waste extra time with
202 // virtual method calls for things it has already gotten
206 ClassInfoData(nsIClassInfo
*aClassInfo
, const char *aName
)
207 : mClassInfo(aClassInfo
),
208 mName(const_cast<char *>(aName
)),
217 nsMemory::Free(mName
);
224 nsresult rv
= mClassInfo
->GetFlags(&mFlags
);
240 return !!(GetFlags() & nsIClassInfo::DOM_OBJECT
);
243 const char* GetName()
247 mClassInfo
->GetClassDescription(&mName
);
251 mMustFreeName
= true;
253 mName
= const_cast<char *>("UnnamedClass");
261 nsIClassInfo
*mClassInfo
; // WEAK
269 nsScriptSecurityManager::GetCurrentJSContext()
271 // Get JSContext from stack.
272 return nsXPConnect::XPConnect()->GetCurrentJSContext();
276 nsScriptSecurityManager::GetSafeJSContext()
278 // Get JSContext from stack.
279 return nsXPConnect::XPConnect()->GetSafeJSContext();
284 nsScriptSecurityManager::SecurityCompareURIs(nsIURI
* aSourceURI
,
287 return NS_SecurityCompareURIs(aSourceURI
, aTargetURI
, sStrictFileOriginPolicy
);
290 // SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI
291 // is consistent with NS_SecurityCompareURIs. See nsNetUtil.h.
293 nsScriptSecurityManager::SecurityHashURI(nsIURI
* aURI
)
295 return NS_SecurityHashURI(aURI
);
299 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel
* aChannel
,
300 nsIPrincipal
** aPrincipal
)
302 NS_PRECONDITION(aChannel
, "Must have channel!");
303 nsCOMPtr
<nsISupports
> owner
;
304 aChannel
->GetOwner(getter_AddRefs(owner
));
306 CallQueryInterface(owner
, aPrincipal
);
312 // OK, get the principal from the URI. Make sure this does the same thing
313 // as nsDocument::Reset and XULDocument::StartDocumentLoad.
314 nsCOMPtr
<nsIURI
> uri
;
315 nsresult rv
= NS_GetFinalChannelURI(aChannel
, getter_AddRefs(uri
));
316 NS_ENSURE_SUCCESS(rv
, rv
);
318 nsCOMPtr
<nsIDocShell
> docShell
;
319 NS_QueryNotificationCallbacks(aChannel
, docShell
);
322 return GetDocShellCodebasePrincipal(uri
, docShell
, aPrincipal
);
325 return GetCodebasePrincipalInternal(uri
, UNKNOWN_APP_ID
,
326 /* isInBrowserElement */ false, aPrincipal
);
330 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal
* aPrincipal
,
333 *aIsSystem
= (aPrincipal
== mSystemPrincipal
);
337 NS_IMETHODIMP_(nsIPrincipal
*)
338 nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext
*cx
)
340 NS_ASSERTION(cx
== GetCurrentJSContext(),
341 "Uh, cx is not the current JS context!");
343 nsresult rv
= NS_ERROR_FAILURE
;
344 nsIPrincipal
*principal
= GetSubjectPrincipal(cx
, &rv
);
355 // Table of security levels
357 DeleteCapability(nsHashKey
*aKey
, void *aData
, void* closure
)
363 //-- Per-Domain Policy - applies to one or more protocols or hosts
366 DomainEntry(const char* aOrigin
,
367 DomainPolicy
* aDomainPolicy
) : mOrigin(aOrigin
),
368 mDomainPolicy(aDomainPolicy
),
371 mDomainPolicy
->Hold();
376 mDomainPolicy
->Drop();
379 bool Matches(const char *anOrigin
)
381 int len
= strlen(anOrigin
);
382 int thisLen
= mOrigin
.Length();
385 if (mOrigin
.RFindChar(':', thisLen
-1, 1) != -1)
386 //-- Policy applies to all URLs of this scheme, compare scheme only
387 return mOrigin
.EqualsIgnoreCase(anOrigin
, thisLen
);
389 //-- Policy applies to a particular host; compare domains
390 if (!mOrigin
.Equals(anOrigin
+ (len
- thisLen
)))
394 char charBefore
= anOrigin
[len
-thisLen
-1];
395 return (charBefore
== '.' || charBefore
== ':' || charBefore
== '/');
399 DomainPolicy
* mDomainPolicy
;
404 DeleteDomainEntry(nsHashKey
*aKey
, void *aData
, void* closure
)
406 DomainEntry
*entry
= (DomainEntry
*) aData
;
409 DomainEntry
*next
= entry
->mNext
;
416 /////////////////////////////
417 // nsScriptSecurityManager //
418 /////////////////////////////
420 ////////////////////////////////////
421 // Methods implementing ISupports //
422 ////////////////////////////////////
423 NS_IMPL_ISUPPORTS4(nsScriptSecurityManager
,
424 nsIScriptSecurityManager
,
425 nsIXPCSecurityManager
,
429 ///////////////////////////////////////////////////
430 // Methods implementing nsIScriptSecurityManager //
431 ///////////////////////////////////////////////////
433 ///////////////// Security Checks /////////////////
436 nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext
*cx
)
438 // Get the security manager
439 nsScriptSecurityManager
*ssm
=
440 nsScriptSecurityManager::GetScriptSecurityManager();
442 NS_ASSERTION(ssm
, "Failed to get security manager service");
447 nsIPrincipal
* subjectPrincipal
= ssm
->GetSubjectPrincipal(cx
, &rv
);
449 NS_ASSERTION(NS_SUCCEEDED(rv
), "CSP: Failed to get nsIPrincipal from js context");
451 return false; // Not just absence of principal, but failure.
453 if (!subjectPrincipal
)
456 nsCOMPtr
<nsIContentSecurityPolicy
> csp
;
457 rv
= subjectPrincipal
->GetCsp(getter_AddRefs(csp
));
458 NS_ASSERTION(NS_SUCCEEDED(rv
), "CSP: Failed to get CSP from principal.");
460 // don't do anything unless there's a CSP
465 bool reportViolation
= false;
466 rv
= csp
->GetAllowsEval(&reportViolation
, &evalOK
);
470 NS_WARNING("CSP: failed to get allowsEval");
471 return true; // fail open to not break sites.
474 if (reportViolation
) {
475 nsAutoString fileName
;
476 unsigned lineNum
= 0;
477 NS_NAMED_LITERAL_STRING(scriptSample
, "call to eval() or related function blocked by CSP");
479 JS::RootedScript
script(cx
);
480 if (JS_DescribeScriptedCaller(cx
, &script
, &lineNum
)) {
481 if (const char *file
= JS_GetScriptFilename(cx
, script
)) {
482 CopyUTF8toUTF16(nsDependentCString(file
), fileName
);
485 csp
->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL
,
497 nsScriptSecurityManager::CheckObjectAccess(JSContext
*cx
, JS::Handle
<JSObject
*> obj
,
498 JS::Handle
<jsid
> id
, JSAccessMode mode
,
499 JS::MutableHandle
<JS::Value
> vp
)
501 // Get the security manager
502 nsScriptSecurityManager
*ssm
=
503 nsScriptSecurityManager::GetScriptSecurityManager();
505 NS_WARN_IF_FALSE(ssm
, "Failed to get security manager service");
509 // Get the object being accessed. We protect these cases:
510 // 1. The Function.prototype.caller property's value, which might lead
511 // an attacker up a call-stack to a function or another object from
512 // a different trust domain.
513 // 2. A user-defined getter or setter function accessible on another
514 // trust domain's window or document object.
515 // vp can be a primitive, in that case, we use obj as the target
517 JSObject
* target
= JSVAL_IS_PRIMITIVE(vp
) ? obj
: JSVAL_TO_OBJECT(vp
);
519 // Do the same-origin check -- this sets a JS exception if the check fails.
520 // Pass the parent object's class name, as we have no class-info for it.
522 ssm
->CheckPropertyAccess(cx
, target
, js::GetObjectClass(obj
)->name
, id
,
523 (mode
& JSACC_WRITE
) ?
524 (int32_t)nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
525 (int32_t)nsIXPCSecurityManager::ACCESS_GET_PROPERTY
);
528 return false; // Security check failed (XXX was an error reported?)
534 nsScriptSecurityManager::CheckPropertyAccess(JSContext
* cx
,
536 const char* aClassName
,
540 return CheckPropertyAccessImpl(aAction
, nullptr, cx
, aJSObject
,
542 aClassName
, aProperty
, nullptr);
546 nsScriptSecurityManager::CheckSameOrigin(JSContext
* cx
,
551 // Get a context if necessary
554 cx
= GetCurrentJSContext();
556 return NS_OK
; // No JS context, so allow access
559 // Get a principal from the context
560 nsIPrincipal
* sourcePrincipal
= GetSubjectPrincipal(cx
, &rv
);
564 if (!sourcePrincipal
)
566 NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
570 if (sourcePrincipal
== mSystemPrincipal
)
572 // This is a system (chrome) script, so allow access
576 // Get the original URI from the source principal.
577 // This has the effect of ignoring any change to document.domain
578 // which must be done to avoid DNS spoofing (bug 154930)
579 nsCOMPtr
<nsIURI
> sourceURI
;
580 sourcePrincipal
->GetDomain(getter_AddRefs(sourceURI
));
582 sourcePrincipal
->GetURI(getter_AddRefs(sourceURI
));
583 NS_ENSURE_TRUE(sourceURI
, NS_ERROR_FAILURE
);
587 if (!SecurityCompareURIs(sourceURI
, aTargetURI
))
589 ReportError(cx
, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI
, aTargetURI
);
590 return NS_ERROR_DOM_BAD_URI
;
596 nsScriptSecurityManager::CheckSameOriginURI(nsIURI
* aSourceURI
,
600 if (!SecurityCompareURIs(aSourceURI
, aTargetURI
))
603 ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"),
604 aSourceURI
, aTargetURI
);
606 return NS_ERROR_DOM_BAD_URI
;
612 nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction
,
613 nsAXPCNativeCallContext
* aCallContext
,
614 JSContext
* cx
, JSObject
* aJSObject
,
616 nsIClassInfo
* aClassInfo
,
617 const char* aClassName
, jsid aProperty
,
618 void** aCachedClassPolicy
)
621 JS::RootedObject
jsObject(cx
, aJSObject
);
622 JS::RootedId
property(cx
, aProperty
);
623 nsIPrincipal
* subjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
627 if (!subjectPrincipal
|| subjectPrincipal
== mSystemPrincipal
)
628 // We have native code or the system principal: just allow access
631 nsCOMPtr
<nsIPrincipal
> objectPrincipal
;
633 // Hold the class info data here so we don't have to go back to virtual
634 // methods all the time
635 ClassInfoData
classInfoData(aClassInfo
, aClassName
);
637 //-- Look up the security policy for this class and subject domain
638 SecurityLevel securityLevel
;
639 rv
= LookupPolicy(subjectPrincipal
, classInfoData
, property
, aAction
,
640 (ClassPolicy
**)aCachedClassPolicy
, &securityLevel
);
644 if (securityLevel
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
646 // No policy found for this property so use the default of last resort.
647 // If we were called from somewhere other than XPConnect
648 // (no XPC call context), assume this is a DOM class. Otherwise,
649 // ask the ClassInfo.
650 if (!aCallContext
|| classInfoData
.IsDOMClass())
651 securityLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
653 securityLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
656 if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel
))
657 // This flag means securityLevel is allAccess, noAccess, or sameOrigin
659 switch (securityLevel
.level
)
661 case SCRIPT_SECURITY_NO_ACCESS
:
662 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
665 case SCRIPT_SECURITY_ALL_ACCESS
:
669 case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
:
671 nsCOMPtr
<nsIPrincipal
> principalHolder
;
674 objectPrincipal
= doGetObjectPrincipal(jsObject
);
675 if (!objectPrincipal
)
676 rv
= NS_ERROR_DOM_SECURITY_ERR
;
680 NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
681 return NS_ERROR_FAILURE
;
684 rv
= CheckSameOriginDOMProp(subjectPrincipal
, objectPrincipal
,
689 NS_ERROR("Bad Security Level Value");
690 return NS_ERROR_FAILURE
;
693 else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
695 rv
= SubjectIsPrivileged() ? NS_OK
: NS_ERROR_DOM_SECURITY_ERR
;
698 if (NS_SUCCEEDED(rv
))
703 //--See if the object advertises a non-default level of access
704 // using nsISecurityCheckedComponent
705 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
706 do_QueryInterface(aObj
);
708 nsXPIDLCString objectSecurityLevel
;
709 if (checkedComponent
)
711 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
712 nsCOMPtr
<nsIInterfaceInfo
> interfaceInfo
;
713 const nsIID
* objIID
= nullptr;
714 rv
= aCallContext
->GetCalleeWrapper(getter_AddRefs(wrapper
));
715 if (NS_SUCCEEDED(rv
) && wrapper
)
716 rv
= wrapper
->FindInterfaceWithMember(property
, getter_AddRefs(interfaceInfo
));
717 if (NS_SUCCEEDED(rv
) && interfaceInfo
)
718 rv
= interfaceInfo
->GetIIDShared(&objIID
);
719 if (NS_SUCCEEDED(rv
) && objIID
)
723 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
724 checkedComponent
->CanGetProperty(objIID
,
725 IDToString(cx
, property
),
726 getter_Copies(objectSecurityLevel
));
728 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
729 checkedComponent
->CanSetProperty(objIID
,
730 IDToString(cx
, property
),
731 getter_Copies(objectSecurityLevel
));
733 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
734 checkedComponent
->CanCallMethod(objIID
,
735 IDToString(cx
, property
),
736 getter_Copies(objectSecurityLevel
));
740 rv
= CheckXPCPermissions(cx
, aObj
, jsObject
, subjectPrincipal
,
741 objectSecurityLevel
);
743 if (NS_FAILED(rv
)) //-- Security tests failed, access is denied, report error
745 nsAutoString stringName
;
748 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY
:
749 stringName
.AssignLiteral("GetPropertyDeniedOrigins");
751 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY
:
752 stringName
.AssignLiteral("SetPropertyDeniedOrigins");
754 case nsIXPCSecurityManager::ACCESS_CALL_METHOD
:
755 stringName
.AssignLiteral("CallMethodDeniedOrigins");
758 // Null out objectPrincipal for now, so we don't leak information about
759 // it. Whenever we can report different error strings to content and
760 // the UI we can take this out again.
761 objectPrincipal
= nullptr;
763 NS_ConvertUTF8toUTF16
className(classInfoData
.GetName());
764 nsAutoCString subjectOrigin
;
765 nsAutoCString subjectDomain
;
766 if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
) {
767 nsCOMPtr
<nsIURI
> uri
, domain
;
768 subjectPrincipal
->GetURI(getter_AddRefs(uri
));
769 if (uri
) { // Object principal might be expanded
770 GetOriginFromURI(uri
, subjectOrigin
);
772 subjectPrincipal
->GetDomain(getter_AddRefs(domain
));
774 GetOriginFromURI(domain
, subjectDomain
);
777 subjectOrigin
.AssignLiteral("the security manager");
779 NS_ConvertUTF8toUTF16
subjectOriginUnicode(subjectOrigin
);
780 NS_ConvertUTF8toUTF16
subjectDomainUnicode(subjectDomain
);
782 nsAutoCString objectOrigin
;
783 nsAutoCString objectDomain
;
784 if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
&&
786 nsCOMPtr
<nsIURI
> uri
, domain
;
787 objectPrincipal
->GetURI(getter_AddRefs(uri
));
788 if (uri
) { // Object principal might be system
789 GetOriginFromURI(uri
, objectOrigin
);
791 objectPrincipal
->GetDomain(getter_AddRefs(domain
));
793 GetOriginFromURI(domain
, objectDomain
);
796 NS_ConvertUTF8toUTF16
objectOriginUnicode(objectOrigin
);
797 NS_ConvertUTF8toUTF16
objectDomainUnicode(objectDomain
);
799 nsXPIDLString errorMsg
;
800 const PRUnichar
*formatStrings
[] =
802 subjectOriginUnicode
.get(),
804 IDToString(cx
, property
),
805 objectOriginUnicode
.get(),
806 subjectDomainUnicode
.get(),
807 objectDomainUnicode
.get()
810 uint32_t length
= ArrayLength(formatStrings
);
812 // XXXbz Our localization system is stupid and can't handle not showing
813 // some strings that get passed in. Which means that we have to get
814 // our length precisely right: it has to be exactly the number of
815 // strings our format string wants. This means we'll have to move
816 // strings in the array as needed, sadly...
817 if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin
||
819 stringName
.AppendLiteral("OnlySubject");
822 // default to a length that doesn't include the domains, then
823 // increase it as needed.
825 if (!subjectDomainUnicode
.IsEmpty()) {
826 stringName
.AppendLiteral("SubjectDomain");
829 if (!objectDomainUnicode
.IsEmpty()) {
830 stringName
.AppendLiteral("ObjectDomain");
832 if (length
!= ArrayLength(formatStrings
)) {
833 // We have an object domain but not a subject domain.
834 // Scoot our string over one slot. See the XXX comment
835 // above for why we need to do this.
836 formatStrings
[length
-1] = formatStrings
[length
];
841 // We need to keep our existing failure rv and not override it
842 // with a likely success code from the following string bundle
843 // call in order to throw the correct security exception later.
844 nsresult rv2
= sStrBundle
->FormatStringFromName(stringName
.get(),
847 getter_Copies(errorMsg
));
848 if (NS_FAILED(rv2
)) {
849 // Might just be missing the string... Do our best
850 errorMsg
= stringName
;
853 SetPendingException(cx
, errorMsg
.get());
861 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
862 nsIPrincipal
* aObject
)
865 ** Get origin of subject and object and compare.
867 if (aSubject
== aObject
)
870 if (!AppAttributesEqual(aSubject
, aObject
)) {
871 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
874 // Default to false, and change if that turns out wrong.
875 bool subjectSetDomain
= false;
876 bool objectSetDomain
= false;
878 nsCOMPtr
<nsIURI
> subjectURI
;
879 nsCOMPtr
<nsIURI
> objectURI
;
881 aSubject
->GetDomain(getter_AddRefs(subjectURI
));
883 aSubject
->GetURI(getter_AddRefs(subjectURI
));
885 subjectSetDomain
= true;
888 aObject
->GetDomain(getter_AddRefs(objectURI
));
890 aObject
->GetURI(getter_AddRefs(objectURI
));
892 objectSetDomain
= true;
895 if (SecurityCompareURIs(subjectURI
, objectURI
))
896 { // If either the subject or the object has changed its principal by
897 // explicitly setting document.domain then the other must also have
898 // done so in order to be considered the same origin. This prevents
899 // DNS spoofing based on document.domain (154930)
901 // If both or neither explicitly set their domain, allow the access
902 if (subjectSetDomain
== objectSetDomain
)
907 ** Access tests failed, so now report error.
909 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
912 // It's important that
914 // CheckSameOriginPrincipal(A, B) == NS_OK
918 // HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
920 // if principals A and B could ever be used as keys in a hashtable.
921 // Violation of this invariant leads to spurious failures of hashtable
922 // lookups. See bug 454850.
925 nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal
* aPrincipal
)
927 nsCOMPtr
<nsIURI
> uri
;
928 aPrincipal
->GetDomain(getter_AddRefs(uri
));
930 aPrincipal
->GetURI(getter_AddRefs(uri
));
931 return SecurityHashURI(uri
);
935 nsScriptSecurityManager::AppAttributesEqual(nsIPrincipal
* aFirst
,
936 nsIPrincipal
* aSecond
)
938 MOZ_ASSERT(aFirst
&& aSecond
, "Don't pass null pointers!");
940 uint32_t firstAppId
= nsIScriptSecurityManager::UNKNOWN_APP_ID
;
941 if (!aFirst
->GetUnknownAppId()) {
942 firstAppId
= aFirst
->GetAppId();
945 uint32_t secondAppId
= nsIScriptSecurityManager::UNKNOWN_APP_ID
;
946 if (!aSecond
->GetUnknownAppId()) {
947 secondAppId
= aSecond
->GetAppId();
950 return ((firstAppId
== secondAppId
) &&
951 (aFirst
->GetIsInBrowserElement() == aSecond
->GetIsInBrowserElement()));
955 nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
956 nsIPrincipal
* aObject
,
961 rv
= aSubject
->Subsumes(aObject
, &subsumes
);
962 if (NS_SUCCEEDED(rv
) && !subsumes
) {
963 rv
= NS_ERROR_DOM_PROP_ACCESS_DENIED
;
966 if (NS_SUCCEEDED(rv
))
970 * Content can't ever touch chrome (we check for UniversalXPConnect later)
972 if (aObject
== mSystemPrincipal
)
973 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
976 ** Access tests failed, so now report error.
978 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
982 nsScriptSecurityManager::LookupPolicy(nsIPrincipal
* aPrincipal
,
983 ClassInfoData
& aClassData
,
984 JS::Handle
<jsid
> aProperty
,
986 ClassPolicy
** aCachedClassPolicy
,
987 SecurityLevel
* result
)
991 JS::RootedId
property(cx
, aProperty
);
992 result
->level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
994 DomainPolicy
* dpolicy
= nullptr;
995 //-- Initialize policies if necessary
996 if (mPolicyPrefsChanged
)
998 if (!mPrefInitialized
) {
1000 NS_ENSURE_SUCCESS(rv
, rv
);
1002 rv
= InitPolicies();
1008 aPrincipal
->GetSecurityPolicy((void**)&dpolicy
);
1011 if (!dpolicy
&& mOriginToPolicyMap
)
1013 //-- Look up the relevant domain policy, if any
1014 if (nsCOMPtr
<nsIExpandedPrincipal
> exp
= do_QueryInterface(aPrincipal
))
1016 // For expanded principals domain origin is not defined so let's just
1017 // use the default policy
1018 dpolicy
= mDefaultPolicy
;
1022 nsAutoCString origin
;
1023 rv
= GetPrincipalDomainOrigin(aPrincipal
, origin
);
1024 NS_ENSURE_SUCCESS(rv
, rv
);
1026 char *start
= origin
.BeginWriting();
1027 const char *nextToLastDot
= nullptr;
1028 const char *lastDot
= nullptr;
1029 const char *colon
= nullptr;
1032 //-- search domain (stop at the end of the string or at the 3rd slash)
1033 for (uint32_t slashes
=0; *p
; p
++)
1035 if (*p
== '/' && ++slashes
== 3)
1037 *p
= '\0'; // truncate at 3rd slash
1042 nextToLastDot
= lastDot
;
1045 else if (!colon
&& *p
== ':')
1049 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : start
);
1050 DomainEntry
*de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&key
);
1053 nsAutoCString
scheme(start
, colon
-start
+1);
1054 nsCStringKey
schemeKey(scheme
);
1055 de
= (DomainEntry
*) mOriginToPolicyMap
->Get(&schemeKey
);
1060 if (de
->Matches(start
))
1062 dpolicy
= de
->mDomainPolicy
;
1069 dpolicy
= mDefaultPolicy
;
1072 aPrincipal
->SetSecurityPolicy((void*)dpolicy
);
1075 ClassPolicy
* cpolicy
= nullptr;
1077 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1079 // No per-domain policy for this principal (the more common case)
1080 // so look for a cached class policy from the object wrapper
1081 cpolicy
= *aCachedClassPolicy
;
1085 { //-- No cached policy for this class, need to look it up
1086 cpolicy
= static_cast<ClassPolicy
*>
1087 (PL_DHashTableOperate(dpolicy
,
1088 aClassData
.GetName(),
1091 if (PL_DHASH_ENTRY_IS_FREE(cpolicy
))
1092 cpolicy
= NO_POLICY_FOR_CLASS
;
1094 if ((dpolicy
== mDefaultPolicy
) && aCachedClassPolicy
)
1095 *aCachedClassPolicy
= cpolicy
;
1098 NS_ASSERTION(JSID_IS_INT(property
) || JSID_IS_OBJECT(property
) ||
1099 JSID_IS_STRING(property
), "Property must be a valid id");
1101 // Only atomized strings are stored in the policies' hash tables.
1102 if (!JSID_IS_STRING(property
))
1105 JS::RootedString
propertyKey(cx
, JSID_TO_STRING(property
));
1107 // We look for a PropertyPolicy in the following places:
1108 // 1) The ClassPolicy for our class we got from our DomainPolicy
1109 // 2) The mWildcardPolicy of our DomainPolicy
1110 // 3) The ClassPolicy for our class we got from mDefaultPolicy
1111 // 4) The mWildcardPolicy of our mDefaultPolicy
1112 PropertyPolicy
* ppolicy
= nullptr;
1113 if (cpolicy
!= NO_POLICY_FOR_CLASS
)
1115 ppolicy
= static_cast<PropertyPolicy
*>
1116 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1121 // If there is no class policy for this property, and we have a wildcard
1122 // policy, try that.
1123 if (dpolicy
->mWildcardPolicy
&&
1124 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1127 static_cast<PropertyPolicy
*>
1128 (PL_DHashTableOperate(dpolicy
->mWildcardPolicy
->mPolicy
,
1133 // If dpolicy is not the defauly policy and there's no class or wildcard
1134 // policy for this property, check the default policy for this class and
1135 // the default wildcard policy
1136 if (dpolicy
!= mDefaultPolicy
&&
1137 (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)))
1139 cpolicy
= static_cast<ClassPolicy
*>
1140 (PL_DHashTableOperate(mDefaultPolicy
,
1141 aClassData
.GetName(),
1144 if (PL_DHASH_ENTRY_IS_BUSY(cpolicy
))
1147 static_cast<PropertyPolicy
*>
1148 (PL_DHashTableOperate(cpolicy
->mPolicy
,
1153 if ((!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
)) &&
1154 mDefaultPolicy
->mWildcardPolicy
)
1157 static_cast<PropertyPolicy
*>
1158 (PL_DHashTableOperate(mDefaultPolicy
->mWildcardPolicy
->mPolicy
,
1164 if (!ppolicy
|| PL_DHASH_ENTRY_IS_FREE(ppolicy
))
1167 // Get the correct security level from the property policy
1168 if (aAction
== nsIXPCSecurityManager::ACCESS_SET_PROPERTY
)
1169 *result
= ppolicy
->mSet
;
1171 *result
= ppolicy
->mGet
;
1178 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext
*cx
, nsIURI
*aURI
)
1180 // Get principal of currently executing script.
1182 nsIPrincipal
* principal
= GetSubjectPrincipal(cx
, &rv
);
1186 // Native code can load all URIs.
1190 rv
= CheckLoadURIWithPrincipal(principal
, aURI
,
1191 nsIScriptSecurityManager::STANDARD
);
1192 if (NS_SUCCEEDED(rv
)) {
1197 // See if we're attempting to load a file: URI. If so, let a
1198 // UniversalXPConnect capability trump the above check.
1199 bool isFile
= false;
1201 if (NS_FAILED(aURI
->SchemeIs("file", &isFile
)) ||
1202 NS_FAILED(aURI
->SchemeIs("resource", &isRes
)))
1203 return NS_ERROR_FAILURE
;
1204 if (isFile
|| isRes
)
1206 if (SubjectIsPrivileged())
1212 if (NS_FAILED(aURI
->GetAsciiSpec(spec
)))
1213 return NS_ERROR_FAILURE
;
1214 nsAutoCString
msg("Access to '");
1216 msg
.AppendLiteral("' from script denied");
1217 SetPendingException(cx
, msg
.get());
1218 return NS_ERROR_DOM_BAD_URI
;
1222 * Helper method to handle cases where a flag passed to
1223 * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
1224 * nsIProtocolHandler flags set.
1225 * @return if success, access is allowed. Otherwise, deny access
1228 DenyAccessIfURIHasFlags(nsIURI
* aURI
, uint32_t aURIFlags
)
1230 NS_PRECONDITION(aURI
, "Must have URI!");
1234 NS_URIChainHasFlags(aURI
, aURIFlags
, &uriHasFlags
);
1235 NS_ENSURE_SUCCESS(rv
, rv
);
1238 return NS_ERROR_DOM_BAD_URI
;
1245 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal
* aPrincipal
,
1249 NS_PRECONDITION(aPrincipal
, "CheckLoadURIWithPrincipal must have a principal");
1250 // If someone passes a flag that we don't understand, we should
1251 // fail, because they may need a security check that we don't
1253 NS_ENSURE_FALSE(aFlags
& ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
1254 nsIScriptSecurityManager::ALLOW_CHROME
|
1255 nsIScriptSecurityManager::DISALLOW_SCRIPT
|
1256 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
|
1257 nsIScriptSecurityManager::DONT_REPORT_ERRORS
),
1258 NS_ERROR_UNEXPECTED
);
1259 NS_ENSURE_ARG_POINTER(aPrincipal
);
1260 NS_ENSURE_ARG_POINTER(aTargetURI
);
1262 // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
1263 // would do such inheriting. That would be URIs that do not have their own
1264 // security context. We do this even for the system principal.
1265 if (aFlags
& nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
) {
1267 DenyAccessIfURIHasFlags(aTargetURI
,
1268 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
);
1269 NS_ENSURE_SUCCESS(rv
, rv
);
1272 if (aPrincipal
== mSystemPrincipal
) {
1277 nsCOMPtr
<nsIURI
> sourceURI
;
1278 aPrincipal
->GetURI(getter_AddRefs(sourceURI
));
1280 nsCOMPtr
<nsIExpandedPrincipal
> expanded
= do_QueryInterface(aPrincipal
);
1282 nsTArray
< nsCOMPtr
<nsIPrincipal
> > *whiteList
;
1283 expanded
->GetWhiteList(&whiteList
);
1284 for (uint32_t i
= 0; i
< whiteList
->Length(); ++i
) {
1285 nsresult rv
= CheckLoadURIWithPrincipal((*whiteList
)[i
],
1288 if (NS_SUCCEEDED(rv
)) {
1289 // Allow access if it succeeded with one of the white listed principals
1293 // None of our whitelisted principals worked.
1294 return NS_ERROR_DOM_BAD_URI
;
1296 NS_ERROR("Non-system principals or expanded principal passed to CheckLoadURIWithPrincipal "
1297 "must have a URI!");
1298 return NS_ERROR_UNEXPECTED
;
1301 // Automatic loads are not allowed from certain protocols.
1302 if (aFlags
& nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
) {
1304 DenyAccessIfURIHasFlags(sourceURI
,
1305 nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT
);
1306 NS_ENSURE_SUCCESS(rv
, rv
);
1309 // If either URI is a nested URI, get the base URI
1310 nsCOMPtr
<nsIURI
> sourceBaseURI
= NS_GetInnermostURI(sourceURI
);
1311 nsCOMPtr
<nsIURI
> targetBaseURI
= NS_GetInnermostURI(aTargetURI
);
1313 //-- get the target scheme
1314 nsAutoCString targetScheme
;
1315 nsresult rv
= targetBaseURI
->GetScheme(targetScheme
);
1316 if (NS_FAILED(rv
)) return rv
;
1318 //-- Some callers do not allow loading javascript:
1319 if ((aFlags
& nsIScriptSecurityManager::DISALLOW_SCRIPT
) &&
1320 targetScheme
.EqualsLiteral("javascript"))
1322 return NS_ERROR_DOM_BAD_URI
;
1325 NS_NAMED_LITERAL_STRING(errorTag
, "CheckLoadURIError");
1326 bool reportErrors
= !(aFlags
& nsIScriptSecurityManager::DONT_REPORT_ERRORS
);
1328 // Check for uris that are only loadable by principals that subsume them
1330 rv
= NS_URIChainHasFlags(targetBaseURI
,
1331 nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS
,
1333 NS_ENSURE_SUCCESS(rv
, rv
);
1336 return aPrincipal
->CheckMayLoad(targetBaseURI
, true, false);
1339 //-- get the source scheme
1340 nsAutoCString sourceScheme
;
1341 rv
= sourceBaseURI
->GetScheme(sourceScheme
);
1342 if (NS_FAILED(rv
)) return rv
;
1344 if (sourceScheme
.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME
)) {
1345 // A null principal can target its own URI.
1346 if (sourceURI
== aTargetURI
) {
1350 else if (targetScheme
.Equals(sourceScheme
,
1351 nsCaseInsensitiveCStringComparator()))
1353 // every scheme can access another URI from the same scheme,
1354 // as long as they don't represent null principals...
1355 // Or they don't require an special permission to do so
1359 rv
= NS_URIChainHasFlags(targetBaseURI
,
1360 nsIProtocolHandler::URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM
,
1362 NS_ENSURE_SUCCESS(rv
, rv
);
1365 // In this case, we allow opening only if the source and target URIS
1366 // are on the same domain, or the opening URI has the webapps
1367 // permision granted
1368 if (!SecurityCompareURIs(sourceBaseURI
,targetBaseURI
) &&
1369 !nsContentUtils::IsExactSitePermAllow(aPrincipal
,WEBAPPS_PERM_NAME
)){
1370 return NS_ERROR_DOM_BAD_URI
;
1376 // If the schemes don't match, the policy is specified by the protocol
1377 // flags on the target URI. Note that the order of policy checks here is
1378 // very important! We start from most restrictive and work our way down.
1379 // Note that since we're working with the innermost URI, we can just use
1380 // the methods that work on chains of nested URIs and they will only look
1381 // at the flags for our one URI.
1383 // Check for system target URI
1384 rv
= DenyAccessIfURIHasFlags(targetBaseURI
,
1385 nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
);
1386 if (NS_FAILED(rv
)) {
1387 // Deny access, since the origin principal is not system
1389 ReportError(nullptr, errorTag
, sourceURI
, aTargetURI
);
1394 // Check for chrome target URI
1395 rv
= NS_URIChainHasFlags(targetBaseURI
,
1396 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1398 NS_ENSURE_SUCCESS(rv
, rv
);
1400 if (aFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) {
1401 if (!targetScheme
.EqualsLiteral("chrome")) {
1402 // for now don't change behavior for resource: or moz-icon:
1406 // allow load only if chrome package is whitelisted
1407 nsCOMPtr
<nsIXULChromeRegistry
> reg(do_GetService(
1408 NS_CHROMEREGISTRY_CONTRACTID
));
1410 bool accessAllowed
= false;
1411 reg
->AllowContentToAccess(targetBaseURI
, &accessAllowed
);
1412 if (accessAllowed
) {
1418 // resource: and chrome: are equivalent, securitywise
1419 // That's bogus!! Fix this. But watch out for
1420 // the view-source stylesheet?
1421 bool sourceIsChrome
;
1422 rv
= NS_URIChainHasFlags(sourceBaseURI
,
1423 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1425 NS_ENSURE_SUCCESS(rv
, rv
);
1426 if (sourceIsChrome
) {
1430 ReportError(nullptr, errorTag
, sourceURI
, aTargetURI
);
1432 return NS_ERROR_DOM_BAD_URI
;
1435 // Check for target URI pointing to a file
1436 rv
= NS_URIChainHasFlags(targetBaseURI
,
1437 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
1439 NS_ENSURE_SUCCESS(rv
, rv
);
1441 // resource: and chrome: are equivalent, securitywise
1442 // That's bogus!! Fix this. But watch out for
1443 // the view-source stylesheet?
1444 bool sourceIsChrome
;
1445 rv
= NS_URIChainHasFlags(sourceURI
,
1446 nsIProtocolHandler::URI_IS_UI_RESOURCE
,
1448 NS_ENSURE_SUCCESS(rv
, rv
);
1449 if (sourceIsChrome
) {
1453 // Now check capability policies
1454 static const char loadURIPrefGroup
[] = "checkloaduri";
1455 ClassInfoData
nameData(nullptr, loadURIPrefGroup
);
1457 SecurityLevel secLevel
;
1458 rv
= LookupPolicy(aPrincipal
, nameData
, EnabledID(),
1459 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1460 nullptr, &secLevel
);
1461 if (NS_SUCCEEDED(rv
) && secLevel
.level
== SCRIPT_SECURITY_ALL_ACCESS
)
1463 // OK for this site!
1468 ReportError(nullptr, errorTag
, sourceURI
, aTargetURI
);
1470 return NS_ERROR_DOM_BAD_URI
;
1473 // OK, everyone is allowed to load this, since unflagged handlers are
1474 // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
1475 // need to warn. At some point we'll want to make this warning into an
1476 // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
1477 rv
= NS_URIChainHasFlags(targetBaseURI
,
1478 nsIProtocolHandler::URI_LOADABLE_BY_ANYONE
,
1480 NS_ENSURE_SUCCESS(rv
, rv
);
1482 nsXPIDLString message
;
1483 NS_ConvertASCIItoUTF16
ucsTargetScheme(targetScheme
);
1484 const PRUnichar
* formatStrings
[] = { ucsTargetScheme
.get() };
1486 FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
1488 ArrayLength(formatStrings
),
1489 getter_Copies(message
));
1490 if (NS_SUCCEEDED(rv
)) {
1491 nsCOMPtr
<nsIConsoleService
> console(
1492 do_GetService("@mozilla.org/consoleservice;1"));
1493 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1495 console
->LogStringMessage(message
.get());
1503 nsScriptSecurityManager::ReportError(JSContext
* cx
, const nsAString
& messageTag
,
1504 nsIURI
* aSource
, nsIURI
* aTarget
)
1507 NS_ENSURE_TRUE(aSource
&& aTarget
, NS_ERROR_NULL_POINTER
);
1509 // Get the source URL spec
1510 nsAutoCString sourceSpec
;
1511 rv
= aSource
->GetAsciiSpec(sourceSpec
);
1512 NS_ENSURE_SUCCESS(rv
, rv
);
1514 // Get the target URL spec
1515 nsAutoCString targetSpec
;
1516 rv
= aTarget
->GetAsciiSpec(targetSpec
);
1517 NS_ENSURE_SUCCESS(rv
, rv
);
1519 // Localize the error message
1520 nsXPIDLString message
;
1521 NS_ConvertASCIItoUTF16
ucsSourceSpec(sourceSpec
);
1522 NS_ConvertASCIItoUTF16
ucsTargetSpec(targetSpec
);
1523 const PRUnichar
*formatStrings
[] = { ucsSourceSpec
.get(), ucsTargetSpec
.get() };
1524 rv
= sStrBundle
->FormatStringFromName(PromiseFlatString(messageTag
).get(),
1526 ArrayLength(formatStrings
),
1527 getter_Copies(message
));
1528 NS_ENSURE_SUCCESS(rv
, rv
);
1530 // If a JS context was passed in, set a JS exception.
1531 // Otherwise, print the error message directly to the JS console
1532 // and to standard output
1535 SetPendingException(cx
, message
.get());
1537 else // Print directly to the console
1539 nsCOMPtr
<nsIConsoleService
> console(
1540 do_GetService("@mozilla.org/consoleservice;1"));
1541 NS_ENSURE_TRUE(console
, NS_ERROR_FAILURE
);
1543 console
->LogStringMessage(message
.get());
1549 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal
* aPrincipal
,
1550 const nsACString
& aTargetURIStr
,
1554 nsCOMPtr
<nsIURI
> target
;
1555 rv
= NS_NewURI(getter_AddRefs(target
), aTargetURIStr
,
1556 nullptr, nullptr, sIOService
);
1557 NS_ENSURE_SUCCESS(rv
, rv
);
1559 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1560 if (rv
== NS_ERROR_DOM_BAD_URI
) {
1561 // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
1565 NS_ENSURE_SUCCESS(rv
, rv
);
1567 // Now start testing fixup -- since aTargetURIStr is a string, not
1568 // an nsIURI, we may well end up fixing it up before loading.
1569 // Note: This needs to stay in sync with the nsIURIFixup api.
1570 nsCOMPtr
<nsIURIFixup
> fixup
= do_GetService(NS_URIFIXUP_CONTRACTID
);
1575 uint32_t flags
[] = {
1576 nsIURIFixup::FIXUP_FLAG_NONE
,
1577 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
,
1578 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
,
1579 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
|
1580 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
1583 for (uint32_t i
= 0; i
< ArrayLength(flags
); ++i
) {
1584 rv
= fixup
->CreateFixupURI(aTargetURIStr
, flags
[i
], nullptr,
1585 getter_AddRefs(target
));
1586 NS_ENSURE_SUCCESS(rv
, rv
);
1588 rv
= CheckLoadURIWithPrincipal(aPrincipal
, target
, aFlags
);
1589 if (rv
== NS_ERROR_DOM_BAD_URI
) {
1590 // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
1594 NS_ENSURE_SUCCESS(rv
, rv
);
1601 nsScriptSecurityManager::ScriptAllowed(JSObject
*aGlobal
)
1603 MOZ_ASSERT(aGlobal
);
1604 MOZ_ASSERT(JS_IsGlobalObject(aGlobal
) || js::IsOuterObject(aGlobal
));
1606 JS::RootedObject
global(cx
, js::UncheckedUnwrap(aGlobal
, /* stopAtOuter = */ false));
1608 // Check the bits on the compartment private.
1609 xpc::Scriptability
& scriptability
= xpc::Scriptability::Get(aGlobal
);
1610 if (!scriptability
.Allowed()) {
1614 // If the compartment is immune to script policy, we're done.
1615 if (scriptability
.IsImmuneToScriptPolicy()) {
1619 // Check for a per-site policy.
1620 static const char jsPrefGroupName
[] = "javascript";
1621 ClassInfoData
nameData(nullptr, jsPrefGroupName
);
1622 SecurityLevel secLevel
;
1623 nsresult rv
= LookupPolicy(doGetObjectPrincipal(global
), nameData
,
1625 nsIXPCSecurityManager::ACCESS_GET_PROPERTY
,
1626 nullptr, &secLevel
);
1627 if (NS_FAILED(rv
) || secLevel
.level
== SCRIPT_SECURITY_NO_ACCESS
) {
1634 ///////////////// Principals ///////////////////////
1636 nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal
**aSubjectPrincipal
)
1639 *aSubjectPrincipal
= doGetSubjectPrincipal(&rv
);
1640 if (NS_SUCCEEDED(rv
))
1641 NS_IF_ADDREF(*aSubjectPrincipal
);
1646 nsScriptSecurityManager::doGetSubjectPrincipal(nsresult
* rv
)
1648 NS_PRECONDITION(rv
, "Null out param");
1649 JSContext
*cx
= GetCurrentJSContext();
1655 return GetSubjectPrincipal(cx
, rv
);
1659 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal
**result
)
1661 NS_ADDREF(*result
= mSystemPrincipal
);
1667 nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem
)
1669 NS_ENSURE_ARG_POINTER(aIsSystem
);
1672 if (!mSystemPrincipal
)
1675 nsCOMPtr
<nsIPrincipal
> subject
;
1676 nsresult rv
= GetSubjectPrincipal(getter_AddRefs(subject
));
1682 // No subject principal means no JS is running;
1683 // this is the equivalent of system principal code
1688 return mSystemPrincipal
->Equals(subject
, aIsSystem
);
1692 nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI
* aURI
, uint32_t aAppId
,
1694 nsIPrincipal
**result
)
1696 // I _think_ it's safe to not create null principals here based on aURI.
1697 // At least all the callers would do the right thing in those cases, as far
1698 // as I can tell. --bz
1700 nsCOMPtr
<nsIURIWithPrincipal
> uriPrinc
= do_QueryInterface(aURI
);
1702 nsCOMPtr
<nsIPrincipal
> principal
;
1703 uriPrinc
->GetPrincipal(getter_AddRefs(principal
));
1704 if (!principal
|| principal
== mSystemPrincipal
) {
1705 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
1708 principal
.forget(result
);
1713 nsRefPtr
<nsPrincipal
> codebase
= new nsPrincipal();
1715 return NS_ERROR_OUT_OF_MEMORY
;
1717 nsresult rv
= codebase
->Init(aURI
, aAppId
, aInMozBrowser
);
1721 NS_ADDREF(*result
= codebase
);
1727 nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI
* aURI
,
1728 nsIPrincipal
** aPrincipal
)
1730 return GetCodebasePrincipalInternal(aURI
,
1731 nsIScriptSecurityManager::UNKNOWN_APP_ID
,
1736 nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI
* aURI
,
1737 nsIPrincipal
** aPrincipal
)
1739 return GetCodebasePrincipalInternal(aURI
, nsIScriptSecurityManager::NO_APP_ID
,
1744 nsScriptSecurityManager::GetCodebasePrincipal(nsIURI
* aURI
,
1745 nsIPrincipal
** aPrincipal
)
1747 return GetNoAppCodebasePrincipal(aURI
, aPrincipal
);
1751 nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI
* aURI
,
1754 nsIPrincipal
** aPrincipal
)
1756 NS_ENSURE_TRUE(aAppId
!= nsIScriptSecurityManager::UNKNOWN_APP_ID
,
1757 NS_ERROR_INVALID_ARG
);
1759 return GetCodebasePrincipalInternal(aURI
, aAppId
, aInMozBrowser
, aPrincipal
);
1763 nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI
* aURI
,
1764 nsIDocShell
* aDocShell
,
1765 nsIPrincipal
** aPrincipal
)
1767 return GetCodebasePrincipalInternal(aURI
,
1768 aDocShell
->GetAppId(),
1769 aDocShell
->GetIsInBrowserElement(),
1774 nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI
*aURI
,
1777 nsIPrincipal
**result
)
1779 NS_ENSURE_ARG(aURI
);
1781 bool inheritsPrincipal
;
1783 NS_URIChainHasFlags(aURI
,
1784 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
1785 &inheritsPrincipal
);
1786 if (NS_FAILED(rv
) || inheritsPrincipal
) {
1787 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID
, result
);
1790 nsCOMPtr
<nsIPrincipal
> principal
;
1791 rv
= CreateCodebasePrincipal(aURI
, aAppId
, aInMozBrowser
,
1792 getter_AddRefs(principal
));
1793 NS_ENSURE_SUCCESS(rv
, rv
);
1794 NS_IF_ADDREF(*result
= principal
);
1800 nsScriptSecurityManager::GetSubjectPrincipal(JSContext
*cx
,
1804 JSCompartment
*compartment
= js::GetContextCompartment(cx
);
1806 // The context should always be in a compartment, either one it has entered
1807 // or the one associated with its global.
1808 MOZ_ASSERT(!!compartment
);
1810 JSPrincipals
*principals
= JS_GetCompartmentPrincipals(compartment
);
1811 return nsJSPrincipals::get(principals
);
1815 nsScriptSecurityManager::GetObjectPrincipal(JSContext
*aCx
, JSObject
*aObj
,
1816 nsIPrincipal
**result
)
1818 JS::Rooted
<JSObject
*> obj(aCx
, aObj
);
1819 *result
= doGetObjectPrincipal(obj
);
1821 return NS_ERROR_FAILURE
;
1828 nsScriptSecurityManager::doGetObjectPrincipal(JSObject
*aObj
)
1830 JSCompartment
*compartment
= js::GetObjectCompartment(aObj
);
1831 JSPrincipals
*principals
= JS_GetCompartmentPrincipals(compartment
);
1832 return nsJSPrincipals::get(principals
);
1835 ////////////////////////////////////////////////
1836 // Methods implementing nsIXPCSecurityManager //
1837 ////////////////////////////////////////////////
1840 nsScriptSecurityManager::CanCreateWrapper(JSContext
*cx
,
1843 nsIClassInfo
*aClassInfo
,
1846 // XXX Special case for nsIXPCException ?
1847 ClassInfoData objClassInfo
= ClassInfoData(aClassInfo
, nullptr);
1848 if (objClassInfo
.IsDOMClass())
1853 //--See if the object advertises a non-default level of access
1854 // using nsISecurityCheckedComponent
1855 nsCOMPtr
<nsISecurityCheckedComponent
> checkedComponent
=
1856 do_QueryInterface(aObj
);
1858 nsXPIDLCString objectSecurityLevel
;
1859 if (checkedComponent
)
1860 checkedComponent
->CanCreateWrapper((nsIID
*)&aIID
, getter_Copies(objectSecurityLevel
));
1862 nsresult rv
= CheckXPCPermissions(cx
, aObj
, nullptr, nullptr, objectSecurityLevel
);
1865 //-- Access denied, report an error
1866 NS_ConvertUTF8toUTF16
strName("CreateWrapperDenied");
1867 nsAutoCString origin
;
1869 nsIPrincipal
* subjectPrincipal
= doGetSubjectPrincipal(&rv2
);
1870 if (NS_SUCCEEDED(rv2
) && subjectPrincipal
) {
1871 GetPrincipalDomainOrigin(subjectPrincipal
, origin
);
1873 NS_ConvertUTF8toUTF16
originUnicode(origin
);
1874 NS_ConvertUTF8toUTF16
className(objClassInfo
.GetName());
1875 const PRUnichar
* formatStrings
[] = {
1879 uint32_t length
= ArrayLength(formatStrings
);
1880 if (originUnicode
.IsEmpty()) {
1883 strName
.AppendLiteral("ForOrigin");
1885 nsXPIDLString errorMsg
;
1886 // We need to keep our existing failure rv and not override it
1887 // with a likely success code from the following string bundle
1888 // call in order to throw the correct security exception later.
1889 rv2
= sStrBundle
->FormatStringFromName(strName
.get(),
1892 getter_Copies(errorMsg
));
1893 NS_ENSURE_SUCCESS(rv2
, rv2
);
1895 SetPendingException(cx
, errorMsg
.get());
1902 nsScriptSecurityManager::CanCreateInstance(JSContext
*cx
,
1905 nsresult rv
= CheckXPCPermissions(cx
, nullptr, nullptr, nullptr, nullptr);
1908 //-- Access denied, report an error
1909 nsAutoCString
errorMsg("Permission denied to create instance of class. CID=");
1910 char cidStr
[NSID_LENGTH
];
1911 aCID
.ToProvidedString(cidStr
);
1912 errorMsg
.Append(cidStr
);
1913 SetPendingException(cx
, errorMsg
.get());
1919 nsScriptSecurityManager::CanGetService(JSContext
*cx
,
1922 nsresult rv
= CheckXPCPermissions(cx
, nullptr, nullptr, nullptr, nullptr);
1925 //-- Access denied, report an error
1926 nsAutoCString
errorMsg("Permission denied to get service. CID=");
1927 char cidStr
[NSID_LENGTH
];
1928 aCID
.ToProvidedString(cidStr
);
1929 errorMsg
.Append(cidStr
);
1930 SetPendingException(cx
, errorMsg
.get());
1938 nsScriptSecurityManager::CanAccess(uint32_t aAction
,
1939 nsAXPCNativeCallContext
* aCallContext
,
1941 JSObject
* aJSObject
,
1943 nsIClassInfo
* aClassInfo
,
1947 return CheckPropertyAccessImpl(aAction
, aCallContext
, cx
,
1948 aJSObject
, aObj
, aClassInfo
,
1949 nullptr, aPropertyName
, aPolicy
);
1953 nsScriptSecurityManager::CheckXPCPermissions(JSContext
* cx
,
1954 nsISupports
* aObj
, JSObject
* aJSObject
,
1955 nsIPrincipal
* aSubjectPrincipal
,
1956 const char* aObjectSecurityLevel
)
1959 JS::RootedObject
jsObject(cx
, aJSObject
);
1960 // Check if the subject is privileged.
1961 if (SubjectIsPrivileged())
1964 //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
1965 if (aObjectSecurityLevel
)
1967 if (PL_strcasecmp(aObjectSecurityLevel
, "allAccess") == 0)
1969 if (cx
&& PL_strcasecmp(aObjectSecurityLevel
, "sameOrigin") == 0)
1974 nsCOMPtr
<nsIXPConnectWrappedJS
> xpcwrappedjs
=
1975 do_QueryInterface(aObj
);
1978 jsObject
= xpcwrappedjs
->GetJSObject();
1979 NS_ENSURE_STATE(jsObject
);
1983 if (!aSubjectPrincipal
)
1985 // No subject principal passed in. Compute it.
1986 aSubjectPrincipal
= GetSubjectPrincipal(cx
, &rv
);
1987 NS_ENSURE_SUCCESS(rv
, rv
);
1989 if (aSubjectPrincipal
&& jsObject
)
1991 nsIPrincipal
* objectPrincipal
= doGetObjectPrincipal(jsObject
);
1993 // Only do anything if we have both a subject and object
1995 if (objectPrincipal
)
1998 rv
= aSubjectPrincipal
->Subsumes(objectPrincipal
, &subsumes
);
1999 NS_ENSURE_SUCCESS(rv
, rv
);
2005 else if (PL_strcasecmp(aObjectSecurityLevel
, "noAccess") != 0)
2007 if (SubjectIsPrivileged())
2012 //-- Access tests failed
2013 return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED
;
2016 /////////////////////////////////////////////
2017 // Method implementing nsIChannelEventSink //
2018 /////////////////////////////////////////////
2020 nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel
* oldChannel
,
2021 nsIChannel
* newChannel
,
2022 uint32_t redirFlags
,
2023 nsIAsyncVerifyRedirectCallback
*cb
)
2025 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
2026 GetChannelPrincipal(oldChannel
, getter_AddRefs(oldPrincipal
));
2028 nsCOMPtr
<nsIURI
> newURI
;
2029 newChannel
->GetURI(getter_AddRefs(newURI
));
2030 nsCOMPtr
<nsIURI
> newOriginalURI
;
2031 newChannel
->GetOriginalURI(getter_AddRefs(newOriginalURI
));
2033 NS_ENSURE_STATE(oldPrincipal
&& newURI
&& newOriginalURI
);
2035 const uint32_t flags
=
2036 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
|
2037 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
2038 nsresult rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newURI
, flags
);
2039 if (NS_SUCCEEDED(rv
) && newOriginalURI
!= newURI
) {
2040 rv
= CheckLoadURIWithPrincipal(oldPrincipal
, newOriginalURI
, flags
);
2046 cb
->OnRedirectVerifyCallback(NS_OK
);
2051 /////////////////////////////////////
2052 // Method implementing nsIObserver //
2053 /////////////////////////////////////
2054 const char sJSEnabledPrefName
[] = "javascript.enabled";
2055 const char sFileOriginPolicyPrefName
[] =
2056 "security.fileuri.strict_origin_policy";
2057 static const char sPolicyPrefix
[] = "capability.policy.";
2059 static const char* kObservedPrefs
[] = {
2061 sFileOriginPolicyPrefName
,
2068 nsScriptSecurityManager::Observe(nsISupports
* aObject
, const char* aTopic
,
2069 const PRUnichar
* aMessage
)
2071 nsresult rv
= NS_OK
;
2072 NS_ConvertUTF16toUTF8
messageStr(aMessage
);
2073 const char *message
= messageStr
.get();
2075 static const char jsPrefix
[] = "javascript.";
2076 static const char securityPrefix
[] = "security.";
2077 if ((PL_strncmp(message
, jsPrefix
, sizeof(jsPrefix
)-1) == 0) ||
2078 (PL_strncmp(message
, securityPrefix
, sizeof(securityPrefix
)-1) == 0) )
2080 ScriptSecurityPrefChanged();
2082 else if (PL_strncmp(message
, sPolicyPrefix
, sizeof(sPolicyPrefix
)-1) == 0)
2084 // This will force re-initialization of the pref table
2085 mPolicyPrefsChanged
= true;
2090 /////////////////////////////////////////////
2091 // Constructor, Destructor, Initialization //
2092 /////////////////////////////////////////////
2093 nsScriptSecurityManager::nsScriptSecurityManager(void)
2094 : mOriginToPolicyMap(nullptr),
2095 mDefaultPolicy(nullptr),
2096 mCapabilities(nullptr),
2097 mPrefInitialized(false),
2098 mIsJavaScriptEnabled(false),
2099 mPolicyPrefsChanged(true)
2101 static_assert(sizeof(intptr_t) == sizeof(void*),
2102 "intptr_t and void* have different lengths on this platform. "
2103 "This may cause a security failure with the SecurityLevel union.");
2106 nsresult
nsScriptSecurityManager::Init()
2110 nsresult rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
2111 NS_ENSURE_SUCCESS(rv
, rv
);
2113 nsCOMPtr
<nsIStringBundleService
> bundleService
=
2114 mozilla::services::GetStringBundleService();
2116 return NS_ERROR_FAILURE
;
2118 rv
= bundleService
->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle
);
2119 NS_ENSURE_SUCCESS(rv
, rv
);
2121 // Create our system principal singleton
2122 nsRefPtr
<nsSystemPrincipal
> system
= new nsSystemPrincipal();
2123 NS_ENSURE_TRUE(system
, NS_ERROR_OUT_OF_MEMORY
);
2125 mSystemPrincipal
= system
;
2127 //-- Register security check callback in the JS engine
2128 // Currently this is used to control access to function.caller
2129 rv
= nsXPConnect::XPConnect()->GetRuntime(&sRuntime
);
2130 NS_ENSURE_SUCCESS(rv
, rv
);
2132 static const JSSecurityCallbacks securityCallbacks
= {
2134 ContentSecurityPolicyPermitsJSAction
2137 MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime
));
2138 JS_SetSecurityCallbacks(sRuntime
, &securityCallbacks
);
2139 JS_InitDestroyPrincipalsCallback(sRuntime
, nsJSPrincipals::Destroy
);
2141 JS_SetTrustedPrincipals(sRuntime
, system
);
2146 static StaticRefPtr
<nsScriptSecurityManager
> gScriptSecMan
;
2148 nsScriptSecurityManager::~nsScriptSecurityManager(void)
2150 Preferences::RemoveObservers(this, kObservedPrefs
);
2151 delete mOriginToPolicyMap
;
2153 mDefaultPolicy
->Drop();
2154 delete mCapabilities
;
2156 mDomainPolicy
->Deactivate();
2157 MOZ_ASSERT(!mDomainPolicy
);
2161 nsScriptSecurityManager::Shutdown()
2164 JS_SetSecurityCallbacks(sRuntime
, nullptr);
2165 JS_SetTrustedPrincipals(sRuntime
, nullptr);
2168 sEnabledID
= JSID_VOID
;
2170 NS_IF_RELEASE(sIOService
);
2171 NS_IF_RELEASE(sStrBundle
);
2174 nsScriptSecurityManager
*
2175 nsScriptSecurityManager::GetScriptSecurityManager()
2177 if (!gScriptSecMan
&& nsXPConnect::XPConnect())
2179 nsRefPtr
<nsScriptSecurityManager
> ssManager
= new nsScriptSecurityManager();
2182 rv
= ssManager
->Init();
2183 if (NS_FAILED(rv
)) {
2187 rv
= nsXPConnect::XPConnect()->
2188 SetDefaultSecurityManager(ssManager
);
2189 if (NS_FAILED(rv
)) {
2190 NS_WARNING("Failed to install xpconnect security manager!");
2194 ClearOnShutdown(&gScriptSecMan
);
2195 gScriptSecMan
= ssManager
;
2197 return gScriptSecMan
;
2200 // Currently this nsGenericFactory constructor is used only from FastLoad
2201 // (XPCOM object deserialization) code, when "creating" the system principal
2204 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
2206 nsIPrincipal
*sysprin
= nullptr;
2208 NS_ADDREF(sysprin
= gScriptSecMan
->mSystemPrincipal
);
2209 return static_cast<nsSystemPrincipal
*>(sysprin
);
2213 nsScriptSecurityManager::InitPolicies()
2215 // Clear any policies cached on XPConnect wrappers
2217 nsXPConnect::XPConnect()->ClearAllWrappedNativeSecurityPolicies();
2218 if (NS_FAILED(rv
)) return rv
;
2220 //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
2221 //-- whose dtor decrements refcount of stored DomainPolicy object
2222 delete mOriginToPolicyMap
;
2224 //-- Marks all the survivor DomainPolicy objects (those cached
2225 //-- by nsPrincipal objects) as invalid: they will be released
2226 //-- on first nsPrincipal::GetSecurityPolicy() attempt.
2227 DomainPolicy::InvalidateAll();
2229 //-- Release old default policy
2230 if(mDefaultPolicy
) {
2231 mDefaultPolicy
->Drop();
2232 mDefaultPolicy
= nullptr;
2235 //-- Initialize a new mOriginToPolicyMap
2236 mOriginToPolicyMap
=
2237 new nsObjectHashtable(nullptr, nullptr, DeleteDomainEntry
, nullptr);
2238 if (!mOriginToPolicyMap
)
2239 return NS_ERROR_OUT_OF_MEMORY
;
2241 //-- Create, refcount and initialize a new default policy
2242 mDefaultPolicy
= new DomainPolicy();
2243 if (!mDefaultPolicy
)
2244 return NS_ERROR_OUT_OF_MEMORY
;
2246 mDefaultPolicy
->Hold();
2247 if (!mDefaultPolicy
->Init())
2248 return NS_ERROR_UNEXPECTED
;
2250 //-- Initialize the table of security levels
2254 new nsObjectHashtable(nullptr, nullptr, DeleteCapability
, nullptr);
2256 return NS_ERROR_OUT_OF_MEMORY
;
2259 // Get a JS context - we need it to create internalized strings later.
2260 AutoSafeJSContext cx
;
2261 rv
= InitDomainPolicy(cx
, "default", mDefaultPolicy
);
2262 NS_ENSURE_SUCCESS(rv
, rv
);
2264 nsAdoptingCString policyNames
=
2265 Preferences::GetCString("capability.policy.policynames");
2267 nsAdoptingCString defaultPolicyNames
=
2268 Preferences::GetCString("capability.policy.default_policynames");
2269 policyNames
+= NS_LITERAL_CSTRING(" ") + defaultPolicyNames
;
2271 //-- Initialize domain policies
2272 char* policyCurrent
= policyNames
.BeginWriting();
2273 bool morePolicies
= true;
2274 while (morePolicies
)
2276 while(*policyCurrent
== ' ' || *policyCurrent
== ',')
2278 if (*policyCurrent
== '\0')
2280 char* nameBegin
= policyCurrent
;
2282 while(*policyCurrent
!= '\0' && *policyCurrent
!= ' ' && *policyCurrent
!= ',')
2285 morePolicies
= (*policyCurrent
!= '\0');
2286 *policyCurrent
= '\0';
2289 nsAutoCString
sitesPrefName(
2290 NS_LITERAL_CSTRING(sPolicyPrefix
) +
2291 nsDependentCString(nameBegin
) +
2292 NS_LITERAL_CSTRING(".sites"));
2293 nsAdoptingCString domainList
=
2294 Preferences::GetCString(sitesPrefName
.get());
2299 DomainPolicy
* domainPolicy
= new DomainPolicy();
2301 return NS_ERROR_OUT_OF_MEMORY
;
2303 if (!domainPolicy
->Init())
2305 delete domainPolicy
;
2306 return NS_ERROR_UNEXPECTED
;
2308 domainPolicy
->Hold();
2309 //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
2310 char* domainStart
= domainList
.BeginWriting();
2311 char* domainCurrent
= domainStart
;
2312 char* lastDot
= nullptr;
2313 char* nextToLastDot
= nullptr;
2314 bool moreDomains
= true;
2317 if (*domainCurrent
== ' ' || *domainCurrent
== '\0')
2319 moreDomains
= (*domainCurrent
!= '\0');
2320 *domainCurrent
= '\0';
2321 nsCStringKey
key(nextToLastDot
? nextToLastDot
+1 : domainStart
);
2322 DomainEntry
*newEntry
= new DomainEntry(domainStart
, domainPolicy
);
2325 domainPolicy
->Drop();
2326 return NS_ERROR_OUT_OF_MEMORY
;
2328 DomainEntry
*existingEntry
= (DomainEntry
*)
2329 mOriginToPolicyMap
->Get(&key
);
2331 mOriginToPolicyMap
->Put(&key
, newEntry
);
2334 if (existingEntry
->Matches(domainStart
))
2336 newEntry
->mNext
= existingEntry
;
2337 mOriginToPolicyMap
->Put(&key
, newEntry
);
2341 while (existingEntry
->mNext
)
2343 if (existingEntry
->mNext
->Matches(domainStart
))
2345 newEntry
->mNext
= existingEntry
->mNext
;
2346 existingEntry
->mNext
= newEntry
;
2349 existingEntry
= existingEntry
->mNext
;
2351 if (!existingEntry
->mNext
)
2352 existingEntry
->mNext
= newEntry
;
2355 domainStart
= domainCurrent
+ 1;
2356 lastDot
= nextToLastDot
= nullptr;
2358 else if (*domainCurrent
== '.')
2360 nextToLastDot
= lastDot
;
2361 lastDot
= domainCurrent
;
2366 rv
= InitDomainPolicy(cx
, nameBegin
, domainPolicy
);
2367 domainPolicy
->Drop();
2372 // Reset the "dirty" flag
2373 mPolicyPrefsChanged
= false;
2380 nsScriptSecurityManager::InitDomainPolicy(JSContext
* cx
,
2381 const char* aPolicyName
,
2382 DomainPolicy
* aDomainPolicy
)
2385 nsAutoCString
policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix
) +
2386 nsDependentCString(aPolicyName
) +
2387 NS_LITERAL_CSTRING("."));
2388 uint32_t prefixLength
= policyPrefix
.Length() - 1; // subtract the '.'
2392 nsIPrefBranch
* branch
= Preferences::GetRootBranch();
2393 NS_ASSERTION(branch
, "failed to get the root pref branch");
2394 rv
= branch
->GetChildList(policyPrefix
.get(), &prefCount
, &prefNames
);
2395 if (NS_FAILED(rv
)) return rv
;
2399 //-- Populate the policy
2400 uint32_t currentPref
= 0;
2401 for (; currentPref
< prefCount
; currentPref
++)
2403 // Get the class name
2404 const char* start
= prefNames
[currentPref
] + prefixLength
+ 1;
2405 char* end
= PL_strchr(start
, '.');
2406 if (!end
) // malformed pref, bail on this one
2408 static const char sitesStr
[] = "sites";
2410 // We dealt with "sites" in InitPolicies(), so no need to do
2412 if (PL_strncmp(start
, sitesStr
, sizeof(sitesStr
)-1) == 0)
2415 // Get the pref value
2416 nsAdoptingCString prefValue
=
2417 Preferences::GetCString(prefNames
[currentPref
]);
2422 SecurityLevel secLevel
;
2423 if (PL_strcasecmp(prefValue
, "noAccess") == 0)
2424 secLevel
.level
= SCRIPT_SECURITY_NO_ACCESS
;
2425 else if (PL_strcasecmp(prefValue
, "allAccess") == 0)
2426 secLevel
.level
= SCRIPT_SECURITY_ALL_ACCESS
;
2427 else if (PL_strcasecmp(prefValue
, "sameOrigin") == 0)
2428 secLevel
.level
= SCRIPT_SECURITY_SAME_ORIGIN_ACCESS
;
2430 { //-- pref value is the name of a capability
2431 nsCStringKey
secLevelKey(prefValue
);
2432 secLevel
.capability
=
2433 reinterpret_cast<char*>(mCapabilities
->Get(&secLevelKey
));
2434 if (!secLevel
.capability
)
2436 secLevel
.capability
= NS_strdup(prefValue
);
2437 if (!secLevel
.capability
)
2439 mCapabilities
->Put(&secLevelKey
,
2440 secLevel
.capability
);
2445 // Find or store this class in the classes table
2446 ClassPolicy
* cpolicy
=
2447 static_cast<ClassPolicy
*>
2448 (PL_DHashTableOperate(aDomainPolicy
, start
,
2453 // If this is the wildcard class (class '*'), save it in mWildcardPolicy
2454 // (we leave it stored in the hashtable too to take care of the cleanup)
2455 if ((*start
== '*') && (end
== start
+ 1)) {
2456 aDomainPolicy
->mWildcardPolicy
= cpolicy
;
2458 // Make sure that cpolicy knows about aDomainPolicy so it can reset
2459 // the mWildcardPolicy pointer as needed if it gets moved in the
2461 cpolicy
->mDomainWeAreWildcardFor
= aDomainPolicy
;
2464 // Get the property name
2466 end
= PL_strchr(start
, '.');
2470 JSString
* propertyKey
= ::JS_InternString(cx
, start
);
2472 return NS_ERROR_OUT_OF_MEMORY
;
2474 // Store this property in the class policy
2475 PropertyPolicy
* ppolicy
=
2476 static_cast<PropertyPolicy
*>
2477 (PL_DHashTableOperate(cpolicy
->mPolicy
, propertyKey
,
2482 if (end
) // The pref specifies an access mode
2485 if (PL_strcasecmp(start
, "set") == 0)
2486 ppolicy
->mSet
= secLevel
;
2488 ppolicy
->mGet
= secLevel
;
2492 if (ppolicy
->mGet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
2493 ppolicy
->mGet
= secLevel
;
2494 if (ppolicy
->mSet
.level
== SCRIPT_SECURITY_UNDEFINED_ACCESS
)
2495 ppolicy
->mSet
= secLevel
;
2499 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount
, prefNames
);
2500 if (currentPref
< prefCount
) // Loop exited early because of out-of-memory error
2501 return NS_ERROR_OUT_OF_MEMORY
;
2506 nsScriptSecurityManager::ScriptSecurityPrefChanged()
2508 // JavaScript defaults to enabled in failure cases.
2509 mIsJavaScriptEnabled
= true;
2511 sStrictFileOriginPolicy
= true;
2514 if (!mPrefInitialized
) {
2520 mIsJavaScriptEnabled
=
2521 Preferences::GetBool(sJSEnabledPrefName
, mIsJavaScriptEnabled
);
2523 sStrictFileOriginPolicy
=
2524 Preferences::GetBool(sFileOriginPolicyPrefName
, false);
2528 nsScriptSecurityManager::InitPrefs()
2530 nsIPrefBranch
* branch
= Preferences::GetRootBranch();
2531 NS_ENSURE_TRUE(branch
, NS_ERROR_FAILURE
);
2533 mPrefInitialized
= true;
2535 // Set the initial value of the "javascript.enabled" prefs
2536 ScriptSecurityPrefChanged();
2538 // set observer callbacks in case the value of the prefs change
2539 Preferences::AddStrongObservers(this, kObservedPrefs
);
2547 GetJarPrefix(uint32_t aAppId
, bool aInMozBrowser
, nsACString
& aJarPrefix
)
2549 MOZ_ASSERT(aAppId
!= nsIScriptSecurityManager::UNKNOWN_APP_ID
);
2551 if (aAppId
== nsIScriptSecurityManager::UNKNOWN_APP_ID
) {
2552 aAppId
= nsIScriptSecurityManager::NO_APP_ID
;
2555 aJarPrefix
.Truncate();
2558 if (aAppId
== nsIScriptSecurityManager::NO_APP_ID
&& !aInMozBrowser
) {
2562 // aJarPrefix = appId + "+" + { 't', 'f' } + "+";
2563 aJarPrefix
.AppendInt(aAppId
);
2564 aJarPrefix
.Append('+');
2565 aJarPrefix
.Append(aInMozBrowser
? 't' : 'f');
2566 aJarPrefix
.Append('+');
2571 } // namespace mozilla
2574 nsScriptSecurityManager::GetJarPrefix(uint32_t aAppId
,
2576 nsACString
& aJarPrefix
)
2578 MOZ_ASSERT(aAppId
!= nsIScriptSecurityManager::UNKNOWN_APP_ID
);
2580 mozilla::GetJarPrefix(aAppId
, aInMozBrowser
, aJarPrefix
);
2585 nsScriptSecurityManager::GetDomainPolicyActive(bool *aRv
)
2587 *aRv
= !!mDomainPolicy
;
2592 nsScriptSecurityManager::ActivateDomainPolicy(nsIDomainPolicy
** aRv
)
2594 // We only allow one domain policy at a time. The holder of the previous
2595 // policy must explicitly deactivate it first.
2596 if (mDomainPolicy
) {
2597 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
2600 mDomainPolicy
= new mozilla::hotness::DomainPolicy();
2601 nsCOMPtr
<nsIDomainPolicy
> ptr
= mDomainPolicy
;
2606 // Intentionally non-scriptable. Script must have a reference to the
2607 // nsIDomainPolicy to deactivate it.
2609 nsScriptSecurityManager::DeactivateDomainPolicy()
2611 mDomainPolicy
= nullptr;
2615 nsScriptSecurityManager::PolicyAllowsScript(nsIURI
* aURI
, bool *aRv
)
2619 // Compute our rule. If we don't have any domain policy set up that might
2620 // provide exceptions to this rule, we're done.
2621 *aRv
= mIsJavaScriptEnabled
;
2622 if (!mDomainPolicy
) {
2626 // We have a domain policy. Grab the appropriate set of exceptions to the
2627 // rule (either the blacklist or the whitelist, depending on whether script
2628 // is enabled or disabled by default).
2629 nsCOMPtr
<nsIDomainSet
> exceptions
;
2630 nsCOMPtr
<nsIDomainSet
> superExceptions
;
2632 mDomainPolicy
->GetBlacklist(getter_AddRefs(exceptions
));
2633 mDomainPolicy
->GetSuperBlacklist(getter_AddRefs(superExceptions
));
2635 mDomainPolicy
->GetWhitelist(getter_AddRefs(exceptions
));
2636 mDomainPolicy
->GetSuperWhitelist(getter_AddRefs(superExceptions
));
2640 rv
= exceptions
->Contains(aURI
, &contains
);
2641 NS_ENSURE_SUCCESS(rv
, rv
);
2646 rv
= superExceptions
->ContainsSuperDomain(aURI
, &contains
);
2647 NS_ENSURE_SUCCESS(rv
, rv
);