LCOV - code coverage report
Current view: directory - caps/src - nsScriptSecurityManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1714 738 43.1 %
Date: 2012-06-02 Functions: 101 70 69.3 %

       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
       4                 :  *
       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/
       9                 :  *
      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.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      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.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Norris Boyd
      24                 :  *   Mitch Stoltz
      25                 :  *   Steve Morse
      26                 :  *   Christopher A. Aillon
      27                 :  *   Giorgio Maone
      28                 :  *   Daniel Veditz
      29                 :  *
      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.
      41                 :  *
      42                 :  * ***** END LICENSE BLOCK ***** */
      43                 : 
      44                 : #include "mozilla/Util.h"
      45                 : 
      46                 : #include "xpcprivate.h"
      47                 : #include "nsScriptSecurityManager.h"
      48                 : #include "nsIServiceManager.h"
      49                 : #include "nsIScriptObjectPrincipal.h"
      50                 : #include "nsIScriptContext.h"
      51                 : #include "nsIURL.h"
      52                 : #include "nsINestedURI.h"
      53                 : #include "nspr.h"
      54                 : #include "nsJSPrincipals.h"
      55                 : #include "nsSystemPrincipal.h"
      56                 : #include "nsPrincipal.h"
      57                 : #include "nsNullPrincipal.h"
      58                 : #include "nsXPIDLString.h"
      59                 : #include "nsCRT.h"
      60                 : #include "nsCRTGlue.h"
      61                 : #include "nsIJSContextStack.h"
      62                 : #include "nsDOMError.h"
      63                 : #include "nsDOMCID.h"
      64                 : #include "jsdbgapi.h"
      65                 : #include "nsIXPConnect.h"
      66                 : #include "nsIXPCSecurityManager.h"
      67                 : #include "nsTextFormatter.h"
      68                 : #include "nsIStringBundle.h"
      69                 : #include "nsNetUtil.h"
      70                 : #include "nsIProperties.h"
      71                 : #include "nsDirectoryServiceDefs.h"
      72                 : #include "nsIFile.h"
      73                 : #include "nsIFileURL.h"
      74                 : #include "nsIZipReader.h"
      75                 : #include "nsIXPConnect.h"
      76                 : #include "nsIScriptGlobalObject.h"
      77                 : #include "nsPIDOMWindow.h"
      78                 : #include "nsIDocShell.h"
      79                 : #include "nsIDocShellTreeItem.h"
      80                 : #include "nsIPrompt.h"
      81                 : #include "nsIWindowWatcher.h"
      82                 : #include "nsIConsoleService.h"
      83                 : #include "nsISecurityCheckedComponent.h"
      84                 : #include "nsIJSRuntimeService.h"
      85                 : #include "nsIObserverService.h"
      86                 : #include "nsIContent.h"
      87                 : #include "nsAutoPtr.h"
      88                 : #include "nsDOMJSUtils.h"
      89                 : #include "nsAboutProtocolUtils.h"
      90                 : #include "nsIClassInfo.h"
      91                 : #include "nsIURIFixup.h"
      92                 : #include "nsCDefaultURIFixup.h"
      93                 : #include "nsIChromeRegistry.h"
      94                 : #include "nsIContentSecurityPolicy.h"
      95                 : #include "nsIAsyncVerifyRedirectCallback.h"
      96                 : #include "mozilla/Preferences.h"
      97                 : 
      98                 : using namespace mozilla;
      99                 : 
     100                 : static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
     101                 : 
     102                 : nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
     103                 : nsIXPConnect    *nsScriptSecurityManager::sXPConnect = nsnull;
     104                 : nsIThreadJSContextStack *nsScriptSecurityManager::sJSContextStack = nsnull;
     105                 : nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
     106                 : JSRuntime       *nsScriptSecurityManager::sRuntime   = 0;
     107                 : bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
     108                 : 
     109                 : ///////////////////////////
     110                 : // Convenience Functions //
     111                 : ///////////////////////////
     112                 : // Result of this function should not be freed.
     113                 : static inline const PRUnichar *
     114               0 : IDToString(JSContext *cx, jsid id)
     115                 : {
     116               0 :     if (JSID_IS_STRING(id))
     117               0 :         return JS_GetInternedStringChars(JSID_TO_STRING(id));
     118                 : 
     119               0 :     JSAutoRequest ar(cx);
     120                 :     jsval idval;
     121               0 :     if (!JS_IdToValue(cx, id, &idval))
     122               0 :         return nsnull;
     123               0 :     JSString *str = JS_ValueToString(cx, idval);
     124               0 :     if(!str)
     125               0 :         return nsnull;
     126               0 :     return JS_GetStringCharsZ(cx, str);
     127                 : }
     128                 : 
     129                 : class nsAutoInPrincipalDomainOriginSetter {
     130                 : public:
     131               1 :     nsAutoInPrincipalDomainOriginSetter() {
     132               1 :         ++sInPrincipalDomainOrigin;
     133               1 :     }
     134               1 :     ~nsAutoInPrincipalDomainOriginSetter() {
     135               1 :         --sInPrincipalDomainOrigin;
     136               1 :     }
     137                 :     static PRUint32 sInPrincipalDomainOrigin;
     138                 : };
     139                 : PRUint32 nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin;
     140                 : 
     141                 : static
     142                 : nsresult
     143               1 : GetOriginFromURI(nsIURI* aURI, nsACString& aOrigin)
     144                 : {
     145               1 :   if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin > 1) {
     146                 :       // Allow a single recursive call to GetPrincipalDomainOrigin, since that
     147                 :       // might be happening on a different principal from the first call.  But
     148                 :       // after that, cut off the recursion; it just indicates that something
     149                 :       // we're doing in this method causes us to reenter a security check here.
     150               0 :       return NS_ERROR_NOT_AVAILABLE;
     151                 :   }
     152                 : 
     153               2 :   nsAutoInPrincipalDomainOriginSetter autoSetter;
     154                 : 
     155               2 :   nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
     156               1 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
     157                 : 
     158               2 :   nsCAutoString hostPort;
     159                 : 
     160               1 :   nsresult rv = uri->GetHostPort(hostPort);
     161               1 :   if (NS_SUCCEEDED(rv)) {
     162               2 :     nsCAutoString scheme;
     163               1 :     rv = uri->GetScheme(scheme);
     164               1 :     NS_ENSURE_SUCCESS(rv, rv);
     165               2 :     aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
     166                 :   }
     167                 :   else {
     168                 :     // Some URIs (e.g., nsSimpleURI) don't support host. Just
     169                 :     // get the full spec.
     170               0 :     rv = uri->GetSpec(aOrigin);
     171               0 :     NS_ENSURE_SUCCESS(rv, rv);
     172                 :   }
     173                 : 
     174               1 :   return NS_OK;
     175                 : }
     176                 : 
     177                 : static
     178                 : nsresult
     179               1 : GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal,
     180                 :                          nsACString& aOrigin)
     181                 : {
     182                 : 
     183               2 :   nsCOMPtr<nsIURI> uri;
     184               1 :   aPrincipal->GetDomain(getter_AddRefs(uri));
     185               1 :   if (!uri) {
     186               1 :     aPrincipal->GetURI(getter_AddRefs(uri));
     187                 :   }
     188               1 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
     189                 : 
     190               1 :   return GetOriginFromURI(uri, aOrigin);
     191                 : }
     192                 : 
     193                 : static nsIScriptContext *
     194               0 : GetScriptContext(JSContext *cx)
     195                 : {
     196               0 :     return GetScriptContextFromJSContext(cx);
     197                 : }
     198                 : 
     199               0 : inline void SetPendingException(JSContext *cx, const char *aMsg)
     200                 : {
     201               0 :     JSAutoRequest ar(cx);
     202               0 :     JS_ReportError(cx, "%s", aMsg);
     203               0 : }
     204                 : 
     205               0 : inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg)
     206                 : {
     207               0 :     JSAutoRequest ar(cx);
     208               0 :     JS_ReportError(cx, "%hs", aMsg);
     209               0 : }
     210                 : 
     211                 : // DomainPolicy members
     212                 : #ifdef DEBUG_CAPS_DomainPolicyLifeCycle
     213                 : PRUint32 DomainPolicy::sObjects=0;
     214                 : void DomainPolicy::_printPopulationInfo()
     215                 : {
     216                 :     printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n",
     217                 :         sGeneration, sObjects);
     218                 : }
     219                 : #endif
     220                 : PRUint32 DomainPolicy::sGeneration = 0;
     221                 : 
     222                 : // Helper class to get stuff from the ClassInfo and not waste extra time with
     223                 : // virtual method calls for things it has already gotten
     224                 : class ClassInfoData
     225                 : {
     226                 : public:
     227          343428 :     ClassInfoData(nsIClassInfo *aClassInfo, const char *aName)
     228                 :         : mClassInfo(aClassInfo),
     229                 :           mName(const_cast<char *>(aName)),
     230                 :           mDidGetFlags(false),
     231          343428 :           mMustFreeName(false)
     232                 :     {
     233          343428 :     }
     234                 : 
     235          343428 :     ~ClassInfoData()
     236                 :     {
     237          343428 :         if (mMustFreeName)
     238               0 :             nsMemory::Free(mName);
     239          343428 :     }
     240                 : 
     241          343427 :     PRUint32 GetFlags()
     242                 :     {
     243          343427 :         if (!mDidGetFlags) {
     244          343427 :             if (mClassInfo) {
     245          100038 :                 nsresult rv = mClassInfo->GetFlags(&mFlags);
     246          100038 :                 if (NS_FAILED(rv)) {
     247               0 :                     mFlags = 0;
     248                 :                 }
     249                 :             } else {
     250          243389 :                 mFlags = 0;
     251                 :             }
     252                 : 
     253          343427 :             mDidGetFlags = true;
     254                 :         }
     255                 : 
     256          343427 :         return mFlags;
     257                 :     }
     258                 : 
     259          343427 :     bool IsDOMClass()
     260                 :     {
     261          343427 :         return !!(GetFlags() & nsIClassInfo::DOM_OBJECT);
     262                 :     }
     263                 : 
     264               1 :     const char* GetName()
     265                 :     {
     266               1 :         if (!mName) {
     267               0 :             if (mClassInfo) {
     268               0 :                 mClassInfo->GetClassDescription(&mName);
     269                 :             }
     270                 : 
     271               0 :             if (mName) {
     272               0 :                 mMustFreeName = true;
     273                 :             } else {
     274               0 :                 mName = const_cast<char *>("UnnamedClass");
     275                 :             }
     276                 :         }
     277                 : 
     278               1 :         return mName;
     279                 :     }
     280                 : 
     281                 : private:
     282                 :     nsIClassInfo *mClassInfo; // WEAK
     283                 :     PRUint32 mFlags;
     284                 :     char *mName;
     285                 :     bool mDidGetFlags;
     286                 :     bool mMustFreeName;
     287                 : };
     288                 : 
     289                 : class AutoCxPusher {
     290                 : public:
     291               1 :     AutoCxPusher(nsIJSContextStack *aStack, JSContext *cx)
     292               1 :         : mStack(aStack), mContext(cx)
     293                 :     {
     294               1 :         if (NS_FAILED(mStack->Push(mContext))) {
     295               0 :             mStack = nsnull;
     296                 :         }
     297               1 :     }
     298                 : 
     299               1 :     ~AutoCxPusher()
     300               1 :     {
     301               1 :         if (mStack) {
     302               1 :             mStack->Pop(nsnull);
     303                 :         }
     304               1 :     }
     305                 : 
     306                 : private:
     307                 :     nsCOMPtr<nsIJSContextStack> mStack;
     308                 :     JSContext *mContext;
     309                 : };
     310                 : 
     311                 : JSContext *
     312          452532 : nsScriptSecurityManager::GetCurrentJSContext()
     313                 : {
     314                 :     // Get JSContext from stack.
     315                 :     JSContext *cx;
     316          452532 :     if (NS_FAILED(sJSContextStack->Peek(&cx)))
     317               0 :         return nsnull;
     318          452532 :     return cx;
     319                 : }
     320                 : 
     321                 : JSContext *
     322            1405 : nsScriptSecurityManager::GetSafeJSContext()
     323                 : {
     324                 :     // Get JSContext from stack.
     325                 :     JSContext *cx;
     326            1405 :     if (NS_FAILED(sJSContextStack->GetSafeJSContext(&cx)))
     327               0 :         return nsnull;
     328            1405 :     return cx;
     329                 : }
     330                 : 
     331                 : /* static */
     332                 : bool
     333              19 : nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
     334                 :                                              nsIURI* aTargetURI)
     335                 : {
     336              19 :     return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
     337                 : }
     338                 : 
     339                 : // SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI
     340                 : // is consistent with NS_SecurityCompareURIs.  See nsNetUtil.h.
     341                 : PRUint32
     342               0 : nsScriptSecurityManager::SecurityHashURI(nsIURI* aURI)
     343                 : {
     344               0 :     return NS_SecurityHashURI(aURI);
     345                 : }
     346                 : 
     347                 : NS_IMETHODIMP
     348             634 : nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
     349                 :                                              nsIPrincipal** aPrincipal)
     350                 : {
     351             634 :     NS_PRECONDITION(aChannel, "Must have channel!");
     352            1268 :     nsCOMPtr<nsISupports> owner;
     353             634 :     aChannel->GetOwner(getter_AddRefs(owner));
     354             634 :     if (owner) {
     355             469 :         CallQueryInterface(owner, aPrincipal);
     356             469 :         if (*aPrincipal) {
     357             469 :             return NS_OK;
     358                 :         }
     359                 :     }
     360                 : 
     361                 :     // OK, get the principal from the URI.  Make sure this does the same thing
     362                 :     // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
     363             330 :     nsCOMPtr<nsIURI> uri;
     364             165 :     nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
     365             165 :     NS_ENSURE_SUCCESS(rv, rv);
     366                 : 
     367             165 :     return GetCodebasePrincipal(uri, aPrincipal);
     368                 : }
     369                 : 
     370                 : NS_IMETHODIMP
     371          361723 : nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
     372                 :                                            bool* aIsSystem)
     373                 : {
     374          361723 :     *aIsSystem = (aPrincipal == mSystemPrincipal);
     375          361723 :     return NS_OK;
     376                 : }
     377                 : 
     378                 : NS_IMETHODIMP_(nsIPrincipal *)
     379               0 : nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx)
     380                 : {
     381               0 :     NS_ASSERTION(cx == GetCurrentJSContext(),
     382                 :                  "Uh, cx is not the current JS context!");
     383                 : 
     384               0 :     nsresult rv = NS_ERROR_FAILURE;
     385               0 :     nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv);
     386               0 :     if (NS_FAILED(rv))
     387               0 :         return nsnull;
     388                 : 
     389               0 :     return principal;
     390                 : }
     391                 : 
     392                 : NS_IMETHODIMP_(nsIPrincipal *)
     393             591 : nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFrame **fp)
     394                 : {
     395             591 :     NS_ASSERTION(cx == GetCurrentJSContext(),
     396                 :                  "Uh, cx is not the current JS context!");
     397                 : 
     398             591 :     nsresult rv = NS_ERROR_FAILURE;
     399             591 :     nsIPrincipal *principal = GetPrincipalAndFrame(cx, fp, &rv);
     400             591 :     if (NS_FAILED(rv))
     401               0 :         return nsnull;
     402                 : 
     403             591 :     return principal;
     404                 : }
     405                 : 
     406                 : NS_IMETHODIMP
     407         1225909 : nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
     408                 :                                               JSStackFrame *fp,
     409                 :                                               nsIPrincipal *principal)
     410                 : {
     411         1225909 :     NS_ASSERTION(principal, "Must pass a non-null principal");
     412                 : 
     413                 :     ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp,
     414         1225909 :                                                 principal);
     415         1225909 :     if (!cp)
     416               0 :         return NS_ERROR_OUT_OF_MEMORY;
     417                 : 
     418         1225909 :     mContextPrincipals = cp;
     419         1225909 :     return NS_OK;
     420                 : }
     421                 : 
     422                 : NS_IMETHODIMP
     423         1225909 : nsScriptSecurityManager::PopContextPrincipal(JSContext *cx)
     424                 : {
     425         1225909 :     NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop");
     426                 : 
     427         1225909 :     ContextPrincipal *next = mContextPrincipals->mNext;
     428         1225909 :     delete mContextPrincipals;
     429         1225909 :     mContextPrincipals = next;
     430                 : 
     431         1225909 :     return NS_OK;
     432                 : }
     433                 : 
     434                 : ////////////////////
     435                 : // Policy Storage //
     436                 : ////////////////////
     437                 : 
     438                 : // Table of security levels
     439                 : static bool
     440               1 : DeleteCapability(nsHashKey *aKey, void *aData, void* closure)
     441                 : {
     442               1 :     NS_Free(aData);
     443               1 :     return true;
     444                 : }
     445                 : 
     446                 : //-- Per-Domain Policy - applies to one or more protocols or hosts
     447                 : struct DomainEntry
     448                 : {
     449               3 :     DomainEntry(const char* aOrigin,
     450                 :                 DomainPolicy* aDomainPolicy) : mOrigin(aOrigin),
     451                 :                                                mDomainPolicy(aDomainPolicy),
     452               3 :                                                mNext(nsnull)
     453                 :     {
     454               3 :         mDomainPolicy->Hold();
     455               3 :     }
     456                 : 
     457               3 :     ~DomainEntry()
     458               3 :     {
     459               3 :         mDomainPolicy->Drop();
     460               3 :     }
     461                 : 
     462               0 :     bool Matches(const char *anOrigin)
     463                 :     {
     464               0 :         int len = strlen(anOrigin);
     465               0 :         int thisLen = mOrigin.Length();
     466               0 :         if (len < thisLen)
     467               0 :             return false;
     468               0 :         if (mOrigin.RFindChar(':', thisLen-1, 1) != -1)
     469                 :         //-- Policy applies to all URLs of this scheme, compare scheme only
     470               0 :             return mOrigin.EqualsIgnoreCase(anOrigin, thisLen);
     471                 : 
     472                 :         //-- Policy applies to a particular host; compare domains
     473               0 :         if (!mOrigin.Equals(anOrigin + (len - thisLen)))
     474               0 :             return false;
     475               0 :         if (len == thisLen)
     476               0 :             return true;
     477               0 :         char charBefore = anOrigin[len-thisLen-1];
     478               0 :         return (charBefore == '.' || charBefore == ':' || charBefore == '/');
     479                 :     }
     480                 : 
     481                 :     nsCString         mOrigin;
     482                 :     DomainPolicy*     mDomainPolicy;
     483                 :     DomainEntry*      mNext;
     484                 : #if defined(DEBUG) || defined(DEBUG_CAPS_HACKER)
     485                 :     nsCString         mPolicyName_DEBUG;
     486                 : #endif
     487                 : };
     488                 : 
     489                 : static bool
     490               3 : DeleteDomainEntry(nsHashKey *aKey, void *aData, void* closure)
     491                 : {
     492               3 :     DomainEntry *entry = (DomainEntry*) aData;
     493               3 :     do
     494                 :     {
     495               3 :         DomainEntry *next = entry->mNext;
     496               3 :         delete entry;
     497               3 :         entry = next;
     498                 :     } while (entry);
     499               3 :     return true;
     500                 : }
     501                 : 
     502                 : /////////////////////////////
     503                 : // nsScriptSecurityManager //
     504                 : /////////////////////////////
     505                 : 
     506                 : ////////////////////////////////////
     507                 : // Methods implementing ISupports //
     508                 : ////////////////////////////////////
     509          296450 : NS_IMPL_ISUPPORTS4(nsScriptSecurityManager,
     510                 :                    nsIScriptSecurityManager,
     511                 :                    nsIXPCSecurityManager,
     512                 :                    nsIChannelEventSink,
     513                 :                    nsIObserver)
     514                 : 
     515                 : ///////////////////////////////////////////////////
     516                 : // Methods implementing nsIScriptSecurityManager //
     517                 : ///////////////////////////////////////////////////
     518                 : 
     519                 : ///////////////// Security Checks /////////////////
     520                 : 
     521                 : /* static */ JSPrincipals *
     522               0 : nsScriptSecurityManager::ObjectPrincipalFinder(JSObject *aObj)
     523                 : {
     524               0 :     return nsJSPrincipals::get(doGetObjectPrincipal(aObj));
     525                 : }
     526                 : 
     527                 : JSBool
     528              54 : nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
     529                 : {
     530                 :     // Get the security manager
     531                 :     nsScriptSecurityManager *ssm =
     532              54 :         nsScriptSecurityManager::GetScriptSecurityManager();
     533                 : 
     534              54 :     NS_ASSERTION(ssm, "Failed to get security manager service");
     535              54 :     if (!ssm)
     536               0 :         return JS_FALSE;
     537                 : 
     538                 :     nsresult rv;
     539              54 :     nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv);
     540                 : 
     541              54 :     NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context");
     542              54 :     if (NS_FAILED(rv))
     543               0 :         return JS_FALSE; // Not just absence of principal, but failure.
     544                 : 
     545              54 :     if (!subjectPrincipal) {
     546                 :         // See bug 553448 for discussion of this case.
     547               0 :         NS_ASSERTION(!JS_GetSecurityCallbacks(js::GetRuntime(cx))->findObjectPrincipals,
     548                 :                      "CSP: Should have been able to find subject principal. "
     549                 :                      "Reluctantly granting access.");
     550               0 :         return JS_TRUE;
     551                 :     }
     552                 : 
     553             108 :     nsCOMPtr<nsIContentSecurityPolicy> csp;
     554              54 :     rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
     555              54 :     NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
     556                 : 
     557                 :     // don't do anything unless there's a CSP
     558              54 :     if (!csp)
     559              54 :         return JS_TRUE;
     560                 : 
     561               0 :     bool evalOK = true;
     562               0 :     rv = csp->GetAllowsEval(&evalOK);
     563                 : 
     564               0 :     if (NS_FAILED(rv))
     565                 :     {
     566               0 :         NS_WARNING("CSP: failed to get allowsEval");
     567               0 :         return JS_TRUE; // fail open to not break sites.
     568                 :     }
     569                 : 
     570               0 :     if (!evalOK) {
     571                 :         // get the script filename, script sample, and line number
     572                 :         // to log with the violation
     573               0 :         JSStackFrame *fp = nsnull;
     574               0 :         nsAutoString fileName;
     575               0 :         PRUint32 lineNum = 0;
     576               0 :         NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
     577                 : 
     578               0 :         fp = JS_FrameIterator(cx, &fp);
     579               0 :         if (fp) {
     580               0 :             JSScript *script = JS_GetFrameScript(cx, fp);
     581               0 :             if (script) {
     582               0 :                 const char *file = JS_GetScriptFilename(cx, script);
     583               0 :                 if (file) {
     584               0 :                     CopyUTF8toUTF16(nsDependentCString(file), fileName);
     585                 :                 }
     586               0 :                 jsbytecode *pc = JS_GetFramePC(cx, fp);
     587               0 :                 if (pc) {
     588               0 :                     lineNum = JS_PCToLineNumber(cx, script, pc);
     589                 :                 }
     590                 :             }
     591                 :         }
     592                 : 
     593               0 :         csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
     594                 :                                  fileName,
     595                 :                                  scriptSample,
     596               0 :                                  lineNum);
     597                 :     }
     598                 : 
     599               0 :     return evalOK;
     600                 : }
     601                 : 
     602                 : 
     603                 : JSBool
     604          404087 : nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj,
     605                 :                                            jsid id, JSAccessMode mode,
     606                 :                                            jsval *vp)
     607                 : {
     608                 :     // Get the security manager
     609                 :     nsScriptSecurityManager *ssm =
     610          404087 :         nsScriptSecurityManager::GetScriptSecurityManager();
     611                 : 
     612          404087 :     NS_ASSERTION(ssm, "Failed to get security manager service");
     613          404087 :     if (!ssm)
     614               0 :         return JS_FALSE;
     615                 : 
     616                 :     // Get the object being accessed.  We protect these cases:
     617                 :     // 1. The Function.prototype.caller property's value, which might lead
     618                 :     //    an attacker up a call-stack to a function or another object from
     619                 :     //    a different trust domain.
     620                 :     // 2. A user-defined getter or setter function accessible on another
     621                 :     //    trust domain's window or document object.
     622                 :     // *vp can be a primitive, in that case, we use obj as the target
     623                 :     // object.
     624          404087 :     JSObject* target = JSVAL_IS_PRIMITIVE(*vp) ? obj : JSVAL_TO_OBJECT(*vp);
     625                 : 
     626                 :     // Do the same-origin check -- this sets a JS exception if the check fails.
     627                 :     // Pass the parent object's class name, as we have no class-info for it.
     628                 :     nsresult rv =
     629          404087 :         ssm->CheckPropertyAccess(cx, target, js::GetObjectClass(obj)->name, id,
     630                 :                                  (mode & JSACC_WRITE) ?
     631                 :                                  (PRInt32)nsIXPCSecurityManager::ACCESS_SET_PROPERTY :
     632          808174 :                                  (PRInt32)nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
     633                 : 
     634          404087 :     if (NS_FAILED(rv))
     635               0 :         return JS_FALSE; // Security check failed (XXX was an error reported?)
     636                 : 
     637          404087 :     return JS_TRUE;
     638                 : }
     639                 : 
     640                 : NS_IMETHODIMP
     641          404087 : nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
     642                 :                                              JSObject* aJSObject,
     643                 :                                              const char* aClassName,
     644                 :                                              jsid aProperty,
     645                 :                                              PRUint32 aAction)
     646                 : {
     647                 :     return CheckPropertyAccessImpl(aAction, nsnull, cx, aJSObject,
     648                 :                                    nsnull, nsnull, nsnull,
     649          404087 :                                    aClassName, aProperty, nsnull);
     650                 : }
     651                 : 
     652                 : NS_IMETHODIMP
     653               0 : nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
     654                 :                                          nsIURI* aTargetURI)
     655                 : {
     656                 :     nsresult rv;
     657                 : 
     658                 :     // Get a context if necessary
     659               0 :     if (!cx)
     660                 :     {
     661               0 :         cx = GetCurrentJSContext();
     662               0 :         if (!cx)
     663               0 :             return NS_OK; // No JS context, so allow access
     664                 :     }
     665                 : 
     666                 :     // Get a principal from the context
     667               0 :     nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv);
     668               0 :     if (NS_FAILED(rv))
     669               0 :         return rv;
     670                 : 
     671               0 :     if (!sourcePrincipal)
     672                 :     {
     673               0 :         NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
     674               0 :         return NS_OK;
     675                 :     }
     676                 : 
     677               0 :     if (sourcePrincipal == mSystemPrincipal)
     678                 :     {
     679                 :         // This is a system (chrome) script, so allow access
     680               0 :         return NS_OK;
     681                 :     }
     682                 : 
     683                 :     // Get the original URI from the source principal.
     684                 :     // This has the effect of ignoring any change to document.domain
     685                 :     // which must be done to avoid DNS spoofing (bug 154930)
     686               0 :     nsCOMPtr<nsIURI> sourceURI;
     687               0 :     sourcePrincipal->GetDomain(getter_AddRefs(sourceURI));
     688               0 :     if (!sourceURI) {
     689               0 :       sourcePrincipal->GetURI(getter_AddRefs(sourceURI));
     690               0 :       NS_ENSURE_TRUE(sourceURI, NS_ERROR_FAILURE);
     691                 :     }
     692                 : 
     693                 :     // Compare origins
     694               0 :     if (!SecurityCompareURIs(sourceURI, aTargetURI))
     695                 :     {
     696               0 :          ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI);
     697               0 :          return NS_ERROR_DOM_BAD_URI;
     698                 :     }
     699               0 :     return NS_OK;
     700                 : }
     701                 : 
     702                 : NS_IMETHODIMP
     703              17 : nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
     704                 :                                             nsIURI* aTargetURI,
     705                 :                                             bool reportError)
     706                 : {
     707              17 :     if (!SecurityCompareURIs(aSourceURI, aTargetURI))
     708                 :     {
     709              11 :          if (reportError) {
     710               0 :             ReportError(nsnull, NS_LITERAL_STRING("CheckSameOriginError"),
     711               0 :                      aSourceURI, aTargetURI);
     712                 :          }
     713              11 :          return NS_ERROR_DOM_BAD_URI;
     714                 :     }
     715               6 :     return NS_OK;
     716                 : }
     717                 : 
     718                 : nsresult
     719         1646942 : nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
     720                 :                                                  nsAXPCNativeCallContext* aCallContext,
     721                 :                                                  JSContext* cx, JSObject* aJSObject,
     722                 :                                                  nsISupports* aObj, nsIURI* aTargetURI,
     723                 :                                                  nsIClassInfo* aClassInfo,
     724                 :                                                  const char* aClassName, jsid aProperty,
     725                 :                                                  void** aCachedClassPolicy)
     726                 : {
     727                 :     nsresult rv;
     728         1646942 :     nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
     729         1646942 :     if (NS_FAILED(rv))
     730               0 :         return rv;
     731                 : 
     732         1646942 :     if (!subjectPrincipal || subjectPrincipal == mSystemPrincipal)
     733                 :         // We have native code or the system principal: just allow access
     734         1646942 :         return NS_OK;
     735                 : 
     736               0 :     nsCOMPtr<nsIPrincipal> objectPrincipal;
     737                 : 
     738                 :     // Hold the class info data here so we don't have to go back to virtual
     739                 :     // methods all the time
     740               0 :     ClassInfoData classInfoData(aClassInfo, aClassName);
     741                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     742                 :     nsCAutoString propertyName;
     743                 :     propertyName.AssignWithConversion((PRUnichar*)IDToString(cx, aProperty));
     744                 :     printf("### CanAccess(%s.%s, %i) ", classInfoData.GetName(), 
     745                 :            propertyName.get(), aAction);
     746                 : #endif
     747                 : 
     748                 :     //-- Look up the security policy for this class and subject domain
     749                 :     SecurityLevel securityLevel;
     750                 :     rv = LookupPolicy(subjectPrincipal, classInfoData, aProperty, aAction, 
     751               0 :                       (ClassPolicy**)aCachedClassPolicy, &securityLevel);
     752               0 :     if (NS_FAILED(rv))
     753               0 :         return rv;
     754                 : 
     755               0 :     if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
     756                 :     {   
     757                 :         // No policy found for this property so use the default of last resort.
     758                 :         // If we were called from somewhere other than XPConnect
     759                 :         // (no XPC call context), assume this is a DOM class. Otherwise,
     760                 :         // ask the ClassInfo.
     761               0 :         if (!aCallContext || classInfoData.IsDOMClass())
     762               0 :             securityLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS;
     763                 :         else
     764               0 :             securityLevel.level = SCRIPT_SECURITY_NO_ACCESS;
     765                 :     }
     766                 : 
     767               0 :     if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel))
     768                 :     // This flag means securityLevel is allAccess, noAccess, or sameOrigin
     769                 :     {
     770               0 :         switch (securityLevel.level)
     771                 :         {
     772                 :         case SCRIPT_SECURITY_NO_ACCESS:
     773                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     774                 :             printf("noAccess ");
     775                 : #endif
     776               0 :             rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
     777               0 :             break;
     778                 : 
     779                 :         case SCRIPT_SECURITY_ALL_ACCESS:
     780                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     781                 :             printf("allAccess ");
     782                 : #endif
     783               0 :             rv = NS_OK;
     784               0 :             break;
     785                 : 
     786                 :         case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS:
     787                 :             {
     788                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     789                 :                 printf("sameOrigin ");
     790                 : #endif
     791               0 :                 nsCOMPtr<nsIPrincipal> principalHolder;
     792               0 :                 if(aJSObject)
     793                 :                 {
     794               0 :                     objectPrincipal = doGetObjectPrincipal(aJSObject);
     795               0 :                     if (!objectPrincipal)
     796               0 :                         rv = NS_ERROR_DOM_SECURITY_ERR;
     797                 :                 }
     798               0 :                 else if(aTargetURI)
     799                 :                 {
     800               0 :                     if (NS_FAILED(GetCodebasePrincipal(
     801                 :                           aTargetURI, getter_AddRefs(objectPrincipal))))
     802               0 :                         return NS_ERROR_FAILURE;
     803                 :                 }
     804                 :                 else
     805                 :                 {
     806               0 :                     NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
     807               0 :                     return NS_ERROR_FAILURE;
     808                 :                 }
     809               0 :                 if(NS_SUCCEEDED(rv))
     810                 :                     rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
     811               0 :                                                 aAction);
     812               0 :                 break;
     813                 :             }
     814                 :         default:
     815                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     816                 :                 printf("ERROR ");
     817                 : #endif
     818               0 :             NS_ERROR("Bad Security Level Value");
     819               0 :             return NS_ERROR_FAILURE;
     820               0 :         }
     821                 :     }
     822                 :     else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability
     823                 :     {
     824                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     825                 :         printf("Cap:%s ", securityLevel.capability);
     826                 : #endif
     827               0 :         bool capabilityEnabled = false;
     828               0 :         rv = IsCapabilityEnabled(securityLevel.capability, &capabilityEnabled);
     829               0 :         if (NS_FAILED(rv) || !capabilityEnabled)
     830               0 :             rv = NS_ERROR_DOM_SECURITY_ERR;
     831                 :         else
     832               0 :             rv = NS_OK;
     833                 :     }
     834                 : 
     835               0 :     if (NS_SUCCEEDED(rv))
     836                 :     {
     837                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     838                 :     printf(" GRANTED.\n");
     839                 : #endif
     840               0 :         return rv;
     841                 :     }
     842                 : 
     843                 :     //--See if the object advertises a non-default level of access
     844                 :     //  using nsISecurityCheckedComponent
     845                 :     nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
     846               0 :         do_QueryInterface(aObj);
     847                 : 
     848               0 :     nsXPIDLCString objectSecurityLevel;
     849               0 :     if (checkedComponent)
     850                 :     {
     851               0 :         nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
     852               0 :         nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
     853               0 :         const nsIID* objIID = nsnull;
     854               0 :         rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
     855               0 :         if (NS_SUCCEEDED(rv) && wrapper)
     856               0 :             rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo));
     857               0 :         if (NS_SUCCEEDED(rv) && interfaceInfo)
     858               0 :             rv = interfaceInfo->GetIIDShared(&objIID);
     859               0 :         if (NS_SUCCEEDED(rv) && objIID)
     860                 :         {
     861               0 :             switch (aAction)
     862                 :             {
     863                 :             case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
     864               0 :                 checkedComponent->CanGetProperty(objIID,
     865                 :                                                  IDToString(cx, aProperty),
     866               0 :                                                  getter_Copies(objectSecurityLevel));
     867               0 :                 break;
     868                 :             case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
     869               0 :                 checkedComponent->CanSetProperty(objIID,
     870                 :                                                  IDToString(cx, aProperty),
     871               0 :                                                  getter_Copies(objectSecurityLevel));
     872               0 :                 break;
     873                 :             case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
     874               0 :                 checkedComponent->CanCallMethod(objIID,
     875                 :                                                 IDToString(cx, aProperty),
     876               0 :                                                 getter_Copies(objectSecurityLevel));
     877                 :             }
     878                 :         }
     879                 :     }
     880                 :     rv = CheckXPCPermissions(cx, aObj, aJSObject, subjectPrincipal,
     881               0 :                              objectSecurityLevel);
     882                 : #ifdef DEBUG_CAPS_CheckPropertyAccessImpl
     883                 :     if(NS_SUCCEEDED(rv))
     884                 :         printf("CheckXPCPerms GRANTED.\n");
     885                 :     else
     886                 :         printf("CheckXPCPerms DENIED.\n");
     887                 : #endif
     888                 : 
     889               0 :     if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error
     890                 :     {
     891               0 :         nsAutoString stringName;
     892               0 :         switch(aAction)
     893                 :         {
     894                 :         case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
     895               0 :             stringName.AssignLiteral("GetPropertyDeniedOrigins");
     896               0 :             break;
     897                 :         case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
     898               0 :             stringName.AssignLiteral("SetPropertyDeniedOrigins");
     899               0 :             break;
     900                 :         case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
     901               0 :             stringName.AssignLiteral("CallMethodDeniedOrigins");
     902                 :         }
     903                 : 
     904                 :         // Null out objectPrincipal for now, so we don't leak information about
     905                 :         // it.  Whenever we can report different error strings to content and
     906                 :         // the UI we can take this out again.
     907               0 :         objectPrincipal = nsnull;
     908                 : 
     909               0 :         NS_ConvertUTF8toUTF16 className(classInfoData.GetName());
     910               0 :         nsCAutoString subjectOrigin;
     911               0 :         nsCAutoString subjectDomain;
     912               0 :         if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) {
     913               0 :             nsCOMPtr<nsIURI> uri, domain;
     914               0 :             subjectPrincipal->GetURI(getter_AddRefs(uri));
     915                 :             // Subject can't be system if we failed the security
     916                 :             // check, so |uri| is non-null.
     917               0 :             NS_ASSERTION(uri, "How did that happen?");
     918               0 :             GetOriginFromURI(uri, subjectOrigin);
     919               0 :             subjectPrincipal->GetDomain(getter_AddRefs(domain));
     920               0 :             if (domain) {
     921               0 :                 GetOriginFromURI(domain, subjectDomain);
     922                 :             }
     923                 :         } else {
     924               0 :             subjectOrigin.AssignLiteral("the security manager");
     925                 :         }
     926               0 :         NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin);
     927               0 :         NS_ConvertUTF8toUTF16 subjectDomainUnicode(subjectDomain);
     928                 : 
     929               0 :         nsCAutoString objectOrigin;
     930               0 :         nsCAutoString objectDomain;
     931               0 :         if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin &&
     932               0 :             objectPrincipal) {
     933               0 :             nsCOMPtr<nsIURI> uri, domain;
     934               0 :             objectPrincipal->GetURI(getter_AddRefs(uri));
     935               0 :             if (uri) { // Object principal might be system
     936               0 :                 GetOriginFromURI(uri, objectOrigin);
     937                 :             }
     938               0 :             objectPrincipal->GetDomain(getter_AddRefs(domain));
     939               0 :             if (domain) {
     940               0 :                 GetOriginFromURI(domain, objectDomain);
     941                 :             }
     942                 :         }
     943               0 :         NS_ConvertUTF8toUTF16 objectOriginUnicode(objectOrigin);
     944               0 :         NS_ConvertUTF8toUTF16 objectDomainUnicode(objectDomain);
     945                 : 
     946               0 :         nsXPIDLString errorMsg;
     947                 :         const PRUnichar *formatStrings[] =
     948                 :         {
     949               0 :             subjectOriginUnicode.get(),
     950               0 :             className.get(),
     951               0 :             IDToString(cx, aProperty),
     952               0 :             objectOriginUnicode.get(),
     953               0 :             subjectDomainUnicode.get(),
     954               0 :             objectDomainUnicode.get()
     955               0 :         };
     956                 : 
     957               0 :         PRUint32 length = ArrayLength(formatStrings);
     958                 : 
     959                 :         // XXXbz Our localization system is stupid and can't handle not showing
     960                 :         // some strings that get passed in.  Which means that we have to get
     961                 :         // our length precisely right: it has to be exactly the number of
     962                 :         // strings our format string wants.  This means we'll have to move
     963                 :         // strings in the array as needed, sadly...
     964               0 :         if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin ||
     965               0 :             !objectPrincipal) {
     966               0 :             stringName.AppendLiteral("OnlySubject");
     967               0 :             length -= 3;
     968                 :         } else {
     969                 :             // default to a length that doesn't include the domains, then
     970                 :             // increase it as needed.
     971               0 :             length -= 2;
     972               0 :             if (!subjectDomainUnicode.IsEmpty()) {
     973               0 :                 stringName.AppendLiteral("SubjectDomain");
     974               0 :                 length += 1;
     975                 :             }
     976               0 :             if (!objectDomainUnicode.IsEmpty()) {
     977               0 :                 stringName.AppendLiteral("ObjectDomain");
     978               0 :                 length += 1;
     979               0 :                 if (length != ArrayLength(formatStrings)) {
     980                 :                     // We have an object domain but not a subject domain.
     981                 :                     // Scoot our string over one slot.  See the XXX comment
     982                 :                     // above for why we need to do this.
     983               0 :                     formatStrings[length-1] = formatStrings[length];
     984                 :                 }
     985                 :             }
     986                 :         }
     987                 :         
     988                 :         // We need to keep our existing failure rv and not override it
     989                 :         // with a likely success code from the following string bundle
     990                 :         // call in order to throw the correct security exception later.
     991                 :         nsresult rv2 = sStrBundle->FormatStringFromName(stringName.get(),
     992                 :                                                         formatStrings,
     993                 :                                                         length,
     994               0 :                                                         getter_Copies(errorMsg));
     995               0 :         if (NS_FAILED(rv2)) {
     996                 :             // Might just be missing the string...  Do our best
     997               0 :             errorMsg = stringName;
     998                 :         }
     999                 : 
    1000               0 :         SetPendingException(cx, errorMsg.get());
    1001                 :     }
    1002                 : 
    1003               0 :     return rv;
    1004                 : }
    1005                 : 
    1006                 : /* static */
    1007                 : nsresult
    1008         1869541 : nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
    1009                 :                                                   nsIPrincipal* aObject)
    1010                 : {
    1011                 :     /*
    1012                 :     ** Get origin of subject and object and compare.
    1013                 :     */
    1014         1869541 :     if (aSubject == aObject)
    1015         1869541 :         return NS_OK;
    1016                 : 
    1017                 :     // Default to false, and change if that turns out wrong.
    1018               0 :     bool subjectSetDomain = false;
    1019               0 :     bool objectSetDomain = false;
    1020                 :     
    1021               0 :     nsCOMPtr<nsIURI> subjectURI;
    1022               0 :     nsCOMPtr<nsIURI> objectURI;
    1023                 : 
    1024               0 :     aSubject->GetDomain(getter_AddRefs(subjectURI));
    1025               0 :     if (!subjectURI) {
    1026               0 :         aSubject->GetURI(getter_AddRefs(subjectURI));
    1027                 :     } else {
    1028               0 :         subjectSetDomain = true;
    1029                 :     }
    1030                 : 
    1031               0 :     aObject->GetDomain(getter_AddRefs(objectURI));
    1032               0 :     if (!objectURI) {
    1033               0 :         aObject->GetURI(getter_AddRefs(objectURI));
    1034                 :     } else {
    1035               0 :         objectSetDomain = true;
    1036                 :     }
    1037                 : 
    1038               0 :     if (SecurityCompareURIs(subjectURI, objectURI))
    1039                 :     {   // If either the subject or the object has changed its principal by
    1040                 :         // explicitly setting document.domain then the other must also have
    1041                 :         // done so in order to be considered the same origin. This prevents
    1042                 :         // DNS spoofing based on document.domain (154930)
    1043                 : 
    1044                 :         // If both or neither explicitly set their domain, allow the access
    1045               0 :         if (subjectSetDomain == objectSetDomain)
    1046               0 :             return NS_OK;
    1047                 :     }
    1048                 : 
    1049                 :     /*
    1050                 :     ** Access tests failed, so now report error.
    1051                 :     */
    1052               0 :     return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1053                 : }
    1054                 : 
    1055                 : // It's important that
    1056                 : //
    1057                 : //   CheckSameOriginPrincipal(A, B) == NS_OK
    1058                 : //
    1059                 : // imply
    1060                 : //
    1061                 : //   HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
    1062                 : //
    1063                 : // if principals A and B could ever be used as keys in a hashtable.
    1064                 : // Violation of this invariant leads to spurious failures of hashtable
    1065                 : // lookups.  See bug 454850.
    1066                 : 
    1067                 : /*static*/ PRUint32
    1068               0 : nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal* aPrincipal)
    1069                 : {
    1070               0 :     nsCOMPtr<nsIURI> uri;
    1071               0 :     aPrincipal->GetDomain(getter_AddRefs(uri));
    1072               0 :     if (!uri)
    1073               0 :         aPrincipal->GetURI(getter_AddRefs(uri));
    1074               0 :     return SecurityHashURI(uri);
    1075                 : }
    1076                 : 
    1077                 : nsresult
    1078               0 : nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
    1079                 :                                                 nsIPrincipal* aObject,
    1080                 :                                                 PRUint32 aAction)
    1081                 : {
    1082                 :     nsresult rv;
    1083                 :     bool subsumes;
    1084               0 :     rv = aSubject->Subsumes(aObject, &subsumes);
    1085               0 :     if (NS_SUCCEEDED(rv) && !subsumes) {
    1086               0 :         rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1087                 :     }
    1088                 :     
    1089               0 :     if (NS_SUCCEEDED(rv))
    1090               0 :         return NS_OK;
    1091                 : 
    1092                 :     /*
    1093                 :     * Content can't ever touch chrome (we check for UniversalXPConnect later)
    1094                 :     */
    1095               0 :     if (aObject == mSystemPrincipal)
    1096               0 :         return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1097                 : 
    1098                 :     /*
    1099                 :     ** Access tests failed, so now report error.
    1100                 :     */
    1101               0 :     return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1102                 : }
    1103                 : 
    1104                 : nsresult
    1105               1 : nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
    1106                 :                                       ClassInfoData& aClassData,
    1107                 :                                       jsid aProperty,
    1108                 :                                       PRUint32 aAction,
    1109                 :                                       ClassPolicy** aCachedClassPolicy,
    1110                 :                                       SecurityLevel* result)
    1111                 : {
    1112                 :     nsresult rv;
    1113               1 :     result->level = SCRIPT_SECURITY_UNDEFINED_ACCESS;
    1114                 : 
    1115               1 :     DomainPolicy* dpolicy = nsnull;
    1116                 :     //-- Initialize policies if necessary
    1117               1 :     if (mPolicyPrefsChanged)
    1118                 :     {
    1119               1 :         if (!mPrefInitialized) {
    1120               0 :             rv = InitPrefs();
    1121               0 :             NS_ENSURE_SUCCESS(rv, rv);
    1122                 :         }
    1123               1 :         rv = InitPolicies();
    1124               1 :         if (NS_FAILED(rv))
    1125               0 :             return rv;
    1126                 :     }
    1127                 :     else
    1128                 :     {
    1129               0 :         aPrincipal->GetSecurityPolicy((void**)&dpolicy);
    1130                 :     }
    1131                 : 
    1132               1 :     if (!dpolicy && mOriginToPolicyMap)
    1133                 :     {
    1134                 :         //-- Look up the relevant domain policy, if any
    1135                 : #ifdef DEBUG_CAPS_LookupPolicy
    1136                 :         printf("DomainLookup ");
    1137                 : #endif
    1138                 : 
    1139               2 :         nsCAutoString origin;
    1140               1 :         rv = GetPrincipalDomainOrigin(aPrincipal, origin);
    1141               1 :         NS_ENSURE_SUCCESS(rv, rv);
    1142                 :  
    1143               1 :         char *start = origin.BeginWriting();
    1144               1 :         const char *nextToLastDot = nsnull;
    1145               1 :         const char *lastDot = nsnull;
    1146               1 :         const char *colon = nsnull;
    1147               1 :         char *p = start;
    1148                 : 
    1149                 :         //-- search domain (stop at the end of the string or at the 3rd slash)
    1150              22 :         for (PRUint32 slashes=0; *p; p++)
    1151                 :         {
    1152              21 :             if (*p == '/' && ++slashes == 3) 
    1153                 :             {
    1154               0 :                 *p = '\0'; // truncate at 3rd slash
    1155               0 :                 break;
    1156                 :             }
    1157              21 :             if (*p == '.')
    1158                 :             {
    1159               0 :                 nextToLastDot = lastDot;
    1160               0 :                 lastDot = p;
    1161                 :             } 
    1162              21 :             else if (!colon && *p == ':')
    1163               1 :                 colon = p;
    1164                 :         }
    1165                 : 
    1166               3 :         nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
    1167               1 :         DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
    1168               1 :         if (!de)
    1169                 :         {
    1170               2 :             nsCAutoString scheme(start, colon-start+1);
    1171               2 :             nsCStringKey schemeKey(scheme);
    1172               1 :             de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
    1173                 :         }
    1174                 : 
    1175               2 :         while (de)
    1176                 :         {
    1177               0 :             if (de->Matches(start))
    1178                 :             {
    1179               0 :                 dpolicy = de->mDomainPolicy;
    1180               0 :                 break;
    1181                 :             }
    1182               0 :             de = de->mNext;
    1183                 :         }
    1184                 : 
    1185               1 :         if (!dpolicy)
    1186               1 :             dpolicy = mDefaultPolicy;
    1187                 : 
    1188               1 :         aPrincipal->SetSecurityPolicy((void*)dpolicy);
    1189                 :     }
    1190                 : 
    1191               1 :     ClassPolicy* cpolicy = nsnull;
    1192                 : 
    1193               1 :     if ((dpolicy == mDefaultPolicy) && aCachedClassPolicy)
    1194                 :     {
    1195                 :         // No per-domain policy for this principal (the more common case)
    1196                 :         // so look for a cached class policy from the object wrapper
    1197               0 :         cpolicy = *aCachedClassPolicy;
    1198                 :     }
    1199                 : 
    1200               1 :     if (!cpolicy)
    1201                 :     { //-- No cached policy for this class, need to look it up
    1202                 : #ifdef DEBUG_CAPS_LookupPolicy
    1203                 :         printf("ClassLookup ");
    1204                 : #endif
    1205                 : 
    1206                 :         cpolicy = static_cast<ClassPolicy*>
    1207                 :                              (PL_DHashTableOperate(dpolicy,
    1208               1 :                                                       aClassData.GetName(),
    1209               1 :                                                       PL_DHASH_LOOKUP));
    1210                 : 
    1211               1 :         if (PL_DHASH_ENTRY_IS_FREE(cpolicy))
    1212               1 :             cpolicy = NO_POLICY_FOR_CLASS;
    1213                 : 
    1214               1 :         if ((dpolicy == mDefaultPolicy) && aCachedClassPolicy)
    1215               0 :             *aCachedClassPolicy = cpolicy;
    1216                 :     }
    1217                 : 
    1218               1 :     NS_ASSERTION(JSID_IS_INT(aProperty) || JSID_IS_OBJECT(aProperty) ||
    1219                 :                  JSID_IS_STRING(aProperty), "Property must be a valid id");
    1220                 : 
    1221                 :     // Only atomized strings are stored in the policies' hash tables.
    1222               1 :     if (!JSID_IS_STRING(aProperty))
    1223               0 :         return NS_OK;
    1224                 : 
    1225               1 :     JSString *propertyKey = JSID_TO_STRING(aProperty);
    1226                 : 
    1227                 :     // We look for a PropertyPolicy in the following places:
    1228                 :     // 1)  The ClassPolicy for our class we got from our DomainPolicy
    1229                 :     // 2)  The mWildcardPolicy of our DomainPolicy
    1230                 :     // 3)  The ClassPolicy for our class we got from mDefaultPolicy
    1231                 :     // 4)  The mWildcardPolicy of our mDefaultPolicy
    1232               1 :     PropertyPolicy* ppolicy = nsnull;
    1233               1 :     if (cpolicy != NO_POLICY_FOR_CLASS)
    1234                 :     {
    1235                 :         ppolicy = static_cast<PropertyPolicy*>
    1236                 :                              (PL_DHashTableOperate(cpolicy->mPolicy,
    1237                 :                                                       propertyKey,
    1238               0 :                                                       PL_DHASH_LOOKUP));
    1239                 :     }
    1240                 : 
    1241                 :     // If there is no class policy for this property, and we have a wildcard
    1242                 :     // policy, try that.
    1243               1 :     if (dpolicy->mWildcardPolicy &&
    1244                 :         (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)))
    1245                 :     {
    1246                 :         ppolicy =
    1247                 :             static_cast<PropertyPolicy*>
    1248                 :                        (PL_DHashTableOperate(dpolicy->mWildcardPolicy->mPolicy,
    1249                 :                                                 propertyKey,
    1250               0 :                                                 PL_DHASH_LOOKUP));
    1251                 :     }
    1252                 : 
    1253                 :     // If dpolicy is not the defauly policy and there's no class or wildcard
    1254                 :     // policy for this property, check the default policy for this class and
    1255                 :     // the default wildcard policy
    1256               1 :     if (dpolicy != mDefaultPolicy &&
    1257                 :         (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)))
    1258                 :     {
    1259                 :         cpolicy = static_cast<ClassPolicy*>
    1260                 :                              (PL_DHashTableOperate(mDefaultPolicy,
    1261               0 :                                                       aClassData.GetName(),
    1262               0 :                                                       PL_DHASH_LOOKUP));
    1263                 : 
    1264               0 :         if (PL_DHASH_ENTRY_IS_BUSY(cpolicy))
    1265                 :         {
    1266                 :             ppolicy =
    1267                 :                 static_cast<PropertyPolicy*>
    1268                 :                            (PL_DHashTableOperate(cpolicy->mPolicy,
    1269                 :                                                     propertyKey,
    1270               0 :                                                     PL_DHASH_LOOKUP));
    1271                 :         }
    1272                 : 
    1273               0 :         if ((!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy)) &&
    1274                 :             mDefaultPolicy->mWildcardPolicy)
    1275                 :         {
    1276                 :             ppolicy =
    1277                 :               static_cast<PropertyPolicy*>
    1278                 :                          (PL_DHashTableOperate(mDefaultPolicy->mWildcardPolicy->mPolicy,
    1279                 :                                                   propertyKey,
    1280               0 :                                                   PL_DHASH_LOOKUP));
    1281                 :         }
    1282                 :     }
    1283                 : 
    1284               1 :     if (!ppolicy || PL_DHASH_ENTRY_IS_FREE(ppolicy))
    1285               1 :         return NS_OK;
    1286                 : 
    1287                 :     // Get the correct security level from the property policy
    1288               0 :     if (aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY)
    1289               0 :         *result = ppolicy->mSet;
    1290                 :     else
    1291               0 :         *result = ppolicy->mGet;
    1292                 : 
    1293               0 :     return NS_OK;
    1294                 : }
    1295                 : 
    1296                 : 
    1297                 : NS_IMETHODIMP
    1298               0 : nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
    1299                 : {
    1300                 :     // Get principal of currently executing script.
    1301                 :     nsresult rv;
    1302               0 :     nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv);
    1303               0 :     if (NS_FAILED(rv))
    1304               0 :         return rv;
    1305                 : 
    1306                 :     // Native code can load all URIs.
    1307               0 :     if (!principal)
    1308               0 :         return NS_OK;
    1309                 : 
    1310                 :     rv = CheckLoadURIWithPrincipal(principal, aURI,
    1311               0 :                                    nsIScriptSecurityManager::STANDARD);
    1312               0 :     if (NS_SUCCEEDED(rv)) {
    1313                 :         // OK to load
    1314               0 :         return NS_OK;
    1315                 :     }
    1316                 : 
    1317                 :     // See if we're attempting to load a file: URI. If so, let a
    1318                 :     // UniversalXPConnect capability trump the above check.
    1319               0 :     bool isFile = false;
    1320               0 :     bool isRes = false;
    1321               0 :     if (NS_FAILED(aURI->SchemeIs("file", &isFile)) ||
    1322               0 :         NS_FAILED(aURI->SchemeIs("resource", &isRes)))
    1323               0 :         return NS_ERROR_FAILURE;
    1324               0 :     if (isFile || isRes)
    1325                 :     {
    1326                 :         bool enabled;
    1327               0 :         if (NS_FAILED(IsCapabilityEnabled("UniversalXPConnect", &enabled)))
    1328               0 :             return NS_ERROR_FAILURE;
    1329               0 :         if (enabled)
    1330               0 :             return NS_OK;
    1331                 :     }
    1332                 : 
    1333                 :     // Report error.
    1334               0 :     nsCAutoString spec;
    1335               0 :     if (NS_FAILED(aURI->GetAsciiSpec(spec)))
    1336               0 :         return NS_ERROR_FAILURE;
    1337               0 :     nsCAutoString msg("Access to '");
    1338               0 :     msg.Append(spec);
    1339               0 :     msg.AppendLiteral("' from script denied");
    1340               0 :     SetPendingException(cx, msg.get());
    1341               0 :     return NS_ERROR_DOM_BAD_URI;
    1342                 : }
    1343                 : 
    1344                 : NS_IMETHODIMP
    1345               0 : nsScriptSecurityManager::CheckLoadURI(nsIURI *aSourceURI, nsIURI *aTargetURI,
    1346                 :                                       PRUint32 aFlags)
    1347                 : {
    1348                 :     // FIXME: bug 327244 -- this function should really die...  Really truly.
    1349               0 :     NS_PRECONDITION(aSourceURI, "CheckLoadURI called with null source URI");
    1350               0 :     NS_ENSURE_ARG_POINTER(aSourceURI);
    1351                 : 
    1352                 :     // Note: this is not _quite_ right if aSourceURI has
    1353                 :     // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
    1354                 :     // CheckLoadURIWithPrincipal anyway, so this is good enough.  This method
    1355                 :     // really needs to go away....
    1356               0 :     nsCOMPtr<nsIPrincipal> sourcePrincipal;
    1357                 :     nsresult rv = CreateCodebasePrincipal(aSourceURI,
    1358               0 :                                           getter_AddRefs(sourcePrincipal));
    1359               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1360               0 :     return CheckLoadURIWithPrincipal(sourcePrincipal, aTargetURI, aFlags);
    1361                 : }
    1362                 : 
    1363                 : /**
    1364                 :  * Helper method to handle cases where a flag passed to
    1365                 :  * CheckLoadURIWithPrincipal means denying loading if the given URI has certain
    1366                 :  * nsIProtocolHandler flags set.
    1367                 :  * @return if success, access is allowed. Otherwise, deny access
    1368                 :  */
    1369                 : static nsresult
    1370             192 : DenyAccessIfURIHasFlags(nsIURI* aURI, PRUint32 aURIFlags)
    1371                 : {
    1372             192 :     NS_PRECONDITION(aURI, "Must have URI!");
    1373                 :     
    1374                 :     bool uriHasFlags;
    1375                 :     nsresult rv =
    1376             192 :         NS_URIChainHasFlags(aURI, aURIFlags, &uriHasFlags);
    1377             192 :     NS_ENSURE_SUCCESS(rv, rv);
    1378                 : 
    1379             192 :     if (uriHasFlags) {
    1380               0 :         return NS_ERROR_DOM_BAD_URI;
    1381                 :     }
    1382                 : 
    1383             192 :     return NS_OK;
    1384                 : }
    1385                 : 
    1386                 : NS_IMETHODIMP
    1387             184 : nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
    1388                 :                                                    nsIURI *aTargetURI,
    1389                 :                                                    PRUint32 aFlags)
    1390                 : {
    1391             184 :     NS_PRECONDITION(aPrincipal, "CheckLoadURIWithPrincipal must have a principal");
    1392                 :     // If someone passes a flag that we don't understand, we should
    1393                 :     // fail, because they may need a security check that we don't
    1394                 :     // provide.
    1395             184 :     NS_ENSURE_FALSE(aFlags & ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
    1396                 :                                nsIScriptSecurityManager::ALLOW_CHROME |
    1397                 :                                nsIScriptSecurityManager::DISALLOW_SCRIPT |
    1398                 :                                nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL),
    1399                 :                     NS_ERROR_UNEXPECTED);
    1400             184 :     NS_ENSURE_ARG_POINTER(aPrincipal);
    1401             184 :     NS_ENSURE_ARG_POINTER(aTargetURI);
    1402                 : 
    1403             184 :     if (aPrincipal == mSystemPrincipal) {
    1404                 :         // Allow access
    1405               0 :         return NS_OK;
    1406                 :     }
    1407                 :     
    1408             368 :     nsCOMPtr<nsIURI> sourceURI;
    1409             184 :     aPrincipal->GetURI(getter_AddRefs(sourceURI));
    1410             184 :     if (!sourceURI) {
    1411                 :         NS_ERROR("Non-system principals passed to CheckLoadURIWithPrincipal "
    1412               0 :                  "must have a URI!");
    1413               0 :         return NS_ERROR_UNEXPECTED;
    1414                 :     }
    1415                 :     
    1416                 :     // Automatic loads are not allowed from certain protocols.
    1417             184 :     if (aFlags & nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT) {
    1418                 :         nsresult rv =
    1419                 :             DenyAccessIfURIHasFlags(sourceURI,
    1420             155 :                                     nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT);
    1421             155 :         NS_ENSURE_SUCCESS(rv, rv);
    1422                 :     }
    1423                 : 
    1424                 :     // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
    1425                 :     // would do such inheriting.  That would be URIs that do not have their own
    1426                 :     // security context.
    1427             184 :     if (aFlags & nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL) {
    1428                 :         nsresult rv =
    1429                 :             DenyAccessIfURIHasFlags(aTargetURI,
    1430              29 :                                     nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT);
    1431              29 :         NS_ENSURE_SUCCESS(rv, rv);
    1432                 :     }
    1433                 : 
    1434                 :     // If either URI is a nested URI, get the base URI
    1435             368 :     nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(sourceURI);
    1436             368 :     nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
    1437                 : 
    1438                 :     //-- get the target scheme
    1439             368 :     nsCAutoString targetScheme;
    1440             184 :     nsresult rv = targetBaseURI->GetScheme(targetScheme);
    1441             184 :     if (NS_FAILED(rv)) return rv;
    1442                 : 
    1443                 :     //-- Some callers do not allow loading javascript:
    1444             339 :     if ((aFlags & nsIScriptSecurityManager::DISALLOW_SCRIPT) &&
    1445             155 :          targetScheme.EqualsLiteral("javascript"))
    1446                 :     {
    1447               1 :        return NS_ERROR_DOM_BAD_URI;
    1448                 :     }
    1449                 : 
    1450             366 :     NS_NAMED_LITERAL_STRING(errorTag, "CheckLoadURIError");
    1451                 : 
    1452                 :     // Check for uris that are only loadable by principals that subsume them
    1453                 :     bool hasFlags;
    1454                 :     rv = NS_URIChainHasFlags(targetBaseURI,
    1455                 :                              nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS,
    1456             183 :                              &hasFlags);
    1457             183 :     NS_ENSURE_SUCCESS(rv, rv);
    1458                 : 
    1459             183 :     if (hasFlags) {
    1460               0 :         return aPrincipal->CheckMayLoad(targetBaseURI, true);
    1461                 :     }
    1462                 : 
    1463                 :     //-- get the source scheme
    1464             366 :     nsCAutoString sourceScheme;
    1465             183 :     rv = sourceBaseURI->GetScheme(sourceScheme);
    1466             183 :     if (NS_FAILED(rv)) return rv;
    1467                 : 
    1468             183 :     if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
    1469                 :         // A null principal can target its own URI.
    1470               7 :         if (sourceURI == aTargetURI) {
    1471               0 :             return NS_OK;
    1472                 :         }
    1473                 :     }
    1474             176 :     else if (targetScheme.Equals(sourceScheme,
    1475             176 :                                  nsCaseInsensitiveCStringComparator()))
    1476                 :     {
    1477                 :         // every scheme can access another URI from the same scheme,
    1478                 :         // as long as they don't represent null principals.
    1479             175 :         return NS_OK;
    1480                 :     }
    1481                 : 
    1482                 :     // If the schemes don't match, the policy is specified by the protocol
    1483                 :     // flags on the target URI.  Note that the order of policy checks here is
    1484                 :     // very important!  We start from most restrictive and work our way down.
    1485                 :     // Note that since we're working with the innermost URI, we can just use
    1486                 :     // the methods that work on chains of nested URIs and they will only look
    1487                 :     // at the flags for our one URI.
    1488                 : 
    1489                 :     // Check for system target URI
    1490                 :     rv = DenyAccessIfURIHasFlags(targetBaseURI,
    1491               8 :                                  nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
    1492               8 :     if (NS_FAILED(rv)) {
    1493                 :         // Deny access, since the origin principal is not system
    1494               0 :         ReportError(nsnull, errorTag, sourceURI, aTargetURI);
    1495               0 :         return rv;
    1496                 :     }
    1497                 : 
    1498                 :     // Check for chrome target URI
    1499                 :     rv = NS_URIChainHasFlags(targetBaseURI,
    1500                 :                              nsIProtocolHandler::URI_IS_UI_RESOURCE,
    1501               8 :                              &hasFlags);
    1502               8 :     NS_ENSURE_SUCCESS(rv, rv);
    1503               8 :     if (hasFlags) {
    1504               1 :         if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
    1505               0 :             if (!targetScheme.EqualsLiteral("chrome")) {
    1506                 :                 // for now don't change behavior for resource: or moz-icon:
    1507               0 :                 return NS_OK;
    1508                 :             }
    1509                 : 
    1510                 :             // allow load only if chrome package is whitelisted
    1511                 :             nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService(
    1512               0 :                                                  NS_CHROMEREGISTRY_CONTRACTID));
    1513               0 :             if (reg) {
    1514               0 :                 bool accessAllowed = false;
    1515               0 :                 reg->AllowContentToAccess(targetBaseURI, &accessAllowed);
    1516               0 :                 if (accessAllowed) {
    1517               0 :                     return NS_OK;
    1518                 :                 }
    1519                 :             }
    1520                 :         }
    1521                 : 
    1522                 :         // resource: and chrome: are equivalent, securitywise
    1523                 :         // That's bogus!!  Fix this.  But watch out for
    1524                 :         // the view-source stylesheet?
    1525                 :         bool sourceIsChrome;
    1526                 :         rv = NS_URIChainHasFlags(sourceBaseURI,
    1527                 :                                  nsIProtocolHandler::URI_IS_UI_RESOURCE,
    1528               1 :                                  &sourceIsChrome);
    1529               1 :         NS_ENSURE_SUCCESS(rv, rv);
    1530               1 :         if (sourceIsChrome) {
    1531               0 :             return NS_OK;
    1532                 :         }
    1533               1 :         ReportError(nsnull, errorTag, sourceURI, aTargetURI);
    1534               1 :         return NS_ERROR_DOM_BAD_URI;
    1535                 :     }
    1536                 : 
    1537                 :     // Check for target URI pointing to a file
    1538                 :     rv = NS_URIChainHasFlags(targetBaseURI,
    1539                 :                              nsIProtocolHandler::URI_IS_LOCAL_FILE,
    1540               7 :                              &hasFlags);
    1541               7 :     NS_ENSURE_SUCCESS(rv, rv);
    1542               7 :     if (hasFlags) {
    1543                 :         // resource: and chrome: are equivalent, securitywise
    1544                 :         // That's bogus!!  Fix this.  But watch out for
    1545                 :         // the view-source stylesheet?
    1546                 :         bool sourceIsChrome;
    1547                 :         rv = NS_URIChainHasFlags(sourceURI,
    1548                 :                                  nsIProtocolHandler::URI_IS_UI_RESOURCE,
    1549               1 :                                  &sourceIsChrome);
    1550               1 :         NS_ENSURE_SUCCESS(rv, rv);
    1551               1 :         if (sourceIsChrome) {
    1552               0 :             return NS_OK;
    1553                 :         }
    1554                 : 
    1555                 :         // Now check capability policies
    1556                 :         static const char loadURIPrefGroup[] = "checkloaduri";
    1557               2 :         ClassInfoData nameData(nsnull, loadURIPrefGroup);
    1558                 : 
    1559                 :         SecurityLevel secLevel;
    1560                 :         rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
    1561                 :                           nsIXPCSecurityManager::ACCESS_GET_PROPERTY, 
    1562               1 :                           nsnull, &secLevel);
    1563               1 :         if (NS_SUCCEEDED(rv) && secLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
    1564                 :         {
    1565                 :             // OK for this site!
    1566               0 :             return NS_OK;
    1567                 :         }
    1568                 : 
    1569               1 :         ReportError(nsnull, errorTag, sourceURI, aTargetURI);
    1570               1 :         return NS_ERROR_DOM_BAD_URI;
    1571                 :     }
    1572                 : 
    1573                 :     // OK, everyone is allowed to load this, since unflagged handlers are
    1574                 :     // deprecated but treated as URI_LOADABLE_BY_ANYONE.  But check whether we
    1575                 :     // need to warn.  At some point we'll want to make this warning into an
    1576                 :     // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
    1577                 :     rv = NS_URIChainHasFlags(targetBaseURI,
    1578                 :                              nsIProtocolHandler::URI_LOADABLE_BY_ANYONE,
    1579               6 :                              &hasFlags);
    1580               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1581               6 :     if (!hasFlags) {
    1582               0 :         nsXPIDLString message;
    1583               0 :         NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme);
    1584               0 :         const PRUnichar* formatStrings[] = { ucsTargetScheme.get() };
    1585                 :         rv = sStrBundle->
    1586               0 :             FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
    1587                 :                                  formatStrings,
    1588                 :                                  ArrayLength(formatStrings),
    1589               0 :                                  getter_Copies(message));
    1590               0 :         if (NS_SUCCEEDED(rv)) {
    1591                 :             nsCOMPtr<nsIConsoleService> console(
    1592               0 :               do_GetService("@mozilla.org/consoleservice;1"));
    1593               0 :             NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
    1594                 : 
    1595               0 :             console->LogStringMessage(message.get());
    1596                 : #ifdef DEBUG
    1597               0 :             fprintf(stderr, "%s\n", NS_ConvertUTF16toUTF8(message).get());
    1598                 : #endif
    1599                 :         }
    1600                 :     }
    1601                 :     
    1602               6 :     return NS_OK;
    1603                 : }
    1604                 : 
    1605                 : nsresult
    1606               2 : nsScriptSecurityManager::ReportError(JSContext* cx, const nsAString& messageTag,
    1607                 :                                      nsIURI* aSource, nsIURI* aTarget)
    1608                 : {
    1609                 :     nsresult rv;
    1610               2 :     NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
    1611                 : 
    1612                 :     // Get the source URL spec
    1613               4 :     nsCAutoString sourceSpec;
    1614               2 :     rv = aSource->GetAsciiSpec(sourceSpec);
    1615               2 :     NS_ENSURE_SUCCESS(rv, rv);
    1616                 : 
    1617                 :     // Get the target URL spec
    1618               4 :     nsCAutoString targetSpec;
    1619               2 :     rv = aTarget->GetAsciiSpec(targetSpec);
    1620               2 :     NS_ENSURE_SUCCESS(rv, rv);
    1621                 : 
    1622                 :     // Localize the error message
    1623               4 :     nsXPIDLString message;
    1624               4 :     NS_ConvertASCIItoUTF16 ucsSourceSpec(sourceSpec);
    1625               4 :     NS_ConvertASCIItoUTF16 ucsTargetSpec(targetSpec);
    1626               2 :     const PRUnichar *formatStrings[] = { ucsSourceSpec.get(), ucsTargetSpec.get() };
    1627               2 :     rv = sStrBundle->FormatStringFromName(PromiseFlatString(messageTag).get(),
    1628                 :                                           formatStrings,
    1629                 :                                           ArrayLength(formatStrings),
    1630               4 :                                           getter_Copies(message));
    1631               2 :     NS_ENSURE_SUCCESS(rv, rv);
    1632                 : 
    1633                 :     // If a JS context was passed in, set a JS exception.
    1634                 :     // Otherwise, print the error message directly to the JS console
    1635                 :     // and to standard output
    1636               2 :     if (cx)
    1637                 :     {
    1638               0 :         SetPendingException(cx, message.get());
    1639                 :     }
    1640                 :     else // Print directly to the console
    1641                 :     {
    1642                 :         nsCOMPtr<nsIConsoleService> console(
    1643               4 :             do_GetService("@mozilla.org/consoleservice;1"));
    1644               2 :         NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
    1645                 : 
    1646               2 :         console->LogStringMessage(message.get());
    1647                 : #ifdef DEBUG
    1648               4 :         fprintf(stderr, "%s\n", NS_LossyConvertUTF16toASCII(message).get());
    1649                 : #endif
    1650                 :     }
    1651               2 :     return NS_OK;
    1652                 : }
    1653                 : 
    1654                 : NS_IMETHODIMP
    1655               0 : nsScriptSecurityManager::CheckLoadURIStr(const nsACString& aSourceURIStr,
    1656                 :                                          const nsACString& aTargetURIStr,
    1657                 :                                          PRUint32 aFlags)
    1658                 : {
    1659                 :     // FIXME: bug 327244 -- this function should really die...  Really truly.
    1660               0 :     nsCOMPtr<nsIURI> source;
    1661               0 :     nsresult rv = NS_NewURI(getter_AddRefs(source), aSourceURIStr,
    1662               0 :                             nsnull, nsnull, sIOService);
    1663               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1664                 : 
    1665                 :     // Note: this is not _quite_ right if aSourceURI has
    1666                 :     // NS_NULLPRINCIPAL_SCHEME, but we'll just extract the scheme in
    1667                 :     // CheckLoadURIWithPrincipal anyway, so this is good enough.  This method
    1668                 :     // really needs to go away....
    1669               0 :     nsCOMPtr<nsIPrincipal> sourcePrincipal;
    1670                 :     rv = CreateCodebasePrincipal(source,
    1671               0 :                                  getter_AddRefs(sourcePrincipal));
    1672               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1673                 : 
    1674                 :     return CheckLoadURIStrWithPrincipal(sourcePrincipal, aTargetURIStr,
    1675               0 :                                         aFlags);
    1676                 : }
    1677                 : 
    1678                 : NS_IMETHODIMP
    1679               2 : nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal* aPrincipal,
    1680                 :                                                       const nsACString& aTargetURIStr,
    1681                 :                                                       PRUint32 aFlags)
    1682                 : {
    1683                 :     nsresult rv;
    1684               4 :     nsCOMPtr<nsIURI> target;
    1685               2 :     rv = NS_NewURI(getter_AddRefs(target), aTargetURIStr,
    1686               2 :                    nsnull, nsnull, sIOService);
    1687               2 :     NS_ENSURE_SUCCESS(rv, rv);
    1688                 : 
    1689               2 :     rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
    1690               2 :     NS_ENSURE_SUCCESS(rv, rv);
    1691                 : 
    1692                 :     // Now start testing fixup -- since aTargetURIStr is a string, not
    1693                 :     // an nsIURI, we may well end up fixing it up before loading.
    1694                 :     // Note: This needs to stay in sync with the nsIURIFixup api.
    1695               2 :     nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
    1696               1 :     if (!fixup) {
    1697               0 :         return rv;
    1698                 :     }
    1699                 : 
    1700                 :     PRUint32 flags[] = {
    1701                 :         nsIURIFixup::FIXUP_FLAG_NONE,
    1702                 :         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
    1703                 :         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
    1704                 :         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP |
    1705                 :         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
    1706               1 :     };
    1707                 : 
    1708               5 :     for (PRUint32 i = 0; i < ArrayLength(flags); ++i) {
    1709               4 :         rv = fixup->CreateFixupURI(aTargetURIStr, flags[i],
    1710               4 :                                    getter_AddRefs(target));
    1711               4 :         NS_ENSURE_SUCCESS(rv, rv);
    1712                 : 
    1713               4 :         rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
    1714               4 :         NS_ENSURE_SUCCESS(rv, rv);
    1715                 :     }
    1716                 : 
    1717               1 :     return rv;
    1718                 : }
    1719                 : 
    1720                 : NS_IMETHODIMP
    1721               0 : nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
    1722                 :                                              void *aTargetObj)
    1723                 : {
    1724                 :     // This check is called for event handlers
    1725                 :     nsresult rv;
    1726                 :     nsIPrincipal* subject =
    1727               0 :         GetFunctionObjectPrincipal(aCx, (JSObject *)aFunObj, nsnull, &rv);
    1728                 : 
    1729                 :     // If subject is null, get a principal from the function object's scope.
    1730               0 :     if (NS_SUCCEEDED(rv) && !subject)
    1731                 :     {
    1732                 : #ifdef DEBUG
    1733                 :         {
    1734               0 :             JS_ASSERT(JS_ObjectIsFunction(aCx, (JSObject *)aFunObj));
    1735               0 :             JSFunction *fun = JS_GetObjectFunction((JSObject *)aFunObj);
    1736               0 :             JSScript *script = JS_GetFunctionScript(aCx, fun);
    1737                 : 
    1738               0 :             NS_ASSERTION(!script, "Null principal for non-native function!");
    1739                 :         }
    1740                 : #endif
    1741                 : 
    1742               0 :         subject = doGetObjectPrincipal((JSObject*)aFunObj);
    1743                 :     }
    1744                 : 
    1745               0 :     if (!subject)
    1746               0 :         return NS_ERROR_FAILURE;
    1747                 : 
    1748               0 :     if (subject == mSystemPrincipal)
    1749                 :         // This is the system principal: just allow access
    1750               0 :         return NS_OK;
    1751                 : 
    1752                 :     // Check if the principal the function was compiled under is
    1753                 :     // allowed to execute scripts.
    1754                 : 
    1755                 :     bool result;
    1756               0 :     rv = CanExecuteScripts(aCx, subject, &result);
    1757               0 :     if (NS_FAILED(rv))
    1758               0 :       return rv;
    1759                 : 
    1760               0 :     if (!result)
    1761               0 :       return NS_ERROR_DOM_SECURITY_ERR;
    1762                 : 
    1763                 :     /*
    1764                 :     ** Get origin of subject and object and compare.
    1765                 :     */
    1766               0 :     JSObject* obj = (JSObject*)aTargetObj;
    1767               0 :     nsIPrincipal* object = doGetObjectPrincipal(obj);
    1768                 : 
    1769               0 :     if (!object)
    1770               0 :         return NS_ERROR_FAILURE;        
    1771                 : 
    1772                 :     bool subsumes;
    1773               0 :     rv = subject->Subsumes(object, &subsumes);
    1774               0 :     if (NS_SUCCEEDED(rv) && !subsumes) {
    1775               0 :         rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1776                 :     }
    1777               0 :     return rv;
    1778                 : }
    1779                 : 
    1780                 : NS_IMETHODIMP
    1781               0 : nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
    1782                 :                                            nsIPrincipal *aPrincipal,
    1783                 :                                            bool *result)
    1784                 : {
    1785               0 :     *result = false; 
    1786                 : 
    1787               0 :     if (aPrincipal == mSystemPrincipal)
    1788                 :     {
    1789                 :         // Even if JavaScript is disabled, we must still execute system scripts
    1790               0 :         *result = true;
    1791               0 :         return NS_OK;
    1792                 :     }
    1793                 : 
    1794                 :     //-- See if the current window allows JS execution
    1795               0 :     nsIScriptContext *scriptContext = GetScriptContext(cx);
    1796               0 :     if (!scriptContext) return NS_ERROR_FAILURE;
    1797                 : 
    1798               0 :     if (!scriptContext->GetScriptsEnabled()) {
    1799                 :         // No scripting on this context, folks
    1800               0 :         *result = false;
    1801               0 :         return NS_OK;
    1802                 :     }
    1803                 :     
    1804               0 :     nsIScriptGlobalObject *sgo = scriptContext->GetGlobalObject();
    1805                 : 
    1806               0 :     if (!sgo) {
    1807               0 :         return NS_ERROR_FAILURE;
    1808                 :     }
    1809                 : 
    1810                 :     // window can be null here if we're running with a non-DOM window
    1811                 :     // as the script global (i.e. a XUL prototype document).
    1812               0 :     nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(sgo);
    1813               0 :     nsCOMPtr<nsIDocShell> docshell;
    1814                 :     nsresult rv;
    1815                 : 
    1816               0 :     if (window) {
    1817               0 :         docshell = window->GetDocShell();
    1818                 :     }
    1819                 : 
    1820               0 :     if (docshell) {
    1821               0 :       rv = docshell->GetCanExecuteScripts(result);
    1822               0 :       if (NS_FAILED(rv)) return rv;
    1823               0 :       if (!*result) return NS_OK;
    1824                 :     }
    1825                 : 
    1826                 :     // OK, the docshell doesn't have script execution explicitly disabled.
    1827                 :     // Check whether our URI is an "about:" URI that allows scripts.  If it is,
    1828                 :     // we need to allow JS to run.  In this case, don't apply the JS enabled
    1829                 :     // pref or policies.  On failures, just press on and don't do this special
    1830                 :     // case.
    1831               0 :     nsCOMPtr<nsIURI> principalURI;
    1832               0 :     aPrincipal->GetURI(getter_AddRefs(principalURI));
    1833               0 :     if (!principalURI) {
    1834                 :         // Broken principal of some sort.  Disallow.
    1835               0 :         *result = false;
    1836               0 :         return NS_ERROR_UNEXPECTED;
    1837                 :     }
    1838                 :         
    1839                 :     bool isAbout;
    1840               0 :     rv = principalURI->SchemeIs("about", &isAbout);
    1841               0 :     if (NS_SUCCEEDED(rv) && isAbout) {
    1842               0 :         nsCOMPtr<nsIAboutModule> module;
    1843               0 :         rv = NS_GetAboutModule(principalURI, getter_AddRefs(module));
    1844               0 :         if (NS_SUCCEEDED(rv)) {
    1845                 :             PRUint32 flags;
    1846               0 :             rv = module->GetURIFlags(principalURI, &flags);
    1847               0 :             if (NS_SUCCEEDED(rv) &&
    1848                 :                 (flags & nsIAboutModule::ALLOW_SCRIPT)) {
    1849               0 :                 *result = true;
    1850               0 :                 return NS_OK;              
    1851                 :             }
    1852                 :         }
    1853                 :     }
    1854                 : 
    1855               0 :     *result = mIsJavaScriptEnabled;
    1856               0 :     if (!*result)
    1857               0 :         return NS_OK; // Do not run scripts
    1858                 : 
    1859                 :     //-- Check for a per-site policy
    1860                 :     static const char jsPrefGroupName[] = "javascript";
    1861               0 :     ClassInfoData nameData(nsnull, jsPrefGroupName);
    1862                 : 
    1863                 :     SecurityLevel secLevel;
    1864                 :     rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
    1865                 :                       nsIXPCSecurityManager::ACCESS_GET_PROPERTY, 
    1866               0 :                       nsnull, &secLevel);
    1867               0 :     if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
    1868                 :     {
    1869               0 :         *result = false;
    1870               0 :         return rv;
    1871                 :     }
    1872                 : 
    1873                 :     //-- Nobody vetoed, so allow the JS to run.
    1874               0 :     *result = true;
    1875               0 :     return NS_OK;
    1876                 : }
    1877                 : 
    1878                 : ///////////////// Principals ///////////////////////
    1879                 : NS_IMETHODIMP
    1880           40139 : nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal)
    1881                 : {
    1882                 :     nsresult rv;
    1883           40139 :     *aSubjectPrincipal = doGetSubjectPrincipal(&rv);
    1884           40139 :     if (NS_SUCCEEDED(rv))
    1885           40139 :         NS_IF_ADDREF(*aSubjectPrincipal);
    1886           40139 :     return rv;
    1887                 : }
    1888                 : 
    1889                 : nsIPrincipal*
    1890           40139 : nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv)
    1891                 : {
    1892           40139 :     NS_PRECONDITION(rv, "Null out param");
    1893           40139 :     JSContext *cx = GetCurrentJSContext();
    1894           40139 :     if (!cx)
    1895                 :     {
    1896               0 :         *rv = NS_OK;
    1897               0 :         return nsnull;
    1898                 :     }
    1899           40139 :     return GetSubjectPrincipal(cx, rv);
    1900                 : }
    1901                 : 
    1902                 : NS_IMETHODIMP
    1903            4421 : nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
    1904                 : {
    1905            4421 :     NS_ADDREF(*result = mSystemPrincipal);
    1906                 : 
    1907            4421 :     return NS_OK;
    1908                 : }
    1909                 : 
    1910                 : NS_IMETHODIMP
    1911           38805 : nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem)
    1912                 : {
    1913           38805 :     NS_ENSURE_ARG_POINTER(aIsSystem);
    1914           38805 :     *aIsSystem = false;
    1915                 : 
    1916           38805 :     if (!mSystemPrincipal)
    1917               0 :         return NS_OK;
    1918                 : 
    1919           77610 :     nsCOMPtr<nsIPrincipal> subject;
    1920           38805 :     nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
    1921           38805 :     if (NS_FAILED(rv))
    1922               0 :         return rv;
    1923                 : 
    1924           38805 :     if(!subject)
    1925                 :     {
    1926                 :         // No subject principal means no JS is running;
    1927                 :         // this is the equivalent of system principal code
    1928               0 :         *aIsSystem = true;
    1929               0 :         return NS_OK;
    1930                 :     }
    1931                 : 
    1932           38805 :     return mSystemPrincipal->Equals(subject, aIsSystem);
    1933                 : }
    1934                 : 
    1935                 : NS_IMETHODIMP
    1936               0 : nsScriptSecurityManager::GetCertificatePrincipal(const nsACString& aCertFingerprint,
    1937                 :                                                  const nsACString& aSubjectName,
    1938                 :                                                  const nsACString& aPrettyName,
    1939                 :                                                  nsISupports* aCertificate,
    1940                 :                                                  nsIURI* aURI,
    1941                 :                                                  nsIPrincipal **result)
    1942                 : {
    1943               0 :     *result = nsnull;
    1944                 :     
    1945               0 :     NS_ENSURE_ARG(!aCertFingerprint.IsEmpty() &&
    1946                 :                   !aSubjectName.IsEmpty() &&
    1947                 :                   aCertificate);
    1948                 : 
    1949                 :     return DoGetCertificatePrincipal(aCertFingerprint, aSubjectName,
    1950                 :                                      aPrettyName, aCertificate, aURI, true,
    1951               0 :                                      result);
    1952                 : }
    1953                 : 
    1954                 : nsresult
    1955               0 : nsScriptSecurityManager::DoGetCertificatePrincipal(const nsACString& aCertFingerprint,
    1956                 :                                                    const nsACString& aSubjectName,
    1957                 :                                                    const nsACString& aPrettyName,
    1958                 :                                                    nsISupports* aCertificate,
    1959                 :                                                    nsIURI* aURI,
    1960                 :                                                    bool aModifyTable,
    1961                 :                                                    nsIPrincipal **result)
    1962                 : {
    1963               0 :     NS_ENSURE_ARG(!aCertFingerprint.IsEmpty());
    1964                 :     
    1965                 :     // Create a certificate principal out of the certificate ID
    1966                 :     // and URI given to us.  We will use this principal to test
    1967                 :     // equality when doing our hashtable lookups below.
    1968               0 :     nsRefPtr<nsPrincipal> certificate = new nsPrincipal();
    1969               0 :     if (!certificate)
    1970               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1971                 : 
    1972                 :     nsresult rv = certificate->Init(aCertFingerprint, aSubjectName,
    1973               0 :                                     aPrettyName, aCertificate, aURI);
    1974               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1975                 : 
    1976                 :     // Check to see if we already have this principal.
    1977               0 :     nsCOMPtr<nsIPrincipal> fromTable;
    1978               0 :     mPrincipals.Get(certificate, getter_AddRefs(fromTable));
    1979               0 :     if (fromTable) {
    1980                 :         // Bingo.  We found the certificate in the table, which means
    1981                 :         // that it has escalated privileges.
    1982                 : 
    1983               0 :         if (aModifyTable) {
    1984                 :             // Make sure this principal has names, so if we ever go to save it
    1985                 :             // we'll save them.  If we get a name mismatch here we'll throw,
    1986                 :             // but that's desirable.
    1987                 :             rv = static_cast<nsPrincipal*>
    1988               0 :                             (static_cast<nsIPrincipal*>(fromTable))
    1989               0 :                 ->EnsureCertData(aSubjectName, aPrettyName, aCertificate);
    1990               0 :             if (NS_FAILED(rv)) {
    1991                 :                 // We have a subject name mismatch for the same cert id.
    1992                 :                 // Hand back the |certificate| object we created and don't give
    1993                 :                 // it any rights from the table.
    1994               0 :                 NS_ADDREF(*result = certificate);
    1995               0 :                 return NS_OK;
    1996                 :             }                
    1997                 :         }
    1998                 :         
    1999               0 :         if (!aURI) {
    2000                 :             // We were asked to just get the base certificate, so output
    2001                 :             // what we have in the table.
    2002                 :             certificate = static_cast<nsPrincipal*>
    2003                 :                                      (static_cast<nsIPrincipal*>
    2004               0 :                                                  (fromTable));
    2005                 :         } else {
    2006                 :             // We found a certificate and now need to install a codebase
    2007                 :             // on it.  We don't want to modify the principal in the hash
    2008                 :             // table, so create a new principal and clone the pertinent
    2009                 :             // things.
    2010               0 :             nsXPIDLCString prefName;
    2011               0 :             nsXPIDLCString id;
    2012               0 :             nsXPIDLCString subjectName;
    2013               0 :             nsXPIDLCString granted;
    2014               0 :             nsXPIDLCString denied;
    2015                 :             bool isTrusted;
    2016               0 :             rv = fromTable->GetPreferences(getter_Copies(prefName),
    2017               0 :                                            getter_Copies(id),
    2018               0 :                                            getter_Copies(subjectName),
    2019               0 :                                            getter_Copies(granted),
    2020               0 :                                            getter_Copies(denied),
    2021               0 :                                            &isTrusted);
    2022                 :             // XXXbz assert something about subjectName and aSubjectName here?
    2023               0 :             if (NS_SUCCEEDED(rv)) {
    2024               0 :                 NS_ASSERTION(!isTrusted, "Shouldn't have isTrusted true here");
    2025                 :                 
    2026               0 :                 certificate = new nsPrincipal();
    2027               0 :                 if (!certificate)
    2028               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2029                 : 
    2030                 :                 rv = certificate->InitFromPersistent(prefName, id,
    2031                 :                                                      subjectName, aPrettyName,
    2032                 :                                                      granted, denied,
    2033                 :                                                      aCertificate,
    2034               0 :                                                      true, false);
    2035               0 :                 if (NS_FAILED(rv))
    2036               0 :                     return rv;
    2037                 :                 
    2038               0 :                 certificate->SetURI(aURI);
    2039                 :             }
    2040                 :         }
    2041                 :     }
    2042                 : 
    2043               0 :     NS_ADDREF(*result = certificate);
    2044                 : 
    2045               0 :     return rv;
    2046                 : }
    2047                 : 
    2048                 : nsresult
    2049             207 : nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, nsIPrincipal **result)
    2050                 : {
    2051                 :     // I _think_ it's safe to not create null principals here based on aURI.
    2052                 :     // At least all the callers would do the right thing in those cases, as far
    2053                 :     // as I can tell.  --bz
    2054                 : 
    2055             414 :     nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
    2056             207 :     if (uriPrinc) {
    2057               0 :         nsCOMPtr<nsIPrincipal> principal;
    2058               0 :         uriPrinc->GetPrincipal(getter_AddRefs(principal));
    2059               0 :         if (!principal || principal == mSystemPrincipal) {
    2060               0 :             return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result);
    2061                 :         }
    2062                 : 
    2063               0 :         principal.forget(result);
    2064                 : 
    2065               0 :         return NS_OK;
    2066                 :     }
    2067                 : 
    2068             414 :     nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
    2069             207 :     if (!codebase)
    2070               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2071                 : 
    2072             414 :     nsresult rv = codebase->Init(EmptyCString(), EmptyCString(),
    2073             621 :                                  EmptyCString(), nsnull, aURI);
    2074             207 :     if (NS_FAILED(rv))
    2075               0 :         return rv;
    2076                 : 
    2077             207 :     NS_ADDREF(*result = codebase);
    2078                 : 
    2079             207 :     return NS_OK;
    2080                 : }
    2081                 : 
    2082                 : NS_IMETHODIMP
    2083             217 : nsScriptSecurityManager::GetCodebasePrincipal(nsIURI *aURI,
    2084                 :                                               nsIPrincipal **result)
    2085                 : {
    2086             217 :     NS_ENSURE_ARG(aURI);
    2087                 :     
    2088                 :     bool inheritsPrincipal;
    2089                 :     nsresult rv =
    2090                 :         NS_URIChainHasFlags(aURI,
    2091                 :                             nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
    2092             217 :                             &inheritsPrincipal);
    2093             217 :     if (NS_FAILED(rv) || inheritsPrincipal) {
    2094              10 :         return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result);
    2095                 :     }
    2096                 :     
    2097             414 :     nsCOMPtr<nsIPrincipal> principal;
    2098             207 :     rv = CreateCodebasePrincipal(aURI, getter_AddRefs(principal));
    2099             207 :     if (NS_FAILED(rv)) return rv;
    2100                 : 
    2101             207 :     if (mPrincipals.Count() > 0)
    2102                 :     {
    2103                 :         //-- Check to see if we already have this principal.
    2104               0 :         nsCOMPtr<nsIPrincipal> fromTable;
    2105               0 :         mPrincipals.Get(principal, getter_AddRefs(fromTable));
    2106               0 :         if (fromTable) {
    2107                 :             // We found an existing codebase principal.  But it might have a
    2108                 :             // generic codebase for this origin on it.  Install our particular
    2109                 :             // codebase.
    2110                 :             // XXXbz this is kinda similar to the code in
    2111                 :             // GetCertificatePrincipal, but just ever so slightly different.
    2112                 :             // Oh, well.
    2113               0 :             nsXPIDLCString prefName;
    2114               0 :             nsXPIDLCString id;
    2115               0 :             nsXPIDLCString subjectName;
    2116               0 :             nsXPIDLCString granted;
    2117               0 :             nsXPIDLCString denied;
    2118                 :             bool isTrusted;
    2119               0 :             rv = fromTable->GetPreferences(getter_Copies(prefName),
    2120               0 :                                            getter_Copies(id),
    2121               0 :                                            getter_Copies(subjectName),
    2122               0 :                                            getter_Copies(granted),
    2123               0 :                                            getter_Copies(denied),
    2124               0 :                                            &isTrusted);
    2125               0 :             if (NS_SUCCEEDED(rv)) {
    2126               0 :                 nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
    2127               0 :                 if (!codebase)
    2128               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2129                 : 
    2130                 :                 rv = codebase->InitFromPersistent(prefName, id,
    2131               0 :                                                   subjectName, EmptyCString(),
    2132                 :                                                   granted, denied,
    2133                 :                                                   nsnull, false,
    2134               0 :                                                   isTrusted);
    2135               0 :                 if (NS_FAILED(rv))
    2136               0 :                     return rv;
    2137                 :                 
    2138               0 :                 codebase->SetURI(aURI);
    2139               0 :                 principal = codebase;
    2140                 :             }
    2141                 : 
    2142                 :         }
    2143                 :     }
    2144                 : 
    2145             207 :     NS_IF_ADDREF(*result = principal);
    2146                 : 
    2147             207 :     return NS_OK;
    2148                 : }
    2149                 : 
    2150                 : NS_IMETHODIMP
    2151               0 : nsScriptSecurityManager::GetPrincipalFromContext(JSContext *cx,
    2152                 :                                                  nsIPrincipal **result)
    2153                 : {
    2154               0 :     *result = nsnull;
    2155                 : 
    2156                 :     nsIScriptContextPrincipal* scp =
    2157               0 :         GetScriptContextPrincipalFromJSContext(cx);
    2158                 : 
    2159               0 :     if (!scp)
    2160                 :     {
    2161               0 :         return NS_ERROR_FAILURE;
    2162                 :     }
    2163                 : 
    2164               0 :     nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
    2165               0 :     if (globalData)
    2166               0 :         NS_IF_ADDREF(*result = globalData->GetPrincipal());
    2167                 : 
    2168               0 :     return NS_OK;
    2169                 : }
    2170                 : 
    2171                 : // static
    2172                 : nsIPrincipal*
    2173          231081 : nsScriptSecurityManager::GetScriptPrincipal(JSContext *cx,
    2174                 :                                             JSScript *script,
    2175                 :                                             nsresult* rv)
    2176                 : {
    2177          231081 :     NS_PRECONDITION(rv, "Null out param");
    2178          231081 :     *rv = NS_OK;
    2179          231081 :     if (!script)
    2180                 :     {
    2181             707 :         return nsnull;
    2182                 :     }
    2183          230374 :     JSPrincipals *jsp = JS_GetScriptPrincipals(cx, script);
    2184          230374 :     if (!jsp) {
    2185               0 :         *rv = NS_ERROR_FAILURE;
    2186               0 :         NS_ERROR("Script compiled without principals!");
    2187               0 :         return nsnull;
    2188                 :     }
    2189          230374 :     return nsJSPrincipals::get(jsp);
    2190                 : }
    2191                 : 
    2192                 : // static
    2193                 : nsIPrincipal*
    2194         1867628 : nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
    2195                 :                                                     JSObject *obj,
    2196                 :                                                     JSStackFrame *fp,
    2197                 :                                                     nsresult *rv)
    2198                 : {
    2199         1867628 :     NS_PRECONDITION(rv, "Null out param");
    2200                 : 
    2201         1867628 :     *rv = NS_OK;
    2202                 : 
    2203         1867628 :     if (!JS_ObjectIsFunction(cx, obj))
    2204                 :     {
    2205                 :         // Protect against pseudo-functions (like SJOWs).
    2206               0 :         nsIPrincipal *result = doGetObjectPrincipal(obj);
    2207               0 :         if (!result)
    2208               0 :             *rv = NS_ERROR_FAILURE;
    2209               0 :         return result;
    2210                 :     }
    2211                 : 
    2212         1867628 :     JSFunction *fun = JS_GetObjectFunction(obj);
    2213         1867628 :     JSScript *script = JS_GetFunctionScript(cx, fun);
    2214                 : 
    2215         1867628 :     if (!script)
    2216                 :     {
    2217                 :         // A native function: skip it in order to find its scripted caller.
    2218               0 :         return nsnull;
    2219                 :     }
    2220                 : 
    2221         1867628 :     JSScript *frameScript = fp ? JS_GetFrameScript(cx, fp) : nsnull;
    2222                 : 
    2223         1867628 :     if (frameScript && frameScript != script)
    2224                 :     {
    2225                 :         // There is a frame script, and it's different from the
    2226                 :         // function script. In this case we're dealing with either
    2227                 :         // an eval or a Script object, and in these cases the
    2228                 :         // principal we want is in the frame's script, not in the
    2229                 :         // function's script. The function's script is where the
    2230                 :         // eval-calling code came from, not where the eval or new
    2231                 :         // Script object came from, and we want the principal of
    2232                 :         // the eval function object or new Script object.
    2233                 : 
    2234               3 :         script = frameScript;
    2235                 :     }
    2236         1867625 :     else if (!js::IsOriginalScriptFunction(fun))
    2237                 :     {
    2238                 :         // Here, obj is a cloned function object.  In this case, the
    2239                 :         // clone's prototype may have been precompiled from brutally
    2240                 :         // shared chrome, or else it is a lambda or nested function.
    2241                 :         // The general case here is a function compiled against a
    2242                 :         // different scope than the one it is parented by at runtime,
    2243                 :         // hence the creation of a clone to carry the correct scope
    2244                 :         // chain linkage.
    2245                 :         //
    2246                 :         // Since principals follow scope, we must get the object
    2247                 :         // principal from the clone's scope chain. There are no
    2248                 :         // reliable principals compiled into the function itself.
    2249                 : 
    2250         1867371 :         nsIPrincipal *result = doGetObjectPrincipal(obj);
    2251         1867371 :         if (!result)
    2252               0 :             *rv = NS_ERROR_FAILURE;
    2253         1867371 :         return result;
    2254                 :     }
    2255                 : 
    2256             257 :     return GetScriptPrincipal(cx, script, rv);
    2257                 : }
    2258                 : 
    2259                 : nsIPrincipal*
    2260         2098452 : nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
    2261                 :                                            JSStackFrame *fp,
    2262                 :                                            nsresult *rv)
    2263                 : {
    2264         2098452 :     NS_PRECONDITION(rv, "Null out param");
    2265         2098452 :     JSObject *obj = JS_GetFrameFunctionObject(cx, fp);
    2266         2098452 :     if (!obj)
    2267                 :     {
    2268                 :         // Must be in a top-level script. Get principal from the script.
    2269          230824 :         JSScript *script = JS_GetFrameScript(cx, fp);
    2270          230824 :         return GetScriptPrincipal(cx, script, rv);
    2271                 :     }
    2272                 : 
    2273         1867628 :     nsIPrincipal* result = GetFunctionObjectPrincipal(cx, obj, fp, rv);
    2274                 : 
    2275                 : #ifdef DEBUG
    2276         1867628 :     if (NS_SUCCEEDED(*rv) && !result)
    2277                 :     {
    2278               0 :         JSFunction *fun = JS_GetObjectFunction(obj);
    2279               0 :         JSScript *script = JS_GetFunctionScript(cx, fun);
    2280                 : 
    2281               0 :         NS_ASSERTION(!script, "Null principal for non-native function!");
    2282                 :     }
    2283                 : #endif
    2284                 : 
    2285         1867628 :     return result;
    2286                 : }
    2287                 : 
    2288                 : nsIPrincipal*
    2289         1687726 : nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
    2290                 :                                               JSStackFrame **frameResult,
    2291                 :                                               nsresult* rv)
    2292                 : {
    2293         1687726 :     NS_PRECONDITION(rv, "Null out param");
    2294                 :     //-- If there's no principal on the stack, look at the global object
    2295                 :     //   and return the innermost frame for annotations.
    2296         1687726 :     *rv = NS_OK;
    2297                 : 
    2298         1687726 :     if (cx)
    2299                 :     {
    2300         1687726 :         JSStackFrame *target = nsnull;
    2301         1687726 :         nsIPrincipal *targetPrincipal = nsnull;
    2302         1747249 :         for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
    2303                 :         {
    2304         1423810 :             if (cp->mCx == cx)
    2305                 :             {
    2306         1364287 :                 target = cp->mFp;
    2307         1364287 :                 targetPrincipal = cp->mPrincipal;
    2308         1364287 :                 break;
    2309                 :             }
    2310                 :         }
    2311                 : 
    2312                 :         // Get principals from innermost JavaScript frame.
    2313         1687726 :         JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
    2314         1688409 :         for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
    2315                 :         {
    2316         1688328 :             if (fp == target)
    2317               4 :                 break;
    2318         1688324 :             nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
    2319         1688324 :             if (result)
    2320                 :             {
    2321         1687641 :                 NS_ASSERTION(NS_SUCCEEDED(*rv), "Weird return");
    2322         1687641 :                 *frameResult = fp;
    2323         1687641 :                 return result;
    2324                 :             }
    2325                 :         }
    2326                 : 
    2327                 :         // If targetPrincipal is non-null, then it means that someone wants to
    2328                 :         // clamp the principals on this context to this principal. Note that
    2329                 :         // fp might not equal target here (fp might be null) because someone
    2330                 :         // could have set aside the frame chain in the meantime.
    2331              85 :         if (targetPrincipal)
    2332                 :         {
    2333              85 :             if (fp && fp == target)
    2334                 :             {
    2335               4 :                 *frameResult = fp;
    2336                 :             }
    2337                 :             else
    2338                 :             {
    2339              81 :                 JSStackFrame *inner = nsnull;
    2340              81 :                 *frameResult = JS_FrameIterator(cx, &inner);
    2341                 :             }
    2342                 : 
    2343              85 :             return targetPrincipal;
    2344                 :         }
    2345                 : 
    2346                 :         nsIScriptContextPrincipal* scp =
    2347               0 :             GetScriptContextPrincipalFromJSContext(cx);
    2348               0 :         if (scp)
    2349                 :         {
    2350               0 :             nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
    2351               0 :             if (!globalData)
    2352                 :             {
    2353               0 :                 *rv = NS_ERROR_FAILURE;
    2354               0 :                 return nsnull;
    2355                 :             }
    2356                 : 
    2357                 :             // Note that we're not in a loop or anything, and nothing comes
    2358                 :             // after this point in the function, so we can just return here.
    2359               0 :             nsIPrincipal* result = globalData->GetPrincipal();
    2360               0 :             if (result)
    2361                 :             {
    2362               0 :                 JSStackFrame *inner = nsnull;
    2363               0 :                 *frameResult = JS_FrameIterator(cx, &inner);
    2364               0 :                 return result;
    2365                 :             }
    2366                 :         }
    2367                 :     }
    2368                 : 
    2369               0 :     return nsnull;
    2370                 : }
    2371                 : 
    2372                 : nsIPrincipal*
    2373         1687135 : nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
    2374                 :                                              nsresult* rv)
    2375                 : {
    2376         1687135 :     NS_PRECONDITION(rv, "Null out param");
    2377                 :     JSStackFrame *fp;
    2378         1687135 :     return GetPrincipalAndFrame(cx, &fp, rv);
    2379                 : }
    2380                 : 
    2381                 : NS_IMETHODIMP
    2382            2170 : nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
    2383                 :                                             nsIPrincipal **result)
    2384                 : {
    2385            2170 :     *result = doGetObjectPrincipal(aObj);
    2386            2170 :     if (!*result)
    2387               0 :         return NS_ERROR_FAILURE;
    2388            2170 :     NS_ADDREF(*result);
    2389            2170 :     return NS_OK;
    2390                 : }
    2391                 : 
    2392                 : // static
    2393                 : nsIPrincipal*
    2394         3739082 : nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
    2395                 : #ifdef DEBUG
    2396                 :                                               , bool aAllowShortCircuit
    2397                 : #endif
    2398                 :                                               )
    2399                 : {
    2400         3739082 :     NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
    2401         3739082 :     nsIPrincipal* result = nsnull;
    2402                 : 
    2403                 : #ifdef DEBUG
    2404         3739082 :     JSObject* origObj = aObj;
    2405                 : #endif
    2406                 :     
    2407         3739082 :     js::Class *jsClass = js::GetObjectClass(aObj);
    2408                 : 
    2409                 :     // A common case seen in this code is that we enter this function
    2410                 :     // with aObj being a Function object, whose parent is a Call
    2411                 :     // object. Neither of those have object principals, so we can skip
    2412                 :     // those objects here before we enter the below loop. That way we
    2413                 :     // avoid wasting time checking properties of their classes etc in
    2414                 :     // the loop.
    2415                 : 
    2416         3739082 :     if (jsClass == &js::FunctionClass) {
    2417         3734742 :         aObj = js::GetObjectParent(aObj);
    2418                 : 
    2419         3734742 :         if (!aObj)
    2420               0 :             return nsnull;
    2421                 : 
    2422         3734742 :         jsClass = js::GetObjectClass(aObj);
    2423                 : 
    2424         3734742 :         if (jsClass == &js::CallClass) {
    2425               0 :             aObj = js::GetObjectParentMaybeScope(aObj);
    2426                 : 
    2427               0 :             if (!aObj)
    2428               0 :                 return nsnull;
    2429                 : 
    2430               0 :             jsClass = js::GetObjectClass(aObj);
    2431                 :         }
    2432                 :     }
    2433                 : 
    2434            5110 :     do {
    2435                 :         // Note: jsClass is set before this loop, and also at the
    2436                 :         // *end* of this loop.
    2437                 :         
    2438         3744192 :         if (IS_WRAPPER_CLASS(jsClass)) {
    2439                 :             result = sXPConnect->GetPrincipal(aObj,
    2440                 : #ifdef DEBUG
    2441                 :                                               aAllowShortCircuit
    2442                 : #else
    2443                 :                                               true
    2444                 : #endif
    2445         3735290 :                                               );
    2446         3735290 :             if (result) {
    2447         3735290 :                 break;
    2448                 :             }
    2449            8902 :         } else if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
    2450            8902 :                                         JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
    2451            3792 :             nsISupports *priv = (nsISupports *) js::GetObjectPrivate(aObj);
    2452                 : 
    2453                 : #ifdef DEBUG
    2454            3792 :             if (aAllowShortCircuit) {
    2455                 :                 nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
    2456            3792 :                     do_QueryInterface(priv);
    2457                 : 
    2458            1896 :                 NS_ASSERTION(!xpcWrapper ||
    2459                 :                              !strcmp(jsClass->name, "XPCNativeWrapper"),
    2460                 :                              "Uh, an nsIXPConnectWrappedNative with the "
    2461                 :                              "wrong JSClass or getObjectOps hooks!");
    2462                 :             }
    2463                 : #endif
    2464                 : 
    2465                 :             nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
    2466            7584 :                 do_QueryInterface(priv);
    2467                 : 
    2468            3792 :             if (objPrin) {
    2469            3792 :                 result = objPrin->GetPrincipal();
    2470                 : 
    2471            3792 :                 if (result) {
    2472                 :                     break;
    2473                 :                 }
    2474                 :             }
    2475                 :         }
    2476                 : 
    2477            5110 :         aObj = js::GetObjectParentMaybeScope(aObj);
    2478                 : 
    2479            5110 :         if (!aObj)
    2480               0 :             break;
    2481                 : 
    2482            5110 :         jsClass = js::GetObjectClass(aObj);
    2483                 :     } while (1);
    2484                 : 
    2485                 : #ifdef DEBUG
    2486         3739082 :     if (aAllowShortCircuit) {
    2487         1869541 :         nsIPrincipal *principal = doGetObjectPrincipal(origObj, false);
    2488                 : 
    2489                 :         // Because of inner window reuse, we can have objects with one principal
    2490                 :         // living in a scope with a different (but same-origin) principal. So
    2491                 :         // just check same-origin here.
    2492         1869541 :         NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
    2493                 :                      "Principal mismatch.  Not good");
    2494                 :     }
    2495                 : #endif
    2496                 : 
    2497         3739082 :     return result;
    2498                 : }
    2499                 : 
    2500                 : nsresult
    2501               0 : nsScriptSecurityManager::SavePrincipal(nsIPrincipal* aToSave)
    2502                 : {
    2503                 :     //-- Save to mPrincipals
    2504               0 :     mPrincipals.Put(aToSave, aToSave);
    2505                 : 
    2506                 :     //-- Save to prefs
    2507               0 :     nsXPIDLCString idPrefName;
    2508               0 :     nsXPIDLCString id;
    2509               0 :     nsXPIDLCString subjectName;
    2510               0 :     nsXPIDLCString grantedList;
    2511               0 :     nsXPIDLCString deniedList;
    2512                 :     bool isTrusted;
    2513               0 :     nsresult rv = aToSave->GetPreferences(getter_Copies(idPrefName),
    2514               0 :                                           getter_Copies(id),
    2515               0 :                                           getter_Copies(subjectName),
    2516               0 :                                           getter_Copies(grantedList),
    2517               0 :                                           getter_Copies(deniedList),
    2518               0 :                                           &isTrusted);
    2519               0 :     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2520                 : 
    2521               0 :     nsCAutoString grantedPrefName;
    2522               0 :     nsCAutoString deniedPrefName;
    2523               0 :     nsCAutoString subjectNamePrefName;
    2524                 :     rv = GetPrincipalPrefNames( idPrefName,
    2525                 :                                 grantedPrefName,
    2526                 :                                 deniedPrefName,
    2527               0 :                                 subjectNamePrefName );
    2528               0 :     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2529                 : 
    2530               0 :     mIsWritingPrefs = true;
    2531               0 :     if (grantedList) {
    2532               0 :         Preferences::SetCString(grantedPrefName.get(), grantedList);
    2533                 :     } else {
    2534               0 :         Preferences::ClearUser(grantedPrefName.get());
    2535                 :     }
    2536                 : 
    2537               0 :     if (deniedList) {
    2538               0 :         Preferences::SetCString(deniedPrefName.get(), deniedList);
    2539                 :     } else {
    2540               0 :         Preferences::ClearUser(deniedPrefName.get());
    2541                 :     }
    2542                 : 
    2543               0 :     if (grantedList || deniedList) {
    2544               0 :         Preferences::SetCString(idPrefName, id);
    2545               0 :         Preferences::SetCString(subjectNamePrefName.get(), subjectName);
    2546                 :     } else {
    2547               0 :         Preferences::ClearUser(idPrefName);
    2548               0 :         Preferences::ClearUser(subjectNamePrefName.get());
    2549                 :     }
    2550                 : 
    2551               0 :     mIsWritingPrefs = false;
    2552                 : 
    2553               0 :     nsIPrefService* prefService = Preferences::GetService();
    2554               0 :     NS_ENSURE_TRUE(prefService, NS_ERROR_FAILURE);
    2555               0 :     return prefService->SavePrefFile(nsnull);
    2556                 : }
    2557                 : 
    2558                 : ///////////////// Capabilities API /////////////////////
    2559                 : NS_IMETHODIMP
    2560          411802 : nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
    2561                 :                                              bool *result)
    2562                 : {
    2563                 :     nsresult rv;
    2564          411802 :     JSStackFrame *fp = nsnull;
    2565          411802 :     JSContext *cx = GetCurrentJSContext();
    2566          411802 :     fp = cx ? JS_FrameIterator(cx, &fp) : nsnull;
    2567                 : 
    2568          411802 :     JSStackFrame *target = nsnull;
    2569          411802 :     nsIPrincipal *targetPrincipal = nsnull;
    2570          429484 :     for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
    2571                 :     {
    2572          358536 :         if (cp->mCx == cx)
    2573                 :         {
    2574          340854 :             target = cp->mFp;
    2575          340854 :             targetPrincipal = cp->mPrincipal;
    2576          340854 :             break;
    2577                 :         }
    2578                 :     }
    2579                 : 
    2580          411802 :     if (!fp)
    2581                 :     {
    2582                 :         // No script code on stack. If we had a principal pushed for this
    2583                 :         // context and fp is null, then we use that principal. Otherwise, we
    2584                 :         // don't have enough information and have to allow execution.
    2585                 : 
    2586                 :         *result = (targetPrincipal && !target)
    2587               0 :                   ? (targetPrincipal == mSystemPrincipal)
    2588            1698 :                   : true;
    2589                 : 
    2590            1698 :         return NS_OK;
    2591                 :     }
    2592                 : 
    2593          410104 :     *result = false;
    2594          410104 :     nsIPrincipal* previousPrincipal = nsnull;
    2595              48 :     do
    2596                 :     {
    2597          410128 :         nsIPrincipal* principal = GetFramePrincipal(cx, fp, &rv);
    2598          410128 :         if (NS_FAILED(rv))
    2599               0 :             return rv;
    2600          410128 :         if (!principal)
    2601              24 :             continue;
    2602                 :         // If caller has a different principal, stop looking up the stack.
    2603          410104 :         if(previousPrincipal)
    2604                 :         {
    2605               0 :             bool isEqual = false;
    2606               0 :             if(NS_FAILED(previousPrincipal->Equals(principal, &isEqual)) || !isEqual)
    2607               0 :                 break;
    2608                 :         }
    2609                 :         else
    2610          410104 :             previousPrincipal = principal;
    2611                 : 
    2612                 :         // First check if the principal is even able to enable the
    2613                 :         // given capability. If not, don't look any further.
    2614                 :         PRInt16 canEnable;
    2615          410104 :         rv = principal->CanEnableCapability(capability, &canEnable);
    2616          410104 :         if (NS_FAILED(rv)) return rv;
    2617          410104 :         if (canEnable != nsIPrincipal::ENABLE_GRANTED &&
    2618                 :             canEnable != nsIPrincipal::ENABLE_WITH_USER_PERMISSION)
    2619               0 :             return NS_OK;
    2620                 : 
    2621                 :         // Now see if the capability is enabled.
    2622          410104 :         void *annotation = JS_GetFrameAnnotation(cx, fp);
    2623          410104 :         rv = principal->IsCapabilityEnabled(capability, annotation, result);
    2624          410104 :         if (NS_FAILED(rv)) return rv;
    2625          410104 :         if (*result)
    2626          410104 :             return NS_OK;
    2627                 : 
    2628                 :         // Capabilities do not extend to calls into C/C++ and then back into
    2629                 :         // the JS engine via JS_EvaluateScript or similar APIs.
    2630               0 :         if (JS_IsGlobalFrame(cx, fp))
    2631               0 :             break;
    2632              24 :     } while (fp != target && (fp = JS_FrameIterator(cx, &fp)) != nsnull);
    2633                 : 
    2634               0 :     if (!previousPrincipal)
    2635                 :     {
    2636                 :         // No principals on the stack, all native code.  Allow
    2637                 :         // execution if the subject principal is the system principal.
    2638                 : 
    2639               0 :         return SubjectPrincipalIsSystem(result);
    2640                 :     }
    2641                 : 
    2642               0 :     return NS_OK;
    2643                 : }
    2644                 : 
    2645                 : void
    2646               0 : nsScriptSecurityManager::FormatCapabilityString(nsAString& aCapability)
    2647                 : {
    2648               0 :     nsAutoString newcaps;
    2649               0 :     nsAutoString rawcap;
    2650               0 :     NS_NAMED_LITERAL_STRING(capdesc, "capdesc.");
    2651                 :     PRInt32 pos;
    2652               0 :     PRInt32 index = kNotFound;
    2653                 :     nsresult rv;
    2654                 : 
    2655                 :     NS_ASSERTION(kNotFound == -1, "Basic constant changed, algorithm broken!");
    2656                 : 
    2657               0 :     do {
    2658               0 :         pos = index+1;
    2659               0 :         index = aCapability.FindChar(' ', pos);
    2660                 :         rawcap = Substring(aCapability, pos,
    2661               0 :                            (index == kNotFound) ? index : index - pos);
    2662                 : 
    2663               0 :         nsXPIDLString capstr;
    2664                 :         rv = sStrBundle->GetStringFromName(
    2665               0 :                             nsPromiseFlatString(capdesc+rawcap).get(),
    2666               0 :                             getter_Copies(capstr));
    2667               0 :         if (NS_SUCCEEDED(rv))
    2668               0 :             newcaps += capstr;
    2669                 :         else
    2670                 :         {
    2671               0 :             nsXPIDLString extensionCap;
    2672               0 :             const PRUnichar* formatArgs[] = { rawcap.get() };
    2673                 :             rv = sStrBundle->FormatStringFromName(
    2674               0 :                                 NS_LITERAL_STRING("ExtensionCapability").get(),
    2675                 :                                 formatArgs,
    2676                 :                                 ArrayLength(formatArgs),
    2677               0 :                                 getter_Copies(extensionCap));
    2678               0 :             if (NS_SUCCEEDED(rv))
    2679               0 :                 newcaps += extensionCap;
    2680                 :             else
    2681               0 :                 newcaps += rawcap;
    2682                 :         }
    2683                 : 
    2684               0 :         newcaps += NS_LITERAL_STRING("\n");
    2685                 :     } while (index != kNotFound);
    2686                 : 
    2687               0 :     aCapability = newcaps;
    2688               0 : }
    2689                 : 
    2690                 : bool
    2691               0 : nsScriptSecurityManager::CheckConfirmDialog(JSContext* cx, nsIPrincipal* aPrincipal,
    2692                 :                                             const char* aCapability, bool *checkValue)
    2693                 : {
    2694                 :     nsresult rv;
    2695               0 :     *checkValue = false;
    2696                 : 
    2697                 :     //-- Get a prompter for the current window.
    2698               0 :     nsCOMPtr<nsIPrompt> prompter;
    2699               0 :     if (cx)
    2700                 :     {
    2701               0 :         nsIScriptContext *scriptContext = GetScriptContext(cx);
    2702               0 :         if (scriptContext)
    2703                 :         {
    2704                 :             nsCOMPtr<nsIDOMWindow> domWin =
    2705               0 :                 do_QueryInterface(scriptContext->GetGlobalObject());
    2706               0 :             if (domWin)
    2707               0 :                 domWin->GetPrompter(getter_AddRefs(prompter));
    2708                 :         }
    2709                 :     }
    2710                 : 
    2711               0 :     if (!prompter)
    2712                 :     {
    2713                 :         //-- Couldn't get prompter from the current window, so get the prompt service.
    2714               0 :         nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
    2715               0 :         if (wwatch)
    2716               0 :           wwatch->GetNewPrompter(0, getter_AddRefs(prompter));
    2717               0 :         if (!prompter)
    2718               0 :             return false;
    2719                 :     }
    2720                 : 
    2721                 :     //-- Localize the dialog text
    2722               0 :     nsXPIDLString check;
    2723               0 :     rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("CheckMessage").get(),
    2724               0 :                                        getter_Copies(check));
    2725               0 :     if (NS_FAILED(rv))
    2726               0 :         return false;
    2727                 : 
    2728               0 :     nsXPIDLString title;
    2729               0 :     rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("Titleline").get(),
    2730               0 :                                        getter_Copies(title));
    2731               0 :     if (NS_FAILED(rv))
    2732               0 :         return false;
    2733                 : 
    2734               0 :     nsXPIDLString yesStr;
    2735               0 :     rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("Yes").get(),
    2736               0 :                                        getter_Copies(yesStr));
    2737               0 :     if (NS_FAILED(rv))
    2738               0 :         return false;
    2739                 : 
    2740               0 :     nsXPIDLString noStr;
    2741               0 :     rv = sStrBundle->GetStringFromName(NS_LITERAL_STRING("No").get(),
    2742               0 :                                        getter_Copies(noStr));
    2743               0 :     if (NS_FAILED(rv))
    2744               0 :         return false;
    2745                 : 
    2746               0 :     nsCAutoString val;
    2747                 :     bool hasCert;
    2748               0 :     aPrincipal->GetHasCertificate(&hasCert);
    2749               0 :     if (hasCert)
    2750               0 :         rv = aPrincipal->GetPrettyName(val);
    2751                 :     else
    2752               0 :         rv = GetPrincipalDomainOrigin(aPrincipal, val);
    2753                 : 
    2754               0 :     if (NS_FAILED(rv))
    2755               0 :         return false;
    2756                 : 
    2757               0 :     NS_ConvertUTF8toUTF16 location(val);
    2758               0 :     NS_ConvertASCIItoUTF16 capability(aCapability);
    2759               0 :     FormatCapabilityString(capability);
    2760               0 :     const PRUnichar *formatStrings[] = { location.get(), capability.get() };
    2761                 : 
    2762               0 :     nsXPIDLString message;
    2763               0 :     rv = sStrBundle->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityQuery").get(),
    2764                 :                                           formatStrings,
    2765                 :                                           ArrayLength(formatStrings),
    2766               0 :                                           getter_Copies(message));
    2767               0 :     if (NS_FAILED(rv))
    2768               0 :         return false;
    2769                 : 
    2770               0 :     PRInt32 buttonPressed = 1; // If the user exits by clicking the close box, assume No (button 1)
    2771               0 :     rv = prompter->ConfirmEx(title.get(), message.get(),
    2772                 :                              (nsIPrompt::BUTTON_DELAY_ENABLE) +
    2773                 :                              (nsIPrompt::BUTTON_POS_1_DEFAULT) +
    2774                 :                              (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) +
    2775                 :                              (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_1),
    2776               0 :                              yesStr.get(), noStr.get(), nsnull, check.get(), checkValue, &buttonPressed);
    2777                 : 
    2778               0 :     if (NS_FAILED(rv))
    2779               0 :         *checkValue = false;
    2780               0 :     return (buttonPressed == 0);
    2781                 : }
    2782                 : 
    2783                 : NS_IMETHODIMP
    2784               0 : nsScriptSecurityManager::RequestCapability(nsIPrincipal* aPrincipal,
    2785                 :                                            const char *capability, PRInt16* canEnable)
    2786                 : {
    2787               0 :     if (NS_FAILED(aPrincipal->CanEnableCapability(capability, canEnable)))
    2788               0 :         return NS_ERROR_FAILURE;
    2789               0 :     if (*canEnable == nsIPrincipal::ENABLE_WITH_USER_PERMISSION)
    2790                 :     {
    2791                 :         // Prompt user for permission to enable capability.
    2792               0 :         JSContext* cx = GetCurrentJSContext();
    2793                 :         // The actual value is irrelevant but we shouldn't be handing out
    2794                 :         // malformed JSBools to XPConnect.
    2795               0 :         bool remember = false;
    2796               0 :         if (CheckConfirmDialog(cx, aPrincipal, capability, &remember))
    2797               0 :             *canEnable = nsIPrincipal::ENABLE_GRANTED;
    2798                 :         else
    2799               0 :             *canEnable = nsIPrincipal::ENABLE_DENIED;
    2800               0 :         if (remember)
    2801                 :         {
    2802                 :             //-- Save principal to prefs and to mPrincipals
    2803               0 :             if (NS_FAILED(aPrincipal->SetCanEnableCapability(capability, *canEnable)))
    2804               0 :                 return NS_ERROR_FAILURE;
    2805               0 :             if (NS_FAILED(SavePrincipal(aPrincipal)))
    2806               0 :                 return NS_ERROR_FAILURE;
    2807                 :         }
    2808                 :     }
    2809               0 :     return NS_OK;
    2810                 : }
    2811                 : 
    2812                 : NS_IMETHODIMP
    2813               0 : nsScriptSecurityManager::EnableCapability(const char *capability)
    2814                 : {
    2815               0 :     JSContext *cx = GetCurrentJSContext();
    2816                 :     JSStackFrame *fp;
    2817                 : 
    2818                 :     //-- Error checks for capability string length (200)
    2819               0 :     if(PL_strlen(capability)>200)
    2820                 :     {
    2821                 :         static const char msg[] = "Capability name too long";
    2822               0 :         SetPendingException(cx, msg);
    2823               0 :         return NS_ERROR_FAILURE;
    2824                 :     }
    2825                 : 
    2826                 :     //-- Check capability string for valid characters
    2827                 :     //
    2828                 :     //   Logically we might have wanted this in nsPrincipal, but performance
    2829                 :     //   worries dictate it can't go in IsCapabilityEnabled() and we may have
    2830                 :     //   to show the capability on a dialog before we call the principal's
    2831                 :     //   EnableCapability().
    2832                 :     //
    2833                 :     //   We don't need to validate the capability string on the other APIs
    2834                 :     //   available to web content. Without the ability to enable junk then
    2835                 :     //   isPrivilegeEnabled, disablePrivilege, and revertPrivilege all do
    2836                 :     //   the right thing (effectively nothing) when passed unallowed chars.
    2837               0 :     for (const char *ch = capability; *ch; ++ch)
    2838                 :     {
    2839               0 :         if (!NS_IS_ALPHA(*ch) && *ch != ' ' && !NS_IS_DIGIT(*ch)
    2840                 :             && *ch != '_' && *ch != '-' && *ch != '.')
    2841                 :         {
    2842                 :             static const char msg[] = "Invalid character in capability name";
    2843               0 :             SetPendingException(cx, msg);
    2844               0 :             return NS_ERROR_FAILURE;
    2845                 :         }
    2846                 :     }
    2847                 : 
    2848                 :     nsresult rv;
    2849               0 :     nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
    2850               0 :     if (NS_FAILED(rv))
    2851               0 :         return rv;
    2852               0 :     if (!principal)
    2853               0 :         return NS_ERROR_NOT_AVAILABLE;
    2854                 : 
    2855               0 :     void *annotation = JS_GetFrameAnnotation(cx, fp);
    2856                 :     bool enabled;
    2857               0 :     if (NS_FAILED(principal->IsCapabilityEnabled(capability, annotation,
    2858                 :                                                  &enabled)))
    2859               0 :         return NS_ERROR_FAILURE;
    2860               0 :     if (enabled)
    2861               0 :         return NS_OK;
    2862                 : 
    2863                 :     PRInt16 canEnable;
    2864               0 :     if (NS_FAILED(RequestCapability(principal, capability, &canEnable)))
    2865               0 :         return NS_ERROR_FAILURE;
    2866                 : 
    2867               0 :     if (canEnable != nsIPrincipal::ENABLE_GRANTED)
    2868                 :     {
    2869               0 :         nsCAutoString val;
    2870                 :         bool hasCert;
    2871                 :         nsresult rv;
    2872               0 :         principal->GetHasCertificate(&hasCert);
    2873               0 :         if (hasCert)
    2874               0 :             rv = principal->GetPrettyName(val);
    2875                 :         else
    2876               0 :             rv = GetPrincipalDomainOrigin(principal, val);
    2877                 : 
    2878               0 :         if (NS_FAILED(rv))
    2879               0 :             return rv;
    2880                 : 
    2881               0 :         NS_ConvertUTF8toUTF16 location(val);
    2882               0 :         NS_ConvertUTF8toUTF16 cap(capability);
    2883               0 :         const PRUnichar *formatStrings[] = { location.get(), cap.get() };
    2884                 : 
    2885               0 :         nsXPIDLString message;
    2886               0 :         rv = sStrBundle->FormatStringFromName(NS_LITERAL_STRING("EnableCapabilityDenied").get(),
    2887                 :                                               formatStrings,
    2888                 :                                               ArrayLength(formatStrings),
    2889               0 :                                               getter_Copies(message));
    2890               0 :         if (NS_FAILED(rv))
    2891               0 :             return rv;
    2892                 : 
    2893               0 :         SetPendingException(cx, message.get());
    2894                 : 
    2895               0 :         return NS_ERROR_FAILURE; // XXX better error code?
    2896                 :     }
    2897               0 :     if (NS_FAILED(principal->EnableCapability(capability, &annotation)))
    2898               0 :         return NS_ERROR_FAILURE;
    2899               0 :     JS_SetFrameAnnotation(cx, fp, annotation);
    2900               0 :     return NS_OK;
    2901                 : }
    2902                 : 
    2903                 : NS_IMETHODIMP
    2904               0 : nsScriptSecurityManager::RevertCapability(const char *capability)
    2905                 : {
    2906               0 :     JSContext *cx = GetCurrentJSContext();
    2907                 :     JSStackFrame *fp;
    2908                 :     nsresult rv;
    2909               0 :     nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
    2910               0 :     if (NS_FAILED(rv))
    2911               0 :         return rv;
    2912               0 :     if (!principal)
    2913               0 :         return NS_ERROR_NOT_AVAILABLE;
    2914               0 :     void *annotation = JS_GetFrameAnnotation(cx, fp);
    2915               0 :     principal->RevertCapability(capability, &annotation);
    2916               0 :     JS_SetFrameAnnotation(cx, fp, annotation);
    2917               0 :     return NS_OK;
    2918                 : }
    2919                 : 
    2920                 : NS_IMETHODIMP
    2921               0 : nsScriptSecurityManager::DisableCapability(const char *capability)
    2922                 : {
    2923               0 :     JSContext *cx = GetCurrentJSContext();
    2924                 :     JSStackFrame *fp;
    2925                 :     nsresult rv;
    2926               0 :     nsIPrincipal* principal = GetPrincipalAndFrame(cx, &fp, &rv);
    2927               0 :     if (NS_FAILED(rv))
    2928               0 :         return rv;
    2929               0 :     if (!principal)
    2930               0 :         return NS_ERROR_NOT_AVAILABLE;
    2931               0 :     void *annotation = JS_GetFrameAnnotation(cx, fp);
    2932               0 :     principal->DisableCapability(capability, &annotation);
    2933               0 :     JS_SetFrameAnnotation(cx, fp, annotation);
    2934               0 :     return NS_OK;
    2935                 : }
    2936                 : 
    2937                 : //////////////// Master Certificate Functions ///////////////////////////////////////
    2938                 : NS_IMETHODIMP
    2939               0 : nsScriptSecurityManager::SetCanEnableCapability(const nsACString& certFingerprint,
    2940                 :                                                 const char* capability,
    2941                 :                                                 PRInt16 canEnable)
    2942                 : {
    2943               0 :     NS_ENSURE_ARG(!certFingerprint.IsEmpty());
    2944                 :     
    2945                 :     nsresult rv;
    2946               0 :     nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv);
    2947               0 :     if (NS_FAILED(rv))
    2948               0 :         return rv;
    2949                 : 
    2950                 :     //-- Get the system certificate
    2951               0 :     if (!mSystemCertificate)
    2952                 :     {
    2953               0 :         nsCOMPtr<nsIFile> systemCertFile;
    2954                 :         nsCOMPtr<nsIProperties> directoryService =
    2955               0 :                  do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
    2956               0 :         if (!directoryService) return NS_ERROR_FAILURE;
    2957               0 :         rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile),
    2958               0 :                               getter_AddRefs(systemCertFile));
    2959               0 :         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2960               0 :         systemCertFile->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
    2961               0 :         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2962               0 :         nsCOMPtr<nsIZipReader> systemCertZip = do_CreateInstance(kZipReaderCID, &rv);
    2963               0 :         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2964               0 :         rv = systemCertZip->Open(systemCertFile);
    2965               0 :         if (NS_SUCCEEDED(rv))
    2966                 :         {
    2967               0 :             rv = systemCertZip->GetCertificatePrincipal(EmptyCString(),
    2968               0 :                                                         getter_AddRefs(mSystemCertificate));
    2969               0 :             if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2970                 :         }
    2971                 :     }
    2972                 : 
    2973                 :     //-- Make sure the caller's principal is the system certificate
    2974               0 :     bool isEqual = false;
    2975               0 :     if (mSystemCertificate)
    2976                 :     {
    2977               0 :         rv = mSystemCertificate->Equals(subjectPrincipal, &isEqual);
    2978               0 :         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2979                 :     }
    2980               0 :     if (!isEqual)
    2981                 :     {
    2982               0 :         JSContext* cx = GetCurrentJSContext();
    2983               0 :         if (!cx) return NS_ERROR_FAILURE;
    2984                 :         static const char msg1[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate";
    2985                 :         static const char msg2[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established";
    2986               0 :         SetPendingException(cx, mSystemCertificate ? msg1 : msg2);
    2987               0 :         return NS_ERROR_FAILURE;
    2988                 :     }
    2989                 : 
    2990                 :     //-- Get the target principal
    2991               0 :     nsCOMPtr<nsIPrincipal> objectPrincipal;
    2992               0 :     rv = DoGetCertificatePrincipal(certFingerprint, EmptyCString(),
    2993               0 :                                    EmptyCString(), nsnull,
    2994                 :                                    nsnull, false,
    2995               0 :                                    getter_AddRefs(objectPrincipal));
    2996               0 :     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2997               0 :     rv = objectPrincipal->SetCanEnableCapability(capability, canEnable);
    2998               0 :     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
    2999               0 :     return SavePrincipal(objectPrincipal);
    3000                 : }
    3001                 : 
    3002                 : ////////////////////////////////////////////////
    3003                 : // Methods implementing nsIXPCSecurityManager //
    3004                 : ////////////////////////////////////////////////
    3005                 : 
    3006                 : NS_IMETHODIMP
    3007          343427 : nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
    3008                 :                                           const nsIID &aIID,
    3009                 :                                           nsISupports *aObj,
    3010                 :                                           nsIClassInfo *aClassInfo,
    3011                 :                                           void **aPolicy)
    3012                 : {
    3013                 : #ifdef DEBUG_CAPS_CanCreateWrapper
    3014                 :     char* iidStr = aIID.ToString();
    3015                 :     printf("### CanCreateWrapper(%s) ", iidStr);
    3016                 :     NS_Free(iidStr);
    3017                 : #endif
    3018                 : // XXX Special case for nsIXPCException ?
    3019          686854 :     ClassInfoData objClassInfo = ClassInfoData(aClassInfo, nsnull);
    3020          343427 :     if (objClassInfo.IsDOMClass())
    3021                 :     {
    3022                 : #ifdef DEBUG_CAPS_CanCreateWrapper
    3023                 :         printf("DOM class - GRANTED.\n");
    3024                 : #endif
    3025            1934 :         return NS_OK;
    3026                 :     }
    3027                 : 
    3028                 :     //--See if the object advertises a non-default level of access
    3029                 :     //  using nsISecurityCheckedComponent
    3030                 :     nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
    3031          682986 :         do_QueryInterface(aObj);
    3032                 : 
    3033          682986 :     nsXPIDLCString objectSecurityLevel;
    3034          341493 :     if (checkedComponent)
    3035           46803 :         checkedComponent->CanCreateWrapper((nsIID *)&aIID, getter_Copies(objectSecurityLevel));
    3036                 : 
    3037          341493 :     nsresult rv = CheckXPCPermissions(cx, aObj, nsnull, nsnull, objectSecurityLevel);
    3038          341493 :     if (NS_FAILED(rv))
    3039                 :     {
    3040                 :         //-- Access denied, report an error
    3041               0 :         NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied");
    3042               0 :         nsCAutoString origin;
    3043                 :         nsresult rv2;
    3044               0 :         nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2);
    3045               0 :         if (NS_SUCCEEDED(rv2) && subjectPrincipal) {
    3046               0 :             GetPrincipalDomainOrigin(subjectPrincipal, origin);
    3047                 :         }
    3048               0 :         NS_ConvertUTF8toUTF16 originUnicode(origin);
    3049               0 :         NS_ConvertUTF8toUTF16 className(objClassInfo.GetName());
    3050                 :         const PRUnichar* formatStrings[] = {
    3051               0 :             className.get(),
    3052               0 :             originUnicode.get()
    3053               0 :         };
    3054               0 :         PRUint32 length = ArrayLength(formatStrings);
    3055               0 :         if (originUnicode.IsEmpty()) {
    3056               0 :             --length;
    3057                 :         } else {
    3058               0 :             strName.AppendLiteral("ForOrigin");
    3059                 :         }
    3060               0 :         nsXPIDLString errorMsg;
    3061                 :         // We need to keep our existing failure rv and not override it
    3062                 :         // with a likely success code from the following string bundle
    3063                 :         // call in order to throw the correct security exception later.
    3064                 :         rv2 = sStrBundle->FormatStringFromName(strName.get(),
    3065                 :                                                formatStrings,
    3066                 :                                                length,
    3067               0 :                                                getter_Copies(errorMsg));
    3068               0 :         NS_ENSURE_SUCCESS(rv2, rv2);
    3069                 : 
    3070               0 :         SetPendingException(cx, errorMsg.get());
    3071                 : 
    3072                 : #ifdef DEBUG_CAPS_CanCreateWrapper
    3073                 :         printf("DENIED.\n");
    3074                 :     }
    3075                 :     else
    3076                 :     {
    3077                 :         printf("GRANTED.\n");
    3078                 : #endif
    3079                 :     }
    3080                 : 
    3081          341493 :     return rv;
    3082                 : }
    3083                 : 
    3084                 : NS_IMETHODIMP
    3085           50617 : nsScriptSecurityManager::CanCreateInstance(JSContext *cx,
    3086                 :                                            const nsCID &aCID)
    3087                 : {
    3088                 : #ifdef DEBUG_CAPS_CanCreateInstance
    3089                 :     char* cidStr = aCID.ToString();
    3090                 :     printf("### CanCreateInstance(%s) ", cidStr);
    3091                 :     NS_Free(cidStr);
    3092                 : #endif
    3093                 : 
    3094           50617 :     nsresult rv = CheckXPCPermissions(nsnull, nsnull, nsnull, nsnull, nsnull);
    3095           50617 :     if (NS_FAILED(rv))
    3096                 :     {
    3097                 :         //-- Access denied, report an error
    3098               0 :         nsCAutoString errorMsg("Permission denied to create instance of class. CID=");
    3099                 :         char cidStr[NSID_LENGTH];
    3100               0 :         aCID.ToProvidedString(cidStr);
    3101               0 :         errorMsg.Append(cidStr);
    3102               0 :         SetPendingException(cx, errorMsg.get());
    3103                 : 
    3104                 : #ifdef DEBUG_CAPS_CanCreateInstance
    3105                 :         printf("DENIED\n");
    3106                 :     }
    3107                 :     else
    3108                 :     {
    3109                 :         printf("GRANTED\n");
    3110                 : #endif
    3111                 :     }
    3112           50617 :     return rv;
    3113                 : }
    3114                 : 
    3115                 : NS_IMETHODIMP
    3116               0 : nsScriptSecurityManager::CanGetService(JSContext *cx,
    3117                 :                                        const nsCID &aCID)
    3118                 : {
    3119                 : #ifdef DEBUG_CAPS_CanGetService
    3120                 :     char* cidStr = aCID.ToString();
    3121                 :     printf("### CanGetService(%s) ", cidStr);
    3122                 :     NS_Free(cidStr);
    3123                 : #endif
    3124                 : 
    3125               0 :     nsresult rv = CheckXPCPermissions(nsnull, nsnull, nsnull, nsnull, nsnull);
    3126               0 :     if (NS_FAILED(rv))
    3127                 :     {
    3128                 :         //-- Access denied, report an error
    3129               0 :         nsCAutoString errorMsg("Permission denied to get service. CID=");
    3130                 :         char cidStr[NSID_LENGTH];
    3131               0 :         aCID.ToProvidedString(cidStr);
    3132               0 :         errorMsg.Append(cidStr);
    3133               0 :         SetPendingException(cx, errorMsg.get());
    3134                 : 
    3135                 : #ifdef DEBUG_CAPS_CanGetService
    3136                 :         printf("DENIED\n");
    3137                 :     }
    3138                 :     else
    3139                 :     {
    3140                 :         printf("GRANTED\n");
    3141                 : #endif
    3142                 :     }
    3143                 : 
    3144               0 :     return rv;
    3145                 : }
    3146                 : 
    3147                 : 
    3148                 : NS_IMETHODIMP
    3149         1242855 : nsScriptSecurityManager::CanAccess(PRUint32 aAction,
    3150                 :                                    nsAXPCNativeCallContext* aCallContext,
    3151                 :                                    JSContext* cx,
    3152                 :                                    JSObject* aJSObject,
    3153                 :                                    nsISupports* aObj,
    3154                 :                                    nsIClassInfo* aClassInfo,
    3155                 :                                    jsid aPropertyName,
    3156                 :                                    void** aPolicy)
    3157                 : {
    3158                 :     return CheckPropertyAccessImpl(aAction, aCallContext, cx,
    3159                 :                                    aJSObject, aObj, nsnull, aClassInfo,
    3160         1242855 :                                    nsnull, aPropertyName, aPolicy);
    3161                 : }
    3162                 : 
    3163                 : nsresult
    3164          392110 : nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
    3165                 :                                              nsISupports* aObj, JSObject* aJSObject,
    3166                 :                                              nsIPrincipal* aSubjectPrincipal,
    3167                 :                                              const char* aObjectSecurityLevel)
    3168                 : {
    3169                 :     //-- Check for the all-powerful UniversalXPConnect privilege
    3170          392110 :     bool ok = false;
    3171          392110 :     if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalXPConnect", &ok)) && ok)
    3172          392110 :         return NS_OK;
    3173                 : 
    3174                 :     //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
    3175               0 :     if (aObjectSecurityLevel)
    3176                 :     {
    3177               0 :         if (PL_strcasecmp(aObjectSecurityLevel, "allAccess") == 0)
    3178               0 :             return NS_OK;
    3179               0 :         if (cx && PL_strcasecmp(aObjectSecurityLevel, "sameOrigin") == 0)
    3180                 :         {
    3181                 :             nsresult rv;
    3182               0 :             if (!aJSObject)
    3183                 :             {
    3184                 :                 nsCOMPtr<nsIXPConnectWrappedJS> xpcwrappedjs =
    3185               0 :                     do_QueryInterface(aObj);
    3186               0 :                 if (xpcwrappedjs)
    3187                 :                 {
    3188               0 :                     rv = xpcwrappedjs->GetJSObject(&aJSObject);
    3189               0 :                     NS_ENSURE_SUCCESS(rv, rv);
    3190                 :                 }
    3191                 :             }
    3192                 : 
    3193               0 :             if (!aSubjectPrincipal)
    3194                 :             {
    3195                 :                 // No subject principal passed in. Compute it.
    3196               0 :                 aSubjectPrincipal = GetSubjectPrincipal(cx, &rv);
    3197               0 :                 NS_ENSURE_SUCCESS(rv, rv);
    3198                 :             }
    3199               0 :             if (aSubjectPrincipal && aJSObject)
    3200                 :             {
    3201               0 :                 nsIPrincipal* objectPrincipal = doGetObjectPrincipal(aJSObject);
    3202                 : 
    3203                 :                 // Only do anything if we have both a subject and object
    3204                 :                 // principal.
    3205               0 :                 if (objectPrincipal)
    3206                 :                 {
    3207                 :                     bool subsumes;
    3208               0 :                     rv = aSubjectPrincipal->Subsumes(objectPrincipal, &subsumes);
    3209               0 :                     NS_ENSURE_SUCCESS(rv, rv);
    3210               0 :                     if (subsumes)
    3211               0 :                         return NS_OK;
    3212                 :                 }
    3213                 :             }
    3214                 :         }
    3215               0 :         else if (PL_strcasecmp(aObjectSecurityLevel, "noAccess") != 0)
    3216                 :         {
    3217               0 :             bool canAccess = false;
    3218               0 :             if (NS_SUCCEEDED(IsCapabilityEnabled(aObjectSecurityLevel, &canAccess)) &&
    3219                 :                 canAccess)
    3220               0 :                 return NS_OK;
    3221                 :         }
    3222                 :     }
    3223                 : 
    3224                 :     //-- Access tests failed
    3225               0 :     return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
    3226                 : }
    3227                 : 
    3228                 : /////////////////////////////////////////////
    3229                 : // Method implementing nsIChannelEventSink //
    3230                 : /////////////////////////////////////////////
    3231                 : NS_IMETHODIMP
    3232             155 : nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel, 
    3233                 :                                                 nsIChannel* newChannel,
    3234                 :                                                 PRUint32 redirFlags,
    3235                 :                                                 nsIAsyncVerifyRedirectCallback *cb)
    3236                 : {
    3237             310 :     nsCOMPtr<nsIPrincipal> oldPrincipal;
    3238             155 :     GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
    3239                 : 
    3240             310 :     nsCOMPtr<nsIURI> newURI;
    3241             155 :     newChannel->GetURI(getter_AddRefs(newURI));
    3242             310 :     nsCOMPtr<nsIURI> newOriginalURI;
    3243             155 :     newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
    3244                 : 
    3245             155 :     NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
    3246                 : 
    3247                 :     const PRUint32 flags =
    3248                 :         nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
    3249             155 :         nsIScriptSecurityManager::DISALLOW_SCRIPT;
    3250             155 :     nsresult rv = CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
    3251             155 :     if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
    3252               0 :         rv = CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
    3253                 :     }
    3254                 : 
    3255             155 :     if (NS_FAILED(rv))
    3256               2 :         return rv;
    3257                 : 
    3258             153 :     cb->OnRedirectVerifyCallback(NS_OK);
    3259             153 :     return NS_OK;
    3260                 : }
    3261                 : 
    3262                 : 
    3263                 : /////////////////////////////////////
    3264                 : // Method implementing nsIObserver //
    3265                 : /////////////////////////////////////
    3266                 : const char sJSEnabledPrefName[] = "javascript.enabled";
    3267                 : const char sFileOriginPolicyPrefName[] =
    3268                 :     "security.fileuri.strict_origin_policy";
    3269                 : static const char sPrincipalPrefix[] = "capability.principal";
    3270                 : static const char sPolicyPrefix[] = "capability.policy.";
    3271                 : 
    3272                 : static const char* kObservedPrefs[] = {
    3273                 :   sJSEnabledPrefName,
    3274                 :   sFileOriginPolicyPrefName,
    3275                 :   sPolicyPrefix,
    3276                 :   sPrincipalPrefix,
    3277                 :   nsnull
    3278                 : };
    3279                 : 
    3280                 : 
    3281                 : NS_IMETHODIMP
    3282             154 : nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic,
    3283                 :                                  const PRUnichar* aMessage)
    3284                 : {
    3285             154 :     nsresult rv = NS_OK;
    3286             308 :     NS_ConvertUTF16toUTF8 messageStr(aMessage);
    3287             154 :     const char *message = messageStr.get();
    3288                 : 
    3289                 :     static const char jsPrefix[] = "javascript.";
    3290                 :     static const char securityPrefix[] = "security.";
    3291             307 :     if ((PL_strncmp(message, jsPrefix, sizeof(jsPrefix)-1) == 0) ||
    3292             153 :         (PL_strncmp(message, securityPrefix, sizeof(securityPrefix)-1) == 0) )
    3293                 :     {
    3294               2 :         ScriptSecurityPrefChanged();
    3295                 :     }
    3296             152 :     else if (PL_strncmp(message, sPolicyPrefix, sizeof(sPolicyPrefix)-1) == 0)
    3297                 :     {
    3298                 :         // This will force re-initialization of the pref table
    3299             152 :         mPolicyPrefsChanged = true;
    3300                 :     }
    3301               0 :     else if ((PL_strncmp(message, sPrincipalPrefix, sizeof(sPrincipalPrefix)-1) == 0) &&
    3302               0 :              !mIsWritingPrefs)
    3303                 :     {
    3304                 :         static const char id[] = "id";
    3305               0 :         char* lastDot = PL_strrchr(message, '.');
    3306                 :         //-- This check makes sure the string copy below doesn't overwrite its bounds
    3307               0 :         if(PL_strlen(lastDot) >= sizeof(id))
    3308                 :         {
    3309               0 :             PL_strcpy(lastDot + 1, id);
    3310               0 :             const char** idPrefArray = (const char**)&message;
    3311               0 :             rv = InitPrincipals(1, idPrefArray);
    3312                 :         }
    3313                 :     }
    3314             154 :     return rv;
    3315                 : }
    3316                 : 
    3317                 : /////////////////////////////////////////////
    3318                 : // Constructor, Destructor, Initialization //
    3319                 : /////////////////////////////////////////////
    3320            1404 : nsScriptSecurityManager::nsScriptSecurityManager(void)
    3321                 :     : mOriginToPolicyMap(nsnull),
    3322                 :       mDefaultPolicy(nsnull),
    3323                 :       mCapabilities(nsnull),
    3324                 :       mContextPrincipals(nsnull),
    3325                 :       mPrefInitialized(false),
    3326                 :       mIsJavaScriptEnabled(false),
    3327                 :       mIsWritingPrefs(false),
    3328            1404 :       mPolicyPrefsChanged(true)
    3329                 : {
    3330                 :     NS_ASSERTION(sizeof(PRWord) == sizeof(void*),
    3331                 :                  "PRWord and void* have different lengths on this platform. "
    3332                 :                  "This may cause a security failure with the SecurityLevel union.");
    3333            1404 :     mPrincipals.Init(31);
    3334            1404 : }
    3335                 : 
    3336            1404 : nsresult nsScriptSecurityManager::Init()
    3337                 : {
    3338            1404 :     nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
    3339            1404 :      if (!xpconnect)
    3340               0 :         return NS_ERROR_FAILURE;
    3341                 : 
    3342            1404 :     NS_ADDREF(sXPConnect = xpconnect);
    3343            1404 :     NS_ADDREF(sJSContextStack = xpconnect);
    3344                 : 
    3345            1404 :     JSContext* cx = GetSafeJSContext();
    3346            1404 :     if (!cx) return NS_ERROR_FAILURE;   // this can happen of xpt loading fails
    3347                 :     
    3348            1404 :     ::JS_BeginRequest(cx);
    3349            1404 :     if (sEnabledID == JSID_VOID)
    3350            1404 :         sEnabledID = INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "enabled"));
    3351            1404 :     ::JS_EndRequest(cx);
    3352                 : 
    3353            1404 :     InitPrefs();
    3354                 : 
    3355            1404 :     nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
    3356            1404 :     NS_ENSURE_SUCCESS(rv, rv);
    3357                 : 
    3358                 :     nsCOMPtr<nsIStringBundleService> bundleService =
    3359            2808 :         mozilla::services::GetStringBundleService();
    3360            1404 :     if (!bundleService)
    3361               0 :         return NS_ERROR_FAILURE;
    3362                 : 
    3363            1404 :     rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle);
    3364            1404 :     NS_ENSURE_SUCCESS(rv, rv);
    3365                 : 
    3366                 :     // Create our system principal singleton
    3367            2808 :     nsRefPtr<nsSystemPrincipal> system = new nsSystemPrincipal();
    3368            1404 :     NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY);
    3369                 : 
    3370            1404 :     mSystemPrincipal = system;
    3371                 : 
    3372                 :     //-- Register security check callback in the JS engine
    3373                 :     //   Currently this is used to control access to function.caller
    3374                 :     nsCOMPtr<nsIJSRuntimeService> runtimeService =
    3375            2808 :         do_QueryInterface(sXPConnect, &rv);
    3376            1404 :     NS_ENSURE_SUCCESS(rv, rv);
    3377                 : 
    3378            1404 :     rv = runtimeService->GetRuntime(&sRuntime);
    3379            1404 :     NS_ENSURE_SUCCESS(rv, rv);
    3380                 : 
    3381                 :     static const JSSecurityCallbacks securityCallbacks = {
    3382                 :         CheckObjectAccess,
    3383                 :         nsJSPrincipals::Subsume,
    3384                 :         nsJSPrincipals::Transcode,
    3385                 :         ObjectPrincipalFinder,
    3386                 :         ContentSecurityPolicyPermitsJSAction
    3387                 :     };
    3388                 : 
    3389            1404 :     MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
    3390            1404 :     JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
    3391            1404 :     JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
    3392                 : 
    3393            1404 :     JS_SetTrustedPrincipals(sRuntime, system);
    3394                 : 
    3395            1404 :     return NS_OK;
    3396                 : }
    3397                 : 
    3398                 : static nsScriptSecurityManager *gScriptSecMan = nsnull;
    3399                 : 
    3400            1464 : jsid nsScriptSecurityManager::sEnabledID   = JSID_VOID;
    3401                 : 
    3402            4209 : nsScriptSecurityManager::~nsScriptSecurityManager(void)
    3403                 : {
    3404            1403 :     Preferences::RemoveObservers(this, kObservedPrefs);
    3405            1403 :     NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
    3406            1403 :     delete mOriginToPolicyMap;
    3407            1403 :     if(mDefaultPolicy)
    3408               1 :         mDefaultPolicy->Drop();
    3409            1403 :     delete mCapabilities;
    3410            1403 :     gScriptSecMan = nsnull;
    3411            5612 : }
    3412                 : 
    3413                 : void
    3414            1404 : nsScriptSecurityManager::Shutdown()
    3415                 : {
    3416            1404 :     if (sRuntime) {
    3417            1404 :         JS_SetSecurityCallbacks(sRuntime, NULL);
    3418            1404 :         JS_SetTrustedPrincipals(sRuntime, NULL);
    3419            1404 :         sRuntime = nsnull;
    3420                 :     }
    3421            1404 :     sEnabledID = JSID_VOID;
    3422                 : 
    3423            1404 :     NS_IF_RELEASE(sIOService);
    3424            1404 :     NS_IF_RELEASE(sXPConnect);
    3425            1404 :     NS_IF_RELEASE(sJSContextStack);
    3426            1404 :     NS_IF_RELEASE(sStrBundle);
    3427            1404 : }
    3428                 : 
    3429                 : nsScriptSecurityManager *
    3430          406937 : nsScriptSecurityManager::GetScriptSecurityManager()
    3431                 : {
    3432          406937 :     if (!gScriptSecMan)
    3433                 :     {
    3434            1404 :         nsScriptSecurityManager* ssManager = new nsScriptSecurityManager();
    3435            1404 :         if (!ssManager)
    3436               0 :             return nsnull;
    3437                 :         nsresult rv;
    3438            1404 :         rv = ssManager->Init();
    3439            1404 :         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to initialize nsScriptSecurityManager");
    3440            1404 :         if (NS_FAILED(rv)) {
    3441               0 :             delete ssManager;
    3442               0 :             return nsnull;
    3443                 :         }
    3444                 :  
    3445                 :         rv = sXPConnect->SetDefaultSecurityManager(ssManager,
    3446            1404 :                                                    nsIXPCSecurityManager::HOOK_ALL);
    3447            1404 :         if (NS_FAILED(rv)) {
    3448               0 :             NS_WARNING("Failed to install xpconnect security manager!");
    3449               0 :             delete ssManager;
    3450               0 :             return nsnull;
    3451                 :         }
    3452                 : 
    3453            1404 :         gScriptSecMan = ssManager;
    3454                 :     }
    3455          406937 :     return gScriptSecMan;
    3456                 : }
    3457                 : 
    3458                 : // Currently this nsGenericFactory constructor is used only from FastLoad
    3459                 : // (XPCOM object deserialization) code, when "creating" the system principal
    3460                 : // singleton.
    3461                 : nsSystemPrincipal *
    3462             934 : nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
    3463                 : {
    3464             934 :     nsIPrincipal *sysprin = nsnull;
    3465             934 :     if (gScriptSecMan)
    3466             934 :         NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
    3467             934 :     return static_cast<nsSystemPrincipal*>(sysprin);
    3468                 : }
    3469                 : 
    3470                 : nsresult
    3471               1 : nsScriptSecurityManager::InitPolicies()
    3472                 : {
    3473                 :     // Clear any policies cached on XPConnect wrappers
    3474               1 :     NS_ENSURE_STATE(sXPConnect);
    3475               1 :     nsresult rv = sXPConnect->ClearAllWrappedNativeSecurityPolicies();
    3476               1 :     if (NS_FAILED(rv)) return rv;
    3477                 : 
    3478                 :     //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items,
    3479                 :     //-- whose dtor decrements refcount of stored DomainPolicy object
    3480               1 :     delete mOriginToPolicyMap;
    3481                 :     
    3482                 :     //-- Marks all the survivor DomainPolicy objects (those cached
    3483                 :     //-- by nsPrincipal objects) as invalid: they will be released
    3484                 :     //-- on first nsPrincipal::GetSecurityPolicy() attempt.
    3485               1 :     DomainPolicy::InvalidateAll();
    3486                 :     
    3487                 :     //-- Release old default policy
    3488               1 :     if(mDefaultPolicy) {
    3489               0 :         mDefaultPolicy->Drop();
    3490               0 :         mDefaultPolicy = nsnull;
    3491                 :     }
    3492                 :     
    3493                 :     //-- Initialize a new mOriginToPolicyMap
    3494                 :     mOriginToPolicyMap =
    3495               1 :       new nsObjectHashtable(nsnull, nsnull, DeleteDomainEntry, nsnull);
    3496               1 :     if (!mOriginToPolicyMap)
    3497               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3498                 : 
    3499                 :     //-- Create, refcount and initialize a new default policy 
    3500               1 :     mDefaultPolicy = new DomainPolicy();
    3501               1 :     if (!mDefaultPolicy)
    3502               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3503                 : 
    3504               1 :     mDefaultPolicy->Hold();
    3505               1 :     if (!mDefaultPolicy->Init())
    3506               0 :         return NS_ERROR_UNEXPECTED;
    3507                 : 
    3508                 :     //-- Initialize the table of security levels
    3509               1 :     if (!mCapabilities)
    3510                 :     {
    3511                 :         mCapabilities = 
    3512               1 :           new nsObjectHashtable(nsnull, nsnull, DeleteCapability, nsnull);
    3513               1 :         if (!mCapabilities)
    3514               0 :             return NS_ERROR_OUT_OF_MEMORY;
    3515                 :     }
    3516                 : 
    3517                 :     // Get a JS context - we need it to create internalized strings later.
    3518               1 :     JSContext* cx = GetSafeJSContext();
    3519               1 :     NS_ASSERTION(cx, "failed to get JS context");
    3520               2 :     AutoCxPusher autoPusher(sJSContextStack, cx);
    3521               1 :     rv = InitDomainPolicy(cx, "default", mDefaultPolicy);
    3522               1 :     NS_ENSURE_SUCCESS(rv, rv);
    3523                 : 
    3524                 :     nsAdoptingCString policyNames =
    3525               2 :         Preferences::GetCString("capability.policy.policynames");
    3526                 : 
    3527                 :     nsAdoptingCString defaultPolicyNames =
    3528               2 :         Preferences::GetCString("capability.policy.default_policynames");
    3529               1 :     policyNames += NS_LITERAL_CSTRING(" ") + defaultPolicyNames;
    3530                 : 
    3531                 :     //-- Initialize domain policies
    3532               1 :     char* policyCurrent = policyNames.BeginWriting();
    3533               1 :     bool morePolicies = true;
    3534               3 :     while (morePolicies)
    3535                 :     {
    3536               3 :         while(*policyCurrent == ' ' || *policyCurrent == ',')
    3537               1 :             policyCurrent++;
    3538               1 :         if (*policyCurrent == '\0')
    3539               0 :             break;
    3540               1 :         char* nameBegin = policyCurrent;
    3541                 : 
    3542              10 :         while(*policyCurrent != '\0' && *policyCurrent != ' ' && *policyCurrent != ',')
    3543               8 :             policyCurrent++;
    3544                 : 
    3545               1 :         morePolicies = (*policyCurrent != '\0');
    3546               1 :         *policyCurrent = '\0';
    3547               1 :         policyCurrent++;
    3548                 : 
    3549                 :         nsCAutoString sitesPrefName(
    3550               1 :             NS_LITERAL_CSTRING(sPolicyPrefix) +
    3551               2 :             nsDependentCString(nameBegin) +
    3552               4 :             NS_LITERAL_CSTRING(".sites"));
    3553                 :         nsAdoptingCString domainList =
    3554               2 :             Preferences::GetCString(sitesPrefName.get());
    3555               1 :         if (!domainList) {
    3556               0 :             continue;
    3557                 :         }
    3558                 : 
    3559               1 :         DomainPolicy* domainPolicy = new DomainPolicy();
    3560               1 :         if (!domainPolicy)
    3561               0 :             return NS_ERROR_OUT_OF_MEMORY;
    3562                 : 
    3563               1 :         if (!domainPolicy->Init())
    3564                 :         {
    3565               0 :             delete domainPolicy;
    3566               0 :             return NS_ERROR_UNEXPECTED;
    3567                 :         }
    3568               1 :         domainPolicy->Hold();
    3569                 :         //-- Parse list of sites and create an entry in mOriginToPolicyMap for each
    3570               1 :         char* domainStart = domainList.BeginWriting();
    3571               1 :         char* domainCurrent = domainStart;
    3572               1 :         char* lastDot = nsnull;
    3573               1 :         char* nextToLastDot = nsnull;
    3574               1 :         bool moreDomains = true;
    3575              23 :         while (moreDomains)
    3576                 :         {
    3577              21 :             if (*domainCurrent == ' ' || *domainCurrent == '\0')
    3578                 :             {
    3579               3 :                 moreDomains = (*domainCurrent != '\0');
    3580               3 :                 *domainCurrent = '\0';
    3581               6 :                 nsCStringKey key(nextToLastDot ? nextToLastDot+1 : domainStart);
    3582               3 :                 DomainEntry *newEntry = new DomainEntry(domainStart, domainPolicy);
    3583               3 :                 if (!newEntry)
    3584                 :                 {
    3585               0 :                     domainPolicy->Drop();
    3586               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    3587                 :                 }
    3588                 : #ifdef DEBUG
    3589               3 :                 newEntry->mPolicyName_DEBUG = nameBegin;
    3590                 : #endif
    3591                 :                 DomainEntry *existingEntry = (DomainEntry *)
    3592               3 :                     mOriginToPolicyMap->Get(&key);
    3593               3 :                 if (!existingEntry)
    3594               3 :                     mOriginToPolicyMap->Put(&key, newEntry);
    3595                 :                 else
    3596                 :                 {
    3597               0 :                     if (existingEntry->Matches(domainStart))
    3598                 :                     {
    3599               0 :                         newEntry->mNext = existingEntry;
    3600               0 :                         mOriginToPolicyMap->Put(&key, newEntry);
    3601                 :                     }
    3602                 :                     else
    3603                 :                     {
    3604               0 :                         while (existingEntry->mNext)
    3605                 :                         {
    3606               0 :                             if (existingEntry->mNext->Matches(domainStart))
    3607                 :                             {
    3608               0 :                                 newEntry->mNext = existingEntry->mNext;
    3609               0 :                                 existingEntry->mNext = newEntry;
    3610               0 :                                 break;
    3611                 :                             }
    3612               0 :                             existingEntry = existingEntry->mNext;
    3613                 :                         }
    3614               0 :                         if (!existingEntry->mNext)
    3615               0 :                             existingEntry->mNext = newEntry;
    3616                 :                     }
    3617                 :                 }
    3618               3 :                 domainStart = domainCurrent + 1;
    3619               6 :                 lastDot = nextToLastDot = nsnull;
    3620                 :             }
    3621              18 :             else if (*domainCurrent == '.')
    3622                 :             {
    3623               0 :                 nextToLastDot = lastDot;
    3624               0 :                 lastDot = domainCurrent;
    3625                 :             }
    3626              21 :             domainCurrent++;
    3627                 :         }
    3628                 : 
    3629               1 :         rv = InitDomainPolicy(cx, nameBegin, domainPolicy);
    3630               1 :         domainPolicy->Drop();
    3631               1 :         if (NS_FAILED(rv))
    3632               0 :             return rv;
    3633                 :     }
    3634                 : 
    3635                 :     // Reset the "dirty" flag
    3636               1 :     mPolicyPrefsChanged = false;
    3637                 : 
    3638                 : #ifdef DEBUG_CAPS_HACKER
    3639                 :     PrintPolicyDB();
    3640                 : #endif
    3641               1 :     return NS_OK;
    3642                 : }
    3643                 : 
    3644                 : 
    3645                 : nsresult
    3646               2 : nsScriptSecurityManager::InitDomainPolicy(JSContext* cx,
    3647                 :                                           const char* aPolicyName,
    3648                 :                                           DomainPolicy* aDomainPolicy)
    3649                 : {
    3650                 :     nsresult rv;
    3651               2 :     nsCAutoString policyPrefix(NS_LITERAL_CSTRING(sPolicyPrefix) +
    3652               4 :                                nsDependentCString(aPolicyName) +
    3653               8 :                                NS_LITERAL_CSTRING("."));
    3654               2 :     PRUint32 prefixLength = policyPrefix.Length() - 1; // subtract the '.'
    3655                 : 
    3656                 :     PRUint32 prefCount;
    3657                 :     char** prefNames;
    3658               2 :     nsIPrefBranch* branch = Preferences::GetRootBranch();
    3659               2 :     NS_ASSERTION(branch, "failed to get the root pref branch");
    3660               2 :     rv = branch->GetChildList(policyPrefix.get(), &prefCount, &prefNames);
    3661               2 :     if (NS_FAILED(rv)) return rv;
    3662               2 :     if (prefCount == 0)
    3663               0 :         return NS_OK;
    3664                 : 
    3665                 :     //-- Populate the policy
    3666               2 :     PRUint32 currentPref = 0;
    3667             153 :     for (; currentPref < prefCount; currentPref++)
    3668                 :     {
    3669                 :         // Get the class name
    3670             151 :         const char* start = prefNames[currentPref] + prefixLength + 1;
    3671             151 :         char* end = PL_strchr(start, '.');
    3672             151 :         if (!end) // malformed pref, bail on this one
    3673               2 :             continue;
    3674                 :         static const char sitesStr[] = "sites";
    3675                 : 
    3676                 :         // We dealt with "sites" in InitPolicies(), so no need to do
    3677                 :         // that again...
    3678             149 :         if (PL_strncmp(start, sitesStr, sizeof(sitesStr)-1) == 0)
    3679               0 :             continue;
    3680                 : 
    3681                 :         // Get the pref value
    3682                 :         nsAdoptingCString prefValue =
    3683             298 :             Preferences::GetCString(prefNames[currentPref]);
    3684             149 :         if (!prefValue) {
    3685               0 :             continue;
    3686                 :         }
    3687                 : 
    3688                 :         SecurityLevel secLevel;
    3689             149 :         if (PL_strcasecmp(prefValue, "noAccess") == 0)
    3690             114 :             secLevel.level = SCRIPT_SECURITY_NO_ACCESS;
    3691              35 :         else if (PL_strcasecmp(prefValue, "allAccess") == 0)
    3692              27 :             secLevel.level = SCRIPT_SECURITY_ALL_ACCESS;
    3693               8 :         else if (PL_strcasecmp(prefValue, "sameOrigin") == 0)
    3694               1 :             secLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS;
    3695                 :         else 
    3696                 :         {  //-- pref value is the name of a capability
    3697              14 :             nsCStringKey secLevelKey(prefValue);
    3698                 :             secLevel.capability =
    3699               7 :                 reinterpret_cast<char*>(mCapabilities->Get(&secLevelKey));
    3700               7 :             if (!secLevel.capability)
    3701                 :             {
    3702               1 :                 secLevel.capability = NS_strdup(prefValue);
    3703               1 :                 if (!secLevel.capability)
    3704                 :                     break;
    3705                 :                 mCapabilities->Put(&secLevelKey, 
    3706               1 :                                    secLevel.capability);
    3707                 :             }
    3708                 :         }
    3709                 : 
    3710             149 :         *end = '\0';
    3711                 :         // Find or store this class in the classes table
    3712                 :         ClassPolicy* cpolicy = 
    3713                 :           static_cast<ClassPolicy*>
    3714                 :                      (PL_DHashTableOperate(aDomainPolicy, start,
    3715             149 :                                               PL_DHASH_ADD));
    3716             149 :         if (!cpolicy)
    3717                 :             break;
    3718                 : 
    3719                 :         // If this is the wildcard class (class '*'), save it in mWildcardPolicy
    3720                 :         // (we leave it stored in the hashtable too to take care of the cleanup)
    3721             149 :         if ((*start == '*') && (end == start + 1)) {
    3722              24 :             aDomainPolicy->mWildcardPolicy = cpolicy;
    3723                 : 
    3724                 :             // Make sure that cpolicy knows about aDomainPolicy so it can reset
    3725                 :             // the mWildcardPolicy pointer as needed if it gets moved in the
    3726                 :             // hashtable.
    3727              24 :             cpolicy->mDomainWeAreWildcardFor = aDomainPolicy;
    3728                 :         }
    3729                 : 
    3730                 :         // Get the property name
    3731             149 :         start = end + 1;
    3732             149 :         end = PL_strchr(start, '.');
    3733             149 :         if (end)
    3734              42 :             *end = '\0';
    3735                 : 
    3736             298 :         JSAutoRequest ar(cx);
    3737                 : 
    3738             149 :         JSString* propertyKey = ::JS_InternString(cx, start);
    3739             149 :         if (!propertyKey)
    3740               0 :             return NS_ERROR_OUT_OF_MEMORY;
    3741                 : 
    3742                 :         // Store this property in the class policy
    3743                 :         PropertyPolicy* ppolicy = 
    3744                 :           static_cast<PropertyPolicy*>
    3745                 :                      (PL_DHashTableOperate(cpolicy->mPolicy, propertyKey,
    3746             149 :                                               PL_DHASH_ADD));
    3747             149 :         if (!ppolicy)
    3748                 :             break;
    3749                 : 
    3750             149 :         if (end) // The pref specifies an access mode
    3751                 :         {
    3752              42 :             start = end + 1;
    3753              42 :             if (PL_strcasecmp(start, "set") == 0)
    3754               9 :                 ppolicy->mSet = secLevel;
    3755                 :             else
    3756              33 :                 ppolicy->mGet = secLevel;
    3757                 :         }
    3758                 :         else
    3759                 :         {
    3760             107 :             if (ppolicy->mGet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
    3761             107 :                 ppolicy->mGet = secLevel;
    3762             107 :             if (ppolicy->mSet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
    3763             107 :                 ppolicy->mSet = secLevel;
    3764                 :         }
    3765                 :     }
    3766                 : 
    3767               2 :     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
    3768               2 :     if (currentPref < prefCount) // Loop exited early because of out-of-memory error
    3769               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3770               2 :     return NS_OK;
    3771                 : }
    3772                 : 
    3773                 : 
    3774                 : // XXXbz We should really just get a prefbranch to handle this...
    3775                 : nsresult
    3776               0 : nsScriptSecurityManager::GetPrincipalPrefNames(const char* prefBase,
    3777                 :                                                nsCString& grantedPref,
    3778                 :                                                nsCString& deniedPref,
    3779                 :                                                nsCString& subjectNamePref)
    3780                 : {
    3781               0 :     char* lastDot = PL_strrchr(prefBase, '.');
    3782               0 :     if (!lastDot) return NS_ERROR_FAILURE;
    3783               0 :     PRInt32 prefLen = lastDot - prefBase + 1;
    3784                 : 
    3785               0 :     grantedPref.Assign(prefBase, prefLen);
    3786               0 :     deniedPref.Assign(prefBase, prefLen);
    3787               0 :     subjectNamePref.Assign(prefBase, prefLen);
    3788                 : 
    3789                 : #define GRANTED "granted"
    3790                 : #define DENIED "denied"
    3791                 : #define SUBJECTNAME "subjectName"
    3792                 : 
    3793               0 :     grantedPref.AppendLiteral(GRANTED);
    3794               0 :     if (grantedPref.Length() != prefLen + sizeof(GRANTED) - 1) {
    3795               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3796                 :     }
    3797                 : 
    3798               0 :     deniedPref.AppendLiteral(DENIED);
    3799               0 :     if (deniedPref.Length() != prefLen + sizeof(DENIED) - 1) {
    3800               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3801                 :     }
    3802                 : 
    3803               0 :     subjectNamePref.AppendLiteral(SUBJECTNAME);
    3804               0 :     if (subjectNamePref.Length() != prefLen + sizeof(SUBJECTNAME) - 1) {
    3805               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3806                 :     }
    3807                 : 
    3808                 : #undef SUBJECTNAME
    3809                 : #undef DENIED
    3810                 : #undef GRANTED
    3811                 :     
    3812               0 :     return NS_OK;
    3813                 : }
    3814                 : 
    3815                 : nsresult
    3816               0 : nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount, const char** aPrefNames)
    3817                 : {
    3818                 :     /* This is the principal preference syntax:
    3819                 :      * capability.principal.[codebase|codebaseTrusted|certificate].<name>.[id|granted|denied]
    3820                 :      * For example:
    3821                 :      * user_pref("capability.principal.certificate.p1.id","12:34:AB:CD");
    3822                 :      * user_pref("capability.principal.certificate.p1.granted","Capability1 Capability2");
    3823                 :      * user_pref("capability.principal.certificate.p1.denied","Capability3");
    3824                 :      */
    3825                 : 
    3826                 :     /* codebaseTrusted means a codebase principal that can enable capabilities even if
    3827                 :      * codebase principals are disabled. Don't use trustedCodebase except with unspoofable
    3828                 :      * URLs such as HTTPS URLs.
    3829                 :      */
    3830                 : 
    3831                 :     static const char idSuffix[] = ".id";
    3832               0 :     for (PRUint32 c = 0; c < aPrefCount; c++)
    3833                 :     {
    3834               0 :         PRInt32 prefNameLen = PL_strlen(aPrefNames[c]) - 
    3835               0 :             (ArrayLength(idSuffix) - 1);
    3836               0 :         if (PL_strcasecmp(aPrefNames[c] + prefNameLen, idSuffix) != 0)
    3837               0 :             continue;
    3838                 : 
    3839               0 :         nsAdoptingCString id = Preferences::GetCString(aPrefNames[c]);
    3840               0 :         if (!id) {
    3841               0 :             return NS_ERROR_FAILURE;
    3842                 :         }
    3843                 : 
    3844               0 :         nsCAutoString grantedPrefName;
    3845               0 :         nsCAutoString deniedPrefName;
    3846               0 :         nsCAutoString subjectNamePrefName;
    3847               0 :         nsresult rv = GetPrincipalPrefNames(aPrefNames[c],
    3848                 :                                             grantedPrefName,
    3849                 :                                             deniedPrefName,
    3850               0 :                                             subjectNamePrefName);
    3851               0 :         if (rv == NS_ERROR_OUT_OF_MEMORY)
    3852               0 :             return rv;
    3853               0 :         if (NS_FAILED(rv))
    3854               0 :             continue;
    3855                 : 
    3856                 :         nsAdoptingCString grantedList =
    3857               0 :             Preferences::GetCString(grantedPrefName.get());
    3858                 :         nsAdoptingCString deniedList =
    3859               0 :             Preferences::GetCString(deniedPrefName.get());
    3860                 :         nsAdoptingCString subjectName =
    3861               0 :             Preferences::GetCString(subjectNamePrefName.get());
    3862                 : 
    3863                 :         //-- Delete prefs if their value is the empty string
    3864               0 :         if (id.IsEmpty() || (grantedList.IsEmpty() && deniedList.IsEmpty()))
    3865                 :         {
    3866               0 :             Preferences::ClearUser(aPrefNames[c]);
    3867               0 :             Preferences::ClearUser(grantedPrefName.get());
    3868               0 :             Preferences::ClearUser(deniedPrefName.get());
    3869               0 :             Preferences::ClearUser(subjectNamePrefName.get());
    3870               0 :             continue;
    3871                 :         }
    3872                 : 
    3873                 :         //-- Create a principal based on the prefs
    3874                 :         static const char certificateName[] = "capability.principal.certificate";
    3875                 :         static const char codebaseName[] = "capability.principal.codebase";
    3876                 :         static const char codebaseTrustedName[] = "capability.principal.codebaseTrusted";
    3877                 : 
    3878               0 :         bool isCert = false;
    3879               0 :         bool isTrusted = false;
    3880                 :         
    3881               0 :         if (PL_strncmp(aPrefNames[c], certificateName,
    3882               0 :                        sizeof(certificateName) - 1) == 0)
    3883                 :         {
    3884               0 :             isCert = true;
    3885                 :         }
    3886               0 :         else if (PL_strncmp(aPrefNames[c], codebaseName,
    3887               0 :                             sizeof(codebaseName) - 1) == 0)
    3888                 :         {
    3889               0 :             isTrusted = (PL_strncmp(aPrefNames[c], codebaseTrustedName,
    3890               0 :                                     sizeof(codebaseTrustedName) - 1) == 0);
    3891                 :         }
    3892                 :         else
    3893                 :         {
    3894               0 :           NS_ERROR("Not a codebase or a certificate?!");
    3895                 :         }
    3896                 : 
    3897               0 :         nsRefPtr<nsPrincipal> newPrincipal = new nsPrincipal();
    3898               0 :         if (!newPrincipal)
    3899               0 :             return NS_ERROR_OUT_OF_MEMORY;
    3900                 : 
    3901               0 :         rv = newPrincipal->InitFromPersistent(aPrefNames[c], id, subjectName,
    3902               0 :                                               EmptyCString(),
    3903                 :                                               grantedList, deniedList, nsnull, 
    3904               0 :                                               isCert, isTrusted);
    3905               0 :         if (NS_SUCCEEDED(rv))
    3906               0 :             mPrincipals.Put(newPrincipal, newPrincipal);
    3907                 :     }
    3908               0 :     return NS_OK;
    3909                 : }
    3910                 : 
    3911                 : inline void
    3912            1406 : nsScriptSecurityManager::ScriptSecurityPrefChanged()
    3913                 : {
    3914                 :     // JavaScript defaults to enabled in failure cases.
    3915            1406 :     mIsJavaScriptEnabled = true;
    3916                 : 
    3917            1406 :     sStrictFileOriginPolicy = true;
    3918                 : 
    3919                 :     nsresult rv;
    3920            1406 :     if (!mPrefInitialized) {
    3921               0 :         rv = InitPrefs();
    3922               0 :         if (NS_FAILED(rv))
    3923               0 :             return;
    3924                 :     }
    3925                 : 
    3926                 :     mIsJavaScriptEnabled =
    3927            1406 :         Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
    3928                 : 
    3929                 :     sStrictFileOriginPolicy =
    3930            1406 :         Preferences::GetBool(sFileOriginPolicyPrefName, false);
    3931                 : }
    3932                 : 
    3933                 : nsresult
    3934            1404 : nsScriptSecurityManager::InitPrefs()
    3935                 : {
    3936                 :     nsresult rv;
    3937            1404 :     nsIPrefBranch* branch = Preferences::GetRootBranch();
    3938            1404 :     NS_ENSURE_TRUE(branch, NS_ERROR_FAILURE);
    3939                 : 
    3940            1404 :     mPrefInitialized = true;
    3941                 : 
    3942                 :     // Set the initial value of the "javascript.enabled" prefs
    3943            1404 :     ScriptSecurityPrefChanged();
    3944                 : 
    3945                 :     // set observer callbacks in case the value of the prefs change
    3946            1404 :     Preferences::AddStrongObservers(this, kObservedPrefs);
    3947                 : 
    3948                 :     PRUint32 prefCount;
    3949                 :     char** prefNames;
    3950                 :     //-- Initialize the principals database from prefs
    3951            1404 :     rv = branch->GetChildList(sPrincipalPrefix, &prefCount, &prefNames);
    3952            1404 :     if (NS_SUCCEEDED(rv) && prefCount > 0)
    3953                 :     {
    3954               0 :         rv = InitPrincipals(prefCount, (const char**)prefNames);
    3955               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
    3956               0 :         NS_ENSURE_SUCCESS(rv, rv);
    3957                 :     }
    3958                 : 
    3959            1404 :     return NS_OK;
    3960            4392 : }
    3961                 : 
    3962                 : ///////////////////////////////////////////////////////////////////////////////
    3963                 : // The following code prints the contents of the policy DB to the console.
    3964                 : #ifdef DEBUG_CAPS_HACKER
    3965                 : 
    3966                 : //typedef PLDHashOperator
    3967                 : //(* PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
    3968                 : //                      PRUint32 number, void *arg);
    3969                 : static PLDHashOperator
    3970                 : PrintPropertyPolicy(PLDHashTable *table, PLDHashEntryHdr *entry,
    3971                 :                     PRUint32 number, void *arg)
    3972                 : {
    3973                 :     PropertyPolicy* pp = (PropertyPolicy*)entry;
    3974                 :     nsCAutoString prop("        ");
    3975                 :     JSContext* cx = (JSContext*)arg;
    3976                 :     prop.AppendInt((PRUint32)pp->key);
    3977                 :     prop += ' ';
    3978                 :     prop.AppendWithConversion((PRUnichar*)JS_GetStringChars(pp->key));
    3979                 :     prop += ": Get=";
    3980                 :     if (SECURITY_ACCESS_LEVEL_FLAG(pp->mGet))
    3981                 :         prop.AppendInt(pp->mGet.level);
    3982                 :     else
    3983                 :         prop += pp->mGet.capability;
    3984                 : 
    3985                 :     prop += " Set=";
    3986                 :     if (SECURITY_ACCESS_LEVEL_FLAG(pp->mSet))
    3987                 :         prop.AppendInt(pp->mSet.level);
    3988                 :     else
    3989                 :         prop += pp->mSet.capability;
    3990                 :         
    3991                 :     printf("%s.\n", prop.get());
    3992                 :     return PL_DHASH_NEXT;
    3993                 : }
    3994                 : 
    3995                 : static PLDHashOperator
    3996                 : PrintClassPolicy(PLDHashTable *table, PLDHashEntryHdr *entry,
    3997                 :                  PRUint32 number, void *arg)
    3998                 : {
    3999                 :     ClassPolicy* cp = (ClassPolicy*)entry;
    4000                 :     printf("    %s\n", cp->key);
    4001                 : 
    4002                 :     PL_DHashTableEnumerate(cp->mPolicy, PrintPropertyPolicy, arg);
    4003                 :     return PL_DHASH_NEXT;
    4004                 : }
    4005                 : 
    4006                 : // typedef bool
    4007                 : // (* nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
    4008                 : static bool
    4009                 : PrintDomainPolicy(nsHashKey *aKey, void *aData, void* aClosure)
    4010                 : {
    4011                 :     DomainEntry* de = (DomainEntry*)aData;
    4012                 :     printf("----------------------------\n");
    4013                 :     printf("Domain: %s Policy Name: %s.\n", de->mOrigin.get(),
    4014                 :            de->mPolicyName_DEBUG.get());
    4015                 :     PL_DHashTableEnumerate(de->mDomainPolicy, PrintClassPolicy, aClosure);
    4016                 :     return true;
    4017                 : }
    4018                 : 
    4019                 : static bool
    4020                 : PrintCapability(nsHashKey *aKey, void *aData, void* aClosure)
    4021                 : {
    4022                 :     char* cap = (char*)aData;
    4023                 :     printf("    %s.\n", cap);
    4024                 :     return true;
    4025                 : }
    4026                 : 
    4027                 : void
    4028                 : nsScriptSecurityManager::PrintPolicyDB()
    4029                 : {
    4030                 :     printf("############## Security Policies ###############\n");
    4031                 :     if(mOriginToPolicyMap)
    4032                 :     {
    4033                 :         JSContext* cx = GetCurrentJSContext();
    4034                 :         if (!cx)
    4035                 :             cx = GetSafeJSContext();
    4036                 :         printf("----------------------------\n");
    4037                 :         printf("Domain: Default.\n");
    4038                 :         PL_DHashTableEnumerate(mDefaultPolicy, PrintClassPolicy, (void*)cx);
    4039                 :         mOriginToPolicyMap->Enumerate(PrintDomainPolicy, (void*)cx);
    4040                 :     }
    4041                 :     printf("############ End Security Policies #############\n\n");
    4042                 :     printf("############## Capabilities ###############\n");
    4043                 :     mCapabilities->Enumerate(PrintCapability);
    4044                 :     printf("############## End Capabilities ###############\n");
    4045                 : }
    4046                 : #endif

Generated by: LCOV version 1.7