Back out Bug 450717
[wine-gecko.git] / caps / include / nsScriptSecurityManager.h
blobb3d51fbef4242afd31293160ff396c5b40cb71b6
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 <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"
47 #include "jsapi.h"
48 #include "jsdbgapi.h"
49 #include "nsIXPCSecurityManager.h"
50 #include "nsInterfaceHashtable.h"
51 #include "nsHashtable.h"
52 #include "nsCOMPtr.h"
53 #include "nsIPrefService.h"
54 #include "nsISecurityPref.h"
55 #include "nsIChannelEventSink.h"
56 #include "nsIJSContextStack.h"
57 #include "nsIObserver.h"
58 #include "pldhash.h"
59 #include "plstr.h"
61 class nsIDocShell;
62 class nsString;
63 class nsIClassInfo;
64 class nsIIOService;
65 class nsIXPConnect;
66 class nsIStringBundle;
67 class nsSystemPrincipal;
68 struct ClassPolicy;
69 class ClassInfoData;
70 class DomainPolicy;
72 #if defined(DEBUG_mstoltz) || defined(DEBUG_caillon)
73 #define DEBUG_CAPS_HACKER
74 #endif
76 #ifdef DEBUG_CAPS_HACKER
77 #define DEBUG_CAPS_CheckPropertyAccessImpl
78 #define DEBUG_CAPS_LookupPolicy
79 #define DEBUG_CAPS_CheckComponentPermissions
80 #endif
82 #if 0
83 #define DEBUG_CAPS_CanCreateWrapper
84 #define DEBUG_CAPS_CanCreateInstance
85 #define DEBUG_CAPS_CanGetService
86 #define DEBUG_CAPS_DomainPolicyLifeCycle
87 #endif
89 /////////////////////
90 // PrincipalKey //
91 /////////////////////
93 class PrincipalKey : public PLDHashEntryHdr
95 public:
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)
105 : mKey(toCopy.mKey)
109 ~PrincipalKey()
113 KeyType GetKey() const
115 return mKey;
118 PRBool KeyEquals(KeyTypePointer aKey) const
120 PRBool eq;
121 mKey->Equals(const_cast<nsIPrincipal*>(aKey),
122 &eq);
123 return eq;
126 static KeyTypePointer KeyToPointer(KeyType aKey)
128 return aKey;
131 static PLDHashNumber HashKey(KeyTypePointer aKey)
133 PRUint32 hash;
134 const_cast<nsIPrincipal*>(aKey)->GetHashValue(&hash);
135 return PLDHashNumber(hash);
138 enum { ALLOW_MEMMOVE = PR_TRUE };
140 private:
141 nsCOMPtr<nsIPrincipal> mKey;
144 ////////////////////
145 // Policy Storage //
146 ////////////////////
148 // Property Policy
149 union SecurityLevel
151 PRInt32 level;
152 char* capability;
155 // Security levels
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
179 SecurityLevel mGet;
180 SecurityLevel mSet;
183 PR_STATIC_CALLBACK(PRBool)
184 InitPropertyPolicyEntry(PLDHashTable *table,
185 PLDHashEntryHdr *entry,
186 const void *key)
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;
192 return PR_TRUE;
195 PR_STATIC_CALLBACK(void)
196 ClearPropertyPolicyEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
198 PropertyPolicy* pp = (PropertyPolicy*)entry;
199 pp->key = JSVAL_VOID;
202 // Class Policy
203 #define NO_POLICY_FOR_CLASS (ClassPolicy*)1
205 struct ClassPolicy : public PLDHashEntryHdr
207 char* key;
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;
215 PR_STATIC_CALLBACK(void)
216 ClearClassPolicyEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
218 ClassPolicy* cp = (ClassPolicy *)entry;
219 if (cp->key)
221 PL_strfree(cp->key);
222 cp->key = nsnull;
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
229 PR_STATIC_CALLBACK(void)
230 MoveClassPolicyEntry(PLDHashTable *table,
231 const PLDHashEntryHdr *from,
232 PLDHashEntryHdr *to);
234 PR_STATIC_CALLBACK(PRBool)
235 InitClassPolicyEntry(PLDHashTable *table,
236 PLDHashEntryHdr *entry,
237 const void *key)
239 static PLDHashTableOps classPolicyOps =
241 PL_DHashAllocTable,
242 PL_DHashFreeTable,
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);
254 if (!cp->key)
255 return PR_FALSE;
256 cp->mPolicy = PL_NewDHashTable(&classPolicyOps, nsnull,
257 sizeof(PropertyPolicy), 16);
258 if (!cp->mPolicy) {
259 PL_strfree(cp->key);
260 cp->key = nsnull;
261 return PR_FALSE;
263 return PR_TRUE;
266 // Domain Policy
267 class DomainPolicy : public PLDHashTable
269 public:
270 DomainPolicy() : mWildcardPolicy(nsnull),
271 mRefCount(0)
273 mGeneration = sGeneration;
275 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
276 ++sObjects;
277 _printPopulationInfo();
278 #endif
282 PRBool Init()
284 static const PLDHashTableOps domainPolicyOps =
286 PL_DHashAllocTable,
287 PL_DHashFreeTable,
288 PL_DHashStringKey,
289 PL_DHashMatchStringKey,
290 MoveClassPolicyEntry,
291 ClearClassPolicyEntry,
292 PL_DHashFinalizeStub,
293 InitClassPolicyEntry
296 return PL_DHashTableInit(this, &domainPolicyOps, nsnull,
297 sizeof(ClassPolicy), 16);
300 ~DomainPolicy()
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);
306 --sObjects;
307 _printPopulationInfo();
308 #endif
312 void Hold()
314 mRefCount++;
317 void Drop()
319 if (--mRefCount == 0)
320 delete this;
323 static void InvalidateAll()
325 sGeneration++;
328 PRBool IsInvalid()
330 return mGeneration != sGeneration;
333 ClassPolicy* mWildcardPolicy;
335 private:
336 PRUint32 mRefCount;
337 PRUint32 mGeneration;
338 static PRUint32 sGeneration;
340 #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
341 static PRUint32 sObjects;
342 static void _printPopulationInfo();
343 #endif
347 PR_STATIC_CALLBACK(void)
348 MoveClassPolicyEntry(PLDHashTable *table,
349 const PLDHashEntryHdr *from,
350 PLDHashEntryHdr *to)
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,
374 public nsIObserver
376 public:
377 static void Shutdown();
379 NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID)
381 NS_DECL_ISUPPORTS
382 NS_DECL_NSISCRIPTSECURITYMANAGER
383 NS_DECL_NSIXPCSECURITYMANAGER
384 NS_DECL_NSIPREFSECURITYCHECK
385 NS_DECL_NSICHANNELEVENTSINK
386 NS_DECL_NSIOBSERVER
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,
402 * false otherwise.
404 static PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
406 static nsresult
407 ReportError(JSContext* cx, const nsAString& messageTag,
408 nsIURI* aSource, nsIURI* aTarget);
409 static nsresult
410 CheckSameOriginPrincipal(nsIPrincipal* aSubject,
411 nsIPrincipal* aObject,
412 PRBool aIsCheckConnect);
414 static PRBool
415 GetStrictFileOriginPolicy()
417 return sStrictFileOriginPolicy;
420 private:
422 // GetScriptSecurityManager is the only call that can make one
423 nsScriptSecurityManager();
424 virtual ~nsScriptSecurityManager();
426 static JSBool
427 CheckObjectAccess(JSContext *cx, JSObject *obj,
428 jsval id, JSAccessMode mode,
429 jsval *vp);
431 // Returns null if a principal cannot be found; generally callers
432 // should error out at that point.
433 static nsIPrincipal*
434 doGetObjectPrincipal(JSObject *obj
435 #ifdef DEBUG
436 , PRBool aAllowShortCircuit = PR_TRUE
437 #endif
440 // Returns null if a principal cannot be found. Note that rv can be NS_OK
441 // when this happens -- this means that there was no JS running.
442 nsIPrincipal*
443 doGetSubjectPrincipal(nsresult* rv);
445 nsresult
446 CheckPropertyAccessImpl(PRUint32 aAction,
447 nsAXPCNativeCallContext* aCallContext,
448 JSContext* cx, JSObject* aJSObject,
449 nsISupports* aObj, nsIURI* aTargetURI,
450 nsIClassInfo* aClassInfo,
451 const char* aClassName, jsval aProperty,
452 void** aCachedClassPolicy);
454 nsresult
455 CheckSameOriginDOMProp(nsIPrincipal* aSubject,
456 nsIPrincipal* aObject,
457 PRUint32 aAction,
458 PRBool aIsCheckConnect);
460 nsresult
461 LookupPolicy(nsIPrincipal* principal,
462 ClassInfoData& aClassData, jsval aProperty,
463 PRUint32 aAction,
464 ClassPolicy** aCachedClassPolicy,
465 SecurityLevel* result);
467 nsresult
468 CreateCodebasePrincipal(nsIURI* aURI, nsIPrincipal** result);
470 // This is just like the API method, but it doesn't check that the subject
471 // name is non-empty or aCertificate is non-null, and it doesn't change the
472 // certificate in the table (if any) in any way if aModifyTable is false.
473 nsresult
474 DoGetCertificatePrincipal(const nsACString& aCertFingerprint,
475 const nsACString& aSubjectName,
476 const nsACString& aPrettyName,
477 nsISupports* aCertificate,
478 nsIURI* aURI,
479 PRBool aModifyTable,
480 nsIPrincipal **result);
482 // Returns null if a principal cannot be found. Note that rv can be NS_OK
483 // when this happens -- this means that there was no script for the
484 // context. Callers MUST pass in a non-null rv here.
485 static nsIPrincipal*
486 GetSubjectPrincipal(JSContext* cx, nsresult* rv);
488 // Returns null if a principal cannot be found. Note that rv can be NS_OK
489 // when this happens -- this means that there was no script for the frame.
490 // Callers MUST pass in a non-null rv here.
491 static nsIPrincipal*
492 GetFramePrincipal(JSContext* cx, JSStackFrame* fp, nsresult* rv);
494 // Returns null if a principal cannot be found. Note that rv can be NS_OK
495 // when this happens -- this means that there was no script. Callers MUST
496 // pass in a non-null rv here.
497 static nsIPrincipal*
498 GetScriptPrincipal(JSContext* cx, JSScript* script, nsresult* rv);
500 // Returns null if a principal cannot be found. Note that rv can be NS_OK
501 // when this happens -- this means that there was no script associated
502 // with the function object, and no global object associated with the scope
503 // of obj (the last object on its parent chain). If the caller is walking
504 // the JS stack, fp must point to the current frame in the stack iteration.
505 // Callers MUST pass in a non-null rv here.
506 static nsIPrincipal*
507 GetFunctionObjectPrincipal(JSContext* cx, JSObject* obj, JSStackFrame *fp,
508 nsresult* rv);
510 // Returns null if a principal cannot be found. Note that rv can be NS_OK
511 // when this happens -- this means that there was no script
512 // running. Callers MUST pass in a non-null rv here.
513 static nsIPrincipal*
514 GetPrincipalAndFrame(JSContext *cx,
515 JSStackFrame** frameResult,
516 nsresult* rv);
518 static PRBool
519 CheckConfirmDialog(JSContext* cx, nsIPrincipal* aPrincipal,
520 const char* aCapability, PRBool *checkValue);
522 static void
523 FormatCapabilityString(nsAString& aCapability);
525 nsresult
526 SavePrincipal(nsIPrincipal* aToSave);
528 nsresult
529 CheckXPCPermissions(nsISupports* aObj,
530 const char* aObjectSecurityLevel);
532 nsresult
533 Init();
535 nsresult
536 InitPrefs();
538 static nsresult
539 GetPrincipalPrefNames(const char* prefBase,
540 nsCString& grantedPref,
541 nsCString& deniedPref,
542 nsCString& subjectNamePref);
544 nsresult
545 InitPolicies();
547 nsresult
548 InitDomainPolicy(JSContext* cx, const char* aPolicyName,
549 DomainPolicy* aDomainPolicy);
551 nsresult
552 InitPrincipals(PRUint32 prefCount, const char** prefNames,
553 nsISecurityPref* securityPref);
556 #ifdef XPC_IDISPATCH_SUPPORT
557 // While this header is included outside of caps, this class isn't
558 // referenced so this should be fine.
559 nsresult
560 CheckComponentPermissions(JSContext *cx, const nsCID &aCID);
561 #endif
562 #ifdef DEBUG_CAPS_HACKER
563 void
564 PrintPolicyDB();
565 #endif
567 // JS strings we need to clean up on shutdown
568 static jsval sEnabledID;
570 inline void
571 ScriptSecurityPrefChanged();
573 static const char sJSEnabledPrefName[];
574 static const char sJSMailEnabledPrefName[];
575 static const char sFileOriginPolicyPrefName[];
577 nsObjectHashtable* mOriginToPolicyMap;
578 DomainPolicy* mDefaultPolicy;
579 nsObjectHashtable* mCapabilities;
581 nsCOMPtr<nsIPrefBranch> mPrefBranch;
582 nsCOMPtr<nsISecurityPref> mSecurityPref;
583 nsCOMPtr<nsIPrincipal> mSystemPrincipal;
584 nsCOMPtr<nsIPrincipal> mSystemCertificate;
585 nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
586 nsCOMPtr<nsIThreadJSContextStack> mJSContextStack;
587 PRPackedBool mIsJavaScriptEnabled;
588 PRPackedBool mIsMailJavaScriptEnabled;
589 PRPackedBool mIsWritingPrefs;
590 PRPackedBool mPolicyPrefsChanged;
591 #ifdef XPC_IDISPATCH_SUPPORT
592 PRPackedBool mXPCDefaultGrantAll;
593 static const char sXPCDefaultGrantAllName[];
594 #endif
596 static PRBool sStrictFileOriginPolicy;
598 static nsIIOService *sIOService;
599 static nsIXPConnect *sXPConnect;
600 static nsIStringBundle *sStrBundle;
601 static JSRuntime *sRuntime;
604 #endif // nsScriptSecurityManager_h__