Back to index

lightning-sunbird  0.9+nobinonly
pk11pars.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 /*
00037  * The following handles the loading, unloading and management of
00038  * various PCKS #11 modules
00039  */
00040 
00041 #include <ctype.h>
00042 #include "pkcs11.h"
00043 #include "seccomon.h"
00044 #include "secmod.h"
00045 #include "secmodi.h"
00046 #include "secmodti.h"
00047 #include "pki3hack.h"
00048 #include "secerr.h"
00049    
00050 #include "pk11pars.h" 
00051 
00052 /* create a new module */
00053 static  SECMODModule *
00054 secmod_NewModule(void)
00055 {
00056     SECMODModule *newMod;
00057     PRArenaPool *arena;
00058 
00059 
00060     /* create an arena in which dllName and commonName can be
00061      * allocated.
00062      */
00063     arena = PORT_NewArena(512);
00064     if (arena == NULL) {
00065        return NULL;
00066     }
00067 
00068     newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule));
00069     if (newMod == NULL) {
00070        PORT_FreeArena(arena,PR_FALSE);
00071        return NULL;
00072     }
00073 
00074     /*
00075      * initialize of the fields of the module
00076      */
00077     newMod->arena = arena;
00078     newMod->internal = PR_FALSE;
00079     newMod->loaded = PR_FALSE;
00080     newMod->isFIPS = PR_FALSE;
00081     newMod->dllName = NULL;
00082     newMod->commonName = NULL;
00083     newMod->library = NULL;
00084     newMod->functionList = NULL;
00085     newMod->slotCount = 0;
00086     newMod->slots = NULL;
00087     newMod->slotInfo = NULL;
00088     newMod->slotInfoCount = 0;
00089     newMod->refCount = 1;
00090     newMod->ssl[0] = 0;
00091     newMod->ssl[1] = 0;
00092     newMod->libraryParams = NULL;
00093     newMod->moduleDBFunc = NULL;
00094     newMod->parent = NULL;
00095     newMod->isCritical = PR_FALSE;
00096     newMod->isModuleDB = PR_FALSE;
00097     newMod->moduleDBOnly = PR_FALSE;
00098     newMod->trustOrder = 0;
00099     newMod->cipherOrder = 0;
00100     newMod->evControlMask = 0;
00101     newMod->refLock = PZ_NewLock(nssILockRefLock);
00102     if (newMod->refLock == NULL) {
00103        PORT_FreeArena(arena,PR_FALSE);
00104        return NULL;
00105     }
00106     return newMod;
00107     
00108 }
00109 
00110 /*
00111  * for 3.4 we continue to use the old SECMODModule structure
00112  */
00113 SECMODModule *
00114 SECMOD_CreateModule(const char *library, const char *moduleName, 
00115                             const char *parameters, const char *nss)
00116 {
00117     SECMODModule *mod = secmod_NewModule();
00118     char *slotParams,*ciphers;
00119     /* pk11pars.h still does not have const char * interfaces */
00120     char *nssc = (char *)nss;
00121     if (mod == NULL) return NULL;
00122 
00123     mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : "");
00124     if (library) {
00125        mod->dllName = PORT_ArenaStrdup(mod->arena,library);
00126     }
00127     /* new field */
00128     if (parameters) {
00129        mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters);
00130     }
00131     mod->internal   = secmod_argHasFlag("flags","internal",nssc);
00132     mod->isFIPS     = secmod_argHasFlag("flags","FIPS",nssc);
00133     mod->isCritical = secmod_argHasFlag("flags","critical",nssc);
00134     slotParams      = secmod_argGetParamValue("slotParams",nssc);
00135     mod->slotInfo   = secmod_argParseSlotInfo(mod->arena,slotParams,
00136                                                  &mod->slotInfoCount);
00137     if (slotParams) PORT_Free(slotParams);
00138     /* new field */
00139     mod->trustOrder  = secmod_argReadLong("trustOrder",nssc,
00140                                           SECMOD_DEFAULT_TRUST_ORDER,NULL);
00141     /* new field */
00142     mod->cipherOrder = secmod_argReadLong("cipherOrder",nssc,
00143                                           SECMOD_DEFAULT_CIPHER_ORDER,NULL);
00144     /* new field */
00145     mod->isModuleDB   = secmod_argHasFlag("flags","moduleDB",nssc);
00146     mod->moduleDBOnly = secmod_argHasFlag("flags","moduleDBOnly",nssc);
00147     if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE;
00148 
00149     ciphers = secmod_argGetParamValue("ciphers",nssc);
00150     secmod_argSetNewCipherFlags(&mod->ssl[0],ciphers);
00151     if (ciphers) PORT_Free(ciphers);
00152 
00153     secmod_PrivateModuleCount++;
00154 
00155     return mod;
00156 }
00157 
00158 static char *
00159 secmod_mkModuleSpec(SECMODModule * module)
00160 {
00161     char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;
00162     int slotCount, i, si;
00163     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
00164 
00165     /* allocate target slot info strings */
00166     slotCount = 0;
00167 
00168     SECMOD_GetReadLock(moduleLock);
00169     if (module->slotCount) {
00170        for (i=0; i < module->slotCount; i++) {
00171            if (module->slots[i]->defaultFlags !=0) {
00172               slotCount++;
00173            }
00174        }
00175     } else {
00176        slotCount = module->slotInfoCount;
00177     }
00178 
00179     slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *));
00180     if (slotStrings == NULL) {
00181         SECMOD_ReleaseReadLock(moduleLock);
00182        goto loser;
00183     }
00184 
00185 
00186     /* build the slot info strings */
00187     if (module->slotCount) {
00188        for (i=0, si= 0; i < module->slotCount; i++) {
00189            if (module->slots[i]->defaultFlags) {
00190               PORT_Assert(si < slotCount);
00191               if (si >= slotCount) break;
00192               slotStrings[si] = secmod_mkSlotString(module->slots[i]->slotID,
00193                      module->slots[i]->defaultFlags,
00194                      module->slots[i]->timeout,
00195                      module->slots[i]->askpw,
00196                      module->slots[i]->hasRootCerts,
00197                      module->slots[i]->hasRootTrust);
00198               si++;
00199            }
00200        }
00201      } else {
00202        for (i=0; i < slotCount; i++) {
00203               slotStrings[i] = secmod_mkSlotString(module->slotInfo[i].slotID,
00204                      module->slotInfo[i].defaultFlags,
00205                      module->slotInfo[i].timeout,
00206                      module->slotInfo[i].askpw,
00207                      module->slotInfo[i].hasRootCerts,
00208                      module->slotInfo[i].hasRootTrust);
00209        }
00210     }
00211 
00212     SECMOD_ReleaseReadLock(moduleLock);
00213     nss = secmod_mkNSS(slotStrings,slotCount,module->internal, module->isFIPS,
00214                      module->isModuleDB, module->moduleDBOnly, 
00215                      module->isCritical, module->trustOrder,
00216                      module->cipherOrder,module->ssl[0],module->ssl[1]);
00217     modSpec= secmod_mkNewModuleSpec(module->dllName,module->commonName,
00218                                           module->libraryParams,nss);
00219     PORT_Free(slotStrings);
00220     PR_smprintf_free(nss);
00221 loser:
00222     return (modSpec);
00223 }
00224     
00225 
00226 char **
00227 SECMOD_GetModuleSpecList(SECMODModule *module)
00228 {
00229     SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc;
00230     if (func) {
00231        return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
00232               module->libraryParams,NULL);
00233     }
00234     return NULL;
00235 }
00236 
00237 SECStatus
00238 SECMOD_AddPermDB(SECMODModule *module)
00239 {
00240     SECMODModuleDBFunc func;
00241     char *moduleSpec;
00242     char **retString;
00243 
00244     if (module->parent == NULL) return SECFailure;
00245 
00246     func  = (SECMODModuleDBFunc) module->parent->moduleDBFunc;
00247     if (func) {
00248        moduleSpec = secmod_mkModuleSpec(module);
00249        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD,
00250               module->parent->libraryParams,moduleSpec);
00251        PORT_Free(moduleSpec);
00252        if (retString != NULL) return SECSuccess;
00253     }
00254     return SECFailure;
00255 }
00256 
00257 SECStatus
00258 SECMOD_DeletePermDB(SECMODModule *module)
00259 {
00260     SECMODModuleDBFunc func;
00261     char *moduleSpec;
00262     char **retString;
00263 
00264     if (module->parent == NULL) return SECFailure;
00265 
00266     func  = (SECMODModuleDBFunc) module->parent->moduleDBFunc;
00267     if (func) {
00268        moduleSpec = secmod_mkModuleSpec(module);
00269        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL,
00270               module->parent->libraryParams,moduleSpec);
00271        PORT_Free(moduleSpec);
00272        if (retString != NULL) return SECSuccess;
00273     }
00274     return SECFailure;
00275 }
00276 
00277 SECStatus
00278 SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList)
00279 {
00280     SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc;
00281     char **retString;
00282     if (func) {
00283        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE,
00284               module->libraryParams,moduleSpecList);
00285        if (retString != NULL) return SECSuccess;
00286     }
00287     return SECFailure;
00288 }
00289 
00290 /*
00291  * load a PKCS#11 module but do not add it to the default NSS trust domain
00292  */
00293 SECMODModule *
00294 SECMOD_LoadModule(char *modulespec,SECMODModule *parent, PRBool recurse)
00295 {
00296     char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL;
00297     SECStatus status;
00298     SECMODModule *module = NULL;
00299     SECStatus rv;
00300 
00301     /* initialize the underlying module structures */
00302     SECMOD_Init();
00303 
00304     status = secmod_argParseModuleSpec(modulespec, &library, &moduleName, 
00305                                                  &parameters, &nss);
00306     if (status != SECSuccess) {
00307        goto loser;
00308     }
00309 
00310     module = SECMOD_CreateModule(library, moduleName, parameters, nss);
00311     if (library) PORT_Free(library);
00312     if (moduleName) PORT_Free(moduleName);
00313     if (parameters) PORT_Free(parameters);
00314     if (nss) PORT_Free(nss);
00315     if (!module) {
00316        goto loser;
00317     }
00318     if (parent) {
00319        module->parent = SECMOD_ReferenceModule(parent);
00320     }
00321 
00322     /* load it */
00323     rv = SECMOD_LoadPKCS11Module(module);
00324     if (rv != SECSuccess) {
00325        goto loser;
00326     }
00327 
00328     if (recurse && module->isModuleDB) {
00329        char ** moduleSpecList;
00330        PORT_SetError(0);
00331 
00332        moduleSpecList = SECMOD_GetModuleSpecList(module);
00333        if (moduleSpecList) {
00334            char **index;
00335 
00336            for (index = moduleSpecList; *index; index++) {
00337               SECMODModule *child;
00338               child = SECMOD_LoadModule(*index,module,PR_TRUE);
00339               if (!child) break;
00340               if (child->isCritical && !child->loaded) {
00341                   int err = PORT_GetError();
00342                   if (!err)  
00343                      err = SEC_ERROR_NO_MODULE;
00344                   SECMOD_DestroyModule(child);
00345                   PORT_SetError(err);
00346                   rv = SECFailure;
00347                   break;
00348               }
00349               SECMOD_DestroyModule(child);
00350            }
00351            SECMOD_FreeModuleSpecList(module,moduleSpecList);
00352        } else {
00353            if (!PORT_GetError())
00354               PORT_SetError(SEC_ERROR_NO_MODULE);
00355            rv = SECFailure;
00356        }
00357     }
00358 
00359     if (rv != SECSuccess) {
00360        goto loser;
00361     }
00362 
00363 
00364     /* inherit the reference */
00365     if (!module->moduleDBOnly) {
00366        SECMOD_AddModuleToList(module);
00367     } else {
00368        SECMOD_AddModuleToDBOnlyList(module);
00369     }
00370    
00371     /* handle any additional work here */
00372     return module;
00373 
00374 loser:
00375     if (module) {
00376        if (module->loaded) {
00377            SECMOD_UnloadModule(module);
00378        }
00379        SECMOD_AddModuleToUnloadList(module);
00380     }
00381     return module;
00382 }
00383 
00384 /*
00385  * load a PKCS#11 module and add it to the default NSS trust domain
00386  */
00387 SECMODModule *
00388 SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse)
00389 {
00390     SECStatus rv = SECSuccess;
00391     SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse);
00392     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
00393 
00394     if (newmod) {
00395        SECMOD_GetReadLock(moduleLock);
00396         rv = STAN_AddModuleToDefaultTrustDomain(newmod);
00397        SECMOD_ReleaseReadLock(moduleLock);
00398         if (SECSuccess != rv) {
00399             SECMOD_DestroyModule(newmod);
00400             return NULL;
00401         }
00402     }
00403     return newmod;
00404 }
00405 
00406 /*
00407  * remove the PKCS#11 module from the default NSS trust domain, call
00408  * C_Finalize, and destroy the module structure
00409  */
00410 SECStatus SECMOD_UnloadUserModule(SECMODModule *mod)
00411 {
00412     SECStatus rv = SECSuccess;
00413     int atype = 0;
00414     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
00415     if (!mod) {
00416         return SECFailure;
00417     }
00418 
00419     SECMOD_GetReadLock(moduleLock);
00420     rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);
00421     SECMOD_ReleaseReadLock(moduleLock);
00422     if (SECSuccess != rv) {
00423         return SECFailure;
00424     }
00425     return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE);
00426 }
00427