Mercurial > trustbridge > nss-cmake-static
view nss/lib/softoken/lgglue.c @ 4:b513267f632f tip
Build DBM module
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:58:03 +0200 |
parents | 1e5118fa0cb1 |
children |
line wrap: on
line source
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * The following code handles the storage of PKCS 11 modules used by the * NSS. This file is written to abstract away how the modules are * stored so we can deside that later. */ #include "sftkdb.h" #include "sftkdbti.h" #include "sdb.h" #include "prsystem.h" #include "prprf.h" #include "prenv.h" #include "lgglue.h" #include "secerr.h" #include "softoken.h" static LGOpenFunc legacy_glue_open = NULL; static LGReadSecmodFunc legacy_glue_readSecmod = NULL; static LGReleaseSecmodFunc legacy_glue_releaseSecmod = NULL; static LGDeleteSecmodFunc legacy_glue_deleteSecmod = NULL; static LGAddSecmodFunc legacy_glue_addSecmod = NULL; static LGShutdownFunc legacy_glue_shutdown = NULL; #ifndef NSS_STATIC /* * The following 3 functions duplicate the work done by bl_LoadLibrary. * We should make bl_LoadLibrary a global and replace the call to * sftkdb_LoadLibrary(const char *libname) with it. */ #ifdef XP_UNIX #include <unistd.h> #define LG_MAX_LINKS 20 static char * sftkdb_resolvePath(const char *orig) { int count = 0; int len =0; int ret = -1; char *resolved = NULL; char *source = NULL; len = 1025; /* MAX PATH +1*/ if (strlen(orig)+1 > len) { /* PATH TOO LONG */ return NULL; } resolved = PORT_Alloc(len); if (!resolved) { return NULL; } source = PORT_Alloc(len); if (!source) { goto loser; } PORT_Strcpy(source, orig); /* Walk down all the links */ while ( count++ < LG_MAX_LINKS) { char *tmp; /* swap our previous sorce out with resolved */ /* read it */ ret = readlink(source, resolved, len-1); if (ret < 0) { break; } resolved[ret] = 0; tmp = source; source = resolved; resolved = tmp; } if (count > 1) { ret = 0; } loser: if (resolved) { PORT_Free(resolved); } if (ret < 0) { if (source) { PORT_Free(source); source = NULL; } } return source; } #endif static PRLibrary * sftkdb_LoadFromPath(const char *path, const char *libname) { char *c; int pathLen, nameLen, fullPathLen; char *fullPathName = NULL; PRLibSpec libSpec; PRLibrary *lib = NULL; /* strip of our parent's library name */ c = strrchr(path, PR_GetDirectorySeparator()); if (!c) { return NULL; /* invalid path */ } pathLen = (c-path)+1; nameLen = strlen(libname); fullPathLen = pathLen + nameLen +1; fullPathName = (char *)PORT_Alloc(fullPathLen); if (fullPathName == NULL) { return NULL; /* memory allocation error */ } PORT_Memcpy(fullPathName, path, pathLen); PORT_Memcpy(fullPathName+pathLen, libname, nameLen); fullPathName[fullPathLen-1] = 0; libSpec.type = PR_LibSpec_Pathname; libSpec.value.pathname = fullPathName; lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL); PORT_Free(fullPathName); return lib; } static PRLibrary * sftkdb_LoadLibrary(const char *libname) { PRLibrary *lib = NULL; PRFuncPtr fn_addr; char *parentLibPath = NULL; fn_addr = (PRFuncPtr) &sftkdb_LoadLibrary; parentLibPath = PR_GetLibraryFilePathname(SOFTOKEN_LIB_NAME, fn_addr); if (!parentLibPath) { goto done; } lib = sftkdb_LoadFromPath(parentLibPath, libname); #ifdef XP_UNIX /* handle symbolic link case */ if (!lib) { char *trueParentLibPath = sftkdb_resolvePath(parentLibPath); if (!trueParentLibPath) { goto done; } lib = sftkdb_LoadFromPath(trueParentLibPath, libname); PORT_Free(trueParentLibPath); } #endif done: if (parentLibPath) { PORT_Free(parentLibPath); } /* still couldn't load it, try the generic path */ if (!lib) { PRLibSpec libSpec; libSpec.type = PR_LibSpec_Pathname; libSpec.value.pathname = libname; lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL); } return lib; } #endif /* STATIC LIBRARIES */ /* * stub files for legacy db's to be able to encrypt and decrypt * various keys and attributes. */ static SECStatus sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText, SECItem **cipherText) { SFTKDBHandle *handle = sdb->app_private; SECStatus rv; if (handle == NULL) { return SECFailure; } /* if we aren't the key handle, try the other handle */ if (handle->type != SFTK_KEYDB_TYPE) { handle = handle->peerDB; } /* not a key handle */ if (handle == NULL || handle->passwordLock == NULL) { return SECFailure; } PZ_Lock(handle->passwordLock); if (handle->passwordKey.data == NULL) { PZ_Unlock(handle->passwordLock); /* PORT_SetError */ return SECFailure; } rv = sftkdb_EncryptAttribute(arena, handle->newKey?handle->newKey:&handle->passwordKey, plainText, cipherText); PZ_Unlock(handle->passwordLock); return rv; } /* * stub files for legacy db's to be able to encrypt and decrypt * various keys and attributes. */ static SECStatus sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText) { SFTKDBHandle *handle = sdb->app_private; SECStatus rv; SECItem *oldKey = NULL; if (handle == NULL) { return SECFailure; } /* if we aren't th handle, try the other handle */ oldKey = handle->oldKey; if (handle->type != SFTK_KEYDB_TYPE) { handle = handle->peerDB; } /* not a key handle */ if (handle == NULL || handle->passwordLock == NULL) { return SECFailure; } PZ_Lock(handle->passwordLock); if (handle->passwordKey.data == NULL) { PZ_Unlock(handle->passwordLock); /* PORT_SetError */ return SECFailure; } rv = sftkdb_DecryptAttribute( oldKey ? oldKey : &handle->passwordKey, cipherText, plainText); PZ_Unlock(handle->passwordLock); return rv; } static const char *LEGACY_LIB_NAME = SHLIB_PREFIX"nssdbm"SHLIB_VERSION"."SHLIB_SUFFIX; /* * 2 bools to tell us if we've check the legacy library successfully or * not. Initialize on startup to false by the C BSS segment; */ static PRBool legacy_glue_libCheckFailed; /* set if we failed the check */ static PRBool legacy_glue_libCheckSucceeded; /* set if we passed the check */ static PRLibrary *legacy_glue_lib = NULL; static SECStatus sftkdbLoad_Legacy(PRBool isFIPS) { PRLibrary *lib = NULL; LGSetCryptFunc setCryptFunction = NULL; if (legacy_glue_lib) { /* this check is necessary because it's possible we loaded the * legacydb to read secmod.db, which told us whether we were in * FIPS mode or not. */ if (isFIPS && !legacy_glue_libCheckSucceeded) { if (legacy_glue_libCheckFailed || !BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) { legacy_glue_libCheckFailed = PR_TRUE; /* don't clobber legacy glue to avoid race. just let it * get cleared in shutdown */ return SECFailure; } legacy_glue_libCheckSucceeded = PR_TRUE; } return SECSuccess; } #ifdef NSS_STATIC #ifdef NSS_DISABLE_DBM return SECFailure; #else lib = (PRLibrary *) 0x8; legacy_glue_open = legacy_Open; legacy_glue_readSecmod = legacy_ReadSecmodDB; legacy_glue_releaseSecmod = legacy_ReleaseSecmodDBData; legacy_glue_deleteSecmod = legacy_DeleteSecmodDB; legacy_glue_addSecmod = legacy_AddSecmodDB; legacy_glue_shutdown = legacy_Shutdown; setCryptFunction = legacy_SetCryptFunctions; #endif #else lib = sftkdb_LoadLibrary(LEGACY_LIB_NAME); if (lib == NULL) { return SECFailure; } legacy_glue_open = (LGOpenFunc)PR_FindFunctionSymbol(lib, "legacy_Open"); legacy_glue_readSecmod = (LGReadSecmodFunc) PR_FindFunctionSymbol(lib, "legacy_ReadSecmodDB"); legacy_glue_releaseSecmod = (LGReleaseSecmodFunc) PR_FindFunctionSymbol(lib, "legacy_ReleaseSecmodDBData"); legacy_glue_deleteSecmod = (LGDeleteSecmodFunc) PR_FindFunctionSymbol(lib, "legacy_DeleteSecmodDB"); legacy_glue_addSecmod = (LGAddSecmodFunc)PR_FindFunctionSymbol(lib, "legacy_AddSecmodDB"); legacy_glue_shutdown = (LGShutdownFunc) PR_FindFunctionSymbol(lib, "legacy_Shutdown"); setCryptFunction = (LGSetCryptFunc) PR_FindFunctionSymbol(lib, "legacy_SetCryptFunctions"); if (!legacy_glue_open || !legacy_glue_readSecmod || !legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod || !legacy_glue_addSecmod || !setCryptFunction) { PR_UnloadLibrary(lib); return SECFailure; } #endif /* NSS_STATIC */ /* verify the loaded library if we are in FIPS mode */ if (isFIPS) { if (!BLAPI_SHVerify(LEGACY_LIB_NAME,(PRFuncPtr)legacy_glue_open)) { #ifndef NSS_STATIC PR_UnloadLibrary(lib); #endif return SECFailure; } legacy_glue_libCheckSucceeded = PR_TRUE; } setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub); legacy_glue_lib = lib; return SECSuccess; } CK_RV sftkdbCall_open(const char *dir, const char *certPrefix, const char *keyPrefix, int certVersion, int keyVersion, int flags, PRBool isFIPS, SDB **certDB, SDB **keyDB) { SECStatus rv; rv = sftkdbLoad_Legacy(isFIPS); if (rv != SECSuccess) { return CKR_GENERAL_ERROR; } if (!legacy_glue_open) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } return (*legacy_glue_open)(dir, certPrefix, keyPrefix, certVersion, keyVersion, flags, certDB, keyDB); } char ** sftkdbCall_ReadSecmodDB(const char *appName, const char *filename, const char *dbname, char *params, PRBool rw) { SECStatus rv; rv = sftkdbLoad_Legacy(PR_FALSE); if (rv != SECSuccess) { return NULL; } if (!legacy_glue_readSecmod) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL; } return (*legacy_glue_readSecmod)(appName, filename, dbname, params, rw); } SECStatus sftkdbCall_ReleaseSecmodDBData(const char *appName, const char *filename, const char *dbname, char **moduleSpecList, PRBool rw) { SECStatus rv; rv = sftkdbLoad_Legacy(PR_FALSE); if (rv != SECSuccess) { return rv; } if (!legacy_glue_releaseSecmod) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } return (*legacy_glue_releaseSecmod)(appName, filename, dbname, moduleSpecList, rw); } SECStatus sftkdbCall_DeleteSecmodDB(const char *appName, const char *filename, const char *dbname, char *args, PRBool rw) { SECStatus rv; rv = sftkdbLoad_Legacy(PR_FALSE); if (rv != SECSuccess) { return rv; } if (!legacy_glue_deleteSecmod) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } return (*legacy_glue_deleteSecmod)(appName, filename, dbname, args, rw); } SECStatus sftkdbCall_AddSecmodDB(const char *appName, const char *filename, const char *dbname, char *module, PRBool rw) { SECStatus rv; rv = sftkdbLoad_Legacy(PR_FALSE); if (rv != SECSuccess) { return rv; } if (!legacy_glue_addSecmod) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } return (*legacy_glue_addSecmod)(appName, filename, dbname, module, rw); } CK_RV sftkdbCall_Shutdown(void) { CK_RV crv = CKR_OK; char *disableUnload = NULL; if (!legacy_glue_lib) { return CKR_OK; } if (legacy_glue_shutdown) { #ifdef NO_FORK_CHECK PRBool parentForkedAfterC_Initialize = PR_FALSE; #endif crv = (*legacy_glue_shutdown)(parentForkedAfterC_Initialize); } #ifndef NSS_STATIC disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD"); if (!disableUnload) { PR_UnloadLibrary(legacy_glue_lib); } #endif legacy_glue_lib = NULL; legacy_glue_open = NULL; legacy_glue_readSecmod = NULL; legacy_glue_releaseSecmod = NULL; legacy_glue_deleteSecmod = NULL; legacy_glue_addSecmod = NULL; legacy_glue_libCheckFailed = PR_FALSE; legacy_glue_libCheckSucceeded = PR_FALSE; return crv; }