Bug 454376 add -lCrun -lCstd for Solaris OS_LIBS, r=bsmedberg
[wine-gecko.git] / caps / src / nsScriptSecurityManager.cpp
bloba08d6d9b3b92cdd9e13e690007eacd1ff29795af
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
13 * License.
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.
22 * Contributor(s):
23 * Norris Boyd
24 * Mitch Stoltz
25 * Steve Morse
26 * Christopher A. Aillon
27 * Giorgio Maone
28 * Daniel Veditz
30 * Alternatively, the contents of this file may be used under the terms of
31 * either of the GNU General Public License Version 2 or later (the "GPL"),
32 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
43 #include "nsScriptSecurityManager.h"
44 #include "nsIServiceManager.h"
45 #include "nsIScriptObjectPrincipal.h"
46 #include "nsIScriptContext.h"
47 #include "nsIURL.h"
48 #include "nsINestedURI.h"
49 #include "nspr.h"
50 #include "nsJSPrincipals.h"
51 #include "nsSystemPrincipal.h"
52 #include "nsPrincipal.h"
53 #include "nsNullPrincipal.h"
54 #include "nsXPIDLString.h"
55 #include "nsCRT.h"
56 #include "nsCRTGlue.h"
57 #include "nsIJSContextStack.h"
58 #include "nsDOMError.h"
59 #include "nsDOMCID.h"
60 #include "jsdbgapi.h"
61 #include "jsarena.h"
62 #include "jsfun.h"
63 #include "jsobj.h"
64 #include "nsIXPConnect.h"
65 #include "nsIXPCSecurityManager.h"
66 #include "nsTextFormatter.h"
67 #include "nsIStringBundle.h"
68 #include "nsNetUtil.h"
69 #include "nsIProperties.h"
70 #include "nsDirectoryServiceDefs.h"
71 #include "nsIFile.h"
72 #include "nsIFileURL.h"
73 #include "nsIZipReader.h"
74 #include "nsIJAR.h"
75 #include "nsIPluginInstance.h"
76 #include "nsIXPConnect.h"
77 #include "nsIScriptGlobalObject.h"
78 #include "nsPIDOMWindow.h"
79 #include "nsIDocShell.h"
80 #include "nsIDocShellTreeItem.h"
81 #include "nsIPrompt.h"
82 #include "nsIWindowWatcher.h"
83 #include "nsIConsoleService.h"
84 #include "nsISecurityCheckedComponent.h"
85 #include "nsIPrefBranch2.h"
86 #include "nsIJSRuntimeService.h"
87 #include "nsIObserverService.h"
88 #include "nsIContent.h"
89 #include "nsAutoPtr.h"
90 #include "nsDOMJSUtils.h"
91 #include "nsAboutProtocolUtils.h"
92 #include "nsIClassInfo.h"
93 #include "nsIURIFixup.h"
94 #include "nsCDefaultURIFixup.h"
95 #include "nsIChromeRegistry.h"
97 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
99 nsIIOService *nsScriptSecurityManager::sIOService = nsnull;
100 nsIXPConnect *nsScriptSecurityManager::sXPConnect = nsnull;
101 nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
102 JSRuntime *nsScriptSecurityManager::sRuntime = 0;
103 PRBool nsScriptSecurityManager::sStrictFileOriginPolicy = PR_TRUE;
105 // Info we need about the JSClasses used by XPConnects wrapped
106 // natives, to avoid having to QI to nsIXPConnectWrappedNative all the
107 // time when doing security checks.
108 static const JSClass *sXPCWrappedNativeJSClass;
109 static JSGetObjectOps sXPCWrappedNativeGetObjOps1;
110 static JSGetObjectOps sXPCWrappedNativeGetObjOps2;
113 ///////////////////////////
114 // Convenience Functions //
115 ///////////////////////////
116 // Result of this function should not be freed.
117 static inline const PRUnichar *
118 JSValIDToString(JSContext *cx, const jsval idval)
120 JSAutoRequest ar(cx);
121 JSString *str = JS_ValueToString(cx, idval);
122 if(!str)
123 return nsnull;
124 return reinterpret_cast<PRUnichar*>(JS_GetStringChars(str));
127 static
128 nsresult
129 GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal,
130 nsACString& aOrigin)
132 aOrigin.Truncate();
134 nsCOMPtr<nsIURI> uri;
135 aPrincipal->GetDomain(getter_AddRefs(uri));
136 if (!uri) {
137 aPrincipal->GetURI(getter_AddRefs(uri));
139 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
141 uri = NS_GetInnermostURI(uri);
142 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
144 nsCAutoString hostPort;
146 nsresult rv = uri->GetHostPort(hostPort);
147 if (NS_SUCCEEDED(rv)) {
148 nsCAutoString scheme;
149 rv = uri->GetScheme(scheme);
150 NS_ENSURE_SUCCESS(rv, rv);
151 aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
153 else {
154 // Some URIs (e.g., nsSimpleURI) don't support host. Just
155 // get the full spec.
156 rv = uri->GetSpec(aOrigin);
157 NS_ENSURE_SUCCESS(rv, rv);
160 return NS_OK;
163 // Inline copy of JS_GetPrivate() for better inlining and optimization
164 // possibilities. Also doesn't take a cx argument as it's not
165 // needed. We access the private data only on objects whose private
166 // data is not expected to change during the lifetime of the object,
167 // so thus we won't worry about locking and holding on to slot values
168 // etc while referencing private data.
169 inline void *
170 caps_GetJSPrivate(JSObject *obj)
172 jsval v;
174 JS_ASSERT(STOBJ_GET_CLASS(obj)->flags & JSCLASS_HAS_PRIVATE);
175 v = obj->fslots[JSSLOT_PRIVATE];
176 if (!JSVAL_IS_INT(v))
177 return NULL;
178 return JSVAL_TO_PRIVATE(v);
181 static nsIScriptContext *
182 GetScriptContext(JSContext *cx)
184 return GetScriptContextFromJSContext(cx);
187 inline void SetPendingException(JSContext *cx, const char *aMsg)
189 JSAutoRequest ar(cx);
190 JS_ReportError(cx, "%s", aMsg);
193 inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg)
195 JSAutoRequest ar(cx);
196 JS_ReportError(cx, "%hs", aMsg);
199 // DomainPolicy members
200 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
201 PRUint32 DomainPolicy::sObjects=0;
202 void DomainPolicy::_printPopulationInfo()
204 printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n",
205 sGeneration, sObjects);
207 #endif
208 PRUint32 DomainPolicy::sGeneration = 0;
210 // Helper class to get stuff from the ClassInfo and not waste extra time with
211 // virtual method calls for things it has already gotten
212 class ClassInfoData
214 public:
215 ClassInfoData(nsIClassInfo *aClassInfo, const char *aName)
216 : mClassInfo(aClassInfo),
217 mName(const_cast<char *>(aName)),
218 mDidGetFlags(PR_FALSE),
219 mMustFreeName(PR_FALSE)
223 ~ClassInfoData()
225 if (mMustFreeName)
226 nsMemory::Free(mName);
229 PRUint32 GetFlags()
231 if (!mDidGetFlags) {
232 if (mClassInfo) {
233 nsresult rv = mClassInfo->GetFlags(&mFlags);
234 if (NS_FAILED(rv)) {
235 mFlags = 0;
237 } else {
238 mFlags = 0;
241 mDidGetFlags = PR_TRUE;
244 return mFlags;
247 PRBool IsDOMClass()
249 return !!(GetFlags() & nsIClassInfo::DOM_OBJECT);
252 PRBool IsContentNode()
254 return !!(GetFlags() & nsIClassInfo::CONTENT_NODE);
257 const char* GetName()
259 if (!mName) {
260 if (mClassInfo) {
261 mClassInfo->GetClassDescription(&mName);
264 if (mName) {
265 mMustFreeName = PR_TRUE;
266 } else {
267 mName = const_cast<char *>("UnnamedClass");
271 return mName;
274 private:
275 nsIClassInfo *mClassInfo; // WEAK
276 PRUint32 mFlags;
277 char *mName;
278 PRPackedBool mDidGetFlags;
279 PRPackedBool mMustFreeName;
282 JSContext *
283 nsScriptSecurityManager::GetCurrentJSContext()
285 // Get JSContext from stack.
286 if (!mJSContextStack)
288 mJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
289 if (!mJSContextStack)
290 return nsnull;
292 JSContext *cx;
293 if (NS_FAILED(mJSContextStack->Peek(&cx)))
294 return nsnull;
295 return cx;
298 JSContext *
299 nsScriptSecurityManager::GetSafeJSContext()
301 // Get JSContext from stack.
302 if (!mJSContextStack) {
303 mJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
304 if (!mJSContextStack)
305 return nsnull;
308 JSContext *cx;
309 if (NS_FAILED(mJSContextStack->GetSafeJSContext(&cx)))
310 return nsnull;
311 return cx;
314 /* static */
315 PRBool
316 nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
317 nsIURI* aTargetURI)
319 return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
322 NS_IMETHODIMP
323 nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
324 nsIPrincipal** aPrincipal)
326 NS_PRECONDITION(aChannel, "Must have channel!");
327 nsCOMPtr<nsISupports> owner;
328 aChannel->GetOwner(getter_AddRefs(owner));
329 if (owner) {
330 CallQueryInterface(owner, aPrincipal);
331 if (*aPrincipal) {
332 return NS_OK;
336 // OK, get the principal from the URI. Make sure this does the same thing
337 // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
338 nsCOMPtr<nsIURI> uri;
339 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
340 NS_ENSURE_SUCCESS(rv, rv);
342 return GetCodebasePrincipal(uri, aPrincipal);
345 NS_IMETHODIMP
346 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
347 PRBool* aIsSystem)
349 *aIsSystem = (aPrincipal == mSystemPrincipal);
350 return NS_OK;
353 NS_IMETHODIMP_(nsIPrincipal *)
354 nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx)
356 NS_ASSERTION(cx == GetCurrentJSContext(),
357 "Uh, cx is not the current JS context!");
359 nsresult rv = NS_ERROR_FAILURE;
360 nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv);
361 if (NS_FAILED(rv))
362 return nsnull;
364 return principal;
367 ////////////////////
368 // Policy Storage //
369 ////////////////////
371 // Table of security levels
372 PR_STATIC_CALLBACK(PRBool)
373 DeleteCapability(nsHashKey *aKey, void *aData, void* closure)
375 NS_Free(aData);
376 return PR_TRUE;
379 //-- Per-Domain Policy - applies to one or more protocols or hosts
380 struct DomainEntry
382 DomainEntry(const char* aOrigin,
383 DomainPolicy* aDomainPolicy) : mOrigin(aOrigin),
384 mDomainPolicy(aDomainPolicy),
385 mNext(nsnull)
387 mDomainPolicy->Hold();
390 ~DomainEntry()
392 mDomainPolicy->Drop();
395 PRBool Matches(const char *anOrigin)
397 int len = strlen(anOrigin);
398 int thisLen = mOrigin.Length();
399 if (len < thisLen)
400 return PR_FALSE;
401 if (mOrigin.RFindChar(':', thisLen-1, 1) != -1)
402 //-- Policy applies to all URLs of this scheme, compare scheme only
403 return mOrigin.EqualsIgnoreCase(anOrigin, thisLen);
405 //-- Policy applies to a particular host; compare domains
406 if (!mOrigin.Equals(anOrigin + (len - thisLen)))
407 return PR_FALSE;
408 if (len == thisLen)
409 return PR_TRUE;
410 char charBefore = anOrigin[len-thisLen-1];
411 return (charBefore == '.' || charBefore == ':' || charBefore == '/');
414 nsCString mOrigin;
415 DomainPolicy* mDomainPolicy;
416 DomainEntry* mNext;
417 #if defined(DEBUG) || defined(DEBUG_CAPS_HACKER)
418 nsCString mPolicyName_DEBUG;
419 #endif
422 PR_STATIC_CALLBACK(PRBool)
423 DeleteDomainEntry(nsHashKey *aKey, void *aData, void* closure)
425 DomainEntry *entry = (DomainEntry*) aData;
428 DomainEntry *next = entry->mNext;
429 delete entry;
430 entry = next;
431 } while (entry);
432 return PR_TRUE;
435 /////////////////////////////
436 // nsScriptSecurityManager //
437 /////////////////////////////
439 ////////////////////////////////////
440 // Methods implementing ISupports //
441 ////////////////////////////////////
442 NS_IMPL_ISUPPORTS5(nsScriptSecurityManager,
443 nsIScriptSecurityManager,
444 nsIXPCSecurityManager,
445 nsIPrefSecurityCheck,
446 nsIChannelEventSink,
447 nsIObserver)
449 ///////////////////////////////////////////////////
450 // Methods implementing nsIScriptSecurityManager //
451 ///////////////////////////////////////////////////
453 ///////////////// Security Checks /////////////////
454 JSBool
455 nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj,
456 jsval id, JSAccessMode mode,
457 jsval *vp)
459 // Get the security manager
460 nsScriptSecurityManager *ssm =
461 nsScriptSecurityManager::GetScriptSecurityManager();
463 NS_ASSERTION(ssm, "Failed to get security manager service");
464 if (!ssm)
465 return JS_FALSE;
467 // Get the object being accessed. We protect these cases:
468 // 1. The Function.prototype.caller property's value, which might lead
469 // an attacker up a call-stack to a function or another object from
470 // a different trust domain.
471 // 2. A user-defined getter or setter function accessible on another
472 // trust domain's window or document object.
473 // *vp can be a primitive, in that case, we use obj as the target
474 // object.
475 JSObject* target = JSVAL_IS_PRIMITIVE(*vp) ? obj : JSVAL_TO_OBJECT(*vp);
477 // Do the same-origin check -- this sets a JS exception if the check fails.
478 // Pass the parent object's class name, as we have no class-info for it.
479 nsresult rv =
480 ssm->CheckPropertyAccess(cx, target, STOBJ_GET_CLASS(obj)->name, id,
481 (mode & JSACC_WRITE) ?
482 nsIXPCSecurityManager::ACCESS_SET_PROPERTY :
483 nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
485 if (NS_FAILED(rv))
486 return JS_FALSE; // Security check failed (XXX was an error reported?)
488 return JS_TRUE;
491 NS_IMETHODIMP
492 nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
493 JSObject* aJSObject,
494 const char* aClassName,
495 jsval aProperty,
496 PRUint32 aAction)
498 return CheckPropertyAccessImpl(aAction, nsnull, cx, aJSObject,
499 nsnull, nsnull, nsnull,
500 aClassName, aProperty, nsnull);
503 NS_IMETHODIMP
504 nsScriptSecurityManager::CheckConnect(JSContext* cx,
505 nsIURI* aTargetURI,
506 const char* aClassName,
507 const char* aPropertyName)
509 // Get a context if necessary
510 if (!cx)
512 cx = GetCurrentJSContext();
513 if (!cx)
514 return NS_OK; // No JS context, so allow the load
517 nsresult rv = CheckLoadURIFromScript(cx, aTargetURI);
518 if (NS_FAILED(rv)) return rv;
520 JSAutoRequest ar(cx);
522 JSString* propertyName = ::JS_InternString(cx, aPropertyName);
523 if (!propertyName)
524 return NS_ERROR_OUT_OF_MEMORY;
526 return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD, nsnull,
527 cx, nsnull, nsnull, aTargetURI,
528 nsnull, aClassName, STRING_TO_JSVAL(propertyName), nsnull);
531 NS_IMETHODIMP
532 nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
533 nsIURI* aTargetURI)
535 nsresult rv;
537 // Get a context if necessary
538 if (!cx)
540 cx = GetCurrentJSContext();
541 if (!cx)
542 return NS_OK; // No JS context, so allow access
545 // Get a principal from the context
546 nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv);
547 if (NS_FAILED(rv))
548 return rv;
550 if (!sourcePrincipal)
552 NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
553 return NS_OK;
556 if (sourcePrincipal == mSystemPrincipal)
558 // This is a system (chrome) script, so allow access
559 return NS_OK;
562 // Get the original URI from the source principal.
563 // This has the effect of ignoring any change to document.domain
564 // which must be done to avoid DNS spoofing (bug 154930)
565 nsCOMPtr<nsIURI> sourceURI;
566 sourcePrincipal->GetDomain(getter_AddRefs(sourceURI));
567 if (!sourceURI) {
568 sourcePrincipal->GetURI(getter_AddRefs(sourceURI));
569 NS_ENSURE_TRUE(sourceURI, NS_ERROR_FAILURE);
572 // Compare origins
573 if (!SecurityCompareURIs(sourceURI, aTargetURI))
575 ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI);
576 return NS_ERROR_DOM_BAD_URI;
578 return NS_OK;
581 NS_IMETHODIMP
582 nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
583 nsIURI* aTargetURI,
584 PRBool reportError)
586 if (!SecurityCompareURIs(aSourceURI, aTargetURI))
588 if (reportError) {
589 ReportError(nsnull, NS_LITERAL_STRING("CheckSameOriginError"),
590 aSourceURI, aTargetURI);
592 return NS_ERROR_DOM_BAD_URI;
594 return NS_OK;
597 nsresult
598 nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
599 nsAXPCNativeCallContext* aCallContext,
600 JSContext* cx, JSObject* aJSObject,
601 nsISupports* aObj, nsIURI* aTargetURI,
602 nsIClassInfo* aClassInfo,
603 const char* aClassName, jsval aProperty,
604 void** aCachedClassPolicy)
606 nsresult rv;
607 nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
608 if (NS_FAILED(rv))
609 return rv;
611 if (!subjectPrincipal || subjectPrincipal == mSystemPrincipal)
612 // We have native code or the system principal: just allow access
613 return NS_OK;
615 nsCOMPtr<nsIPrincipal> objectPrincipal;
617 // Hold the class info data here so we don't have to go back to virtual
618 // methods all the time
619 ClassInfoData classInfoData(aClassInfo, aClassName);
620 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
621 nsCAutoString propertyName;
622 propertyName.AssignWithConversion((PRUnichar*)JSValIDToString(cx, aProperty));
623 printf("### CanAccess(%s.%s, %i) ", classInfoData.GetName(),
624 propertyName.get(), aAction);
625 #endif
627 //-- Look up the security policy for this class and subject domain
628 SecurityLevel securityLevel;
629 rv = LookupPolicy(subjectPrincipal, classInfoData, aProperty, aAction,
630 (ClassPolicy**)aCachedClassPolicy, &securityLevel);
631 if (NS_FAILED(rv))
632 return rv;
634 if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
636 // No policy found for this property so use the default of last resort.
637 // If we were called from somewhere other than XPConnect
638 // (no XPC call context), assume this is a DOM class. Otherwise,
639 // ask the ClassInfo.
640 if (!aCallContext || classInfoData.IsDOMClass())
641 securityLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS;
642 else
643 securityLevel.level = SCRIPT_SECURITY_NO_ACCESS;
646 if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel))
647 // This flag means securityLevel is allAccess, noAccess, or sameOrigin
649 switch (securityLevel.level)
651 case SCRIPT_SECURITY_NO_ACCESS:
652 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
653 printf("noAccess ");
654 #endif
655 rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
656 break;
658 case SCRIPT_SECURITY_ALL_ACCESS:
659 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
660 printf("allAccess ");
661 #endif
662 rv = NS_OK;
663 break;
665 case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS:
667 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
668 printf("sameOrigin ");
669 #endif
670 nsCOMPtr<nsIPrincipal> principalHolder;
671 if(aJSObject)
673 objectPrincipal = doGetObjectPrincipal(aJSObject);
674 if (!objectPrincipal)
675 rv = NS_ERROR_DOM_SECURITY_ERR;
677 else if(aTargetURI)
679 if (NS_FAILED(GetCodebasePrincipal(
680 aTargetURI, getter_AddRefs(objectPrincipal))))
681 return NS_ERROR_FAILURE;
683 else
685 NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
686 return NS_ERROR_FAILURE;
688 if(NS_SUCCEEDED(rv))
689 rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
690 aAction, aTargetURI != nsnull);
691 break;
693 default:
694 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
695 printf("ERROR ");
696 #endif
697 NS_ERROR("Bad Security Level Value");
698 return NS_ERROR_FAILURE;
701 else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
703 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
704 printf("Cap:%s ", securityLevel.capability);
705 #endif
706 PRBool capabilityEnabled = PR_FALSE;
707 rv = IsCapabilityEnabled(securityLevel.capability, &capabilityEnabled);
708 if (NS_FAILED(rv) || !capabilityEnabled)
709 rv = NS_ERROR_DOM_SECURITY_ERR;
710 else
711 rv = NS_OK;
714 if (NS_SUCCEEDED(rv) && classInfoData.IsContentNode())
716 // No access to anonymous content from the web! (bug 164086)
717 nsIContent *content = static_cast<nsIContent*>(aObj);
718 if (content->IsInNativeAnonymousSubtree()) {
719 rv = NS_ERROR_DOM_SECURITY_ERR;
723 if (NS_SUCCEEDED(rv))
725 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
726 printf(" GRANTED.\n");
727 #endif
728 return rv;
731 //--See if the object advertises a non-default level of access
732 // using nsISecurityCheckedComponent
733 nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
734 do_QueryInterface(aObj);
736 nsXPIDLCString objectSecurityLevel;
737 if (checkedComponent)
739 nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
740 nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
741 const nsIID* objIID;
742 rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
743 if (NS_SUCCEEDED(rv))
744 rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo));
745 if (NS_SUCCEEDED(rv))
746 rv = interfaceInfo->GetIIDShared(&objIID);
747 if (NS_SUCCEEDED(rv))
749 switch (aAction)
751 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
752 checkedComponent->CanGetProperty(objIID,
753 JSValIDToString(cx, aProperty),
754 getter_Copies(objectSecurityLevel));
755 break;
756 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
757 checkedComponent->CanSetProperty(objIID,
758 JSValIDToString(cx, aProperty),
759 getter_Copies(objectSecurityLevel));
760 break;
761 case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
762 checkedComponent->CanCallMethod(objIID,
763 JSValIDToString(cx, aProperty),
764 getter_Copies(objectSecurityLevel));
768 rv = CheckXPCPermissions(aObj, objectSecurityLevel);
769 #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
770 if(NS_SUCCEEDED(rv))
771 printf("CheckXPCPerms GRANTED.\n");
772 else
773 printf("CheckXPCPerms DENIED.\n");
774 #endif
776 if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error
778 nsAutoString stringName;
779 switch(aAction)
781 case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
782 stringName.AssignLiteral("GetPropertyDeniedOrigins");
783 break;
784 case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
785 stringName.AssignLiteral("SetPropertyDeniedOrigins");
786 break;
787 case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
788 stringName.AssignLiteral("CallMethodDeniedOrigins");
791 NS_ConvertUTF8toUTF16 className(classInfoData.GetName());
792 nsCAutoString subjectOrigin;
793 GetPrincipalDomainOrigin(subjectPrincipal, subjectOrigin);
794 NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin);
796 nsCAutoString objectOrigin;
797 if (objectPrincipal) {
798 GetPrincipalDomainOrigin(objectPrincipal, objectOrigin);
800 NS_ConvertUTF8toUTF16 objectOriginUnicode(objectOrigin);
802 nsXPIDLString errorMsg;
803 const PRUnichar *formatStrings[] =
805 subjectOriginUnicode.get(),
806 className.get(),
807 JSValIDToString(cx, aProperty),
808 objectOriginUnicode.get()
811 PRUint32 length = NS_ARRAY_LENGTH(formatStrings);
813 if (!objectPrincipal) {
814 stringName.AppendLiteral("OnlySubject");
815 --length;
818 // We need to keep our existing failure rv and not override it
819 // with a likely success code from the following string bundle
820 // call in order to throw the correct security exception later.
821 nsresult rv2 = sStrBundle->FormatStringFromName(stringName.get(),
822 formatStrings,
823 length,
824 getter_Copies(errorMsg));
825 if (NS_FAILED(rv2)) {
826 // Might just be missing the string... Do our best
827 errorMsg = stringName;
830 SetPendingException(cx, errorMsg.get());
833 return rv;
836 /* static */
837 nsresult
838 nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
839 nsIPrincipal* aObject,
840 PRBool aIsCheckConnect)
843 ** Get origin of subject and object and compare.
845 if (aSubject == aObject)
846 return NS_OK;
848 // These booleans are only used when !aIsCheckConnect. Default
849 // them to false, and change if that turns out wrong.
850 PRBool subjectSetDomain = PR_FALSE;
851 PRBool objectSetDomain = PR_FALSE;
853 nsCOMPtr<nsIURI> subjectURI;
854 nsCOMPtr<nsIURI> objectURI;
856 if (aIsCheckConnect)
858 // Don't use domain for CheckConnect calls, since that's called for
859 // data-only load checks like XMLHTTPRequest (bug 290100).
860 aSubject->GetURI(getter_AddRefs(subjectURI));
861 aObject->GetURI(getter_AddRefs(objectURI));
863 else
865 aSubject->GetDomain(getter_AddRefs(subjectURI));
866 if (!subjectURI) {
867 aSubject->GetURI(getter_AddRefs(subjectURI));
868 } else {
869 subjectSetDomain = PR_TRUE;
872 aObject->GetDomain(getter_AddRefs(objectURI));
873 if (!objectURI) {
874 aObject->GetURI(getter_AddRefs(objectURI));
875 } else {
876 objectSetDomain = PR_TRUE;
880 if (SecurityCompareURIs(subjectURI, objectURI))
881 { // If either the subject or the object has changed its principal by
882 // explicitly setting document.domain then the other must also have
883 // done so in order to be considered the same origin. This prevents
884 // DNS spoofing based on document.domain (154930)
886 // But this restriction does not apply to CheckConnect calls, since
887 // that's called for data-only load checks like XMLHTTPRequest where
888 // we ignore domain (bug 290100).
889 if (aIsCheckConnect)
890 return NS_OK;
892 // If both or neither explicitly set their domain, allow the access
893 if (subjectSetDomain == objectSetDomain)
894 return NS_OK;
898 ** Access tests failed, so now report error.
900 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
904 nsresult
905 nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
906 nsIPrincipal* aObject,
907 PRUint32 aAction,
908 PRBool aIsCheckConnect)
910 nsresult rv;
911 if (aIsCheckConnect) {
912 // Don't do equality compares, just do a same-origin compare,
913 // since the object principal isn't a real principal, just a
914 // GetCodebasePrincipal() on whatever URI we started with.
915 rv = CheckSameOriginPrincipal(aSubject, aObject, aIsCheckConnect);
916 } else {
917 PRBool subsumes;
918 rv = aSubject->Subsumes(aObject, &subsumes);
919 if (NS_SUCCEEDED(rv) && !subsumes) {
920 rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
924 if (NS_SUCCEEDED(rv))
925 return NS_OK;
928 * Content can't ever touch chrome (we check for UniversalXPConnect later)
930 if (aObject == mSystemPrincipal)
931 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
934 * If we failed the origin tests it still might be the case that we
935 * are a signed script and have permissions to do this operation.
936 * Check for that here.
938 PRBool capabilityEnabled = PR_FALSE;
939 const char* cap = aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY ?
940 "UniversalBrowserWrite" : "UniversalBrowserRead";
941 rv = IsCapabilityEnabled(cap, &capabilityEnabled);
942 NS_ENSURE_SUCCESS(rv, rv);
943 if (capabilityEnabled)
944 return NS_OK;
947 ** Access tests failed, so now report error.
949 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
952 nsresult
953 nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
954 ClassInfoData& aClassData,
955 jsval aProperty,
956 PRUint32 aAction,
957 ClassPolicy** aCachedClassPolicy,
958 SecurityLevel* result)
960 nsresult rv;
961 result->level = SCRIPT_SECURITY_UNDEFINED_ACCESS;
963 DomainPolicy* dpolicy = nsnull;
964 //-- Initialize policies if necessary
965 if (mPolicyPrefsChanged)
967 rv = InitPolicies();
968 if (NS_FAILED(rv))
969 return rv;
971 else
973 aPrincipal->GetSecurityPolicy((void**)&dpolicy);
976 if (!dpolicy && mOriginToPolicyMap)
978 //-- Look up the relevant domain policy, if any
979 #ifdef DEBUG_CAPS_LookupPolicy
980 printf("DomainLookup ");
981 #endif
983 nsCAutoString origin;
984 rv = GetPrincipalDomainOrigin(aPrincipal, origin);
985 NS_ENSURE_SUCCESS(rv, rv);
987 char *start = origin.BeginWriting();
988 const char *nextToLastDot = nsnull;
989 const char *lastDot = nsnull;
990 const char *colon = nsnull;
991 char *p = start;
993 //-- search domain (stop at the end of the string or at the 3rd slash)
994 for (PRUint32 slashes=0; *p; p++)
996 if (*p == '/' && ++slashes == 3)
998 *p = '\0'; // truncate at 3rd slash
999 break;
1001 if (*p == '.')
1003 nextToLastDot = lastDot;
1004 lastDot = p;
1006 else if (!colon && *p == ':')
1007 colon = p;
1010 nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
1011 DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
1012 if (!de)
1014 nsCAutoString scheme(start, colon-start+1);
1015 nsCStringKey schemeKey(scheme);
1016 de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
1019 while (de)
1021 if (de->Matches(start))
1023 dpolicy = de->mDomainPolicy;
1024 break;
1026 de = de->mNext;
1029 if (!dpolicy)
1030 dpolicy = mDefaultPolicy;
1032 aPrincipal->SetSecurityPolicy((void*)dpolicy);
1035 ClassPolicy* cpolicy = nsnull;
1037 if ((dpolicy == mDefaultPolicy) && aCachedClassPolicy)
1039 // No per-domain policy for this principal (the more common case)
1040 // so look for a cached class policy from the object wrapper
1041 cpolicy = *aCachedClassPolicy;
1044 if (!cpolicy)
1045 { //-- No cached policy for this class, need to look it up
1046 #ifdef DEBUG_CAPS_LookupPolicy
1047 printf("ClassLookup ");
1048 #endif
1050 cpolicy = static_cast<ClassPolicy*>
1051 (PL_DHashTableOperate(dpolicy,
1052 aClassData.GetName(),
1053 PL_DHASH_LOOKUP));
1055 if (PL_DHASH_ENTRY_IS_FREE(cpolicy))
1056 cpolicy = NO_POLICY_FOR_CLASS;
1058 if ((dpolicy == mDefaultPolicy) && aCachedClassPolicy)
1059 *aCachedClassPolicy = cpolicy;
1062 // We look for a PropertyPolicy in the following places:
1063 // 1) The ClassPolicy for our class we got from our DomainPolicy
1064 // 2) The mWildcardPolicy of our DomainPolicy
1065 // 3) The ClassPolicy for our class we got from mDefaultPolicy
1066 // 4) The mWildcardPolicy of our mDefaultPolicy
1067 PropertyPolicy* ppolicy = nsnull;
1068 if (cpolicy != NO_POLICY_FOR_CLASS)
1070 ppolicy = static_cast<PropertyPolicy*>
1071 (PL_DHashTableOperate(cpolicy->mPolicy,
1072 (void*)aProperty,
1073 PL_DHASH_LOOKUP));
1076 // If there is no class policy for this property, and we have a wildcard
1077 // policy, try that.
1078 if (dpolicy->mWildcardPolicy &&
1079 (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)))
1081 ppolicy =
1082 static_cast<PropertyPolicy*>
1083 (PL_DHashTableOperate(dpolicy->mWildcardPolicy->mPolicy,
1084 (void*)aProperty,
1085 PL_DHASH_LOOKUP));
1088 // If dpolicy is not the defauly policy and there's no class or wildcard
1089 // policy for this property, check the default policy for this class and
1090 // the default wildcard policy
1091 if (dpolicy != mDefaultPolicy &&
1092 (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)))
1094 cpolicy = static_cast<ClassPolicy*>
1095 (PL_DHashTableOperate(mDefaultPolicy,
1096 aClassData.GetName(),
1097 PL_DHASH_LOOKUP));
1099 if (PL_DHASH_ENTRY_IS_BUSY(cpolicy))
1101 ppolicy =
1102 static_cast<PropertyPolicy*>
1103 (PL_DHashTableOperate(cpolicy->mPolicy,
1104 (void*)aProperty,
1105 PL_DHASH_LOOKUP));
1108 if ((!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)) &&
1109 mDefaultPolicy->mWildcardPolicy)
1111 ppolicy =
1112 static_cast<PropertyPolicy*>
1113 (PL_DHashTableOperate(mDefaultPolicy->mWildcardPolicy->mPolicy,
1114 (void*)aProperty,
1115 PL_DHASH_LOOKUP));
1119 if (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy))
1120 return NS_OK;
1122 // Get the correct security level from the property policy
1123 if (aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY)
1124 *result = ppolicy->mSet;
1125 else
1126 *result = ppolicy->mGet;
1128 return NS_OK;
1132 NS_IMETHODIMP
1133 nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
1135 // Get principal of currently executing script.
1136 nsresult rv;
1137 nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv);
1138 if (NS_FAILED(rv))
1139 return rv;
1141 // Native code can load all URIs.
1142 if (!principal)
1143 return NS_OK;
1145 rv = CheckLoadURIWithPrincipal(principal, aURI,
1146 nsIScriptSecurityManager::STANDARD);
1147 if (NS_SUCCEEDED(rv)) {
1148 // OK to load
1149 return NS_OK;
1152 // See if we're attempting to load a file: URI. If so, let a
1153 // UniversalFileRead capability trump the above check.
1154 PRBool isFile = PR_FALSE;
1155 PRBool isRes = PR_FALSE;
1156 if (NS_FAILED(aURI->SchemeIs("file", &isFile)) ||
1157 NS_FAILED(aURI->SchemeIs("resource", &isRes)))
1158 return NS_ERROR_FAILURE;
1159 if (isFile || isRes)
1161 PRBool enabled;
1162 if (NS_FAILED(IsCapabilityEnabled("UniversalFileRead", &enabled)))
1163 return NS_ERROR_FAILURE;
1164 if (enabled)
1165 return NS_OK;
1168 // Report error.
1169 nsCAutoString spec;
1170 if (NS_FAILED(aURI->GetAsciiSpec(spec)))
1171 return NS_ERROR_FAILURE;
1172 JS_ReportError(cx, "Access to '%s' from script denied", spec.get());
1173 return NS_ERROR_DOM_BAD_URI;
1176 NS_IMETHODIMP
1177 nsScriptSecurityManager::CheckLoadURI(nsIURI *aSourceURI, nsIURI *aTargetURI,
1178 PRUint32 aFlags)
1180 // FIXME: bug 327244 -- this function should really die... Really truly.
1181 NS_PRECONDITION(aSourceURI, "CheckLoadURI called with null source URI");
1182 NS_ENSURE_ARG_POINTER(aSourceURI);
1184 // Note: this is not _quite_ right if aSourceURI has
1185 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1186 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1187 // really needs to go away....
1188 nsCOMPtr<nsIPrincipal> sourcePrincipal;
1189 nsresult rv = CreateCodebasePrincipal(aSourceURI,
1190 getter_AddRefs(sourcePrincipal));
1191 NS_ENSURE_SUCCESS(rv, rv);
1192 return CheckLoadURIWithPrincipal(sourcePrincipal, aTargetURI, aFlags);
1196 * Helper method to handle cases where a flag passed to
1197 * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
1198 * nsIProtocolHandler flags set.
1199 * @return if success, access is allowed. Otherwise, deny access
1201 static nsresult
1202 DenyAccessIfURIHasFlags(nsIURI* aURI, PRUint32 aURIFlags)
1204 NS_PRECONDITION(aURI, "Must have URI!");
1206 PRBool uriHasFlags;
1207 nsresult rv =
1208 NS_URIChainHasFlags(aURI, aURIFlags, &uriHasFlags);
1209 NS_ENSURE_SUCCESS(rv, rv);
1211 if (uriHasFlags) {
1212 return NS_ERROR_DOM_BAD_URI;
1215 return NS_OK;
1218 NS_IMETHODIMP
1219 nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
1220 nsIURI *aTargetURI,
1221 PRUint32 aFlags)
1223 NS_PRECONDITION(aPrincipal, "CheckLoadURIWithPrincipal must have a principal");
1224 // If someone passes a flag that we don't understand, we should
1225 // fail, because they may need a security check that we don't
1226 // provide.
1227 NS_ENSURE_FALSE(aFlags & ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
1228 nsIScriptSecurityManager::ALLOW_CHROME |
1229 nsIScriptSecurityManager::DISALLOW_SCRIPT |
1230 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL),
1231 NS_ERROR_UNEXPECTED);
1232 NS_ENSURE_ARG_POINTER(aPrincipal);
1234 if (aPrincipal == mSystemPrincipal) {
1235 // Allow access
1236 return NS_OK;
1239 nsCOMPtr<nsIURI> sourceURI;
1240 aPrincipal->GetURI(getter_AddRefs(sourceURI));
1241 if (!sourceURI) {
1242 NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
1243 "must have a URI!");
1244 return NS_ERROR_UNEXPECTED;
1247 // Automatic loads are not allowed from certain protocols.
1248 if (aFlags & nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT) {
1249 nsresult rv =
1250 DenyAccessIfURIHasFlags(sourceURI,
1251 nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT);
1252 NS_ENSURE_SUCCESS(rv, rv);
1255 // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
1256 // would do such inheriting. That would be URIs that do not have their own
1257 // security context.
1258 if (aFlags & nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL) {
1259 nsresult rv =
1260 DenyAccessIfURIHasFlags(aTargetURI,
1261 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT);
1262 NS_ENSURE_SUCCESS(rv, rv);
1265 // If either URI is a nested URI, get the base URI
1266 nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(sourceURI);
1267 nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
1269 //-- get the target scheme
1270 nsCAutoString targetScheme;
1271 nsresult rv = targetBaseURI->GetScheme(targetScheme);
1272 if (NS_FAILED(rv)) return rv;
1274 //-- Some callers do not allow loading javascript:
1275 if ((aFlags & nsIScriptSecurityManager::DISALLOW_SCRIPT) &&
1276 targetScheme.EqualsLiteral("javascript"))
1278 return NS_ERROR_DOM_BAD_URI;
1281 //-- get the source scheme
1282 nsCAutoString sourceScheme;
1283 rv = sourceBaseURI->GetScheme(sourceScheme);
1284 if (NS_FAILED(rv)) return rv;
1286 if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
1287 // A null principal can target its own URI.
1288 if (sourceURI == aTargetURI) {
1289 return NS_OK;
1292 else if (targetScheme.Equals(sourceScheme,
1293 nsCaseInsensitiveCStringComparator()))
1295 // every scheme can access another URI from the same scheme,
1296 // as long as they don't represent null principals.
1297 return NS_OK;
1300 NS_NAMED_LITERAL_STRING(errorTag, "CheckLoadURIError");
1302 // If the schemes don't match, the policy is specified by the protocol
1303 // flags on the target URI. Note that the order of policy checks here is
1304 // very important! We start from most restrictive and work our way down.
1305 // Note that since we're working with the innermost URI, we can just use
1306 // the methods that work on chains of nested URIs and they will only look
1307 // at the flags for our one URI.
1309 // Check for system target URI
1310 rv = DenyAccessIfURIHasFlags(targetBaseURI,
1311 nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
1312 if (NS_FAILED(rv)) {
1313 // Deny access, since the origin principal is not system
1314 ReportError(nsnull, errorTag, sourceURI, aTargetURI);
1315 return rv;
1318 // Check for chrome target URI
1319 PRBool hasFlags;
1320 rv = NS_URIChainHasFlags(targetBaseURI,
1321 nsIProtocolHandler::URI_IS_UI_RESOURCE,
1322 &hasFlags);
1323 NS_ENSURE_SUCCESS(rv, rv);
1324 if (hasFlags) {
1325 if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
1326 if (!targetScheme.EqualsLiteral("chrome")) {
1327 // for now don't change behavior for resource: or moz-icon:
1328 return NS_OK;
1331 // allow load only if chrome package is whitelisted
1332 nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService(
1333 NS_CHROMEREGISTRY_CONTRACTID));
1334 if (reg) {
1335 PRBool accessAllowed = PR_FALSE;
1336 reg->AllowContentToAccess(targetBaseURI, &accessAllowed);
1337 if (accessAllowed) {
1338 return NS_OK;
1343 // resource: and chrome: are equivalent, securitywise
1344 // That's bogus!! Fix this. But watch out for
1345 // the view-source stylesheet?
1346 PRBool sourceIsChrome;
1347 rv = NS_URIChainHasFlags(sourceBaseURI,
1348 nsIProtocolHandler::URI_IS_UI_RESOURCE,
1349 &sourceIsChrome);
1350 NS_ENSURE_SUCCESS(rv, rv);
1351 if (sourceIsChrome) {
1352 return NS_OK;
1354 ReportError(nsnull, errorTag, sourceURI, aTargetURI);
1355 return NS_ERROR_DOM_BAD_URI;
1358 // Check for target URI pointing to a file
1359 rv = NS_URIChainHasFlags(targetBaseURI,
1360 nsIProtocolHandler::URI_IS_LOCAL_FILE,
1361 &hasFlags);
1362 NS_ENSURE_SUCCESS(rv, rv);
1363 if (hasFlags) {
1364 // resource: and chrome: are equivalent, securitywise
1365 // That's bogus!! Fix this. But watch out for
1366 // the view-source stylesheet?
1367 PRBool sourceIsChrome;
1368 rv = NS_URIChainHasFlags(sourceURI,
1369 nsIProtocolHandler::URI_IS_UI_RESOURCE,
1370 &sourceIsChrome);
1371 NS_ENSURE_SUCCESS(rv, rv);
1372 if (sourceIsChrome) {
1373 return NS_OK;
1376 // Now check capability policies
1377 static const char loadURIPrefGroup[] = "checkloaduri";
1378 ClassInfoData nameData(nsnull, loadURIPrefGroup);
1380 SecurityLevel secLevel;
1381 rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
1382 nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
1383 nsnull, &secLevel);
1384 if (NS_SUCCEEDED(rv) && secLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
1386 // OK for this site!
1387 return NS_OK;
1390 ReportError(nsnull, errorTag, sourceURI, aTargetURI);
1391 return NS_ERROR_DOM_BAD_URI;
1394 // OK, everyone is allowed to load this, since unflagged handlers are
1395 // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
1396 // need to warn. At some point we'll want to make this warning into an
1397 // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
1398 rv = NS_URIChainHasFlags(targetBaseURI,
1399 nsIProtocolHandler::URI_LOADABLE_BY_ANYONE,
1400 &hasFlags);
1401 NS_ENSURE_SUCCESS(rv, rv);
1402 if (!hasFlags) {
1403 nsXPIDLString message;
1404 NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme);
1405 const PRUnichar* formatStrings[] = { ucsTargetScheme.get() };
1406 rv = sStrBundle->
1407 FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
1408 formatStrings,
1409 NS_ARRAY_LENGTH(formatStrings),
1410 getter_Copies(message));
1411 if (NS_SUCCEEDED(rv)) {
1412 nsCOMPtr<nsIConsoleService> console(
1413 do_GetService("@mozilla.org/consoleservice;1"));
1414 NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
1416 console->LogStringMessage(message.get());
1417 #ifdef DEBUG
1418 fprintf(stderr, "%s\n", NS_ConvertUTF16toUTF8(message).get());
1419 #endif
1423 return NS_OK;
1426 nsresult
1427 nsScriptSecurityManager::ReportError(JSContext* cx, const nsAString& messageTag,
1428 nsIURI* aSource, nsIURI* aTarget)
1430 nsresult rv;
1431 NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
1433 // Get the source URL spec
1434 nsCAutoString sourceSpec;
1435 rv = aSource->GetAsciiSpec(sourceSpec);
1436 NS_ENSURE_SUCCESS(rv, rv);
1438 // Get the target URL spec
1439 nsCAutoString targetSpec;
1440 rv = aTarget->GetAsciiSpec(targetSpec);
1441 NS_ENSURE_SUCCESS(rv, rv);
1443 // Localize the error message
1444 nsXPIDLString message;
1445 NS_ConvertASCIItoUTF16 ucsSourceSpec(sourceSpec);
1446 NS_ConvertASCIItoUTF16 ucsTargetSpec(targetSpec);
1447 const PRUnichar *formatStrings[] = { ucsSourceSpec.get(), ucsTargetSpec.get() };
1448 rv = sStrBundle->FormatStringFromName(PromiseFlatString(messageTag).get(),
1449 formatStrings,
1450 NS_ARRAY_LENGTH(formatStrings),
1451 getter_Copies(message));
1452 NS_ENSURE_SUCCESS(rv, rv);
1454 // If a JS context was passed in, set a JS exception.
1455 // Otherwise, print the error message directly to the JS console
1456 // and to standard output
1457 if (cx)
1459 SetPendingException(cx, message.get());
1461 else // Print directly to the console
1463 nsCOMPtr<nsIConsoleService> console(
1464 do_GetService("@mozilla.org/consoleservice;1"));
1465 NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
1467 console->LogStringMessage(message.get());
1468 #ifdef DEBUG
1469 fprintf(stderr, "%s\n", NS_LossyConvertUTF16toASCII(message).get());
1470 #endif
1472 return NS_OK;
1475 NS_IMETHODIMP
1476 nsScriptSecurityManager::CheckLoadURIStr(const nsACString& aSourceURIStr,
1477 const nsACString& aTargetURIStr,
1478 PRUint32 aFlags)
1480 // FIXME: bug 327244 -- this function should really die... Really truly.
1481 nsCOMPtr<nsIURI> source;
1482 nsresult rv = NS_NewURI(getter_AddRefs(source), aSourceURIStr,
1483 nsnull, nsnull, sIOService);
1484 NS_ENSURE_SUCCESS(rv, rv);
1486 // Note: this is not _quite_ right if aSourceURI has
1487 // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
1488 // CheckLoadURIWithPrincipal anyway, so this is good enough. This method
1489 // really needs to go away....
1490 nsCOMPtr<nsIPrincipal> sourcePrincipal;
1491 rv = CreateCodebasePrincipal(source,
1492 getter_AddRefs(sourcePrincipal));
1493 NS_ENSURE_SUCCESS(rv, rv);
1495 return CheckLoadURIStrWithPrincipal(sourcePrincipal, aTargetURIStr,
1496 aFlags);
1499 NS_IMETHODIMP
1500 nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal* aPrincipal,
1501 const nsACString& aTargetURIStr,
1502 PRUint32 aFlags)
1504 nsresult rv;
1505 nsCOMPtr<nsIURI> target;
1506 rv = NS_NewURI(getter_AddRefs(target), aTargetURIStr,
1507 nsnull, nsnull, sIOService);
1508 NS_ENSURE_SUCCESS(rv, rv);
1510 rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
1511 NS_ENSURE_SUCCESS(rv, rv);
1513 // Now start testing fixup -- since aTargetURIStr is a string, not
1514 // an nsIURI, we may well end up fixing it up before loading.
1515 // Note: This needs to stay in sync with the nsIURIFixup api.
1516 nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
1517 if (!fixup) {
1518 return rv;
1521 PRUint32 flags[] = {
1522 nsIURIFixup::FIXUP_FLAG_NONE,
1523 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
1524 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
1525 nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP |
1526 nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
1529 for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(flags); ++i) {
1530 rv = fixup->CreateFixupURI(aTargetURIStr, flags[i],
1531 getter_AddRefs(target));
1532 NS_ENSURE_SUCCESS(rv, rv);
1534 rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
1535 NS_ENSURE_SUCCESS(rv, rv);
1538 return rv;
1541 NS_IMETHODIMP
1542 nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
1543 void *aTargetObj)
1545 // This check is called for event handlers
1546 nsresult rv;
1547 nsIPrincipal* subject =
1548 GetFunctionObjectPrincipal(aCx, (JSObject *)aFunObj, nsnull, &rv);
1550 // If subject is null, get a principal from the function object's scope.
1551 if (NS_SUCCEEDED(rv) && !subject)
1553 #ifdef DEBUG
1555 JSFunction *fun =
1556 (JSFunction *)caps_GetJSPrivate((JSObject *)aFunObj);
1557 JSScript *script = JS_GetFunctionScript(aCx, fun);
1559 NS_ASSERTION(!script, "Null principal for non-native function!");
1561 #endif
1563 subject = doGetObjectPrincipal((JSObject*)aFunObj);
1566 if (!subject)
1567 return NS_ERROR_FAILURE;
1569 if (subject == mSystemPrincipal)
1570 // This is the system principal: just allow access
1571 return NS_OK;
1573 // Check if the principal the function was compiled under is
1574 // allowed to execute scripts.
1576 PRBool result;
1577 rv = CanExecuteScripts(aCx, subject, &result);
1578 if (NS_FAILED(rv))
1579 return rv;
1581 if (!result)
1582 return NS_ERROR_DOM_SECURITY_ERR;
1585 ** Get origin of subject and object and compare.
1587 JSObject* obj = (JSObject*)aTargetObj;
1588 nsIPrincipal* object = doGetObjectPrincipal(obj);
1590 if (!object)
1591 return NS_ERROR_FAILURE;
1593 PRBool subsumes;
1594 rv = subject->Subsumes(object, &subsumes);
1595 if (NS_SUCCEEDED(rv) && !subsumes) {
1596 rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
1598 return rv;
1601 NS_IMETHODIMP
1602 nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
1603 nsIPrincipal *aPrincipal,
1604 PRBool *result)
1606 *result = PR_FALSE;
1608 if (aPrincipal == mSystemPrincipal)
1610 // Even if JavaScript is disabled, we must still execute system scripts
1611 *result = PR_TRUE;
1612 return NS_OK;
1615 //-- See if the current window allows JS execution
1616 nsIScriptContext *scriptContext = GetScriptContext(cx);
1617 if (!scriptContext) return NS_ERROR_FAILURE;
1619 if (!scriptContext->GetScriptsEnabled()) {
1620 // No scripting on this context, folks
1621 *result = PR_FALSE;
1622 return NS_OK;
1625 nsIScriptGlobalObject *sgo = scriptContext->GetGlobalObject();
1627 if (!sgo) {
1628 return NS_ERROR_FAILURE;
1631 // window can be null here if we're running with a non-DOM window
1632 // as the script global (i.e. a XUL prototype document).
1633 nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(sgo);
1634 nsCOMPtr<nsIDocShell> docshell;
1635 nsresult rv;
1637 if (window) {
1638 docshell = window->GetDocShell();
1641 nsCOMPtr<nsIDocShellTreeItem> globalObjTreeItem =
1642 do_QueryInterface(docshell);
1644 if (globalObjTreeItem)
1646 nsCOMPtr<nsIDocShellTreeItem> treeItem(globalObjTreeItem);
1647 nsCOMPtr<nsIDocShellTreeItem> parentItem;
1649 // Walk up the docshell tree to see if any containing docshell disallows scripts
1652 rv = docshell->GetAllowJavascript(result);
1653 if (NS_FAILED(rv)) return rv;
1654 if (!*result)
1655 return NS_OK; // Do not run scripts
1656 treeItem->GetParent(getter_AddRefs(parentItem));
1657 treeItem.swap(parentItem);
1658 docshell = do_QueryInterface(treeItem);
1659 #ifdef DEBUG
1660 if (treeItem && !docshell) {
1661 NS_ERROR("cannot get a docshell from a treeItem!");
1663 #endif // DEBUG
1664 } while (treeItem && docshell);
1667 // OK, the docshell doesn't have script execution explicitly disabled.
1668 // Check whether our URI is an "about:" URI that allows scripts. If it is,
1669 // we need to allow JS to run. In this case, don't apply the JS enabled
1670 // pref or policies. On failures, just press on and don't do this special
1671 // case.
1672 nsCOMPtr<nsIURI> principalURI;
1673 aPrincipal->GetURI(getter_AddRefs(principalURI));
1674 if (!principalURI) {
1675 // Broken principal of some sort. Disallow.
1676 *result = PR_FALSE;
1677 return NS_ERROR_UNEXPECTED;
1680 PRBool isAbout;
1681 rv = principalURI->SchemeIs("about", &isAbout);
1682 if (NS_SUCCEEDED(rv) && isAbout) {
1683 nsCOMPtr<nsIAboutModule> module;
1684 rv = NS_GetAboutModule(principalURI, getter_AddRefs(module));
1685 if (NS_SUCCEEDED(rv)) {
1686 PRUint32 flags;
1687 rv = module->GetURIFlags(principalURI, &flags);
1688 if (NS_SUCCEEDED(rv) &&
1689 (flags & nsIAboutModule::ALLOW_SCRIPT)) {
1690 *result = PR_TRUE;
1691 return NS_OK;
1696 //-- See if JS is disabled globally (via prefs)
1697 *result = mIsJavaScriptEnabled;
1698 if (mIsJavaScriptEnabled != mIsMailJavaScriptEnabled && globalObjTreeItem)
1700 nsCOMPtr<nsIDocShellTreeItem> rootItem;
1701 globalObjTreeItem->GetRootTreeItem(getter_AddRefs(rootItem));
1702 docshell = do_QueryInterface(rootItem);
1703 if (docshell)
1705 // Is this script running from mail?
1706 PRUint32 appType;
1707 rv = docshell->GetAppType(&appType);
1708 if (NS_FAILED(rv)) return rv;
1709 if (appType == nsIDocShell::APP_TYPE_MAIL)
1711 *result = mIsMailJavaScriptEnabled;
1716 if (!*result)
1717 return NS_OK; // Do not run scripts
1719 //-- Check for a per-site policy
1720 static const char jsPrefGroupName[] = "javascript";
1721 ClassInfoData nameData(nsnull, jsPrefGroupName);
1723 SecurityLevel secLevel;
1724 rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
1725 nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
1726 nsnull, &secLevel);
1727 if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
1729 *result = PR_FALSE;
1730 return rv;
1733 //-- Nobody vetoed, so allow the JS to run.
1734 *result = PR_TRUE;
1735 return NS_OK;
1738 ///////////////// Principals ///////////////////////
1739 NS_IMETHODIMP
1740 nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal)
1742 nsresult rv;
1743 *aSubjectPrincipal = doGetSubjectPrincipal(&rv);
1744 if (NS_SUCCEEDED(rv))
1745 NS_IF_ADDREF(*aSubjectPrincipal);
1746 return rv;
1749 nsIPrincipal*
1750 nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv)
1752 NS_PRECONDITION(rv, "Null out param");
1753 JSContext *cx = GetCurrentJSContext();
1754 if (!cx)
1756 *rv = NS_OK;
1757 return nsnull;
1759 return GetSubjectPrincipal(cx, rv);
1762 NS_IMETHODIMP
1763 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
1765 NS_ADDREF(*result = mSystemPrincipal);
1767 return NS_OK;
1770 NS_IMETHODIMP
1771 nsScriptSecurityManager::SubjectPrincipalIsSystem(PRBool* aIsSystem)
1773 NS_ENSURE_ARG_POINTER(aIsSystem);
1774 *aIsSystem = PR_FALSE;
1776 if (!mSystemPrincipal)
1777 return NS_OK;
1779 nsCOMPtr<nsIPrincipal> subject;
1780 nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
1781 if (NS_FAILED(rv))
1782 return rv;
1784 if(!subject)
1786 // No subject principal means no JS is running;
1787 // this is the equivalent of system principal code
1788 *aIsSystem = PR_TRUE;
1789 return NS_OK;
1792 return mSystemPrincipal->Equals(subject, aIsSystem);
1795 NS_IMETHODIMP
1796 nsScriptSecurityManager::GetCertificatePrincipal(const nsACString& aCertFingerprint,
1797 const nsACString& aSubjectName,
1798 const nsACString& aPrettyName,
1799 nsISupports* aCertificate,
1800 nsIURI* aURI,
1801 nsIPrincipal **result)
1803 *result = nsnull;
1805 NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() &&
1806 !aSubjectName.IsEmpty() &&
1807 aCertificate);
1809 return DoGetCertificatePrincipal(aCertFingerprint, aSubjectName,
1810 aPrettyName, aCertificate, aURI, PR_TRUE,
1811 result);
1814 nsresult
1815 nsScriptSecurityManager::DoGetCertificatePrincipal(const nsACString& aCertFingerprint,
1816 const nsACString& aSubjectName,
1817 const nsACString& aPrettyName,
1818 nsISupports* aCertificate,
1819 nsIURI* aURI,
1820 PRBool aModifyTable,
1821 nsIPrincipal **result)
1823 NS_ENSURE_ARG(!aCertFingerprint.IsEmpty());
1825 // Create a certificate principal out of the certificate ID
1826 // and URI given to us. We will use this principal to test
1827 // equality when doing our hashtable lookups below.
1828 nsRefPtr<nsPrincipal> certificate = new nsPrincipal();
1829 if (!certificate)
1830 return NS_ERROR_OUT_OF_MEMORY;
1832 nsresult rv = certificate->Init(aCertFingerprint, aSubjectName,
1833 aPrettyName, aCertificate, aURI);
1834 NS_ENSURE_SUCCESS(rv, rv);
1836 // Check to see if we already have this principal.
1837 nsCOMPtr<nsIPrincipal> fromTable;
1838 mPrincipals.Get(certificate, getter_AddRefs(fromTable));
1839 if (fromTable) {
1840 // Bingo. We found the certificate in the table, which means
1841 // that it has escalated privileges.
1843 if (aModifyTable) {
1844 // Make sure this principal has names, so if we ever go to save it
1845 // we'll save them. If we get a name mismatch here we'll throw,
1846 // but that's desirable.
1847 rv = static_cast<nsPrincipal*>
1848 (static_cast<nsIPrincipal*>(fromTable))
1849 ->EnsureCertData(aSubjectName, aPrettyName, aCertificate);
1850 if (NS_FAILED(rv)) {
1851 // We have a subject name mismatch for the same cert id.
1852 // Hand back the |certificate| object we created and don't give
1853 // it any rights from the table.
1854 NS_ADDREF(*result = certificate);
1855 return NS_OK;
1859 if (!aURI) {
1860 // We were asked to just get the base certificate, so output
1861 // what we have in the table.
1862 certificate = static_cast<nsPrincipal*>
1863 (static_cast<nsIPrincipal*>
1864 (fromTable));
1865 } else {
1866 // We found a certificate and now need to install a codebase
1867 // on it. We don't want to modify the principal in the hash
1868 // table, so create a new principal and clone the pertinent
1869 // things.
1870 nsXPIDLCString prefName;
1871 nsXPIDLCString id;
1872 nsXPIDLCString subjectName;
1873 nsXPIDLCString granted;
1874 nsXPIDLCString denied;
1875 PRBool isTrusted;
1876 rv = fromTable->GetPreferences(getter_Copies(prefName),
1877 getter_Copies(id),
1878 getter_Copies(subjectName),
1879 getter_Copies(granted),
1880 getter_Copies(denied),
1881 &isTrusted);
1882 // XXXbz assert something about subjectName and aSubjectName here?
1883 if (NS_SUCCEEDED(rv)) {
1884 NS_ASSERTION(!isTrusted, "Shouldn't have isTrusted true here");
1886 certificate = new nsPrincipal();
1887 if (!certificate)
1888 return NS_ERROR_OUT_OF_MEMORY;
1890 rv = certificate->InitFromPersistent(prefName, id,
1891 subjectName, aPrettyName,
1892 granted, denied,
1893 aCertificate,
1894 PR_TRUE, PR_FALSE);
1895 if (NS_FAILED(rv))
1896 return rv;
1898 certificate->SetURI(aURI);
1903 NS_ADDREF(*result = certificate);
1905 return rv;
1908 nsresult
1909 nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, nsIPrincipal **result)
1911 // I _think_ it's safe to not create null principals here based on aURI.
1912 // At least all the callers would do the right thing in those cases, as far
1913 // as I can tell. --bz
1914 nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
1915 if (!codebase)
1916 return NS_ERROR_OUT_OF_MEMORY;
1918 nsresult rv = codebase->Init(EmptyCString(), EmptyCString(),
1919 EmptyCString(), nsnull, aURI);
1920 if (NS_FAILED(rv))
1921 return rv;
1923 NS_ADDREF(*result = codebase);
1925 return NS_OK;
1928 NS_IMETHODIMP
1929 nsScriptSecurityManager::GetCodebasePrincipal(nsIURI *aURI,
1930 nsIPrincipal **result)
1932 NS_ENSURE_ARG(aURI);
1934 PRBool inheritsPrincipal;
1935 nsresult rv =
1936 NS_URIChainHasFlags(aURI,
1937 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
1938 &inheritsPrincipal);
1939 if (NS_FAILED(rv) || inheritsPrincipal) {
1940 return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result);
1943 nsCOMPtr<nsIPrincipal> principal;
1944 rv = CreateCodebasePrincipal(aURI, getter_AddRefs(principal));
1945 if (NS_FAILED(rv)) return rv;
1947 if (mPrincipals.Count() > 0)
1949 //-- Check to see if we already have this principal.
1950 nsCOMPtr<nsIPrincipal> fromTable;
1951 mPrincipals.Get(principal, getter_AddRefs(fromTable));
1952 if (!fromTable)
1954 //-- Check to see if we have a more general principal
1956 // XXXbz if only GetOrigin returned a URI! Or better yet if the
1957 // HashKey function on principals were smarter. As it is, we can
1958 // have cases where two principals will have different hashkeys but
1959 // test equal via KeyEquals, which is absolutely silly. That's
1960 // what we're working around here.
1961 nsXPIDLCString originUrl;
1962 rv = principal->GetOrigin(getter_Copies(originUrl));
1963 if (NS_FAILED(rv)) return rv;
1964 nsCOMPtr<nsIURI> newURI;
1965 rv = NS_NewURI(getter_AddRefs(newURI), originUrl, nsnull, sIOService);
1966 if (NS_FAILED(rv)) return rv;
1967 nsCOMPtr<nsIPrincipal> principal2;
1968 rv = CreateCodebasePrincipal(newURI, getter_AddRefs(principal2));
1969 if (NS_FAILED(rv)) return rv;
1970 mPrincipals.Get(principal2, getter_AddRefs(fromTable));
1973 if (fromTable) {
1974 // We found an existing codebase principal. But it might have a
1975 // generic codebase for this origin on it. Install our particular
1976 // codebase.
1977 // XXXbz this is kinda similar to the code in
1978 // GetCertificatePrincipal, but just ever so slightly different.
1979 // Oh, well.
1980 nsXPIDLCString prefName;
1981 nsXPIDLCString id;
1982 nsXPIDLCString subjectName;
1983 nsXPIDLCString granted;
1984 nsXPIDLCString denied;
1985 PRBool isTrusted;
1986 rv = fromTable->GetPreferences(getter_Copies(prefName),
1987 getter_Copies(id),
1988 getter_Copies(subjectName),
1989 getter_Copies(granted),
1990 getter_Copies(denied),
1991 &isTrusted);
1992 if (NS_SUCCEEDED(rv)) {
1993 nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
1994 if (!codebase)
1995 return NS_ERROR_OUT_OF_MEMORY;
1997 rv = codebase->InitFromPersistent(prefName, id,
1998 subjectName, EmptyCString(),
1999 granted, denied,
2000 nsnull, PR_FALSE,
2001 isTrusted);
2002 if (NS_FAILED(rv))
2003 return rv;
2005 codebase->SetURI(aURI);
2006 principal = codebase;
2012 NS_IF_ADDREF(*result = principal);
2014 return NS_OK;
2017 NS_IMETHODIMP
2018 nsScriptSecurityManager::GetPrincipalFromContext(JSContext *cx,
2019 nsIPrincipal **result)
2021 *result = nsnull;
2023 nsIScriptContext *scriptContext = GetScriptContext(cx);
2025 if (!scriptContext)
2027 return NS_ERROR_FAILURE;
2030 nsCOMPtr<nsIScriptObjectPrincipal> globalData =
2031 do_QueryInterface(scriptContext->GetGlobalObject());
2032 if (globalData)
2033 NS_IF_ADDREF(*result = globalData->GetPrincipal());
2035 return NS_OK;
2038 // static
2039 nsIPrincipal*
2040 nsScriptSecurityManager::GetScriptPrincipal(JSContext *cx,
2041 JSScript *script,
2042 nsresult* rv)
2044 NS_PRECONDITION(rv, "Null out param");
2045 *rv = NS_OK;
2046 if (!script)
2048 return nsnull;
2050 JSPrincipals *jsp = JS_GetScriptPrincipals(cx, script);
2051 if (!jsp) {
2052 *rv = NS_ERROR_FAILURE;
2053 NS_ERROR("Script compiled without principals!");
2054 return nsnull;
2056 nsJSPrincipals *nsJSPrin = static_cast<nsJSPrincipals *>(jsp);
2057 nsIPrincipal* result = nsJSPrin->nsIPrincipalPtr;
2058 if (!result)
2059 *rv = NS_ERROR_FAILURE;
2060 return result;
2063 // static
2064 nsIPrincipal*
2065 nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
2066 JSObject *obj,
2067 JSStackFrame *fp,
2068 nsresult *rv)
2070 NS_PRECONDITION(rv, "Null out param");
2071 JSFunction *fun = (JSFunction *) caps_GetJSPrivate(obj);
2072 JSScript *script = JS_GetFunctionScript(cx, fun);
2074 *rv = NS_OK;
2076 if (!script)
2078 // A native function: skip it in order to find its scripted caller.
2079 return nsnull;
2082 JSScript *frameScript = fp ? JS_GetFrameScript(cx, fp) : nsnull;
2084 if (frameScript && frameScript != script)
2086 // There is a frame script, and it's different from the
2087 // function script. In this case we're dealing with either
2088 // an eval or a Script object, and in these cases the
2089 // principal we want is in the frame's script, not in the
2090 // function's script. The function's script is where the
2091 // eval-calling code came from, not where the eval or new
2092 // Script object came from, and we want the principal of
2093 // the eval function object or new Script object.
2095 script = frameScript;
2097 else if (JS_GetFunctionObject(fun) != obj)
2099 // Here, obj is a cloned function object. In this case, the
2100 // clone's prototype may have been precompiled from brutally
2101 // shared chrome, or else it is a lambda or nested function.
2102 // The general case here is a function compiled against a
2103 // different scope than the one it is parented by at runtime,
2104 // hence the creation of a clone to carry the correct scope
2105 // chain linkage.
2107 // Since principals follow scope, we must get the object
2108 // principal from the clone's scope chain. There are no
2109 // reliable principals compiled into the function itself.
2111 nsIPrincipal *result = doGetObjectPrincipal(obj);
2112 if (!result)
2113 *rv = NS_ERROR_FAILURE;
2114 return result;
2117 return GetScriptPrincipal(cx, script, rv);
2120 // static
2121 nsIPrincipal*
2122 nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
2123 JSStackFrame *fp,
2124 nsresult *rv)
2126 NS_PRECONDITION(rv, "Null out param");
2127 JSObject *obj = JS_GetFrameFunctionObject(cx, fp);
2128 if (!obj)
2130 // Must be in a top-level script. Get principal from the script.
2131 JSScript *script = JS_GetFrameScript(cx, fp);
2132 return GetScriptPrincipal(cx, script, rv);
2135 nsIPrincipal* result = GetFunctionObjectPrincipal(cx, obj, fp, rv);
2137 #ifdef DEBUG
2138 if (NS_SUCCEEDED(*rv) && !result)
2140 JSFunction *fun = (JSFunction *)caps_GetJSPrivate(obj);
2141 JSScript *script = JS_GetFunctionScript(cx, fun);
2143 NS_ASSERTION(!script, "Null principal for non-native function!");
2145 #endif
2147 return result;
2150 // static
2151 nsIPrincipal*
2152 nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
2153 JSStackFrame **frameResult,
2154 nsresult* rv)
2156 NS_PRECONDITION(rv, "Null out param");
2157 //-- If there's no principal on the stack, look at the global object
2158 // and return the innermost frame for annotations.
2159 *rv = NS_OK;
2160 if (cx)
2162 // Get principals from innermost frame of JavaScript or Java.
2163 JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
2164 for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
2166 nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
2167 if (result)
2169 NS_ASSERTION(NS_SUCCEEDED(*rv), "Weird return");
2170 *frameResult = fp;
2171 return result;
2175 nsIScriptContext *scriptContext = GetScriptContext(cx);
2176 if (scriptContext)
2178 nsCOMPtr<nsIScriptObjectPrincipal> globalData =
2179 do_QueryInterface(scriptContext->GetGlobalObject());
2180 if (!globalData)
2182 *rv = NS_ERROR_FAILURE;
2183 return nsnull;
2186 // Note that we're not in a loop or anything, and nothing comes
2187 // after this point in the function, so we can just return here.
2188 nsIPrincipal* result = globalData->GetPrincipal();
2189 if (result)
2191 JSStackFrame *inner = nsnull;
2192 *frameResult = JS_FrameIterator(cx, &inner);
2193 return result;
2198 return nsnull;
2201 // static
2202 nsIPrincipal*
2203 nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
2204 nsresult* rv)
2206 NS_PRECONDITION(rv, "Null out param");
2207 JSStackFrame *fp;
2208 return GetPrincipalAndFrame(cx, &fp, rv);
2211 NS_IMETHODIMP
2212 nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
2213 nsIPrincipal **result)
2215 *result = doGetObjectPrincipal(aObj);
2216 if (!*result)
2217 return NS_ERROR_FAILURE;
2218 NS_ADDREF(*result);
2219 return NS_OK;
2222 // static
2223 nsIPrincipal*
2224 nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
2225 #ifdef DEBUG
2226 , PRBool aAllowShortCircuit
2227 #endif
2230 NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
2231 nsIPrincipal* result = nsnull;
2233 #ifdef DEBUG
2234 JSObject* origObj = aObj;
2235 #endif
2237 const JSClass *jsClass = STOBJ_GET_CLASS(aObj);
2239 // A common case seen in this code is that we enter this function
2240 // with aObj being a Function object, whose parent is a Call
2241 // object. Neither of those have object principals, so we can skip
2242 // those objects here before we enter the below loop. That way we
2243 // avoid wasting time checking properties of their classes etc in
2244 // the loop.
2246 if (jsClass == &js_FunctionClass) {
2247 aObj = STOBJ_GET_PARENT(aObj);
2249 if (!aObj)
2250 return nsnull;
2252 jsClass = STOBJ_GET_CLASS(aObj);
2254 if (jsClass == &js_CallClass) {
2255 aObj = STOBJ_GET_PARENT(aObj);
2257 if (!aObj)
2258 return nsnull;
2260 jsClass = STOBJ_GET_CLASS(aObj);
2264 do {
2265 // Note: jsClass is set before this loop, and also at the
2266 // *end* of this loop.
2268 // NOTE: These class and getObjectOps hook checks better match
2269 // what IS_WRAPPER_CLASS() does in xpconnect!
2270 if (jsClass == sXPCWrappedNativeJSClass ||
2271 jsClass->getObjectOps == sXPCWrappedNativeGetObjOps1 ||
2272 jsClass->getObjectOps == sXPCWrappedNativeGetObjOps2) {
2273 nsIXPConnectWrappedNative *xpcWrapper =
2274 (nsIXPConnectWrappedNative *)caps_GetJSPrivate(aObj);
2276 if (xpcWrapper) {
2277 #ifdef DEBUG
2278 if (aAllowShortCircuit) {
2279 #endif
2280 result = xpcWrapper->GetObjectPrincipal();
2282 if (result) {
2283 break;
2285 #ifdef DEBUG
2287 #endif
2289 // If not, check if it points to an
2290 // nsIScriptObjectPrincipal
2291 nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
2292 do_QueryWrappedNative(xpcWrapper);
2293 if (objPrin) {
2294 result = objPrin->GetPrincipal();
2296 if (result) {
2297 break;
2301 } else if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
2302 JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
2303 nsISupports *priv = (nsISupports *)caps_GetJSPrivate(aObj);
2305 #ifdef DEBUG
2306 if (aAllowShortCircuit) {
2307 nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
2308 do_QueryInterface(priv);
2310 NS_ASSERTION(!xpcWrapper ||
2311 !strcmp(jsClass->name, "XPCNativeWrapper"),
2312 "Uh, an nsIXPConnectWrappedNative with the "
2313 "wrong JSClass or getObjectOps hooks!");
2315 #endif
2317 nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
2318 do_QueryInterface(priv);
2320 if (objPrin) {
2321 result = objPrin->GetPrincipal();
2323 if (result) {
2324 break;
2329 aObj = STOBJ_GET_PARENT(aObj);
2331 if (!aObj)
2332 break;
2334 jsClass = STOBJ_GET_CLASS(aObj);
2335 } while (1);
2337 NS_ASSERTION(!aAllowShortCircuit ||
2338 result == doGetObjectPrincipal(origObj, PR_FALSE),
2339 "Principal mismatch. Not good");
2341 return result;
2344 nsresult
2345 nsScriptSecurityManager::SavePrincipal(nsIPrincipal* aToSave)
2347 //-- Save to mPrincipals
2348 mPrincipals.Put(aToSave, aToSave);
2350 //-- Save to prefs
2351 nsXPIDLCString idPrefName;
2352 nsXPIDLCString id;
2353 nsXPIDLCString subjectName;
2354 nsXPIDLCString grantedList;
2355 nsXPIDLCString deniedList;
2356 PRBool isTrusted;
2357 nsresult rv = aToSave->GetPreferences(getter_Copies(idPrefName),
2358 getter_Copies(id),
2359 getter_Copies(subjectName),
2360 getter_Copies(grantedList),
2361 getter_Copies(deniedList),
2362 &isTrusted);
2363 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2365 nsCAutoString grantedPrefName;
2366 nsCAutoString deniedPrefName;
2367 nsCAutoString subjectNamePrefName;
2368 rv = GetPrincipalPrefNames( idPrefName,
2369 grantedPrefName,
2370 deniedPrefName,
2371 subjectNamePrefName );
2372 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2374 mIsWritingPrefs = PR_TRUE;
2375 if (grantedList)
2376 mSecurityPref->SecuritySetCharPref(grantedPrefName.get(), grantedList);
2377 else
2378 mSecurityPref->SecurityClearUserPref(grantedPrefName.get());
2380 if (deniedList)
2381 mSecurityPref->SecuritySetCharPref(deniedPrefName.get(), deniedList);
2382 else
2383 mSecurityPref->SecurityClearUserPref(deniedPrefName.get());
2385 if (grantedList || deniedList) {
2386 mSecurityPref->SecuritySetCharPref(idPrefName, id);
2387 mSecurityPref->SecuritySetCharPref(subjectNamePrefName.get(),
2388 subjectName);
2390 else {
2391 mSecurityPref->SecurityClearUserPref(idPrefName);
2392 mSecurityPref->SecurityClearUserPref(subjectNamePrefName.get());
2395 mIsWritingPrefs = PR_FALSE;
2397 nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
2398 NS_ENSURE_SUCCESS(rv, rv);
2399 return prefService->SavePrefFile(nsnull);
2402 ///////////////// Capabilities API /////////////////////
2403 NS_IMETHODIMP
2404 nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
2405 PRBool *result)
2407 nsresult rv;
2408 JSStackFrame *fp = nsnull;
2409 JSContext *cx = GetCurrentJSContext();
2410 fp = cx ? JS_FrameIterator(cx, &fp) : nsnull;
2411 if (!fp)
2413 // No script code on stack. Allow execution.
2414 *result = PR_TRUE;
2415 return NS_OK;
2417 *result = PR_FALSE;
2418 nsIPrincipal* previousPrincipal = nsnull;
2421 nsIPrincipal* principal = GetFramePrincipal(cx, fp, &rv);
2422 if (NS_FAILED(rv))
2423 return rv;
2424 if (!principal)
2425 continue;
2426 // If caller has a different principal, stop looking up the stack.
2427 if(previousPrincipal)
2429 PRBool isEqual = PR_FALSE;
2430 if(NS_FAILED(previousPrincipal->Equals(principal, &isEqual)) || !isEqual)
2431 break;
2433 else
2434 previousPrincipal = principal;
2436 // First check if the principal is even able to enable the
2437 // given capability. If not, don't look any further.
2438 PRInt16 canEnable;
2439 rv = principal->CanEnableCapability(capability, &canEnable);
2440 if (NS_FAILED(rv)) return rv;
2441 if (canEnable != nsIPrincipal::ENABLE_GRANTED &&
2442 canEnable != nsIPrincipal::ENABLE_WITH_USER_PERMISSION)
2443 return NS_OK;
2445 // Now see if the capability is enabled.
2446 void *annotation = JS_GetFrameAnnotation(cx, fp);
2447 rv = principal->IsCapabilityEnabled(capability, annotation, result);
2448 if (NS_FAILED(rv)) return rv;
2449 if (*result)
2450 return NS_OK;
2451 } while ((fp = JS_FrameIterator(cx, &fp)) != nsnull);
2453 if (!previousPrincipal)
2455 // No principals on the stack, all native code. Allow
2456 // execution if the subject principal is the system principal.
2458 return SubjectPrincipalIsSystem(result);
2461 return NS_OK;
2464 void
2465 nsScriptSecurityManager::FormatCapabilityString(nsAString& aCapability)
2467 nsAutoString newcaps;
2468 nsAutoString rawcap;
2469 NS_NAMED_LITERAL_STRING(capdesc, "capdesc.");
2470 PRInt32 pos;
2471 PRInt32 index = kNotFound;
2472 nsresult rv;
2474 NS_ASSERTION(kNotFound == -1, "Basic constant changed, algorithm broken!");
2476 do {
2477 pos = index+1;
2478 index = aCapability.FindChar(' ', pos);
2479 rawcap = Substring(aCapability, pos,
2480 (index == kNotFound) ? index : index - pos);
2482 nsXPIDLString capstr;
2483 rv = sStrBundle->GetStringFromName(
2484 nsPromiseFlatString(capdesc+rawcap).get(),
2485 getter_Copies(capstr));
2486 if (NS_SUCCEEDED(rv))
2487 newcaps += capstr;
2488 else
2490 nsXPIDLString extensionCap;
2491 const PRUnichar* formatArgs[] = { rawcap.get() };
2492 rv = sStrBundle->FormatStringFromName(
2493 NS_LITERAL_STRING("ExtensionCapability").get(),
2494 formatArgs,
2495 NS_ARRAY_LENGTH(formatArgs),
2496 getter_Copies(extensionCap));
2497 if (NS_SUCCEEDED(rv))
2498 newcaps += extensionCap;
2499 else
2500 newcaps += rawcap;
2503 newcaps += NS_LITERAL_STRING("\n");
2504 } while (index != kNotFound);
2506 aCapability = newcaps;
2509 PRBool
2510 nsScriptSecurityManager::CheckConfirmDialog(JSContext* cx, nsIPrincipal* aPrincipal,
2511 const char* aCapability, PRBool *checkValue)
2513 nsresult rv;
2514 *checkValue = PR_FALSE;
2516 //-- Get a prompter for the current window.
2517 nsCOMPtr<nsIPrompt> prompter;
2518 if (cx)
2520 nsIScriptContext *scriptContext = GetScriptContext(cx);
2521 if (scriptContext)
2523 nsCOMPtr<nsIDOMWindowInternal> domWin =
2524 do_QueryInterface(scriptContext->GetGlobalObject());
2525 if (domWin)
2526 domWin->GetPrompter(getter_AddRefs(prompter));
2530 if (!prompter)
2532 //-- Couldn't get prompter from the current window, so get the prompt service.
2533 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
2534 if (wwatch)
2535 wwatch->GetNewPrompter(0, getter_AddRefs(prompter));
2536 if (!prompter)
2537 return PR_FALSE;
2540 //-- Localize the dialog text
2541 nsXPIDLString check;
2542 rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("CheckMessage").get(),
2543 getter_Copies(check));
2544 if (NS_FAILED(rv))
2545 return PR_FALSE;
2547 nsXPIDLString title;
2548 rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("Titleline").get(),
2549 getter_Copies(title));
2550 if (NS_FAILED(rv))
2551 return PR_FALSE;
2553 nsXPIDLString yesStr;
2554 rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("Yes").get(),
2555 getter_Copies(yesStr));
2556 if (NS_FAILED(rv))
2557 return PR_FALSE;
2559 nsXPIDLString noStr;
2560 rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("No").get(),
2561 getter_Copies(noStr));
2562 if (NS_FAILED(rv))
2563 return PR_FALSE;
2565 nsCAutoString val;
2566 PRBool hasCert;
2567 aPrincipal->GetHasCertificate(&hasCert);
2568 if (hasCert)
2569 rv = aPrincipal->GetPrettyName(val);
2570 else
2571 rv = GetPrincipalDomainOrigin(aPrincipal, val);
2573 if (NS_FAILED(rv))
2574 return PR_FALSE;
2576 NS_ConvertUTF8toUTF16 location(val);
2577 NS_ConvertASCIItoUTF16 capability(aCapability);
2578 FormatCapabilityString(capability);
2579 const PRUnichar *formatStrings[] = { location.get(), capability.get() };
2581 nsXPIDLString message;
2582 rv = sStrBundle->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityQuery").get(),
2583 formatStrings,
2584 NS_ARRAY_LENGTH(formatStrings),
2585 getter_Copies(message));
2586 if (NS_FAILED(rv))
2587 return PR_FALSE;
2589 PRInt32 buttonPressed = 1; // If the user exits by clicking the close box, assume No (button 1)
2590 rv = prompter->ConfirmEx(title.get(), message.get(),
2591 (nsIPrompt::BUTTON_DELAY_ENABLE) +
2592 (nsIPrompt::BUTTON_POS_1_DEFAULT) +
2593 (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) +
2594 (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_1),
2595 yesStr.get(), noStr.get(), nsnull, check.get(), checkValue, &buttonPressed);
2597 if (NS_FAILED(rv))
2598 *checkValue = PR_FALSE;
2599 return (buttonPressed == 0);
2602 NS_IMETHODIMP
2603 nsScriptSecurityManager::RequestCapability(nsIPrincipal* aPrincipal,
2604 const char *capability, PRInt16* canEnable)
2606 if (NS_FAILED(aPrincipal->CanEnableCapability(capability, canEnable)))
2607 return NS_ERROR_FAILURE;
2608 if (*canEnable == nsIPrincipal::ENABLE_WITH_USER_PERMISSION)
2610 // Prompt user for permission to enable capability.
2611 JSContext* cx = GetCurrentJSContext();
2612 PRBool remember;
2613 if (CheckConfirmDialog(cx, aPrincipal, capability, &remember))
2614 *canEnable = nsIPrincipal::ENABLE_GRANTED;
2615 else
2616 *canEnable = nsIPrincipal::ENABLE_DENIED;
2617 if (remember)
2619 //-- Save principal to prefs and to mPrincipals
2620 if (NS_FAILED(aPrincipal->SetCanEnableCapability(capability, *canEnable)))
2621 return NS_ERROR_FAILURE;
2622 if (NS_FAILED(SavePrincipal(aPrincipal)))
2623 return NS_ERROR_FAILURE;
2626 return NS_OK;
2629 NS_IMETHODIMP
2630 nsScriptSecurityManager::EnableCapability(const char *capability)
2632 JSContext *cx = GetCurrentJSContext();
2633 JSStackFrame *fp;
2635 //-- Error checks for capability string length (200)
2636 if(PL_strlen(capability)>200)
2638 static const char msg[] = "Capability name too long";
2639 SetPendingException(cx, msg);
2640 return NS_ERROR_FAILURE;
2643 //-- Check capability string for valid characters
2645 // Logically we might have wanted this in nsPrincipal, but performance
2646 // worries dictate it can't go in IsCapabilityEnabled() and we may have
2647 // to show the capability on a dialog before we call the principal's
2648 // EnableCapability().
2650 // We don't need to validate the capability string on the other APIs
2651 // available to web content. Without the ability to enable junk then
2652 // isPrivilegeEnabled, disablePrivilege, and revertPrivilege all do
2653 // the right thing (effectively nothing) when passed unallowed chars.
2654 for (const char *ch = capability; *ch; ++ch)
2656 if (!NS_IS_ALPHA(*ch) && *ch != ' ' && !NS_IS_DIGIT(*ch)
2657 && *ch != '_' && *ch != '-' && *ch != '.')
2659 static const char msg[] = "Invalid character in capability name";
2660 SetPendingException(cx, msg);
2661 return NS_ERROR_FAILURE;
2665 nsresult rv;
2666 nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
2667 if (NS_FAILED(rv))
2668 return rv;
2669 if (!principal)
2670 return NS_ERROR_NOT_AVAILABLE;
2672 void *annotation = JS_GetFrameAnnotation(cx, fp);
2673 PRBool enabled;
2674 if (NS_FAILED(principal->IsCapabilityEnabled(capability, annotation,
2675 &enabled)))
2676 return NS_ERROR_FAILURE;
2677 if (enabled)
2678 return NS_OK;
2680 PRInt16 canEnable;
2681 if (NS_FAILED(RequestCapability(principal, capability, &canEnable)))
2682 return NS_ERROR_FAILURE;
2684 if (canEnable != nsIPrincipal::ENABLE_GRANTED)
2686 nsCAutoString val;
2687 PRBool hasCert;
2688 nsresult rv;
2689 principal->GetHasCertificate(&hasCert);
2690 if (hasCert)
2691 rv = principal->GetPrettyName(val);
2692 else
2693 rv = GetPrincipalDomainOrigin(principal, val);
2695 if (NS_FAILED(rv))
2696 return rv;
2698 NS_ConvertUTF8toUTF16 location(val);
2699 NS_ConvertUTF8toUTF16 cap(capability);
2700 const PRUnichar *formatStrings[] = { location.get(), cap.get() };
2702 nsXPIDLString message;
2703 rv = sStrBundle->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityDenied").get(),
2704 formatStrings,
2705 NS_ARRAY_LENGTH(formatStrings),
2706 getter_Copies(message));
2707 if (NS_FAILED(rv))
2708 return rv;
2710 SetPendingException(cx, message.get());
2712 return NS_ERROR_FAILURE; // XXX better error code?
2714 if (NS_FAILED(principal->EnableCapability(capability, &annotation)))
2715 return NS_ERROR_FAILURE;
2716 JS_SetFrameAnnotation(cx, fp, annotation);
2717 return NS_OK;
2720 NS_IMETHODIMP
2721 nsScriptSecurityManager::RevertCapability(const char *capability)
2723 JSContext *cx = GetCurrentJSContext();
2724 JSStackFrame *fp;
2725 nsresult rv;
2726 nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
2727 if (NS_FAILED(rv))
2728 return rv;
2729 if (!principal)
2730 return NS_ERROR_NOT_AVAILABLE;
2731 void *annotation = JS_GetFrameAnnotation(cx, fp);
2732 principal->RevertCapability(capability, &annotation);
2733 JS_SetFrameAnnotation(cx, fp, annotation);
2734 return NS_OK;
2737 NS_IMETHODIMP
2738 nsScriptSecurityManager::DisableCapability(const char *capability)
2740 JSContext *cx = GetCurrentJSContext();
2741 JSStackFrame *fp;
2742 nsresult rv;
2743 nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
2744 if (NS_FAILED(rv))
2745 return rv;
2746 if (!principal)
2747 return NS_ERROR_NOT_AVAILABLE;
2748 void *annotation = JS_GetFrameAnnotation(cx, fp);
2749 principal->DisableCapability(capability, &annotation);
2750 JS_SetFrameAnnotation(cx, fp, annotation);
2751 return NS_OK;
2754 //////////////// Master Certificate Functions ///////////////////////////////////////
2755 NS_IMETHODIMP
2756 nsScriptSecurityManager::SetCanEnableCapability(const nsACString& certFingerprint,
2757 const char* capability,
2758 PRInt16 canEnable)
2760 NS_ENSURE_ARG(!certFingerprint.IsEmpty());
2762 nsresult rv;
2763 nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv);
2764 if (NS_FAILED(rv))
2765 return rv;
2767 //-- Get the system certificate
2768 if (!mSystemCertificate)
2770 nsCOMPtr<nsIFile> systemCertFile;
2771 nsCOMPtr<nsIProperties> directoryService =
2772 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
2773 if (!directoryService) return NS_ERROR_FAILURE;
2774 rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile),
2775 getter_AddRefs(systemCertFile));
2776 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2777 systemCertFile->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
2778 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2779 nsCOMPtr<nsIZipReader> systemCertZip = do_CreateInstance(kZipReaderCID, &rv);
2780 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2781 rv = systemCertZip->Open(systemCertFile);
2782 if (NS_SUCCEEDED(rv))
2784 nsCOMPtr<nsIJAR> systemCertJar(do_QueryInterface(systemCertZip, &rv));
2785 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2786 rv = systemCertJar->GetCertificatePrincipal(nsnull,
2787 getter_AddRefs(mSystemCertificate));
2788 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2792 //-- Make sure the caller's principal is the system certificate
2793 PRBool isEqual = PR_FALSE;
2794 if (mSystemCertificate)
2796 rv = mSystemCertificate->Equals(subjectPrincipal, &isEqual);
2797 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2799 if (!isEqual)
2801 JSContext* cx = GetCurrentJSContext();
2802 if (!cx) return NS_ERROR_FAILURE;
2803 static const char msg1[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate";
2804 static const char msg2[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established";
2805 SetPendingException(cx, mSystemCertificate ? msg1 : msg2);
2806 return NS_ERROR_FAILURE;
2809 //-- Get the target principal
2810 nsCOMPtr<nsIPrincipal> objectPrincipal;
2811 rv = DoGetCertificatePrincipal(certFingerprint, EmptyCString(),
2812 EmptyCString(), nsnull,
2813 nsnull, PR_FALSE,
2814 getter_AddRefs(objectPrincipal));
2815 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2816 rv = objectPrincipal->SetCanEnableCapability(capability, canEnable);
2817 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
2818 return SavePrincipal(objectPrincipal);
2821 ////////////////////////////////////////////////
2822 // Methods implementing nsIXPCSecurityManager //
2823 ////////////////////////////////////////////////
2825 NS_IMETHODIMP
2826 nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
2827 const nsIID &aIID,
2828 nsISupports *aObj,
2829 nsIClassInfo *aClassInfo,
2830 void **aPolicy)
2832 #ifdef DEBUG_CAPS_CanCreateWrapper
2833 char* iidStr = aIID.ToString();
2834 printf("### CanCreateWrapper(%s) ", iidStr);
2835 nsCRT::free(iidStr);
2836 #endif
2837 // XXX Special case for nsIXPCException ?
2838 ClassInfoData objClassInfo = ClassInfoData(aClassInfo, nsnull);
2839 if (objClassInfo.IsDOMClass())
2841 #ifdef DEBUG_CAPS_CanCreateWrapper
2842 printf("DOM class - GRANTED.\n");
2843 #endif
2844 return NS_OK;
2847 //--See if the object advertises a non-default level of access
2848 // using nsISecurityCheckedComponent
2849 nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
2850 do_QueryInterface(aObj);
2852 nsXPIDLCString objectSecurityLevel;
2853 if (checkedComponent)
2854 checkedComponent->CanCreateWrapper((nsIID *)&aIID, getter_Copies(objectSecurityLevel));
2856 nsresult rv = CheckXPCPermissions(aObj, objectSecurityLevel);
2857 if (NS_FAILED(rv))
2859 //-- Access denied, report an error
2860 NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied");
2861 nsCAutoString origin;
2862 nsresult rv2;
2863 nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2);
2864 if (NS_SUCCEEDED(rv2) && subjectPrincipal) {
2865 GetPrincipalDomainOrigin(subjectPrincipal, origin);
2867 NS_ConvertUTF8toUTF16 originUnicode(origin);
2868 NS_ConvertUTF8toUTF16 className(objClassInfo.GetName());
2869 const PRUnichar* formatStrings[] = {
2870 className.get(),
2871 originUnicode.get()
2873 PRUint32 length = NS_ARRAY_LENGTH(formatStrings);
2874 if (originUnicode.IsEmpty()) {
2875 --length;
2876 } else {
2877 strName.AppendLiteral("ForOrigin");
2879 nsXPIDLString errorMsg;
2880 // We need to keep our existing failure rv and not override it
2881 // with a likely success code from the following string bundle
2882 // call in order to throw the correct security exception later.
2883 rv2 = sStrBundle->FormatStringFromName(strName.get(),
2884 formatStrings,
2885 length,
2886 getter_Copies(errorMsg));
2887 NS_ENSURE_SUCCESS(rv2, rv2);
2889 SetPendingException(cx, errorMsg.get());
2891 #ifdef DEBUG_CAPS_CanCreateWrapper
2892 printf("DENIED.\n");
2894 else
2896 printf("GRANTED.\n");
2897 #endif
2900 return rv;
2903 #ifdef XPC_IDISPATCH_SUPPORT
2904 nsresult
2905 nsScriptSecurityManager::CheckComponentPermissions(JSContext *cx,
2906 const nsCID &aCID)
2908 nsresult rv;
2909 nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
2910 if (NS_FAILED(rv))
2911 return rv;
2913 // Reformat the CID string so it's suitable for prefs
2914 nsXPIDLCString cidTemp;
2915 cidTemp.Adopt(aCID.ToString());
2916 nsCAutoString cid(NS_LITERAL_CSTRING("CID") +
2917 Substring(cidTemp, 1, cidTemp.Length() - 2));
2918 ToUpperCase(cid);
2920 #ifdef DEBUG_CAPS_CheckComponentPermissions
2921 printf("### CheckComponentPermissions(ClassID.%s) ",cid.get());
2922 #endif
2924 // Look up the policy for this class.
2925 // while this isn't a property we'll treat it as such, using ACCESS_CALL_METHOD
2926 JSAutoRequest ar(cx);
2927 jsval cidVal = STRING_TO_JSVAL(::JS_InternString(cx, cid.get()));
2929 ClassInfoData nameData(nsnull, "ClassID");
2930 SecurityLevel securityLevel;
2931 rv = LookupPolicy(subjectPrincipal, nameData, cidVal,
2932 nsIXPCSecurityManager::ACCESS_CALL_METHOD,
2933 nsnull, &securityLevel);
2934 if (NS_FAILED(rv))
2935 return rv;
2937 // If there's no policy stored, use the "security.classID.allowByDefault" pref
2938 if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
2939 securityLevel.level = mXPCDefaultGrantAll ? SCRIPT_SECURITY_ALL_ACCESS :
2940 SCRIPT_SECURITY_NO_ACCESS;
2942 if (securityLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
2944 #ifdef DEBUG_CAPS_CheckComponentPermissions
2945 printf(" GRANTED.\n");
2946 #endif
2947 return NS_OK;
2950 #ifdef DEBUG_CAPS_CheckComponentPermissions
2951 printf(" DENIED.\n");
2952 #endif
2953 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2955 #endif
2957 NS_IMETHODIMP
2958 nsScriptSecurityManager::CanCreateInstance(JSContext *cx,
2959 const nsCID &aCID)
2961 #ifdef DEBUG_CAPS_CanCreateInstance
2962 char* cidStr = aCID.ToString();
2963 printf("### CanCreateInstance(%s) ", cidStr);
2964 nsCRT::free(cidStr);
2965 #endif
2967 nsresult rv = CheckXPCPermissions(nsnull, nsnull);
2968 if (NS_FAILED(rv))
2969 #ifdef XPC_IDISPATCH_SUPPORT
2971 rv = CheckComponentPermissions(cx, aCID);
2973 if (NS_FAILED(rv))
2974 #endif
2976 //-- Access denied, report an error
2977 nsCAutoString errorMsg("Permission denied to create instance of class. CID=");
2978 char cidStr[NSID_LENGTH];
2979 aCID.ToProvidedString(cidStr);
2980 errorMsg.Append(cidStr);
2981 SetPendingException(cx, errorMsg.get());
2983 #ifdef DEBUG_CAPS_CanCreateInstance
2984 printf("DENIED\n");
2986 else
2988 printf("GRANTED\n");
2989 #endif
2991 return rv;
2994 NS_IMETHODIMP
2995 nsScriptSecurityManager::CanGetService(JSContext *cx,
2996 const nsCID &aCID)
2998 #ifdef DEBUG_CAPS_CanGetService
2999 char* cidStr = aCID.ToString();
3000 printf("### CanGetService(%s) ", cidStr);
3001 nsCRT::free(cidStr);
3002 #endif
3004 nsresult rv = CheckXPCPermissions(nsnull, nsnull);
3005 if (NS_FAILED(rv))
3007 //-- Access denied, report an error
3008 nsCAutoString errorMsg("Permission denied to get service. CID=");
3009 char cidStr[NSID_LENGTH];
3010 aCID.ToProvidedString(cidStr);
3011 errorMsg.Append(cidStr);
3012 SetPendingException(cx, errorMsg.get());
3014 #ifdef DEBUG_CAPS_CanGetService
3015 printf("DENIED\n");
3017 else
3019 printf("GRANTED\n");
3020 #endif
3023 return rv;
3027 NS_IMETHODIMP
3028 nsScriptSecurityManager::CanAccess(PRUint32 aAction,
3029 nsAXPCNativeCallContext* aCallContext,
3030 JSContext* cx,
3031 JSObject* aJSObject,
3032 nsISupports* aObj,
3033 nsIClassInfo* aClassInfo,
3034 jsval aPropertyName,
3035 void** aPolicy)
3037 return CheckPropertyAccessImpl(aAction, aCallContext, cx,
3038 aJSObject, aObj, nsnull, aClassInfo,
3039 nsnull, aPropertyName, aPolicy);
3042 nsresult
3043 nsScriptSecurityManager::CheckXPCPermissions(nsISupports* aObj,
3044 const char* aObjectSecurityLevel)
3046 //-- Check for the all-powerful UniversalXPConnect privilege
3047 PRBool ok = PR_FALSE;
3048 if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalXPConnect", &ok)) && ok)
3049 return NS_OK;
3051 //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
3052 if (aObjectSecurityLevel)
3054 if (PL_strcasecmp(aObjectSecurityLevel, "allAccess") == 0)
3055 return NS_OK;
3056 else if (PL_strcasecmp(aObjectSecurityLevel, "noAccess") != 0)
3058 PRBool canAccess = PR_FALSE;
3059 if (NS_SUCCEEDED(IsCapabilityEnabled(aObjectSecurityLevel, &canAccess)) &&
3060 canAccess)
3061 return NS_OK;
3065 //-- If user allows scripting of plugins by untrusted scripts,
3066 // and the target object is a plugin, allow the access.
3067 if(aObj)
3069 nsresult rv;
3070 nsCOMPtr<nsIPluginInstance> plugin(do_QueryInterface(aObj, &rv));
3071 if (NS_SUCCEEDED(rv))
3073 static PRBool prefSet = PR_FALSE;
3074 static PRBool allowPluginAccess = PR_FALSE;
3075 if (!prefSet)
3077 rv = mSecurityPref->SecurityGetBoolPref("security.xpconnect.plugin.unrestricted",
3078 &allowPluginAccess);
3079 prefSet = PR_TRUE;
3081 if (allowPluginAccess)
3082 return NS_OK;
3086 //-- Access tests failed
3087 return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
3090 //////////////////////////////////////////////
3091 // Method implementing nsIPrefSecurityCheck //
3092 //////////////////////////////////////////////
3094 NS_IMETHODIMP
3095 nsScriptSecurityManager::CanAccessSecurityPreferences(PRBool* _retval)
3097 return IsCapabilityEnabled("CapabilityPreferencesAccess", _retval);
3100 /////////////////////////////////////////////
3101 // Method implementing nsIChannelEventSink //
3102 /////////////////////////////////////////////
3103 NS_IMETHODIMP
3104 nsScriptSecurityManager::OnChannelRedirect(nsIChannel* oldChannel,
3105 nsIChannel* newChannel,
3106 PRUint32 redirFlags)
3108 nsCOMPtr<nsIPrincipal> oldPrincipal;
3109 GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
3111 nsCOMPtr<nsIURI> newURI;
3112 newChannel->GetURI(getter_AddRefs(newURI));
3114 NS_ENSURE_STATE(oldPrincipal && newURI);
3116 const PRUint32 flags =
3117 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
3118 nsIScriptSecurityManager::DISALLOW_SCRIPT;
3119 return CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
3123 /////////////////////////////////////
3124 // Method implementing nsIObserver //
3125 /////////////////////////////////////
3126 static const char sPrincipalPrefix[] = "capability.principal";
3127 static const char sPolicyPrefix[] = "capability.policy.";
3129 NS_IMETHODIMP
3130 nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic,
3131 const PRUnichar* aMessage)
3133 nsresult rv = NS_OK;
3134 NS_ConvertUTF16toUTF8 messageStr(aMessage);
3135 const char *message = messageStr.get();
3137 static const char jsPrefix[] = "javascript.";
3138 static const char securityPrefix[] = "security.";
3139 if ((PL_strncmp(message, jsPrefix, sizeof(jsPrefix)-1) == 0) ||
3140 (PL_strncmp(message, securityPrefix, sizeof(securityPrefix)-1) == 0) )
3142 ScriptSecurityPrefChanged();
3144 else if (PL_strncmp(message, sPolicyPrefix, sizeof(sPolicyPrefix)-1) == 0)
3146 // This will force re-initialization of the pref table
3147 mPolicyPrefsChanged = PR_TRUE;
3149 else if ((PL_strncmp(message, sPrincipalPrefix, sizeof(sPrincipalPrefix)-1) == 0) &&
3150 !mIsWritingPrefs)
3152 static const char id[] = "id";
3153 char* lastDot = PL_strrchr(message, '.');
3154 //-- This check makes sure the string copy below doesn't overwrite its bounds
3155 if(PL_strlen(lastDot) >= sizeof(id))
3157 PL_strcpy(lastDot + 1, id);
3158 const char** idPrefArray = (const char**)&message;
3159 rv = InitPrincipals(1, idPrefArray, mSecurityPref);
3162 return rv;
3165 /////////////////////////////////////////////
3166 // Constructor, Destructor, Initialization //
3167 /////////////////////////////////////////////
3168 nsScriptSecurityManager::nsScriptSecurityManager(void)
3169 : mOriginToPolicyMap(nsnull),
3170 mDefaultPolicy(nsnull),
3171 mCapabilities(nsnull),
3172 mIsJavaScriptEnabled(PR_FALSE),
3173 mIsMailJavaScriptEnabled(PR_FALSE),
3174 mIsWritingPrefs(PR_FALSE),
3175 mPolicyPrefsChanged(PR_TRUE)
3176 #ifdef XPC_IDISPATCH_SUPPORT
3177 , mXPCDefaultGrantAll(PR_FALSE)
3178 #endif
3180 NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure.");
3181 mPrincipals.Init(31);
3185 nsresult nsScriptSecurityManager::Init()
3187 JSContext* cx = GetSafeJSContext();
3188 if (!cx) return NS_ERROR_FAILURE; // this can happen of xpt loading fails
3190 ::JS_BeginRequest(cx);
3191 if (sEnabledID == JSVAL_VOID)
3192 sEnabledID = STRING_TO_JSVAL(::JS_InternString(cx, "enabled"));
3193 ::JS_EndRequest(cx);
3195 nsresult rv = InitPrefs();
3196 NS_ENSURE_SUCCESS(rv, rv);
3198 rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
3199 NS_ENSURE_SUCCESS(rv, rv);
3201 rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
3202 NS_ENSURE_SUCCESS(rv, rv);
3204 nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
3205 NS_ENSURE_SUCCESS(rv, rv);
3207 rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle);
3208 NS_ENSURE_SUCCESS(rv, rv);
3210 // Create our system principal singleton
3211 nsRefPtr<nsSystemPrincipal> system = new nsSystemPrincipal();
3212 NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY);
3214 rv = system->Init();
3215 NS_ENSURE_SUCCESS(rv, rv);
3217 mSystemPrincipal = system;
3219 //-- Register security check callback in the JS engine
3220 // Currently this is used to control access to function.caller
3221 nsCOMPtr<nsIJSRuntimeService> runtimeService =
3222 do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv);
3223 NS_ENSURE_SUCCESS(rv, rv);
3225 rv = runtimeService->GetRuntime(&sRuntime);
3226 NS_ENSURE_SUCCESS(rv, rv);
3228 static JSSecurityCallbacks securityCallbacks = {
3229 CheckObjectAccess,
3230 NULL,
3231 NULL
3234 #ifdef DEBUG
3235 JSSecurityCallbacks *oldcallbacks =
3236 #endif
3237 JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
3238 NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
3240 sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeJSClass,
3241 &sXPCWrappedNativeGetObjOps1,
3242 &sXPCWrappedNativeGetObjOps2);
3243 return NS_OK;
3246 static nsScriptSecurityManager *gScriptSecMan = nsnull;
3248 jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID;
3250 nsScriptSecurityManager::~nsScriptSecurityManager(void)
3252 delete mOriginToPolicyMap;
3253 if(mDefaultPolicy)
3254 mDefaultPolicy->Drop();
3255 delete mCapabilities;
3256 gScriptSecMan = nsnull;
3259 void
3260 nsScriptSecurityManager::Shutdown()
3262 if (sRuntime) {
3263 JS_SetRuntimeSecurityCallbacks(sRuntime, NULL);
3264 sRuntime = nsnull;
3266 sEnabledID = JSVAL_VOID;
3268 NS_IF_RELEASE(sIOService);
3269 NS_IF_RELEASE(sXPConnect);
3270 NS_IF_RELEASE(sStrBundle);
3273 nsScriptSecurityManager *
3274 nsScriptSecurityManager::GetScriptSecurityManager()
3276 if (!gScriptSecMan)
3278 nsScriptSecurityManager* ssManager = new nsScriptSecurityManager();
3279 if (!ssManager)
3280 return nsnull;
3281 nsresult rv;
3282 rv = ssManager->Init();
3283 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to initialize nsScriptSecurityManager");
3284 if (NS_FAILED(rv)) {
3285 delete ssManager;
3286 return nsnull;
3289 rv = nsJSPrincipals::Startup();
3290 if (NS_FAILED(rv)) {
3291 NS_WARNING("can't initialize JS engine security protocol glue!");
3292 delete ssManager;
3293 return nsnull;
3296 rv = sXPConnect->SetDefaultSecurityManager(ssManager,
3297 nsIXPCSecurityManager::HOOK_ALL);
3298 if (NS_FAILED(rv)) {
3299 NS_WARNING("Failed to install xpconnect security manager!");
3300 delete ssManager;
3301 return nsnull;
3304 gScriptSecMan = ssManager;
3306 return gScriptSecMan;
3309 // Currently this nsGenericFactory constructor is used only from FastLoad
3310 // (XPCOM object deserialization) code, when "creating" the system principal
3311 // singleton.
3312 nsSystemPrincipal *
3313 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
3315 nsIPrincipal *sysprin = nsnull;
3316 if (gScriptSecMan)
3317 NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
3318 return static_cast<nsSystemPrincipal*>(sysprin);
3321 nsresult
3322 nsScriptSecurityManager::InitPolicies()
3324 // Clear any policies cached on XPConnect wrappers
3325 NS_ENSURE_STATE(sXPConnect);
3326 nsresult rv = sXPConnect->ClearAllWrappedNativeSecurityPolicies();
3327 if (NS_FAILED(rv)) return rv;
3329 //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
3330 //-- whose dtor decrements refcount of stored DomainPolicy object
3331 delete mOriginToPolicyMap;
3333 //-- Marks all the survivor DomainPolicy objects (those cached
3334 //-- by nsPrincipal objects) as invalid: they will be released
3335 //-- on first nsPrincipal::GetSecurityPolicy() attempt.
3336 DomainPolicy::InvalidateAll();
3338 //-- Release old default policy
3339 if(mDefaultPolicy) {
3340 mDefaultPolicy->Drop();
3341 mDefaultPolicy = nsnull;
3344 //-- Initialize a new mOriginToPolicyMap
3345 mOriginToPolicyMap =
3346 new nsObjectHashtable(nsnull, nsnull, DeleteDomainEntry, nsnull);
3347 if (!mOriginToPolicyMap)
3348 return NS_ERROR_OUT_OF_MEMORY;
3350 //-- Create, refcount and initialize a new default policy
3351 mDefaultPolicy = new DomainPolicy();
3352 if (!mDefaultPolicy)
3353 return NS_ERROR_OUT_OF_MEMORY;
3355 mDefaultPolicy->Hold();
3356 if (!mDefaultPolicy->Init())
3357 return NS_ERROR_UNEXPECTED;
3359 //-- Initialize the table of security levels
3360 if (!mCapabilities)
3362 mCapabilities =
3363 new nsObjectHashtable(nsnull, nsnull, DeleteCapability, nsnull);
3364 if (!mCapabilities)
3365 return NS_ERROR_OUT_OF_MEMORY;
3368 // Get a JS context - we need it to create internalized strings later.
3369 JSContext* cx = GetSafeJSContext();
3370 NS_ASSERTION(cx, "failed to get JS context");
3371 rv = InitDomainPolicy(cx, "default", mDefaultPolicy);
3372 NS_ENSURE_SUCCESS(rv, rv);
3374 nsXPIDLCString policyNames;
3375 rv = mSecurityPref->SecurityGetCharPref("capability.policy.policynames",
3376 getter_Copies(policyNames));
3378 nsXPIDLCString defaultPolicyNames;
3379 rv = mSecurityPref->SecurityGetCharPref("capability.policy.default_policynames",
3380 getter_Copies(defaultPolicyNames));
3381 policyNames += NS_LITERAL_CSTRING(" ") + defaultPolicyNames;
3383 //-- Initialize domain policies
3384 char* policyCurrent = policyNames.BeginWriting();
3385 PRBool morePolicies = PR_TRUE;
3386 while (morePolicies)
3388 while(*policyCurrent == ' ' || *policyCurrent == ',')
3389 policyCurrent++;
3390 if (*policyCurrent == '\0')
3391 break;
3392 char* nameBegin = policyCurrent;
3394 while(*policyCurrent != '\0' && *policyCurrent != ' ' && *policyCurrent != ',')
3395 policyCurrent++;
3397 morePolicies = (*policyCurrent != '\0');
3398 *policyCurrent = '\0';
3399 policyCurrent++;
3401 nsCAutoString sitesPrefName(
3402 NS_LITERAL_CSTRING(sPolicyPrefix) +
3403 nsDependentCString(nameBegin) +
3404 NS_LITERAL_CSTRING(".sites"));
3405 nsXPIDLCString domainList;
3406 rv = mSecurityPref->SecurityGetCharPref(sitesPrefName.get(),
3407 getter_Copies(domainList));
3408 if (NS_FAILED(rv))
3409 continue;
3411 DomainPolicy* domainPolicy = new DomainPolicy();
3412 if (!domainPolicy)
3413 return NS_ERROR_OUT_OF_MEMORY;
3415 if (!domainPolicy->Init())
3417 delete domainPolicy;
3418 return NS_ERROR_UNEXPECTED;
3420 domainPolicy->Hold();
3421 //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
3422 char* domainStart = domainList.BeginWriting();
3423 char* domainCurrent = domainStart;
3424 char* lastDot = nsnull;
3425 char* nextToLastDot = nsnull;
3426 PRBool moreDomains = PR_TRUE;
3427 while (moreDomains)
3429 if (*domainCurrent == ' ' || *domainCurrent == '\0')
3431 moreDomains = (*domainCurrent != '\0');
3432 *domainCurrent = '\0';
3433 nsCStringKey key(nextToLastDot ? nextToLastDot+1 : domainStart);
3434 DomainEntry *newEntry = new DomainEntry(domainStart, domainPolicy);
3435 if (!newEntry)
3437 domainPolicy->Drop();
3438 return NS_ERROR_OUT_OF_MEMORY;
3440 #ifdef DEBUG
3441 newEntry->mPolicyName_DEBUG = nameBegin;
3442 #endif
3443 DomainEntry *existingEntry = (DomainEntry *)
3444 mOriginToPolicyMap->Get(&key);
3445 if (!existingEntry)
3446 mOriginToPolicyMap->Put(&key, newEntry);
3447 else
3449 if (existingEntry->Matches(domainStart))
3451 newEntry->mNext = existingEntry;
3452 mOriginToPolicyMap->Put(&key, newEntry);
3454 else
3456 while (existingEntry->mNext)
3458 if (existingEntry->mNext->Matches(domainStart))
3460 newEntry->mNext = existingEntry->mNext;
3461 existingEntry->mNext = newEntry;
3462 break;
3464 existingEntry = existingEntry->mNext;
3466 if (!existingEntry->mNext)
3467 existingEntry->mNext = newEntry;
3470 domainStart = domainCurrent + 1;
3471 lastDot = nextToLastDot = nsnull;
3473 else if (*domainCurrent == '.')
3475 nextToLastDot = lastDot;
3476 lastDot = domainCurrent;
3478 domainCurrent++;
3481 rv = InitDomainPolicy(cx, nameBegin, domainPolicy);
3482 domainPolicy->Drop();
3483 if (NS_FAILED(rv))
3484 return rv;
3487 // Reset the "dirty" flag
3488 mPolicyPrefsChanged = PR_FALSE;
3490 #ifdef DEBUG_CAPS_HACKER
3491 PrintPolicyDB();
3492 #endif
3493 return NS_OK;
3497 nsresult
3498 nsScriptSecurityManager::InitDomainPolicy(JSContext* cx,
3499 const char* aPolicyName,
3500 DomainPolicy* aDomainPolicy)
3502 nsresult rv;
3503 nsCAutoString policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix) +
3504 nsDependentCString(aPolicyName) +
3505 NS_LITERAL_CSTRING("."));
3506 PRUint32 prefixLength = policyPrefix.Length() - 1; // subtract the '.'
3508 PRUint32 prefCount;
3509 char** prefNames;
3510 rv = mPrefBranch->GetChildList(policyPrefix.get(),
3511 &prefCount, &prefNames);
3512 if (NS_FAILED(rv)) return rv;
3513 if (prefCount == 0)
3514 return NS_OK;
3516 //-- Populate the policy
3517 PRUint32 currentPref = 0;
3518 for (; currentPref < prefCount; currentPref++)
3520 // Get the class name
3521 const char* start = prefNames[currentPref] + prefixLength + 1;
3522 char* end = PL_strchr(start, '.');
3523 if (!end) // malformed pref, bail on this one
3524 continue;
3525 static const char sitesStr[] = "sites";
3527 // We dealt with "sites" in InitPolicies(), so no need to do
3528 // that again...
3529 if (PL_strncmp(start, sitesStr, sizeof(sitesStr)-1) == 0)
3530 continue;
3532 // Get the pref value
3533 nsXPIDLCString prefValue;
3534 rv = mSecurityPref->SecurityGetCharPref(prefNames[currentPref],
3535 getter_Copies(prefValue));
3536 if (NS_FAILED(rv) || !prefValue)
3537 continue;
3539 SecurityLevel secLevel;
3540 if (PL_strcasecmp(prefValue, "noAccess") == 0)
3541 secLevel.level = SCRIPT_SECURITY_NO_ACCESS;
3542 else if (PL_strcasecmp(prefValue, "allAccess") == 0)
3543 secLevel.level = SCRIPT_SECURITY_ALL_ACCESS;
3544 else if (PL_strcasecmp(prefValue, "sameOrigin") == 0)
3545 secLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS;
3546 else
3547 { //-- pref value is the name of a capability
3548 nsCStringKey secLevelKey(prefValue);
3549 secLevel.capability =
3550 reinterpret_cast<char*>(mCapabilities->Get(&secLevelKey));
3551 if (!secLevel.capability)
3553 secLevel.capability = NS_strdup(prefValue);
3554 if (!secLevel.capability)
3555 break;
3556 mCapabilities->Put(&secLevelKey,
3557 secLevel.capability);
3561 *end = '\0';
3562 // Find or store this class in the classes table
3563 ClassPolicy* cpolicy =
3564 static_cast<ClassPolicy*>
3565 (PL_DHashTableOperate(aDomainPolicy, start,
3566 PL_DHASH_ADD));
3567 if (!cpolicy)
3568 break;
3570 // If this is the wildcard class (class '*'), save it in mWildcardPolicy
3571 // (we leave it stored in the hashtable too to take care of the cleanup)
3572 if ((*start == '*') && (end == start + 1)) {
3573 aDomainPolicy->mWildcardPolicy = cpolicy;
3575 // Make sure that cpolicy knows about aDomainPolicy so it can reset
3576 // the mWildcardPolicy pointer as needed if it gets moved in the
3577 // hashtable.
3578 cpolicy->mDomainWeAreWildcardFor = aDomainPolicy;
3581 // Get the property name
3582 start = end + 1;
3583 end = PL_strchr(start, '.');
3584 if (end)
3585 *end = '\0';
3587 JSAutoRequest ar(cx);
3589 JSString* propertyKey = ::JS_InternString(cx, start);
3590 if (!propertyKey)
3591 return NS_ERROR_OUT_OF_MEMORY;
3593 // Store this property in the class policy
3594 const void* ppkey =
3595 reinterpret_cast<const void*>(STRING_TO_JSVAL(propertyKey));
3596 PropertyPolicy* ppolicy =
3597 static_cast<PropertyPolicy*>
3598 (PL_DHashTableOperate(cpolicy->mPolicy, ppkey,
3599 PL_DHASH_ADD));
3600 if (!ppolicy)
3601 break;
3603 if (end) // The pref specifies an access mode
3605 start = end + 1;
3606 if (PL_strcasecmp(start, "set") == 0)
3607 ppolicy->mSet = secLevel;
3608 else
3609 ppolicy->mGet = secLevel;
3611 else
3613 if (ppolicy->mGet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
3614 ppolicy->mGet = secLevel;
3615 if (ppolicy->mSet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
3616 ppolicy->mSet = secLevel;
3620 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
3621 if (currentPref < prefCount) // Loop exited early because of out-of-memory error
3622 return NS_ERROR_OUT_OF_MEMORY;
3623 return NS_OK;
3627 // XXXbz We should really just get a prefbranch to handle this...
3628 nsresult
3629 nsScriptSecurityManager::GetPrincipalPrefNames(const char* prefBase,
3630 nsCString& grantedPref,
3631 nsCString& deniedPref,
3632 nsCString& subjectNamePref)
3634 char* lastDot = PL_strrchr(prefBase, '.');
3635 if (!lastDot) return NS_ERROR_FAILURE;
3636 PRInt32 prefLen = lastDot - prefBase + 1;
3638 grantedPref.Assign(prefBase, prefLen);
3639 deniedPref.Assign(prefBase, prefLen);
3640 subjectNamePref.Assign(prefBase, prefLen);
3642 #define GRANTED "granted"
3643 #define DENIED "denied"
3644 #define SUBJECTNAME "subjectName"
3646 grantedPref.AppendLiteral(GRANTED);
3647 if (grantedPref.Length() != prefLen + sizeof(GRANTED) - 1) {
3648 return NS_ERROR_OUT_OF_MEMORY;
3651 deniedPref.AppendLiteral(DENIED);
3652 if (deniedPref.Length() != prefLen + sizeof(DENIED) - 1) {
3653 return NS_ERROR_OUT_OF_MEMORY;
3656 subjectNamePref.AppendLiteral(SUBJECTNAME);
3657 if (subjectNamePref.Length() != prefLen + sizeof(SUBJECTNAME) - 1) {
3658 return NS_ERROR_OUT_OF_MEMORY;
3661 #undef SUBJECTNAME
3662 #undef DENIED
3663 #undef GRANTED
3665 return NS_OK;
3668 nsresult
3669 nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount, const char** aPrefNames,
3670 nsISecurityPref* aSecurityPref)
3672 /* This is the principal preference syntax:
3673 * capability.principal.[codebase|codebaseTrusted|certificate].<name>.[id|granted|denied]
3674 * For example:
3675 * user_pref("capability.principal.certificate.p1.id","12:34:AB:CD");
3676 * user_pref("capability.principal.certificate.p1.granted","Capability1 Capability2");
3677 * user_pref("capability.principal.certificate.p1.denied","Capability3");
3680 /* codebaseTrusted means a codebase principal that can enable capabilities even if
3681 * codebase principals are disabled. Don't use trustedCodebase except with unspoofable
3682 * URLs such as HTTPS URLs.
3685 static const char idSuffix[] = ".id";
3686 for (PRUint32 c = 0; c < aPrefCount; c++)
3688 PRInt32 prefNameLen = PL_strlen(aPrefNames[c]) -
3689 (NS_ARRAY_LENGTH(idSuffix) - 1);
3690 if (PL_strcasecmp(aPrefNames[c] + prefNameLen, idSuffix) != 0)
3691 continue;
3693 nsXPIDLCString id;
3694 if (NS_FAILED(mSecurityPref->SecurityGetCharPref(aPrefNames[c], getter_Copies(id))))
3695 return NS_ERROR_FAILURE;
3697 nsCAutoString grantedPrefName;
3698 nsCAutoString deniedPrefName;
3699 nsCAutoString subjectNamePrefName;
3700 nsresult rv = GetPrincipalPrefNames(aPrefNames[c],
3701 grantedPrefName,
3702 deniedPrefName,
3703 subjectNamePrefName);
3704 if (rv == NS_ERROR_OUT_OF_MEMORY)
3705 return rv;
3706 if (NS_FAILED(rv))
3707 continue;
3709 nsXPIDLCString grantedList;
3710 mSecurityPref->SecurityGetCharPref(grantedPrefName.get(),
3711 getter_Copies(grantedList));
3712 nsXPIDLCString deniedList;
3713 mSecurityPref->SecurityGetCharPref(deniedPrefName.get(),
3714 getter_Copies(deniedList));
3715 nsXPIDLCString subjectName;
3716 mSecurityPref->SecurityGetCharPref(subjectNamePrefName.get(),
3717 getter_Copies(subjectName));
3719 //-- Delete prefs if their value is the empty string
3720 if (id.IsEmpty() || (grantedList.IsEmpty() && deniedList.IsEmpty()))
3722 mSecurityPref->SecurityClearUserPref(aPrefNames[c]);
3723 mSecurityPref->SecurityClearUserPref(grantedPrefName.get());
3724 mSecurityPref->SecurityClearUserPref(deniedPrefName.get());
3725 mSecurityPref->SecurityClearUserPref(subjectNamePrefName.get());
3726 continue;
3729 //-- Create a principal based on the prefs
3730 static const char certificateName[] = "capability.principal.certificate";
3731 static const char codebaseName[] = "capability.principal.codebase";
3732 static const char codebaseTrustedName[] = "capability.principal.codebaseTrusted";
3734 PRBool isCert = PR_FALSE;
3735 PRBool isTrusted = PR_FALSE;
3737 if (PL_strncmp(aPrefNames[c], certificateName,
3738 sizeof(certificateName) - 1) == 0)
3740 isCert = PR_TRUE;
3742 else if (PL_strncmp(aPrefNames[c], codebaseName,
3743 sizeof(codebaseName) - 1) == 0)
3745 isTrusted = (PL_strncmp(aPrefNames[c], codebaseTrustedName,
3746 sizeof(codebaseTrustedName) - 1) == 0);
3748 else
3750 NS_ERROR("Not a codebase or a certificate?!");
3753 nsRefPtr<nsPrincipal> newPrincipal = new nsPrincipal();
3754 if (!newPrincipal)
3755 return NS_ERROR_OUT_OF_MEMORY;
3757 rv = newPrincipal->InitFromPersistent(aPrefNames[c], id, subjectName,
3758 EmptyCString(),
3759 grantedList, deniedList, nsnull,
3760 isCert, isTrusted);
3761 if (NS_SUCCEEDED(rv))
3762 mPrincipals.Put(newPrincipal, newPrincipal);
3764 return NS_OK;
3767 const char nsScriptSecurityManager::sJSEnabledPrefName[] =
3768 "javascript.enabled";
3769 const char nsScriptSecurityManager::sJSMailEnabledPrefName[] =
3770 "javascript.allow.mailnews";
3771 const char nsScriptSecurityManager::sFileOriginPolicyPrefName[] =
3772 "security.fileuri.strict_origin_policy";
3773 #ifdef XPC_IDISPATCH_SUPPORT
3774 const char nsScriptSecurityManager::sXPCDefaultGrantAllName[] =
3775 "security.classID.allowByDefault";
3776 #endif
3778 inline void
3779 nsScriptSecurityManager::ScriptSecurityPrefChanged()
3781 PRBool temp;
3782 nsresult rv = mSecurityPref->SecurityGetBoolPref(sJSEnabledPrefName, &temp);
3783 // JavaScript defaults to enabled in failure cases.
3784 mIsJavaScriptEnabled = NS_FAILED(rv) || temp;
3786 rv = mSecurityPref->SecurityGetBoolPref(sJSMailEnabledPrefName, &temp);
3787 // JavaScript in Mail defaults to disabled in failure cases.
3788 // disable javascript in mailnews for TB 3.0 beta1
3789 mIsMailJavaScriptEnabled = PR_FALSE; // NS_SUCCEEDED(rv) && temp;
3791 rv = mSecurityPref->SecurityGetBoolPref(sFileOriginPolicyPrefName, &temp);
3792 sStrictFileOriginPolicy = NS_SUCCEEDED(rv) && temp;
3794 #ifdef XPC_IDISPATCH_SUPPORT
3795 rv = mSecurityPref->SecurityGetBoolPref(sXPCDefaultGrantAllName, &temp);
3796 // Granting XPC Priveleges defaults to disabled in failure cases.
3797 mXPCDefaultGrantAll = NS_SUCCEEDED(rv) && temp;
3798 #endif
3801 nsresult
3802 nsScriptSecurityManager::InitPrefs()
3804 nsresult rv;
3805 nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
3806 NS_ENSURE_SUCCESS(rv, rv);
3807 rv = prefService->GetBranch(nsnull, getter_AddRefs(mPrefBranch));
3808 NS_ENSURE_SUCCESS(rv, rv);
3809 nsCOMPtr<nsIPrefBranch2> prefBranchInternal(do_QueryInterface(mPrefBranch, &rv));
3810 NS_ENSURE_SUCCESS(rv, rv);
3811 mSecurityPref = do_QueryInterface(mPrefBranch, &rv);
3812 NS_ENSURE_SUCCESS(rv, rv);
3814 // Set the initial value of the "javascript.enabled" prefs
3815 ScriptSecurityPrefChanged();
3816 // set observer callbacks in case the value of the prefs change
3817 prefBranchInternal->AddObserver(sJSEnabledPrefName, this, PR_FALSE);
3818 prefBranchInternal->AddObserver(sJSMailEnabledPrefName, this, PR_FALSE);
3819 prefBranchInternal->AddObserver(sFileOriginPolicyPrefName, this, PR_FALSE);
3820 #ifdef XPC_IDISPATCH_SUPPORT
3821 prefBranchInternal->AddObserver(sXPCDefaultGrantAllName, this, PR_FALSE);
3822 #endif
3823 PRUint32 prefCount;
3824 char** prefNames;
3826 // Set a callback for policy pref changes
3827 prefBranchInternal->AddObserver(sPolicyPrefix, this, PR_FALSE);
3829 //-- Initialize the principals database from prefs
3830 rv = mPrefBranch->GetChildList(sPrincipalPrefix, &prefCount, &prefNames);
3831 if (NS_SUCCEEDED(rv) && prefCount > 0)
3833 rv = InitPrincipals(prefCount, (const char**)prefNames, mSecurityPref);
3834 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
3835 NS_ENSURE_SUCCESS(rv, rv);
3837 //-- Set a callback for principal changes
3838 prefBranchInternal->AddObserver(sPrincipalPrefix, this, PR_FALSE);
3840 return NS_OK;
3843 ///////////////////////////////////////////////////////////////////////////////
3844 // The following code prints the contents of the policy DB to the console.
3845 #ifdef DEBUG_CAPS_HACKER
3847 //typedef PLDHashOperator
3848 //(* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
3849 // PRUint32 number, void *arg);
3850 PR_STATIC_CALLBACK(PLDHashOperator)
3851 PrintPropertyPolicy(PLDHashTable *table, PLDHashEntryHdr *entry,
3852 PRUint32 number, void *arg)
3854 PropertyPolicy* pp = (PropertyPolicy*)entry;
3855 nsCAutoString prop(" ");
3856 JSContext* cx = (JSContext*)arg;
3857 prop.AppendInt((PRUint32)pp->key);
3858 prop += ' ';
3859 prop.AppendWithConversion((PRUnichar*)JSValIDToString(cx, pp->key));
3860 prop += ": Get=";
3861 if (SECURITY_ACCESS_LEVEL_FLAG(pp->mGet))
3862 prop.AppendInt(pp->mGet.level);
3863 else
3864 prop += pp->mGet.capability;
3866 prop += " Set=";
3867 if (SECURITY_ACCESS_LEVEL_FLAG(pp->mSet))
3868 prop.AppendInt(pp->mSet.level);
3869 else
3870 prop += pp->mSet.capability;
3872 printf("%s.\n", prop.get());
3873 return PL_DHASH_NEXT;
3876 PR_STATIC_CALLBACK(PLDHashOperator)
3877 PrintClassPolicy(PLDHashTable *table, PLDHashEntryHdr *entry,
3878 PRUint32 number, void *arg)
3880 ClassPolicy* cp = (ClassPolicy*)entry;
3881 printf(" %s\n", cp->key);
3883 PL_DHashTableEnumerate(cp->mPolicy, PrintPropertyPolicy, arg);
3884 return PL_DHASH_NEXT;
3887 // typedef PRBool
3888 // (*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
3889 PR_STATIC_CALLBACK(PRBool)
3890 PrintDomainPolicy(nsHashKey *aKey, void *aData, void* aClosure)
3892 DomainEntry* de = (DomainEntry*)aData;
3893 printf("----------------------------\n");
3894 printf("Domain: %s Policy Name: %s.\n", de->mOrigin.get(),
3895 de->mPolicyName_DEBUG.get());
3896 PL_DHashTableEnumerate(de->mDomainPolicy, PrintClassPolicy, aClosure);
3897 return PR_TRUE;
3900 PR_STATIC_CALLBACK(PRBool)
3901 PrintCapability(nsHashKey *aKey, void *aData, void* aClosure)
3903 char* cap = (char*)aData;
3904 printf(" %s.\n", cap);
3905 return PR_TRUE;
3908 void
3909 nsScriptSecurityManager::PrintPolicyDB()
3911 printf("############## Security Policies ###############\n");
3912 if(mOriginToPolicyMap)
3914 JSContext* cx = GetCurrentJSContext();
3915 if (!cx)
3916 cx = GetSafeJSContext();
3917 printf("----------------------------\n");
3918 printf("Domain: Default.\n");
3919 PL_DHashTableEnumerate(mDefaultPolicy, PrintClassPolicy, (void*)cx);
3920 mOriginToPolicyMap->Enumerate(PrintDomainPolicy, (void*)cx);
3922 printf("############ End Security Policies #############\n\n");
3923 printf("############## Capabilities ###############\n");
3924 mCapabilities->Enumerate(PrintCapability);
3925 printf("############## End Capabilities ###############\n");
3927 #endif