1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
23 * Norris Boyd <nboyd@atg.com>
24 * Mitch Stoltz <mstoltz@netscape.com>
25 * Christopher A. Aillon <christopher@aillon.com>
26 * Giorgio Maone <g.maone@informaction.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #ifndef nsScriptSecurityManager_h__
43 #define nsScriptSecurityManager_h__
45 #include "nsIScriptSecurityManager.h"
46 #include "nsIPrincipal.h"
49 #include "nsIXPCSecurityManager.h"
50 #include "nsInterfaceHashtable.h"
51 #include "nsHashtable.h"
53 #include "nsIPrefService.h"
54 #include "nsIChannelEventSink.h"
55 #include "nsIJSContextStack.h"
56 #include "nsIObserver.h"
59 #include "nsIScriptExternalNameSet.h"
66 class nsIStringBundle
;
67 class nsSystemPrincipal
;
72 #if defined(DEBUG_mstoltz) || defined(DEBUG_caillon)
73 #define DEBUG_CAPS_HACKER
76 #ifdef DEBUG_CAPS_HACKER
77 #define DEBUG_CAPS_CheckPropertyAccessImpl
78 #define DEBUG_CAPS_LookupPolicy
79 #define DEBUG_CAPS_CheckComponentPermissions
83 #define DEBUG_CAPS_CanCreateWrapper
84 #define DEBUG_CAPS_CanCreateInstance
85 #define DEBUG_CAPS_CanGetService
86 #define DEBUG_CAPS_DomainPolicyLifeCycle
93 class PrincipalKey
: public PLDHashEntryHdr
96 typedef const nsIPrincipal
* KeyType
;
97 typedef const nsIPrincipal
* KeyTypePointer
;
99 PrincipalKey(const nsIPrincipal
* key
)
100 : mKey(const_cast<nsIPrincipal
*>(key
))
104 PrincipalKey(const PrincipalKey
& toCopy
)
113 KeyType
GetKey() const
118 PRBool
KeyEquals(KeyTypePointer aKey
) const
121 mKey
->Equals(const_cast<nsIPrincipal
*>(aKey
),
126 static KeyTypePointer
KeyToPointer(KeyType aKey
)
131 static PLDHashNumber
HashKey(KeyTypePointer aKey
)
134 const_cast<nsIPrincipal
*>(aKey
)->GetHashValue(&hash
);
135 return PLDHashNumber(hash
);
138 enum { ALLOW_MEMMOVE
= PR_TRUE
};
141 nsCOMPtr
<nsIPrincipal
> mKey
;
156 // These values all have the low bit set (except UNDEFINED_ACCESS)
157 // to distinguish them from pointer values, because no pointer
158 // to allocated memory ever has the low bit set. A SecurityLevel
159 // contains either one of these constants or a pointer to a string
160 // representing the name of a capability.
162 #define SCRIPT_SECURITY_UNDEFINED_ACCESS 0
163 #define SCRIPT_SECURITY_ACCESS_IS_SET_BIT 1
164 #define SCRIPT_SECURITY_NO_ACCESS \
165 ((1 << 0) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
166 #define SCRIPT_SECURITY_SAME_ORIGIN_ACCESS \
167 ((1 << 1) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
168 #define SCRIPT_SECURITY_ALL_ACCESS \
169 ((1 << 2) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
171 #define SECURITY_ACCESS_LEVEL_FLAG(_sl) \
172 ((_sl.level == 0) || \
173 (_sl.level & SCRIPT_SECURITY_ACCESS_IS_SET_BIT))
176 struct PropertyPolicy
: public PLDHashEntryHdr
178 jsval key
; // property name as jsval
184 InitPropertyPolicyEntry(PLDHashTable
*table
,
185 PLDHashEntryHdr
*entry
,
188 PropertyPolicy
* pp
= (PropertyPolicy
*)entry
;
189 pp
->key
= (jsval
)key
;
190 pp
->mGet
.level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
191 pp
->mSet
.level
= SCRIPT_SECURITY_UNDEFINED_ACCESS
;
196 ClearPropertyPolicyEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
198 PropertyPolicy
* pp
= (PropertyPolicy
*)entry
;
199 pp
->key
= JSVAL_VOID
;
203 #define NO_POLICY_FOR_CLASS (ClassPolicy*)1
205 struct ClassPolicy
: public PLDHashEntryHdr
208 PLDHashTable
* mPolicy
;
210 // Note: the DomainPolicy owns us, so if if dies we will too. Hence no
211 // need to refcount it here (and in fact, we'd probably leak if we tried).
212 DomainPolicy
* mDomainWeAreWildcardFor
;
216 ClearClassPolicyEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
218 ClassPolicy
* cp
= (ClassPolicy
*)entry
;
224 PL_DHashTableDestroy(cp
->mPolicy
);
227 // Note: actual impl is going to be after the DomainPolicy class definition,
228 // since we need to access members of DomainPolicy in the impl
230 MoveClassPolicyEntry(PLDHashTable
*table
,
231 const PLDHashEntryHdr
*from
,
232 PLDHashEntryHdr
*to
);
235 InitClassPolicyEntry(PLDHashTable
*table
,
236 PLDHashEntryHdr
*entry
,
239 static PLDHashTableOps classPolicyOps
=
243 PL_DHashVoidPtrKeyStub
,
244 PL_DHashMatchEntryStub
,
245 PL_DHashMoveEntryStub
,
246 ClearPropertyPolicyEntry
,
247 PL_DHashFinalizeStub
,
248 InitPropertyPolicyEntry
251 ClassPolicy
* cp
= (ClassPolicy
*)entry
;
252 cp
->mDomainWeAreWildcardFor
= nsnull
;
253 cp
->key
= PL_strdup((const char*)key
);
256 cp
->mPolicy
= PL_NewDHashTable(&classPolicyOps
, nsnull
,
257 sizeof(PropertyPolicy
), 16);
267 class DomainPolicy
: public PLDHashTable
270 DomainPolicy() : mWildcardPolicy(nsnull
),
273 mGeneration
= sGeneration
;
275 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
277 _printPopulationInfo();
284 static const PLDHashTableOps domainPolicyOps
=
289 PL_DHashMatchStringKey
,
290 MoveClassPolicyEntry
,
291 ClearClassPolicyEntry
,
292 PL_DHashFinalizeStub
,
296 return PL_DHashTableInit(this, &domainPolicyOps
, nsnull
,
297 sizeof(ClassPolicy
), 16);
302 PL_DHashTableFinish(this);
303 NS_ASSERTION(mRefCount
== 0, "Wrong refcount in DomainPolicy dtor");
304 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
305 printf("DomainPolicy deleted with mRefCount = %d\n", mRefCount
);
307 _printPopulationInfo();
319 if (--mRefCount
== 0)
323 static void InvalidateAll()
330 return mGeneration
!= sGeneration
;
333 ClassPolicy
* mWildcardPolicy
;
337 PRUint32 mGeneration
;
338 static PRUint32 sGeneration
;
340 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
341 static PRUint32 sObjects
;
342 static void _printPopulationInfo();
348 MoveClassPolicyEntry(PLDHashTable
*table
,
349 const PLDHashEntryHdr
*from
,
352 memcpy(to
, from
, table
->entrySize
);
354 // Now update the mDefaultPolicy pointer that points to us, if any.
355 ClassPolicy
* cp
= static_cast<ClassPolicy
*>(to
);
356 if (cp
->mDomainWeAreWildcardFor
) {
357 NS_ASSERTION(cp
->mDomainWeAreWildcardFor
->mWildcardPolicy
==
358 static_cast<const ClassPolicy
*>(from
),
359 "Unexpected wildcard policy on mDomainWeAreWildcardFor");
360 cp
->mDomainWeAreWildcardFor
->mWildcardPolicy
= cp
;
364 /////////////////////////////
365 // nsScriptSecurityManager //
366 /////////////////////////////
367 #define NS_SCRIPTSECURITYMANAGER_CID \
368 { 0x7ee2a4c0, 0x4b93, 0x17d3, \
369 { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
371 class nsScriptSecurityManager
: public nsIScriptSecurityManager
,
372 public nsIChannelEventSink
,
376 static void Shutdown();
378 NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID
)
381 NS_DECL_NSISCRIPTSECURITYMANAGER
382 NS_DECL_NSIXPCSECURITYMANAGER
383 NS_DECL_NSICHANNELEVENTSINK
386 static nsScriptSecurityManager
*
387 GetScriptSecurityManager();
389 static nsSystemPrincipal
*
390 SystemPrincipalSingletonConstructor();
392 JSContext
* GetCurrentJSContext();
394 JSContext
* GetSafeJSContext();
397 * Utility method for comparing two URIs. For security purposes, two URIs
398 * are equivalent if their schemes, hosts, and ports (if any) match. This
399 * method returns true if aSubjectURI and aObjectURI have the same origin,
402 static PRBool
SecurityCompareURIs(nsIURI
* aSourceURI
, nsIURI
* aTargetURI
);
403 static PRUint32
SecurityHashURI(nsIURI
* aURI
);
406 ReportError(JSContext
* cx
, const nsAString
& messageTag
,
407 nsIURI
* aSource
, nsIURI
* aTarget
);
410 CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
411 nsIPrincipal
* aObject
);
413 HashPrincipalByOrigin(nsIPrincipal
* aPrincipal
);
416 GetStrictFileOriginPolicy()
418 return sStrictFileOriginPolicy
;
423 // GetScriptSecurityManager is the only call that can make one
424 nsScriptSecurityManager();
425 virtual ~nsScriptSecurityManager();
428 CheckObjectAccess(JSContext
*cx
, JSObject
*obj
,
429 jsval id
, JSAccessMode mode
,
432 // Decides, based on CSP, whether or not eval() and stuff can be executed.
434 ContentSecurityPolicyPermitsJSAction(JSContext
*cx
);
436 // Returns null if a principal cannot be found; generally callers
437 // should error out at that point.
439 doGetObjectPrincipal(JSObject
*obj
441 , PRBool aAllowShortCircuit
= PR_TRUE
445 // Returns null if a principal cannot be found. Note that rv can be NS_OK
446 // when this happens -- this means that there was no JS running.
448 doGetSubjectPrincipal(nsresult
* rv
);
451 CheckPropertyAccessImpl(PRUint32 aAction
,
452 nsAXPCNativeCallContext
* aCallContext
,
453 JSContext
* cx
, JSObject
* aJSObject
,
454 nsISupports
* aObj
, nsIURI
* aTargetURI
,
455 nsIClassInfo
* aClassInfo
,
456 const char* aClassName
, jsval aProperty
,
457 void** aCachedClassPolicy
);
460 CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
461 nsIPrincipal
* aObject
,
465 LookupPolicy(nsIPrincipal
* principal
,
466 ClassInfoData
& aClassData
, jsval aProperty
,
468 ClassPolicy
** aCachedClassPolicy
,
469 SecurityLevel
* result
);
472 CreateCodebasePrincipal(nsIURI
* aURI
, nsIPrincipal
** result
);
474 // This is just like the API method, but it doesn't check that the subject
475 // name is non-empty or aCertificate is non-null, and it doesn't change the
476 // certificate in the table (if any) in any way if aModifyTable is false.
478 DoGetCertificatePrincipal(const nsACString
& aCertFingerprint
,
479 const nsACString
& aSubjectName
,
480 const nsACString
& aPrettyName
,
481 nsISupports
* aCertificate
,
484 nsIPrincipal
**result
);
486 // Returns null if a principal cannot be found. Note that rv can be NS_OK
487 // when this happens -- this means that there was no script for the
488 // context. Callers MUST pass in a non-null rv here.
490 GetSubjectPrincipal(JSContext
* cx
, nsresult
* rv
);
492 // Returns null if a principal cannot be found. Note that rv can be NS_OK
493 // when this happens -- this means that there was no script for the frame.
494 // Callers MUST pass in a non-null rv here.
496 GetFramePrincipal(JSContext
* cx
, JSStackFrame
* fp
, nsresult
* rv
);
498 // Returns null if a principal cannot be found. Note that rv can be NS_OK
499 // when this happens -- this means that there was no script. Callers MUST
500 // pass in a non-null rv here.
502 GetScriptPrincipal(JSContext
* cx
, JSScript
* script
, nsresult
* rv
);
504 // Returns null if a principal cannot be found. Note that rv can be NS_OK
505 // when this happens -- this means that there was no script associated
506 // with the function object, and no global object associated with the scope
507 // of obj (the last object on its parent chain). If the caller is walking
508 // the JS stack, fp must point to the current frame in the stack iteration.
509 // Callers MUST pass in a non-null rv here.
511 GetFunctionObjectPrincipal(JSContext
* cx
, JSObject
* obj
, JSStackFrame
*fp
,
514 // Returns null if a principal cannot be found. Note that rv can be NS_OK
515 // when this happens -- this means that there was no script
516 // running. Callers MUST pass in a non-null rv here.
518 GetPrincipalAndFrame(JSContext
*cx
,
519 JSStackFrame
** frameResult
,
523 CheckConfirmDialog(JSContext
* cx
, nsIPrincipal
* aPrincipal
,
524 const char* aCapability
, PRBool
*checkValue
);
527 FormatCapabilityString(nsAString
& aCapability
);
530 SavePrincipal(nsIPrincipal
* aToSave
);
533 * Check capability levels for an |aObj| that implements
534 * nsISecurityCheckedComponent.
536 * NB: This function also checks to see if aObj is a plugin and the user
537 * has set the "security.xpconnect.plugin.unrestricted" pref to allow
538 * anybody to script plugin objects from anywhere.
540 * @param cx The context we're running on.
541 * NB: If null, "sameOrigin" does not have any effect.
542 * @param aObj The nsISupports representation of the object in question
543 * object, possibly null.
544 * @param aJSObject The JSObject representation of the object in question
545 * if |cx| is non-null and |aObjectSecurityLevel| is
546 * "sameOrigin". If null will be calculated from aObj (if
547 * non-null) if and only if aObj is an XPCWrappedJS. The
548 * rationale behind this is that if we're creating a JS
549 * wrapper for an XPCWrappedJS, this object definitely
550 * expects to be exposed to JS.
551 * @param aSubjectPrincipal The nominal subject principal used when
552 * aObjectSecurityLevel is "sameOrigin". If null,
553 * this is calculated if it's needed.
554 * @param aObjectSecurityLevel Can be one of three values:
555 * - allAccess: Allow access no matter what.
556 * - noAccess: Deny access no matter what.
557 * - sameOrigin: If |cx| is null, behave like noAccess.
558 * Otherwise, possibly compute a subject
559 * and object principal and return true if
560 * and only if the subject has greater than
561 * or equal privileges to the object.
564 CheckXPCPermissions(JSContext
* cx
,
565 nsISupports
* aObj
, JSObject
* aJSObject
,
566 nsIPrincipal
* aSubjectPrincipal
,
567 const char* aObjectSecurityLevel
);
576 GetPrincipalPrefNames(const char* prefBase
,
577 nsCString
& grantedPref
,
578 nsCString
& deniedPref
,
579 nsCString
& subjectNamePref
);
585 InitDomainPolicy(JSContext
* cx
, const char* aPolicyName
,
586 DomainPolicy
* aDomainPolicy
);
589 InitPrincipals(PRUint32 prefCount
, const char** prefNames
);
592 #ifdef XPC_IDISPATCH_SUPPORT
593 // While this header is included outside of caps, this class isn't
594 // referenced so this should be fine.
596 CheckComponentPermissions(JSContext
*cx
, const nsCID
&aCID
);
598 #ifdef DEBUG_CAPS_HACKER
603 struct ContextPrincipal
{
604 ContextPrincipal(ContextPrincipal
*next
, JSContext
*cx
,
605 JSStackFrame
*fp
, nsIPrincipal
*principal
)
606 : mNext(next
), mCx(cx
), mFp(fp
), mPrincipal(principal
) {}
608 ContextPrincipal
*mNext
;
611 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
614 // JS strings we need to clean up on shutdown
615 static jsval sEnabledID
;
618 ScriptSecurityPrefChanged();
620 static const char sJSEnabledPrefName
[];
621 static const char sFileOriginPolicyPrefName
[];
623 nsObjectHashtable
* mOriginToPolicyMap
;
624 DomainPolicy
* mDefaultPolicy
;
625 nsObjectHashtable
* mCapabilities
;
627 nsCOMPtr
<nsIPrefBranch
> mPrefBranch
;
628 nsCOMPtr
<nsIPrincipal
> mSystemPrincipal
;
629 nsCOMPtr
<nsIPrincipal
> mSystemCertificate
;
630 ContextPrincipal
*mContextPrincipals
;
631 nsInterfaceHashtable
<PrincipalKey
, nsIPrincipal
> mPrincipals
;
632 PRPackedBool mIsJavaScriptEnabled
;
633 PRPackedBool mIsWritingPrefs
;
634 PRPackedBool mPolicyPrefsChanged
;
635 #ifdef XPC_IDISPATCH_SUPPORT
636 PRPackedBool mXPCDefaultGrantAll
;
637 static const char sXPCDefaultGrantAllName
[];
640 static PRBool sStrictFileOriginPolicy
;
642 static nsIIOService
*sIOService
;
643 static nsIXPConnect
*sXPConnect
;
644 static nsIThreadJSContextStack
* sJSContextStack
;
645 static nsIStringBundle
*sStrBundle
;
646 static JSRuntime
*sRuntime
;
649 #define NS_SECURITYNAMESET_CID \
650 { 0x7c02eadc, 0x76, 0x4d03, \
651 { 0x99, 0x8d, 0x80, 0xd7, 0x79, 0xc4, 0x85, 0x89 } }
652 #define NS_SECURITYNAMESET_CONTRACTID "@mozilla.org/security/script/nameset;1"
654 class nsSecurityNameSet
: public nsIScriptExternalNameSet
658 virtual ~nsSecurityNameSet();
662 NS_IMETHOD
InitializeNameSet(nsIScriptContext
* aScriptContext
);
665 #endif // nsScriptSecurityManager_h__