1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * The following code handles the storage of PKCS 11 modules used by the
38 * NSS. This file is written to abstract away how the modules are
39 * stored so we can deside that later.
51 static LGOpenFunc legacy_glue_open = NULL;
52 static LGReadSecmodFunc legacy_glue_readSecmod = NULL;
53 static LGReleaseSecmodFunc legacy_glue_releaseSecmod = NULL;
54 static LGDeleteSecmodFunc legacy_glue_deleteSecmod = NULL;
55 static LGAddSecmodFunc legacy_glue_addSecmod = NULL;
56 static LGShutdownFunc legacy_glue_shutdown = NULL;
59 * The following 3 functions duplicate the work done by bl_LoadLibrary.
60 * We should make bl_LoadLibrary a global and replace the call to
61 * sftkdb_LoadLibrary(const char *libname) with it.
65 #define LG_MAX_LINKS 20
67 sftkdb_resolvePath(const char *orig)
72 char *resolved = NULL;
75 len = 1025; /* MAX PATH +1*/
76 if (strlen(orig)+1 > len) {
80 resolved = PORT_Alloc(len);
84 source = PORT_Alloc(len);
88 PORT_Strcpy(source, orig);
89 /* Walk down all the links */
90 while ( count++ < LG_MAX_LINKS) {
92 /* swap our previous sorce out with resolved */
94 ret = readlink(source, resolved, len-1);
99 tmp = source; source = resolved; resolved = tmp;
120 sftkdb_LoadFromPath(const char *path, const char *libname)
123 int pathLen, nameLen, fullPathLen;
124 char *fullPathName = NULL;
126 PRLibrary *lib = NULL;
129 /* strip of our parent's library name */
130 c = strrchr(path, PR_GetDirectorySeparator());
132 return NULL; /* invalid path */
134 pathLen = (c-path)+1;
135 nameLen = strlen(libname);
136 fullPathLen = pathLen + nameLen +1;
137 fullPathName = (char *)PORT_Alloc(fullPathLen);
138 if (fullPathName == NULL) {
139 return NULL; /* memory allocation error */
141 PORT_Memcpy(fullPathName, path, pathLen);
142 PORT_Memcpy(fullPathName+pathLen, libname, nameLen);
143 fullPathName[fullPathLen-1] = 0;
145 libSpec.type = PR_LibSpec_Pathname;
146 libSpec.value.pathname = fullPathName;
147 lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
148 PORT_Free(fullPathName);
154 sftkdb_LoadLibrary(const char *libname)
156 PRLibrary *lib = NULL;
158 char *parentLibPath = NULL;
160 fn_addr = (PRFuncPtr) &sftkdb_LoadLibrary;
161 parentLibPath = PR_GetLibraryFilePathname(SOFTOKEN_LIB_NAME, fn_addr);
163 if (!parentLibPath) {
167 lib = sftkdb_LoadFromPath(parentLibPath, libname);
169 /* handle symbolic link case */
171 char *trueParentLibPath = sftkdb_resolvePath(parentLibPath);
172 if (!trueParentLibPath) {
175 lib = sftkdb_LoadFromPath(trueParentLibPath, libname);
176 PORT_Free(trueParentLibPath);
182 PORT_Free(parentLibPath);
185 /* still couldn't load it, try the generic path */
188 libSpec.type = PR_LibSpec_Pathname;
189 libSpec.value.pathname = libname;
190 lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
197 * stub files for legacy db's to be able to encrypt and decrypt
198 * various keys and attributes.
201 sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
202 SECItem **cipherText)
204 SFTKDBHandle *handle = sdb->app_private;
207 if (handle == NULL) {
211 /* if we aren't the key handle, try the other handle */
212 if (handle->type != SFTK_KEYDB_TYPE) {
213 handle = handle->peerDB;
216 /* not a key handle */
217 if (handle == NULL || handle->passwordLock == NULL) {
221 PZ_Lock(handle->passwordLock);
222 if (handle->passwordKey.data == NULL) {
223 PZ_Unlock(handle->passwordLock);
228 rv = sftkdb_EncryptAttribute(arena,
229 handle->newKey?handle->newKey:&handle->passwordKey,
230 plainText, cipherText);
231 PZ_Unlock(handle->passwordLock);
237 * stub files for legacy db's to be able to encrypt and decrypt
238 * various keys and attributes.
241 sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
243 SFTKDBHandle *handle = sdb->app_private;
245 SECItem *oldKey = NULL;
247 if (handle == NULL) {
251 /* if we aren't th handle, try the other handle */
252 oldKey = handle->oldKey;
253 if (handle->type != SFTK_KEYDB_TYPE) {
254 handle = handle->peerDB;
257 /* not a key handle */
258 if (handle == NULL || handle->passwordLock == NULL) {
262 PZ_Lock(handle->passwordLock);
263 if (handle->passwordKey.data == NULL) {
264 PZ_Unlock(handle->passwordLock);
268 rv = sftkdb_DecryptAttribute( oldKey ? oldKey : &handle->passwordKey,
269 cipherText, plainText);
270 PZ_Unlock(handle->passwordLock);
275 static const char *LEGACY_LIB_NAME =
276 SHLIB_PREFIX"nssdbm"SHLIB_VERSION"."SHLIB_SUFFIX;
278 * 2 bools to tell us if we've check the legacy library successfully or
279 * not. Initialize on startup to false by the C BSS segment;
281 static PRBool legacy_glue_libCheckFailed; /* set if we failed the check */
282 static PRBool legacy_glue_libCheckSucceeded; /* set if we passed the check */
283 static PRLibrary *legacy_glue_lib = NULL;
285 sftkdbLoad_Legacy(PRBool isFIPS)
287 PRLibrary *lib = NULL;
288 LGSetCryptFunc setCryptFunction = NULL;
290 if (legacy_glue_lib) {
291 /* this check is necessary because it's possible we loaded the
292 * legacydb to read secmod.db, which told us whether we were in
293 * FIPS mode or not. */
294 if (isFIPS && !legacy_glue_libCheckSucceeded) {
295 if (legacy_glue_libCheckFailed ||
296 !BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) {
297 legacy_glue_libCheckFailed = PR_TRUE;
298 /* don't clobber legacy glue to avoid race. just let it
299 * get cleared in shutdown */
302 legacy_glue_libCheckSucceeded = PR_TRUE;
307 lib = sftkdb_LoadLibrary(LEGACY_LIB_NAME);
312 legacy_glue_open = (LGOpenFunc)PR_FindFunctionSymbol(lib, "legacy_Open");
313 legacy_glue_readSecmod = (LGReadSecmodFunc) PR_FindFunctionSymbol(lib,
314 "legacy_ReadSecmodDB");
315 legacy_glue_releaseSecmod = (LGReleaseSecmodFunc) PR_FindFunctionSymbol(lib,
316 "legacy_ReleaseSecmodDBData");
317 legacy_glue_deleteSecmod = (LGDeleteSecmodFunc) PR_FindFunctionSymbol(lib,
318 "legacy_DeleteSecmodDB");
319 legacy_glue_addSecmod = (LGAddSecmodFunc)PR_FindFunctionSymbol(lib,
320 "legacy_AddSecmodDB");
321 legacy_glue_shutdown = (LGShutdownFunc) PR_FindFunctionSymbol(lib,
323 setCryptFunction = (LGSetCryptFunc) PR_FindFunctionSymbol(lib,
324 "legacy_SetCryptFunctions");
326 if (!legacy_glue_open || !legacy_glue_readSecmod ||
327 !legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod ||
328 !legacy_glue_addSecmod || !setCryptFunction) {
329 PR_UnloadLibrary(lib);
333 /* verify the loaded library if we are in FIPS mode */
335 if (!BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) {
336 PR_UnloadLibrary(lib);
339 legacy_glue_libCheckSucceeded = PR_TRUE;
342 setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub);
343 legacy_glue_lib = lib;
348 sftkdbCall_open(const char *dir, const char *certPrefix, const char *keyPrefix,
349 int certVersion, int keyVersion, int flags, PRBool isFIPS,
350 SDB **certDB, SDB **keyDB)
354 rv = sftkdbLoad_Legacy(isFIPS);
355 if (rv != SECSuccess) {
356 return CKR_GENERAL_ERROR;
358 if (!legacy_glue_open) {
359 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
362 return (*legacy_glue_open)(dir, certPrefix, keyPrefix,
363 certVersion, keyVersion,
364 flags, certDB, keyDB);
368 sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
369 const char *dbname, char *params, PRBool rw)
373 rv = sftkdbLoad_Legacy(PR_FALSE);
374 if (rv != SECSuccess) {
377 if (!legacy_glue_readSecmod) {
378 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
381 return (*legacy_glue_readSecmod)(appName, filename, dbname, params, rw);
385 sftkdbCall_ReleaseSecmodDBData(const char *appName,
386 const char *filename, const char *dbname,
387 char **moduleSpecList, PRBool rw)
391 rv = sftkdbLoad_Legacy(PR_FALSE);
392 if (rv != SECSuccess) {
395 if (!legacy_glue_releaseSecmod) {
396 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
399 return (*legacy_glue_releaseSecmod)(appName, filename, dbname,
404 sftkdbCall_DeleteSecmodDB(const char *appName,
405 const char *filename, const char *dbname,
406 char *args, PRBool rw)
410 rv = sftkdbLoad_Legacy(PR_FALSE);
411 if (rv != SECSuccess) {
414 if (!legacy_glue_deleteSecmod) {
415 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
418 return (*legacy_glue_deleteSecmod)(appName, filename, dbname, args, rw);
422 sftkdbCall_AddSecmodDB(const char *appName,
423 const char *filename, const char *dbname,
424 char *module, PRBool rw)
428 rv = sftkdbLoad_Legacy(PR_FALSE);
429 if (rv != SECSuccess) {
432 if (!legacy_glue_addSecmod) {
433 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
436 return (*legacy_glue_addSecmod)(appName, filename, dbname, module, rw);
440 sftkdbCall_Shutdown(void)
443 char *disableUnload = NULL;
444 if (!legacy_glue_lib) {
447 if (legacy_glue_shutdown) {
449 PRBool parentForkedAfterC_Initialize = PR_FALSE;
451 crv = (*legacy_glue_shutdown)(parentForkedAfterC_Initialize);
453 disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
454 if (!disableUnload) {
455 PR_UnloadLibrary(legacy_glue_lib);
457 legacy_glue_lib = NULL;
458 legacy_glue_open = NULL;
459 legacy_glue_readSecmod = NULL;
460 legacy_glue_releaseSecmod = NULL;
461 legacy_glue_deleteSecmod = NULL;
462 legacy_glue_addSecmod = NULL;
463 legacy_glue_libCheckFailed = PR_FALSE;
464 legacy_glue_libCheckSucceeded = PR_FALSE;