mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-17 20:57:30 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
765
security/nss/lib/util/utilmod.c
Normal file
765
security/nss/lib/util/utilmod.c
Normal file
|
|
@ -0,0 +1,765 @@
|
|||
/* 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. For the rest of NSS, only one kind of database handle exists:
|
||||
*
|
||||
* SFTKDBHandle
|
||||
*
|
||||
* There is one SFTKDBHandle for each key database and one for each cert
|
||||
* database. These databases are opened as associated pairs, one pair per
|
||||
* slot. SFTKDBHandles are reference counted objects.
|
||||
*
|
||||
* Each SFTKDBHandle points to a low level database handle (SDB). This handle
|
||||
* represents the underlying physical database. These objects are not
|
||||
* reference counted, and are 'owned' by their respective SFTKDBHandles.
|
||||
*/
|
||||
|
||||
#include "prprf.h"
|
||||
#include "prsystem.h"
|
||||
#include "secport.h"
|
||||
#include "utilpars.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef XP_UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define os_open _open
|
||||
#define os_fdopen _fdopen
|
||||
#define os_stat _stat
|
||||
#define os_truncate_open_flags _O_CREAT | _O_RDWR | _O_TRUNC
|
||||
#define os_append_open_flags _O_CREAT | _O_RDWR | _O_APPEND
|
||||
#define os_open_permissions_type int
|
||||
#define os_open_permissions_default _S_IREAD | _S_IWRITE
|
||||
#define os_stat_type struct _stat
|
||||
#else
|
||||
#define os_open open
|
||||
#define os_fdopen fdopen
|
||||
#define os_stat stat
|
||||
#define os_truncate_open_flags O_CREAT | O_RDWR | O_TRUNC
|
||||
#define os_append_open_flags O_CREAT | O_RDWR | O_APPEND
|
||||
#define os_open_permissions_type mode_t
|
||||
#define os_open_permissions_default 0600
|
||||
#define os_stat_type struct stat
|
||||
#endif
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* Secmod database.
|
||||
*
|
||||
* The new secmod database is simply a text file with each of the module
|
||||
* entries in the following form:
|
||||
*
|
||||
* #
|
||||
* # This is a comment The next line is the library to load
|
||||
* library=libmypkcs11.so
|
||||
* name="My PKCS#11 module"
|
||||
* params="my library's param string"
|
||||
* nss="NSS parameters"
|
||||
* other="parameters for other libraries and applications"
|
||||
*
|
||||
* library=libmynextpk11.so
|
||||
* name="My other PKCS#11 module"
|
||||
*/
|
||||
|
||||
/*
|
||||
* Smart string cat functions. Automatically manage the memory.
|
||||
* The first parameter is the destination string. If it's null, we
|
||||
* allocate memory for it. If it's not, we reallocate memory
|
||||
* so the the concanenated string fits.
|
||||
*/
|
||||
static char *
|
||||
nssutil_DupnCat(char *baseString, const char *str, int str_len)
|
||||
{
|
||||
int baseStringLen = baseString ? PORT_Strlen(baseString) : 0;
|
||||
int len = baseStringLen + 1;
|
||||
char *newString;
|
||||
|
||||
len += str_len;
|
||||
newString = (char *)PORT_Realloc(baseString, len);
|
||||
if (newString == NULL) {
|
||||
PORT_Free(baseString);
|
||||
return NULL;
|
||||
}
|
||||
PORT_Memcpy(&newString[baseStringLen], str, str_len);
|
||||
newString[len - 1] = 0;
|
||||
return newString;
|
||||
}
|
||||
|
||||
/* Same as nssutil_DupnCat except it concatenates the full string, not a
|
||||
* partial one */
|
||||
static char *
|
||||
nssutil_DupCat(char *baseString, const char *str)
|
||||
{
|
||||
return nssutil_DupnCat(baseString, str, PORT_Strlen(str));
|
||||
}
|
||||
|
||||
/* function to free up all the memory associated with a null terminated
|
||||
* array of module specs */
|
||||
static SECStatus
|
||||
nssutil_releaseSpecList(char **moduleSpecList)
|
||||
{
|
||||
if (moduleSpecList) {
|
||||
char **index;
|
||||
for (index = moduleSpecList; *index; index++) {
|
||||
PORT_Free(*index);
|
||||
}
|
||||
PORT_Free(moduleSpecList);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#define SECMOD_STEP 10
|
||||
static SECStatus
|
||||
nssutil_growList(char ***pModuleList, int *useCount, int last)
|
||||
{
|
||||
char **newModuleList;
|
||||
|
||||
*useCount += SECMOD_STEP;
|
||||
newModuleList = (char **)PORT_Realloc(*pModuleList,
|
||||
*useCount * sizeof(char *));
|
||||
if (newModuleList == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memset(&newModuleList[last], 0, sizeof(char *) * SECMOD_STEP);
|
||||
*pModuleList = newModuleList;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static char *
|
||||
_NSSUTIL_GetOldSecmodName(const char *dbname, const char *filename)
|
||||
{
|
||||
char *file = NULL;
|
||||
char *dirPath = PORT_Strdup(dbname);
|
||||
char *sep;
|
||||
|
||||
sep = PORT_Strrchr(dirPath, *NSSUTIL_PATH_SEPARATOR);
|
||||
#ifdef _WIN32
|
||||
if (!sep) {
|
||||
/* utilparst.h defines NSSUTIL_PATH_SEPARATOR as "/" for all
|
||||
* platforms. */
|
||||
sep = PORT_Strrchr(dirPath, '\\');
|
||||
}
|
||||
#endif
|
||||
if (sep) {
|
||||
*sep = 0;
|
||||
file = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s", dirPath, filename);
|
||||
} else {
|
||||
file = PR_smprintf("%s", filename);
|
||||
}
|
||||
PORT_Free(dirPath);
|
||||
return file;
|
||||
}
|
||||
|
||||
static SECStatus nssutil_AddSecmodDBEntry(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname,
|
||||
const char *module, PRBool rw);
|
||||
|
||||
enum lfopen_mode { lfopen_truncate,
|
||||
lfopen_append };
|
||||
|
||||
FILE *
|
||||
lfopen(const char *name, enum lfopen_mode om, os_open_permissions_type open_perms)
|
||||
{
|
||||
int fd;
|
||||
FILE *file;
|
||||
|
||||
fd = os_open(name,
|
||||
(om == lfopen_truncate) ? os_truncate_open_flags : os_append_open_flags,
|
||||
open_perms);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
file = os_fdopen(fd, (om == lfopen_truncate) ? "w+" : "a+");
|
||||
if (!file) {
|
||||
close(fd);
|
||||
}
|
||||
/* file inherits fd */
|
||||
return file;
|
||||
}
|
||||
|
||||
#define MAX_LINE_LENGTH 2048
|
||||
|
||||
/*
|
||||
* Read all the existing modules in out of the file.
|
||||
*/
|
||||
static char **
|
||||
nssutil_ReadSecmodDB(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *params, PRBool rw)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
char **moduleList = NULL;
|
||||
int moduleCount = 1;
|
||||
int useCount = SECMOD_STEP;
|
||||
char line[MAX_LINE_LENGTH];
|
||||
PRBool internal = PR_FALSE;
|
||||
PRBool skipParams = PR_FALSE;
|
||||
char *moduleString = NULL;
|
||||
char *paramsValue = NULL;
|
||||
PRBool failed = PR_TRUE;
|
||||
|
||||
moduleList = (char **)PORT_ZAlloc(useCount * sizeof(char *));
|
||||
if (moduleList == NULL)
|
||||
return NULL;
|
||||
|
||||
if (dbname == NULL) {
|
||||
goto return_default;
|
||||
}
|
||||
|
||||
/* do we really want to use streams here */
|
||||
fd = fopen(dbname, "r");
|
||||
if (fd == NULL)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* the following loop takes line separated config lines and collapses
|
||||
* the lines to a single string, escaping and quoting as necessary.
|
||||
*/
|
||||
/* loop state variables */
|
||||
moduleString = NULL; /* current concatenated string */
|
||||
internal = PR_FALSE; /* is this an internal module */
|
||||
skipParams = PR_FALSE; /* did we find an override parameter block*/
|
||||
paramsValue = NULL; /* the current parameter block value */
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
int len = PORT_Strlen(line);
|
||||
|
||||
/* remove the ending newline */
|
||||
if (len && line[len - 1] == '\n') {
|
||||
len--;
|
||||
line[len] = 0;
|
||||
}
|
||||
if (*line == '#') {
|
||||
continue;
|
||||
}
|
||||
if (*line != 0) {
|
||||
/*
|
||||
* The PKCS #11 group standard assumes blocks of strings
|
||||
* separated by new lines, clumped by new lines. Internally
|
||||
* we take strings separated by spaces, so we may need to escape
|
||||
* certain spaces.
|
||||
*/
|
||||
char *value = PORT_Strchr(line, '=');
|
||||
|
||||
/* there is no value, write out the stanza as is */
|
||||
if (value == NULL || value[1] == 0) {
|
||||
if (moduleString) {
|
||||
moduleString = nssutil_DupnCat(moduleString, " ", 1);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
}
|
||||
moduleString = nssutil_DupCat(moduleString, line);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
/* value is already quoted, just write it out */
|
||||
} else if (value[1] == '"') {
|
||||
if (moduleString) {
|
||||
moduleString = nssutil_DupnCat(moduleString, " ", 1);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
}
|
||||
moduleString = nssutil_DupCat(moduleString, line);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
/* we have an override parameter section, remember that
|
||||
* we found this (see following comment about why this
|
||||
* is necessary). */
|
||||
if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
|
||||
skipParams = PR_TRUE;
|
||||
}
|
||||
/*
|
||||
* The internal token always overrides it's parameter block
|
||||
* from the passed in parameters, so wait until then end
|
||||
* before we include the parameter block in case we need to
|
||||
* override it. NOTE: if the parameter block is quoted with ("),
|
||||
* this override does not happen. This allows you to override
|
||||
* the application's parameter configuration.
|
||||
*
|
||||
* parameter block state is controlled by the following variables:
|
||||
* skipParams - Bool : set to true of we have an override param
|
||||
* block (all other blocks, either implicit or explicit are
|
||||
* ignored).
|
||||
* paramsValue - char * : pointer to the current param block. In
|
||||
* the absence of overrides, paramsValue is set to the first
|
||||
* parameter block we find. All subsequent blocks are ignored.
|
||||
* When we find an internal token, the application passed
|
||||
* parameters take precident.
|
||||
*/
|
||||
} else if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
|
||||
/* already have parameters */
|
||||
if (paramsValue) {
|
||||
continue;
|
||||
}
|
||||
paramsValue = NSSUTIL_Quote(&value[1], '"');
|
||||
if (paramsValue == NULL)
|
||||
goto loser;
|
||||
continue;
|
||||
} else {
|
||||
/* may need to quote */
|
||||
char *newLine;
|
||||
if (moduleString) {
|
||||
moduleString = nssutil_DupnCat(moduleString, " ", 1);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
}
|
||||
moduleString = nssutil_DupnCat(moduleString, line, value - line + 1);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
newLine = NSSUTIL_Quote(&value[1], '"');
|
||||
if (newLine == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString, newLine);
|
||||
PORT_Free(newLine);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* check to see if it's internal? */
|
||||
if (PORT_Strncasecmp(line, "NSS=", 4) == 0) {
|
||||
/* This should be case insensitive! reviewers make
|
||||
* me fix it if it's not */
|
||||
if (PORT_Strstr(line, "internal")) {
|
||||
internal = PR_TRUE;
|
||||
/* override the parameters */
|
||||
if (paramsValue) {
|
||||
PORT_Free(paramsValue);
|
||||
}
|
||||
paramsValue = NSSUTIL_Quote(params, '"');
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((moduleString == NULL) || (*moduleString == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we are here, we have found a complete stanza. Now write out
|
||||
* any param section we may have found.
|
||||
*/
|
||||
if (paramsValue) {
|
||||
/* we had an override */
|
||||
if (!skipParams) {
|
||||
moduleString = nssutil_DupnCat(moduleString, " parameters=", 12);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString, paramsValue);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
}
|
||||
PORT_Free(paramsValue);
|
||||
paramsValue = NULL;
|
||||
}
|
||||
|
||||
if ((moduleCount + 1) >= useCount) {
|
||||
SECStatus rv;
|
||||
rv = nssutil_growList(&moduleList, &useCount, moduleCount + 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
if (internal) {
|
||||
moduleList[0] = moduleString;
|
||||
} else {
|
||||
moduleList[moduleCount] = moduleString;
|
||||
moduleCount++;
|
||||
}
|
||||
moduleString = NULL;
|
||||
internal = PR_FALSE;
|
||||
skipParams = PR_FALSE;
|
||||
}
|
||||
|
||||
if (moduleString) {
|
||||
PORT_Free(moduleString);
|
||||
moduleString = NULL;
|
||||
}
|
||||
done:
|
||||
/* if we couldn't open a pkcs11 database, look for the old one */
|
||||
if (fd == NULL) {
|
||||
char *olddbname = _NSSUTIL_GetOldSecmodName(dbname, filename);
|
||||
PRStatus status;
|
||||
|
||||
/* couldn't get the old name */
|
||||
if (!olddbname) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* old one exists */
|
||||
status = PR_Access(olddbname, PR_ACCESS_EXISTS);
|
||||
if (status == PR_SUCCESS) {
|
||||
PR_smprintf_free(olddbname);
|
||||
PORT_ZFree(moduleList, useCount * sizeof(char *));
|
||||
PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bail:
|
||||
if (olddbname) {
|
||||
PR_smprintf_free(olddbname);
|
||||
}
|
||||
}
|
||||
|
||||
return_default:
|
||||
|
||||
if (!moduleList[0]) {
|
||||
char *newParams;
|
||||
moduleString = PORT_Strdup(NSSUTIL_DEFAULT_INTERNAL_INIT1);
|
||||
newParams = NSSUTIL_Quote(params, '"');
|
||||
if (newParams == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString, newParams);
|
||||
PORT_Free(newParams);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString,
|
||||
NSSUTIL_DEFAULT_INTERNAL_INIT2);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString,
|
||||
NSSUTIL_DEFAULT_SFTKN_FLAGS);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
moduleString = nssutil_DupCat(moduleString,
|
||||
NSSUTIL_DEFAULT_INTERNAL_INIT3);
|
||||
if (moduleString == NULL)
|
||||
goto loser;
|
||||
moduleList[0] = moduleString;
|
||||
moduleString = NULL;
|
||||
}
|
||||
failed = PR_FALSE;
|
||||
|
||||
loser:
|
||||
/*
|
||||
* cleanup
|
||||
*/
|
||||
/* deal with trust cert db here */
|
||||
if (moduleString) {
|
||||
PORT_Free(moduleString);
|
||||
moduleString = NULL;
|
||||
}
|
||||
if (paramsValue) {
|
||||
PORT_Free(paramsValue);
|
||||
paramsValue = NULL;
|
||||
}
|
||||
if (failed || (moduleList[0] == NULL)) {
|
||||
/* This is wrong! FIXME */
|
||||
nssutil_releaseSpecList(moduleList);
|
||||
moduleList = NULL;
|
||||
failed = PR_TRUE;
|
||||
}
|
||||
if (fd != NULL) {
|
||||
fclose(fd);
|
||||
} else if (!failed && rw) {
|
||||
/* update our internal module */
|
||||
nssutil_AddSecmodDBEntry(appName, filename, dbname, moduleList[0], rw);
|
||||
}
|
||||
return moduleList;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
nssutil_ReleaseSecmodDBData(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char **moduleSpecList, PRBool rw)
|
||||
{
|
||||
if (moduleSpecList) {
|
||||
nssutil_releaseSpecList(moduleSpecList);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a module from the Data Base
|
||||
*/
|
||||
static SECStatus
|
||||
nssutil_DeleteSecmodDBEntry(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname,
|
||||
const char *args,
|
||||
PRBool rw)
|
||||
{
|
||||
/* SHDB_FIXME implement */
|
||||
os_stat_type stat_existing;
|
||||
os_open_permissions_type file_mode;
|
||||
FILE *fd = NULL;
|
||||
FILE *fd2 = NULL;
|
||||
char line[MAX_LINE_LENGTH];
|
||||
char *dbname2 = NULL;
|
||||
char *block = NULL;
|
||||
char *name = NULL;
|
||||
char *lib = NULL;
|
||||
int name_len = 0, lib_len = 0;
|
||||
PRBool skip = PR_FALSE;
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
if (dbname == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (!rw) {
|
||||
PORT_SetError(SEC_ERROR_READ_ONLY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
dbname2 = PORT_Strdup(dbname);
|
||||
if (dbname2 == NULL)
|
||||
goto loser;
|
||||
dbname2[strlen(dbname) - 1]++;
|
||||
|
||||
/* get the permissions of the existing file, or use the default */
|
||||
if (!os_stat(dbname, &stat_existing)) {
|
||||
file_mode = stat_existing.st_mode;
|
||||
} else {
|
||||
file_mode = os_open_permissions_default;
|
||||
}
|
||||
|
||||
/* do we really want to use streams here */
|
||||
fd = fopen(dbname, "r");
|
||||
if (fd == NULL)
|
||||
goto loser;
|
||||
|
||||
fd2 = lfopen(dbname2, lfopen_truncate, file_mode);
|
||||
|
||||
if (fd2 == NULL)
|
||||
goto loser;
|
||||
|
||||
name = NSSUTIL_ArgGetParamValue("name", args);
|
||||
if (name) {
|
||||
name_len = PORT_Strlen(name);
|
||||
}
|
||||
lib = NSSUTIL_ArgGetParamValue("library", args);
|
||||
if (lib) {
|
||||
lib_len = PORT_Strlen(lib);
|
||||
}
|
||||
|
||||
/*
|
||||
* the following loop takes line separated config files and collapses
|
||||
* the lines to a single string, escaping and quoting as necessary.
|
||||
*/
|
||||
/* loop state variables */
|
||||
block = NULL;
|
||||
skip = PR_FALSE;
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
/* If we are processing a block (we haven't hit a blank line yet */
|
||||
if (*line != '\n') {
|
||||
/* skip means we are in the middle of a block we are deleting */
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
/* if we haven't found the block yet, check to see if this block
|
||||
* matches our requirements */
|
||||
if (!found && ((name && (PORT_Strncasecmp(line, "name=", 5) == 0) &&
|
||||
(PORT_Strncmp(line + 5, name, name_len) == 0)) ||
|
||||
(lib && (PORT_Strncasecmp(line, "library=", 8) == 0) &&
|
||||
(PORT_Strncmp(line + 8, lib, lib_len) == 0)))) {
|
||||
|
||||
/* yup, we don't need to save any more data, */
|
||||
PORT_Free(block);
|
||||
block = NULL;
|
||||
/* we don't need to collect more of this block */
|
||||
skip = PR_TRUE;
|
||||
/* we don't need to continue searching for the block */
|
||||
found = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
/* not our match, continue to collect data in this block */
|
||||
block = nssutil_DupCat(block, line);
|
||||
continue;
|
||||
}
|
||||
/* we've collected a block of data that wasn't the module we were
|
||||
* looking for, write it out */
|
||||
if (block) {
|
||||
fwrite(block, PORT_Strlen(block), 1, fd2);
|
||||
PORT_Free(block);
|
||||
block = NULL;
|
||||
}
|
||||
/* If we didn't just delete the this block, keep the blank line */
|
||||
if (!skip) {
|
||||
fputs(line, fd2);
|
||||
}
|
||||
/* we are definately not in a deleted block anymore */
|
||||
skip = PR_FALSE;
|
||||
}
|
||||
fclose(fd);
|
||||
fclose(fd2);
|
||||
if (found) {
|
||||
/* rename dbname2 to dbname */
|
||||
PR_Delete(dbname);
|
||||
PR_Rename(dbname2, dbname);
|
||||
} else {
|
||||
PR_Delete(dbname2);
|
||||
}
|
||||
PORT_Free(dbname2);
|
||||
PORT_Free(lib);
|
||||
PORT_Free(name);
|
||||
PORT_Free(block);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
if (fd != NULL) {
|
||||
fclose(fd);
|
||||
}
|
||||
if (fd2 != NULL) {
|
||||
fclose(fd2);
|
||||
}
|
||||
if (dbname2) {
|
||||
PR_Delete(dbname2);
|
||||
PORT_Free(dbname2);
|
||||
}
|
||||
PORT_Free(lib);
|
||||
PORT_Free(name);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a module to the Data base
|
||||
*/
|
||||
static SECStatus
|
||||
nssutil_AddSecmodDBEntry(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
const char *module, PRBool rw)
|
||||
{
|
||||
os_stat_type stat_existing;
|
||||
os_open_permissions_type file_mode;
|
||||
FILE *fd = NULL;
|
||||
char *block = NULL;
|
||||
PRBool libFound = PR_FALSE;
|
||||
|
||||
if (dbname == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* can't write to a read only module */
|
||||
if (!rw) {
|
||||
PORT_SetError(SEC_ERROR_READ_ONLY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* remove the previous version if it exists */
|
||||
(void)nssutil_DeleteSecmodDBEntry(appName, filename, dbname, module, rw);
|
||||
|
||||
/* get the permissions of the existing file, or use the default */
|
||||
if (!os_stat(dbname, &stat_existing)) {
|
||||
file_mode = stat_existing.st_mode;
|
||||
} else {
|
||||
file_mode = os_open_permissions_default;
|
||||
}
|
||||
|
||||
fd = lfopen(dbname, lfopen_append, file_mode);
|
||||
if (fd == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
module = NSSUTIL_ArgStrip(module);
|
||||
while (*module) {
|
||||
int count;
|
||||
char *keyEnd = PORT_Strchr(module, '=');
|
||||
char *value;
|
||||
|
||||
if (PORT_Strncmp(module, "library=", 8) == 0) {
|
||||
libFound = PR_TRUE;
|
||||
}
|
||||
if (keyEnd == NULL) {
|
||||
block = nssutil_DupCat(block, module);
|
||||
break;
|
||||
}
|
||||
block = nssutil_DupnCat(block, module, keyEnd - module + 1);
|
||||
if (block == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
value = NSSUTIL_ArgFetchValue(&keyEnd[1], &count);
|
||||
if (value) {
|
||||
block = nssutil_DupCat(block, NSSUTIL_ArgStrip(value));
|
||||
PORT_Free(value);
|
||||
}
|
||||
if (block == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
block = nssutil_DupnCat(block, "\n", 1);
|
||||
module = keyEnd + 1 + count;
|
||||
module = NSSUTIL_ArgStrip(module);
|
||||
}
|
||||
if (block) {
|
||||
if (!libFound) {
|
||||
fprintf(fd, "library=\n");
|
||||
}
|
||||
fwrite(block, PORT_Strlen(block), 1, fd);
|
||||
fprintf(fd, "\n");
|
||||
PORT_Free(block);
|
||||
block = NULL;
|
||||
}
|
||||
fclose(fd);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PORT_Free(block);
|
||||
fclose(fd);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
char **
|
||||
NSSUTIL_DoModuleDBFunction(unsigned long function, char *parameters, void *args)
|
||||
{
|
||||
char *secmod = NULL;
|
||||
char *appName = NULL;
|
||||
char *filename = NULL;
|
||||
NSSDBType dbType = NSS_DB_TYPE_NONE;
|
||||
PRBool rw;
|
||||
static char *success = "Success";
|
||||
char **rvstr = NULL;
|
||||
|
||||
secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName,
|
||||
&filename, &rw);
|
||||
if ((dbType == NSS_DB_TYPE_LEGACY) ||
|
||||
(dbType == NSS_DB_TYPE_MULTIACCESS)) {
|
||||
/* we can't handle the old database, only softoken can */
|
||||
PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
|
||||
rvstr = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (function) {
|
||||
case SECMOD_MODULE_DB_FUNCTION_FIND:
|
||||
rvstr = nssutil_ReadSecmodDB(appName, filename,
|
||||
secmod, (char *)parameters, rw);
|
||||
break;
|
||||
case SECMOD_MODULE_DB_FUNCTION_ADD:
|
||||
rvstr = (nssutil_AddSecmodDBEntry(appName, filename,
|
||||
secmod, (char *)args, rw) == SECSuccess)
|
||||
? &success
|
||||
: NULL;
|
||||
break;
|
||||
case SECMOD_MODULE_DB_FUNCTION_DEL:
|
||||
rvstr = (nssutil_DeleteSecmodDBEntry(appName, filename,
|
||||
secmod, (char *)args, rw) == SECSuccess)
|
||||
? &success
|
||||
: NULL;
|
||||
break;
|
||||
case SECMOD_MODULE_DB_FUNCTION_RELEASE:
|
||||
rvstr = (nssutil_ReleaseSecmodDBData(appName, filename,
|
||||
secmod, (char **)args, rw) == SECSuccess)
|
||||
? &success
|
||||
: NULL;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
if (secmod)
|
||||
PR_smprintf_free(secmod);
|
||||
if (appName)
|
||||
PORT_Free(appName);
|
||||
if (filename)
|
||||
PORT_Free(filename);
|
||||
return rvstr;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue