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 "nsISecurityPref.h"
55 #include "nsIChannelEventSink.h"
56 #include "nsIJSContextStack.h"
57 #include "nsIObserver.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 nsIPrefSecurityCheck
,
373 public nsIChannelEventSink
,
377 static void Shutdown();
379 NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID
)
382 NS_DECL_NSISCRIPTSECURITYMANAGER
383 NS_DECL_NSIXPCSECURITYMANAGER
384 NS_DECL_NSIPREFSECURITYCHECK
385 NS_DECL_NSICHANNELEVENTSINK
388 static nsScriptSecurityManager
*
389 GetScriptSecurityManager();
391 static nsSystemPrincipal
*
392 SystemPrincipalSingletonConstructor();
394 JSContext
* GetCurrentJSContext();
396 JSContext
* GetSafeJSContext();
399 * Utility method for comparing two URIs. For security purposes, two URIs
400 * are equivalent if their schemes, hosts, and ports (if any) match. This
401 * method returns true if aSubjectURI and aObjectURI have the same origin,
404 static PRBool
SecurityCompareURIs(nsIURI
* aSourceURI
, nsIURI
* aTargetURI
);
405 static PRUint32
SecurityHashURI(nsIURI
* aURI
);
408 ReportError(JSContext
* cx
, const nsAString
& messageTag
,
409 nsIURI
* aSource
, nsIURI
* aTarget
);
412 CheckSameOriginPrincipal(nsIPrincipal
* aSubject
,
413 nsIPrincipal
* aObject
,
414 PRBool aIsCheckConnect
);
416 HashPrincipalByOrigin(nsIPrincipal
* aPrincipal
);
419 GetStrictFileOriginPolicy()
421 return sStrictFileOriginPolicy
;
426 // GetScriptSecurityManager is the only call that can make one
427 nsScriptSecurityManager();
428 virtual ~nsScriptSecurityManager();
431 CheckObjectAccess(JSContext
*cx
, JSObject
*obj
,
432 jsval id
, JSAccessMode mode
,
435 // Returns null if a principal cannot be found; generally callers
436 // should error out at that point.
438 doGetObjectPrincipal(JSObject
*obj
440 , PRBool aAllowShortCircuit
= PR_TRUE
444 // Returns null if a principal cannot be found. Note that rv can be NS_OK
445 // when this happens -- this means that there was no JS running.
447 doGetSubjectPrincipal(nsresult
* rv
);
450 CheckPropertyAccessImpl(PRUint32 aAction
,
451 nsAXPCNativeCallContext
* aCallContext
,
452 JSContext
* cx
, JSObject
* aJSObject
,
453 nsISupports
* aObj
, nsIURI
* aTargetURI
,
454 nsIClassInfo
* aClassInfo
,
455 const char* aClassName
, jsval aProperty
,
456 void** aCachedClassPolicy
);
459 CheckSameOriginDOMProp(nsIPrincipal
* aSubject
,
460 nsIPrincipal
* aObject
,
462 PRBool aIsCheckConnect
);
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 CheckXPCPermissions(nsISupports
* aObj
,
534 const char* aObjectSecurityLevel
);
543 GetPrincipalPrefNames(const char* prefBase
,
544 nsCString
& grantedPref
,
545 nsCString
& deniedPref
,
546 nsCString
& subjectNamePref
);
552 InitDomainPolicy(JSContext
* cx
, const char* aPolicyName
,
553 DomainPolicy
* aDomainPolicy
);
556 InitPrincipals(PRUint32 prefCount
, const char** prefNames
,
557 nsISecurityPref
* securityPref
);
560 #ifdef XPC_IDISPATCH_SUPPORT
561 // While this header is included outside of caps, this class isn't
562 // referenced so this should be fine.
564 CheckComponentPermissions(JSContext
*cx
, const nsCID
&aCID
);
566 #ifdef DEBUG_CAPS_HACKER
571 // JS strings we need to clean up on shutdown
572 static jsval sEnabledID
;
575 ScriptSecurityPrefChanged();
577 static const char sJSEnabledPrefName
[];
578 static const char sJSMailEnabledPrefName
[];
579 static const char sFileOriginPolicyPrefName
[];
581 nsObjectHashtable
* mOriginToPolicyMap
;
582 DomainPolicy
* mDefaultPolicy
;
583 nsObjectHashtable
* mCapabilities
;
585 nsCOMPtr
<nsIPrefBranch
> mPrefBranch
;
586 nsCOMPtr
<nsISecurityPref
> mSecurityPref
;
587 nsCOMPtr
<nsIPrincipal
> mSystemPrincipal
;
588 nsCOMPtr
<nsIPrincipal
> mSystemCertificate
;
589 nsInterfaceHashtable
<PrincipalKey
, nsIPrincipal
> mPrincipals
;
590 PRPackedBool mIsJavaScriptEnabled
;
591 PRPackedBool mIsMailJavaScriptEnabled
;
592 PRPackedBool mIsWritingPrefs
;
593 PRPackedBool mPolicyPrefsChanged
;
594 #ifdef XPC_IDISPATCH_SUPPORT
595 PRPackedBool mXPCDefaultGrantAll
;
596 static const char sXPCDefaultGrantAllName
[];
599 static PRBool sStrictFileOriginPolicy
;
601 static nsIIOService
*sIOService
;
602 static nsIXPConnect
*sXPConnect
;
603 static nsIThreadJSContextStack
* sJSContextStack
;
604 static nsIStringBundle
*sStrBundle
;
605 static JSRuntime
*sRuntime
;
608 #endif // nsScriptSecurityManager_h__