Back to index

lightning-sunbird  0.9+nobinonly
nsSecurityManagerFactory.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*Factory for internal browser security resource managers*/
00038 
00039 #include "nsCOMPtr.h"
00040 #include "nsIModule.h"
00041 #include "nsIGenericFactory.h"
00042 #include "nsIScriptSecurityManager.h"
00043 #include "nsScriptSecurityManager.h"
00044 #include "nsIPrincipal.h"
00045 #include "nsPrincipal.h"
00046 #include "nsSystemPrincipal.h"
00047 #include "nsIScriptNameSpaceManager.h"
00048 #include "nsIScriptExternalNameSet.h"
00049 #include "nsIScriptContext.h"
00050 #include "nsICategoryManager.h"
00051 #include "nsXPIDLString.h"
00052 #include "nsCOMPtr.h"
00053 #include "nsIServiceManager.h"
00054 #include "nsString.h"
00055 #include "nsPrefsCID.h"
00056 
00058 // nsSecurityNameSet //
00060 
00061 #define NS_SECURITYNAMESET_CID \
00062  { 0x7c02eadc, 0x76, 0x4d03, \
00063  { 0x99, 0x8d, 0x80, 0xd7, 0x79, 0xc4, 0x85, 0x89 } }
00064 #define NS_SECURITYNAMESET_CONTRACTID "@mozilla.org/security/script/nameset;1"
00065 
00066 class nsSecurityNameSet : public nsIScriptExternalNameSet 
00067 {
00068 public:
00069     nsSecurityNameSet();
00070     virtual ~nsSecurityNameSet();
00071     
00072     NS_DECL_ISUPPORTS
00073 
00074     NS_IMETHOD InitializeNameSet(nsIScriptContext* aScriptContext);
00075 };
00076 
00077 nsSecurityNameSet::nsSecurityNameSet()
00078 {
00079 }
00080 
00081 nsSecurityNameSet::~nsSecurityNameSet()
00082 {
00083 }
00084 
00085 NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
00086 
00087 static char *
00088 getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv)
00089 {
00090     if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
00091         JS_ReportError(cx, "String argument expected");
00092         return nsnull;
00093     }
00094 
00095     /*
00096      * We don't want to use JS_ValueToString because we want to be able
00097      * to have an object to represent a target in subsequent versions.
00098      */
00099     JSString *str = JSVAL_TO_STRING(argv[argNum]);
00100     if (!str)
00101         return nsnull;
00102 
00103     return JS_GetStringBytes(str);
00104 }
00105 
00106 static void
00107 getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum,
00108                       uintN argc, jsval *argv, nsCString& aRetval)
00109 {
00110     if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
00111         JS_ReportError(cx, "String argument expected");
00112         aRetval.Truncate();
00113         return;
00114     }
00115 
00116     /*
00117      * We don't want to use JS_ValueToString because we want to be able
00118      * to have an object to represent a target in subsequent versions.
00119      */
00120     JSString *str = JSVAL_TO_STRING(argv[argNum]);
00121     if (!str) {
00122         aRetval.Truncate();
00123         return;
00124     }
00125 
00126     PRUnichar *data = (PRUnichar*)JS_GetStringChars(str);
00127     CopyUTF16toUTF8(data, aRetval);
00128 }
00129 
00130 PR_STATIC_CALLBACK(JSBool)
00131 netscape_security_isPrivilegeEnabled(JSContext *cx, JSObject *obj, uintN argc,
00132                                      jsval *argv, jsval *rval)
00133 {
00134     JSBool result = JS_FALSE;
00135     char *cap = getStringArgument(cx, obj, 0, argc, argv);
00136     if (cap) {
00137         nsresult rv;
00138         nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00139                  do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00140         if (NS_SUCCEEDED(rv)) {
00141             //            NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00142 
00143             rv = securityManager->IsCapabilityEnabled(cap, &result);
00144             if (NS_FAILED(rv)) 
00145                 result = JS_FALSE;
00146         }
00147     }
00148     *rval = BOOLEAN_TO_JSVAL(result);
00149     return JS_TRUE;
00150 }
00151 
00152 
00153 PR_STATIC_CALLBACK(JSBool)
00154 netscape_security_enablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
00155                                   jsval *argv, jsval *rval)
00156 {
00157     char *cap = getStringArgument(cx, obj, 0, argc, argv);
00158     if (!cap)
00159         return JS_FALSE;
00160 
00161     nsresult rv;
00162     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00163              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00164     if (NS_FAILED(rv)) 
00165         return JS_FALSE;
00166 
00167     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00168 
00169     rv = securityManager->EnableCapability(cap);
00170     if (NS_FAILED(rv))
00171         return JS_FALSE;
00172     return JS_TRUE;
00173 }
00174 
00175 PR_STATIC_CALLBACK(JSBool)
00176 netscape_security_disablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
00177                                    jsval *argv, jsval *rval)
00178 {
00179     char *cap = getStringArgument(cx, obj, 0, argc, argv);
00180     if (!cap)
00181         return JS_FALSE;
00182 
00183     nsresult rv;
00184     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00185              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00186     if (NS_FAILED(rv)) 
00187         return JS_FALSE;
00188 
00189     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00190 
00191     rv = securityManager->DisableCapability(cap);
00192     if (NS_FAILED(rv))
00193         return JS_FALSE;
00194     return JS_TRUE;
00195 }
00196 
00197 PR_STATIC_CALLBACK(JSBool)
00198 netscape_security_revertPrivilege(JSContext *cx, JSObject *obj, uintN argc,
00199                                   jsval *argv, jsval *rval)
00200 {
00201     char *cap = getStringArgument(cx, obj, 0, argc, argv);
00202     if (!cap)
00203         return JS_FALSE;
00204 
00205     nsresult rv;
00206     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00207              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00208     if (NS_FAILED(rv)) 
00209         return JS_FALSE;
00210 
00211     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00212 
00213     rv = securityManager->RevertCapability(cap);
00214     if (NS_FAILED(rv))
00215         return JS_FALSE;
00216     return JS_TRUE;
00217 }
00218 
00219 PR_STATIC_CALLBACK(JSBool)
00220 netscape_security_setCanEnablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
00221                                         jsval *argv, jsval *rval)
00222 {
00223     if (argc < 2) return JS_FALSE;
00224     nsCAutoString principalFingerprint;
00225     getUTF8StringArgument(cx, obj, 0, argc, argv, principalFingerprint);
00226     char *cap = getStringArgument(cx, obj, 1, argc, argv);
00227     if (principalFingerprint.IsEmpty() || !cap)
00228         return JS_FALSE;
00229 
00230     nsresult rv;
00231     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00232              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00233     if (NS_FAILED(rv)) 
00234         return JS_FALSE;
00235 
00236     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00237 
00238     rv = securityManager->SetCanEnableCapability(principalFingerprint, cap, 
00239                                                  nsIPrincipal::ENABLE_GRANTED);
00240     if (NS_FAILED(rv))
00241         return JS_FALSE;
00242     return JS_TRUE;
00243 }
00244 
00245 PR_STATIC_CALLBACK(JSBool)
00246 netscape_security_invalidate(JSContext *cx, JSObject *obj, uintN argc,
00247                              jsval *argv, jsval *rval)
00248 {
00249     nsCAutoString principalFingerprint;
00250     getUTF8StringArgument(cx, obj, 0, argc, argv, principalFingerprint);
00251     if (principalFingerprint.IsEmpty())
00252         return JS_FALSE;
00253 
00254     nsresult rv;
00255     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
00256              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
00257     if (NS_FAILED(rv)) 
00258         return JS_FALSE;
00259 
00260     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
00261 
00262     rv = securityManager->SetCanEnableCapability(principalFingerprint,
00263                                                  nsPrincipal::sInvalid,
00264                                                  nsIPrincipal::ENABLE_GRANTED);
00265     if (NS_FAILED(rv))
00266         return JS_FALSE;
00267     return JS_TRUE;
00268 }
00269 
00270 static JSFunctionSpec PrivilegeManager_static_methods[] = {
00271     { "isPrivilegeEnabled", netscape_security_isPrivilegeEnabled,   1},
00272     { "enablePrivilege",    netscape_security_enablePrivilege,      1},
00273     { "disablePrivilege",   netscape_security_disablePrivilege,     1},
00274     { "revertPrivilege",    netscape_security_revertPrivilege,      1},
00275     //-- System Cert Functions
00276     { "setCanEnablePrivilege", netscape_security_setCanEnablePrivilege,   2},
00277     { "invalidate",            netscape_security_invalidate,              1},
00278     {0}
00279 };
00280 
00281 /*
00282  * "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege,
00283  * et. al. so that code that worked with 4.0 can still work.
00284  */
00285 NS_IMETHODIMP 
00286 nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
00287 {
00288     JSContext *cx = (JSContext *) aScriptContext->GetNativeContext();
00289     JSObject *global = JS_GetGlobalObject(cx);
00290 
00291     /*
00292      * Find Object.prototype's class by walking up the global object's
00293      * prototype chain.
00294      */
00295     JSObject *obj = global;
00296     JSObject *proto;
00297     while ((proto = JS_GetPrototype(cx, obj)) != nsnull)
00298         obj = proto;
00299     JSClass *objectClass = JS_GetClass(cx, obj);
00300 
00301     jsval v;
00302     if (!JS_GetProperty(cx, global, "netscape", &v))
00303         return NS_ERROR_FAILURE;
00304     JSObject *securityObj;
00305     if (JSVAL_IS_OBJECT(v)) {
00306         /*
00307          * "netscape" property of window object exists; must be LiveConnect
00308          * package. Get the "security" property.
00309          */
00310         obj = JSVAL_TO_OBJECT(v);
00311         if (!JS_GetProperty(cx, obj, "security", &v) || !JSVAL_IS_OBJECT(v))
00312             return NS_ERROR_FAILURE;
00313         securityObj = JSVAL_TO_OBJECT(v);
00314     } else {
00315         /* define netscape.security object */
00316         obj = JS_DefineObject(cx, global, "netscape", objectClass, nsnull, 0);
00317         if (obj == nsnull)
00318             return NS_ERROR_FAILURE;
00319         securityObj = JS_DefineObject(cx, obj, "security", objectClass,
00320                                       nsnull, 0);
00321         if (securityObj == nsnull)
00322             return NS_ERROR_FAILURE;
00323     }
00324 
00325     /* Define PrivilegeManager object with the necessary "static" methods. */
00326     obj = JS_DefineObject(cx, securityObj, "PrivilegeManager", objectClass,
00327                           nsnull, 0);
00328     if (obj == nsnull)
00329         return NS_ERROR_FAILURE;
00330 
00331     return JS_DefineFunctions(cx, obj, PrivilegeManager_static_methods)
00332            ? NS_OK
00333            : NS_ERROR_FAILURE;
00334 }
00335 
00336 
00337 
00338 NS_GENERIC_FACTORY_CONSTRUCTOR(nsPrincipal)
00339 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityNameSet)
00340 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsSystemPrincipal,
00341     nsScriptSecurityManager::SystemPrincipalSingletonConstructor)
00342 
00343 
00344 NS_DECL_CLASSINFO(nsPrincipal)
00345 NS_DECL_CLASSINFO(nsSystemPrincipal)
00346 
00347 
00348 static NS_IMETHODIMP
00349 Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID, 
00350                                    void **aResult)
00351 {
00352     if (!aResult)
00353         return NS_ERROR_NULL_POINTER;
00354     *aResult = nsnull;
00355     if (aOuter)
00356         return NS_ERROR_NO_AGGREGATION;
00357     nsScriptSecurityManager *obj = nsScriptSecurityManager::GetScriptSecurityManager();
00358     if (!obj) 
00359         return NS_ERROR_OUT_OF_MEMORY;
00360     if (NS_FAILED(obj->QueryInterface(aIID, aResult)))
00361         return NS_ERROR_FAILURE;
00362     return NS_OK;
00363 }
00364 
00365 static NS_METHOD 
00366 RegisterSecurityNameSet(nsIComponentManager *aCompMgr,
00367                         nsIFile *aPath,
00368                         const char *registryLocation,
00369                         const char *componentType,
00370                         const nsModuleComponentInfo *info)
00371 {
00372     nsresult rv = NS_OK;
00373 
00374     nsCOMPtr<nsICategoryManager> catman =
00375         do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
00376 
00377     if (NS_FAILED(rv))
00378         return rv;
00379 
00380     nsXPIDLCString previous;
00381     rv = catman->AddCategoryEntry(JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY,
00382                                   "PrivilegeManager",
00383                                   NS_SECURITYNAMESET_CONTRACTID,
00384                                   PR_TRUE, PR_TRUE, getter_Copies(previous));
00385     NS_ENSURE_SUCCESS(rv, rv);
00386 
00387     rv = catman->AddCategoryEntry("app-startup", "Script Security Manager",
00388                                   "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID,
00389                                   PR_TRUE, PR_TRUE,
00390                                   getter_Copies(previous));
00391     NS_ENSURE_SUCCESS(rv, rv);
00392 
00393     return rv;
00394 }
00395 
00396 
00397 static const nsModuleComponentInfo capsComponentInfo[] =
00398 {
00399     { NS_SCRIPTSECURITYMANAGER_CLASSNAME, 
00400       NS_SCRIPTSECURITYMANAGER_CID, 
00401       NS_SCRIPTSECURITYMANAGER_CONTRACTID,
00402       Construct_nsIScriptSecurityManager,
00403       RegisterSecurityNameSet,
00404       nsnull,
00405       nsnull,
00406       nsnull,
00407       nsnull,
00408       nsnull,
00409       nsIClassInfo::MAIN_THREAD_ONLY
00410     },
00411 
00412     { NS_SCRIPTSECURITYMANAGER_CLASSNAME, 
00413       NS_SCRIPTSECURITYMANAGER_CID, 
00414       NS_GLOBAL_PREF_SECURITY_CHECK,
00415       Construct_nsIScriptSecurityManager,
00416       RegisterSecurityNameSet,
00417       nsnull,
00418       nsnull,
00419       nsnull,
00420       nsnull,
00421       nsnull,
00422       nsIClassInfo::MAIN_THREAD_ONLY
00423     },
00424 
00425 
00426     { NS_PRINCIPAL_CLASSNAME, 
00427       NS_PRINCIPAL_CID, 
00428       NS_PRINCIPAL_CONTRACTID,
00429       nsPrincipalConstructor,
00430       nsnull,
00431       nsnull,
00432       nsnull,
00433       NS_CI_INTERFACE_GETTER_NAME(nsPrincipal),
00434       nsnull,
00435       &NS_CLASSINFO_NAME(nsPrincipal),
00436       nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::EAGER_CLASSINFO
00437     },
00438 
00439     { NS_SYSTEMPRINCIPAL_CLASSNAME, 
00440       NS_SYSTEMPRINCIPAL_CID, 
00441       NS_SYSTEMPRINCIPAL_CONTRACTID,
00442       nsSystemPrincipalConstructor,
00443       nsnull,
00444       nsnull,
00445       nsnull,
00446       NS_CI_INTERFACE_GETTER_NAME(nsSystemPrincipal),
00447       nsnull,
00448       &NS_CLASSINFO_NAME(nsSystemPrincipal),
00449       nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY |
00450       nsIClassInfo::EAGER_CLASSINFO
00451     },
00452 
00453     { "Security Script Name Set",
00454       NS_SECURITYNAMESET_CID,
00455       NS_SECURITYNAMESET_CONTRACTID,
00456       nsSecurityNameSetConstructor,
00457       nsnull,
00458       nsnull,
00459       nsnull,
00460       nsnull,
00461       nsnull,
00462       nsnull,
00463       nsIClassInfo::MAIN_THREAD_ONLY
00464     }
00465 };
00466 
00467 
00468 void PR_CALLBACK
00469 CapsModuleDtor(nsIModule* thisModules)
00470 {
00471     nsScriptSecurityManager::Shutdown();
00472 }
00473 
00474 NS_IMPL_NSGETMODULE_WITH_DTOR(nsSecurityManagerModule, capsComponentInfo,
00475                               CapsModuleDtor)
00476