security/nss/lib/util/utilmod.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 /*
michael@0 5 * The following code handles the storage of PKCS 11 modules used by the
michael@0 6 * NSS. For the rest of NSS, only one kind of database handle exists:
michael@0 7 *
michael@0 8 * SFTKDBHandle
michael@0 9 *
michael@0 10 * There is one SFTKDBHandle for each key database and one for each cert
michael@0 11 * database. These databases are opened as associated pairs, one pair per
michael@0 12 * slot. SFTKDBHandles are reference counted objects.
michael@0 13 *
michael@0 14 * Each SFTKDBHandle points to a low level database handle (SDB). This handle
michael@0 15 * represents the underlying physical database. These objects are not
michael@0 16 * reference counted, and are 'owned' by their respective SFTKDBHandles.
michael@0 17 */
michael@0 18
michael@0 19 #include "prprf.h"
michael@0 20 #include "prsystem.h"
michael@0 21 #include "secport.h"
michael@0 22 #include "utilpars.h"
michael@0 23 #include "secerr.h"
michael@0 24
michael@0 25 #if defined (_WIN32)
michael@0 26 #include <io.h>
michael@0 27 #endif
michael@0 28 #ifdef XP_UNIX
michael@0 29 #include <unistd.h>
michael@0 30 #endif
michael@0 31
michael@0 32 #include <sys/types.h>
michael@0 33 #include <sys/stat.h>
michael@0 34 #include <fcntl.h>
michael@0 35
michael@0 36 #if defined (_WIN32)
michael@0 37 #define os_open _open
michael@0 38 #define os_fdopen _fdopen
michael@0 39 #define os_stat _stat
michael@0 40 #define os_truncate_open_flags _O_CREAT|_O_RDWR|_O_TRUNC
michael@0 41 #define os_append_open_flags _O_CREAT|_O_RDWR|_O_APPEND
michael@0 42 #define os_open_permissions_type int
michael@0 43 #define os_open_permissions_default _S_IREAD | _S_IWRITE
michael@0 44 #define os_stat_type struct _stat
michael@0 45 #else
michael@0 46 #define os_open open
michael@0 47 #define os_fdopen fdopen
michael@0 48 #define os_stat stat
michael@0 49 #define os_truncate_open_flags O_CREAT|O_RDWR|O_TRUNC
michael@0 50 #define os_append_open_flags O_CREAT|O_RDWR|O_APPEND
michael@0 51 #define os_open_permissions_type mode_t
michael@0 52 #define os_open_permissions_default 0600
michael@0 53 #define os_stat_type struct stat
michael@0 54 #endif
michael@0 55
michael@0 56 /****************************************************************
michael@0 57 *
michael@0 58 * Secmod database.
michael@0 59 *
michael@0 60 * The new secmod database is simply a text file with each of the module
michael@0 61 * entries in the following form:
michael@0 62 *
michael@0 63 * #
michael@0 64 * # This is a comment The next line is the library to load
michael@0 65 * library=libmypkcs11.so
michael@0 66 * name="My PKCS#11 module"
michael@0 67 * params="my library's param string"
michael@0 68 * nss="NSS parameters"
michael@0 69 * other="parameters for other libraries and applications"
michael@0 70 *
michael@0 71 * library=libmynextpk11.so
michael@0 72 * name="My other PKCS#11 module"
michael@0 73 */
michael@0 74
michael@0 75
michael@0 76 /*
michael@0 77 * Smart string cat functions. Automatically manage the memory.
michael@0 78 * The first parameter is the source string. If it's null, we
michael@0 79 * allocate memory for it. If it's not, we reallocate memory
michael@0 80 * so the the concanenated string fits.
michael@0 81 */
michael@0 82 static char *
michael@0 83 nssutil_DupnCat(char *baseString, const char *str, int str_len)
michael@0 84 {
michael@0 85 int len = (baseString ? PORT_Strlen(baseString) : 0) + 1;
michael@0 86 char *newString;
michael@0 87
michael@0 88 len += str_len;
michael@0 89 newString = (char *) PORT_Realloc(baseString,len);
michael@0 90 if (newString == NULL) {
michael@0 91 PORT_Free(baseString);
michael@0 92 return NULL;
michael@0 93 }
michael@0 94 if (baseString == NULL) *newString = 0;
michael@0 95 return PORT_Strncat(newString,str, str_len);
michael@0 96 }
michael@0 97
michael@0 98 /* Same as nssutil_DupnCat except it concatenates the full string, not a
michael@0 99 * partial one */
michael@0 100 static char *
michael@0 101 nssutil_DupCat(char *baseString, const char *str)
michael@0 102 {
michael@0 103 return nssutil_DupnCat(baseString, str, PORT_Strlen(str));
michael@0 104 }
michael@0 105
michael@0 106 /* function to free up all the memory associated with a null terminated
michael@0 107 * array of module specs */
michael@0 108 static SECStatus
michael@0 109 nssutil_releaseSpecList(char **moduleSpecList)
michael@0 110 {
michael@0 111 if (moduleSpecList) {
michael@0 112 char **index;
michael@0 113 for(index = moduleSpecList; *index; index++) {
michael@0 114 PORT_Free(*index);
michael@0 115 }
michael@0 116 PORT_Free(moduleSpecList);
michael@0 117 }
michael@0 118 return SECSuccess;
michael@0 119 }
michael@0 120
michael@0 121 #define SECMOD_STEP 10
michael@0 122 static SECStatus
michael@0 123 nssutil_growList(char ***pModuleList, int *useCount, int last)
michael@0 124 {
michael@0 125 char **newModuleList;
michael@0 126
michael@0 127 *useCount += SECMOD_STEP;
michael@0 128 newModuleList = (char **)PORT_Realloc(*pModuleList,
michael@0 129 *useCount*sizeof(char *));
michael@0 130 if (newModuleList == NULL) {
michael@0 131 return SECFailure;
michael@0 132 }
michael@0 133 PORT_Memset(&newModuleList[last],0, sizeof(char *)*SECMOD_STEP);
michael@0 134 *pModuleList = newModuleList;
michael@0 135 return SECSuccess;
michael@0 136 }
michael@0 137
michael@0 138 static
michael@0 139 char *_NSSUTIL_GetOldSecmodName(const char *dbname,const char *filename)
michael@0 140 {
michael@0 141 char *file = NULL;
michael@0 142 char *dirPath = PORT_Strdup(dbname);
michael@0 143 char *sep;
michael@0 144
michael@0 145 sep = PORT_Strrchr(dirPath,*NSSUTIL_PATH_SEPARATOR);
michael@0 146 #ifdef _WIN32
michael@0 147 if (!sep) {
michael@0 148 /* utilparst.h defines NSSUTIL_PATH_SEPARATOR as "/" for all
michael@0 149 * platforms. */
michael@0 150 sep = PORT_Strrchr(dirPath,'\\');
michael@0 151 }
michael@0 152 #endif
michael@0 153 if (sep) {
michael@0 154 *sep = 0;
michael@0 155 file = PR_smprintf("%s"NSSUTIL_PATH_SEPARATOR"%s", dirPath, filename);
michael@0 156 } else {
michael@0 157 file = PR_smprintf("%s", filename);
michael@0 158 }
michael@0 159 PORT_Free(dirPath);
michael@0 160 return file;
michael@0 161 }
michael@0 162
michael@0 163 static SECStatus nssutil_AddSecmodDBEntry(const char *appName,
michael@0 164 const char *filename,
michael@0 165 const char *dbname,
michael@0 166 char *module, PRBool rw);
michael@0 167
michael@0 168 enum lfopen_mode { lfopen_truncate, lfopen_append };
michael@0 169
michael@0 170 FILE *
michael@0 171 lfopen(const char *name, enum lfopen_mode om, os_open_permissions_type open_perms)
michael@0 172 {
michael@0 173 int fd;
michael@0 174 FILE *file;
michael@0 175
michael@0 176 fd = os_open(name,
michael@0 177 (om == lfopen_truncate) ? os_truncate_open_flags : os_append_open_flags,
michael@0 178 open_perms);
michael@0 179 if (fd < 0) {
michael@0 180 return NULL;
michael@0 181 }
michael@0 182 file = os_fdopen(fd, (om == lfopen_truncate) ? "w+" : "a+");
michael@0 183 if (!file) {
michael@0 184 close(fd);
michael@0 185 }
michael@0 186 /* file inherits fd */
michael@0 187 return file;
michael@0 188 }
michael@0 189
michael@0 190 #define MAX_LINE_LENGTH 2048
michael@0 191
michael@0 192 /*
michael@0 193 * Read all the existing modules in out of the file.
michael@0 194 */
michael@0 195 static char **
michael@0 196 nssutil_ReadSecmodDB(const char *appName,
michael@0 197 const char *filename, const char *dbname,
michael@0 198 char *params, PRBool rw)
michael@0 199 {
michael@0 200 FILE *fd = NULL;
michael@0 201 char **moduleList = NULL;
michael@0 202 int moduleCount = 1;
michael@0 203 int useCount = SECMOD_STEP;
michael@0 204 char line[MAX_LINE_LENGTH];
michael@0 205 PRBool internal = PR_FALSE;
michael@0 206 PRBool skipParams = PR_FALSE;
michael@0 207 char *moduleString = NULL;
michael@0 208 char *paramsValue=NULL;
michael@0 209 PRBool failed = PR_TRUE;
michael@0 210
michael@0 211 moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
michael@0 212 if (moduleList == NULL) return NULL;
michael@0 213
michael@0 214 if (dbname == NULL) {
michael@0 215 goto return_default;
michael@0 216 }
michael@0 217
michael@0 218 /* do we really want to use streams here */
michael@0 219 fd = fopen(dbname, "r");
michael@0 220 if (fd == NULL) goto done;
michael@0 221
michael@0 222 /*
michael@0 223 * the following loop takes line separated config lines and collapses
michael@0 224 * the lines to a single string, escaping and quoting as necessary.
michael@0 225 */
michael@0 226 /* loop state variables */
michael@0 227 moduleString = NULL; /* current concatenated string */
michael@0 228 internal = PR_FALSE; /* is this an internal module */
michael@0 229 skipParams = PR_FALSE; /* did we find an override parameter block*/
michael@0 230 paramsValue = NULL; /* the current parameter block value */
michael@0 231 while (fgets(line, sizeof(line), fd) != NULL) {
michael@0 232 int len = PORT_Strlen(line);
michael@0 233
michael@0 234 /* remove the ending newline */
michael@0 235 if (len && line[len-1] == '\n') {
michael@0 236 len--;
michael@0 237 line[len] = 0;
michael@0 238 }
michael@0 239 if (*line == '#') {
michael@0 240 continue;
michael@0 241 }
michael@0 242 if (*line != 0) {
michael@0 243 /*
michael@0 244 * The PKCS #11 group standard assumes blocks of strings
michael@0 245 * separated by new lines, clumped by new lines. Internally
michael@0 246 * we take strings separated by spaces, so we may need to escape
michael@0 247 * certain spaces.
michael@0 248 */
michael@0 249 char *value = PORT_Strchr(line,'=');
michael@0 250
michael@0 251 /* there is no value, write out the stanza as is */
michael@0 252 if (value == NULL || value[1] == 0) {
michael@0 253 if (moduleString) {
michael@0 254 moduleString = nssutil_DupnCat(moduleString," ", 1);
michael@0 255 if (moduleString == NULL) goto loser;
michael@0 256 }
michael@0 257 moduleString = nssutil_DupCat(moduleString, line);
michael@0 258 if (moduleString == NULL) goto loser;
michael@0 259 /* value is already quoted, just write it out */
michael@0 260 } else if (value[1] == '"') {
michael@0 261 if (moduleString) {
michael@0 262 moduleString = nssutil_DupnCat(moduleString," ", 1);
michael@0 263 if (moduleString == NULL) goto loser;
michael@0 264 }
michael@0 265 moduleString = nssutil_DupCat(moduleString, line);
michael@0 266 if (moduleString == NULL) goto loser;
michael@0 267 /* we have an override parameter section, remember that
michael@0 268 * we found this (see following comment about why this
michael@0 269 * is necessary). */
michael@0 270 if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
michael@0 271 skipParams = PR_TRUE;
michael@0 272 }
michael@0 273 /*
michael@0 274 * The internal token always overrides it's parameter block
michael@0 275 * from the passed in parameters, so wait until then end
michael@0 276 * before we include the parameter block in case we need to
michael@0 277 * override it. NOTE: if the parameter block is quoted with ("),
michael@0 278 * this override does not happen. This allows you to override
michael@0 279 * the application's parameter configuration.
michael@0 280 *
michael@0 281 * parameter block state is controlled by the following variables:
michael@0 282 * skipParams - Bool : set to true of we have an override param
michael@0 283 * block (all other blocks, either implicit or explicit are
michael@0 284 * ignored).
michael@0 285 * paramsValue - char * : pointer to the current param block. In
michael@0 286 * the absence of overrides, paramsValue is set to the first
michael@0 287 * parameter block we find. All subsequent blocks are ignored.
michael@0 288 * When we find an internal token, the application passed
michael@0 289 * parameters take precident.
michael@0 290 */
michael@0 291 } else if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
michael@0 292 /* already have parameters */
michael@0 293 if (paramsValue) {
michael@0 294 continue;
michael@0 295 }
michael@0 296 paramsValue = NSSUTIL_Quote(&value[1], '"');
michael@0 297 if (paramsValue == NULL) goto loser;
michael@0 298 continue;
michael@0 299 } else {
michael@0 300 /* may need to quote */
michael@0 301 char *newLine;
michael@0 302 if (moduleString) {
michael@0 303 moduleString = nssutil_DupnCat(moduleString," ", 1);
michael@0 304 if (moduleString == NULL) goto loser;
michael@0 305 }
michael@0 306 moduleString = nssutil_DupnCat(moduleString,line,value-line+1);
michael@0 307 if (moduleString == NULL) goto loser;
michael@0 308 newLine = NSSUTIL_Quote(&value[1],'"');
michael@0 309 if (newLine == NULL) goto loser;
michael@0 310 moduleString = nssutil_DupCat(moduleString,newLine);
michael@0 311 PORT_Free(newLine);
michael@0 312 if (moduleString == NULL) goto loser;
michael@0 313 }
michael@0 314
michael@0 315 /* check to see if it's internal? */
michael@0 316 if (PORT_Strncasecmp(line, "NSS=", 4) == 0) {
michael@0 317 /* This should be case insensitive! reviewers make
michael@0 318 * me fix it if it's not */
michael@0 319 if (PORT_Strstr(line,"internal")) {
michael@0 320 internal = PR_TRUE;
michael@0 321 /* override the parameters */
michael@0 322 if (paramsValue) {
michael@0 323 PORT_Free(paramsValue);
michael@0 324 }
michael@0 325 paramsValue = NSSUTIL_Quote(params, '"');
michael@0 326 }
michael@0 327 }
michael@0 328 continue;
michael@0 329 }
michael@0 330 if ((moduleString == NULL) || (*moduleString == 0)) {
michael@0 331 continue;
michael@0 332 }
michael@0 333
michael@0 334 /*
michael@0 335 * if we are here, we have found a complete stanza. Now write out
michael@0 336 * any param section we may have found.
michael@0 337 */
michael@0 338 if (paramsValue) {
michael@0 339 /* we had an override */
michael@0 340 if (!skipParams) {
michael@0 341 moduleString = nssutil_DupnCat(moduleString," parameters=", 12);
michael@0 342 if (moduleString == NULL) goto loser;
michael@0 343 moduleString = nssutil_DupCat(moduleString, paramsValue);
michael@0 344 if (moduleString == NULL) goto loser;
michael@0 345 }
michael@0 346 PORT_Free(paramsValue);
michael@0 347 paramsValue = NULL;
michael@0 348 }
michael@0 349
michael@0 350 if ((moduleCount+1) >= useCount) {
michael@0 351 SECStatus rv;
michael@0 352 rv = nssutil_growList(&moduleList, &useCount, moduleCount+1);
michael@0 353 if (rv != SECSuccess) {
michael@0 354 goto loser;
michael@0 355 }
michael@0 356 }
michael@0 357
michael@0 358 if (internal) {
michael@0 359 moduleList[0] = moduleString;
michael@0 360 } else {
michael@0 361 moduleList[moduleCount] = moduleString;
michael@0 362 moduleCount++;
michael@0 363 }
michael@0 364 moduleString = NULL;
michael@0 365 internal = PR_FALSE;
michael@0 366 skipParams = PR_FALSE;
michael@0 367 }
michael@0 368
michael@0 369 if (moduleString) {
michael@0 370 PORT_Free(moduleString);
michael@0 371 moduleString = NULL;
michael@0 372 }
michael@0 373 done:
michael@0 374 /* if we couldn't open a pkcs11 database, look for the old one */
michael@0 375 if (fd == NULL) {
michael@0 376 char *olddbname = _NSSUTIL_GetOldSecmodName(dbname,filename);
michael@0 377 PRStatus status;
michael@0 378
michael@0 379 /* couldn't get the old name */
michael@0 380 if (!olddbname) {
michael@0 381 goto bail;
michael@0 382 }
michael@0 383
michael@0 384 /* old one exists */
michael@0 385 status = PR_Access(olddbname, PR_ACCESS_EXISTS);
michael@0 386 if (status == PR_SUCCESS) {
michael@0 387 PR_smprintf_free(olddbname);
michael@0 388 PORT_ZFree(moduleList, useCount*sizeof(char **));
michael@0 389 PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
michael@0 390 return NULL;
michael@0 391 }
michael@0 392
michael@0 393 bail:
michael@0 394 if (olddbname) {
michael@0 395 PR_smprintf_free(olddbname);
michael@0 396 }
michael@0 397 }
michael@0 398
michael@0 399 return_default:
michael@0 400
michael@0 401 if (!moduleList[0]) {
michael@0 402 char * newParams;
michael@0 403 moduleString = PORT_Strdup(NSSUTIL_DEFAULT_INTERNAL_INIT1);
michael@0 404 newParams = NSSUTIL_Quote(params,'"');
michael@0 405 if (newParams == NULL) goto loser;
michael@0 406 moduleString = nssutil_DupCat(moduleString, newParams);
michael@0 407 PORT_Free(newParams);
michael@0 408 if (moduleString == NULL) goto loser;
michael@0 409 moduleString = nssutil_DupCat(moduleString,
michael@0 410 NSSUTIL_DEFAULT_INTERNAL_INIT2);
michael@0 411 if (moduleString == NULL) goto loser;
michael@0 412 moduleString = nssutil_DupCat(moduleString,
michael@0 413 NSSUTIL_DEFAULT_SFTKN_FLAGS);
michael@0 414 if (moduleString == NULL) goto loser;
michael@0 415 moduleString = nssutil_DupCat(moduleString,
michael@0 416 NSSUTIL_DEFAULT_INTERNAL_INIT3);
michael@0 417 if (moduleString == NULL) goto loser;
michael@0 418 moduleList[0] = moduleString;
michael@0 419 moduleString = NULL;
michael@0 420 }
michael@0 421 failed = PR_FALSE;
michael@0 422
michael@0 423 loser:
michael@0 424 /*
michael@0 425 * cleanup
michael@0 426 */
michael@0 427 /* deal with trust cert db here */
michael@0 428 if (moduleString) {
michael@0 429 PORT_Free(moduleString);
michael@0 430 moduleString = NULL;
michael@0 431 }
michael@0 432 if (paramsValue) {
michael@0 433 PORT_Free(paramsValue);
michael@0 434 paramsValue = NULL;
michael@0 435 }
michael@0 436 if (failed || (moduleList[0] == NULL)) {
michael@0 437 /* This is wrong! FIXME */
michael@0 438 nssutil_releaseSpecList(moduleList);
michael@0 439 moduleList = NULL;
michael@0 440 failed = PR_TRUE;
michael@0 441 }
michael@0 442 if (fd != NULL) {
michael@0 443 fclose(fd);
michael@0 444 } else if (!failed && rw) {
michael@0 445 /* update our internal module */
michael@0 446 nssutil_AddSecmodDBEntry(appName, filename, dbname, moduleList[0], rw);
michael@0 447 }
michael@0 448 return moduleList;
michael@0 449 }
michael@0 450
michael@0 451 static SECStatus
michael@0 452 nssutil_ReleaseSecmodDBData(const char *appName,
michael@0 453 const char *filename, const char *dbname,
michael@0 454 char **moduleSpecList, PRBool rw)
michael@0 455 {
michael@0 456 if (moduleSpecList) {
michael@0 457 nssutil_releaseSpecList(moduleSpecList);
michael@0 458 }
michael@0 459 return SECSuccess;
michael@0 460 }
michael@0 461
michael@0 462
michael@0 463 /*
michael@0 464 * Delete a module from the Data Base
michael@0 465 */
michael@0 466 static SECStatus
michael@0 467 nssutil_DeleteSecmodDBEntry(const char *appName,
michael@0 468 const char *filename,
michael@0 469 const char *dbname,
michael@0 470 char *args,
michael@0 471 PRBool rw)
michael@0 472 {
michael@0 473 /* SHDB_FIXME implement */
michael@0 474 os_stat_type stat_existing;
michael@0 475 os_open_permissions_type file_mode;
michael@0 476 FILE *fd = NULL;
michael@0 477 FILE *fd2 = NULL;
michael@0 478 char line[MAX_LINE_LENGTH];
michael@0 479 char *dbname2 = NULL;
michael@0 480 char *block = NULL;
michael@0 481 char *name = NULL;
michael@0 482 char *lib = NULL;
michael@0 483 int name_len, lib_len;
michael@0 484 PRBool skip = PR_FALSE;
michael@0 485 PRBool found = PR_FALSE;
michael@0 486
michael@0 487 if (dbname == NULL) {
michael@0 488 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 489 return SECFailure;
michael@0 490 }
michael@0 491
michael@0 492 if (!rw) {
michael@0 493 PORT_SetError(SEC_ERROR_READ_ONLY);
michael@0 494 return SECFailure;
michael@0 495 }
michael@0 496
michael@0 497 dbname2 = PORT_Strdup(dbname);
michael@0 498 if (dbname2 == NULL) goto loser;
michael@0 499 dbname2[strlen(dbname)-1]++;
michael@0 500
michael@0 501 /* get the permissions of the existing file, or use the default */
michael@0 502 if (!os_stat(dbname, &stat_existing)) {
michael@0 503 file_mode = stat_existing.st_mode;
michael@0 504 } else {
michael@0 505 file_mode = os_open_permissions_default;
michael@0 506 }
michael@0 507
michael@0 508 /* do we really want to use streams here */
michael@0 509 fd = fopen(dbname, "r");
michael@0 510 if (fd == NULL) goto loser;
michael@0 511
michael@0 512 fd2 = lfopen(dbname2, lfopen_truncate, file_mode);
michael@0 513
michael@0 514 if (fd2 == NULL) goto loser;
michael@0 515
michael@0 516 name = NSSUTIL_ArgGetParamValue("name",args);
michael@0 517 if (name) {
michael@0 518 name_len = PORT_Strlen(name);
michael@0 519 }
michael@0 520 lib = NSSUTIL_ArgGetParamValue("library",args);
michael@0 521 if (lib) {
michael@0 522 lib_len = PORT_Strlen(lib);
michael@0 523 }
michael@0 524
michael@0 525
michael@0 526 /*
michael@0 527 * the following loop takes line separated config files and collapses
michael@0 528 * the lines to a single string, escaping and quoting as necessary.
michael@0 529 */
michael@0 530 /* loop state variables */
michael@0 531 block = NULL;
michael@0 532 skip = PR_FALSE;
michael@0 533 while (fgets(line, sizeof(line), fd) != NULL) {
michael@0 534 /* If we are processing a block (we haven't hit a blank line yet */
michael@0 535 if (*line != '\n') {
michael@0 536 /* skip means we are in the middle of a block we are deleting */
michael@0 537 if (skip) {
michael@0 538 continue;
michael@0 539 }
michael@0 540 /* if we haven't found the block yet, check to see if this block
michael@0 541 * matches our requirements */
michael@0 542 if (!found && ((name && (PORT_Strncasecmp(line,"name=",5) == 0) &&
michael@0 543 (PORT_Strncmp(line+5,name,name_len) == 0)) ||
michael@0 544 (lib && (PORT_Strncasecmp(line,"library=",8) == 0) &&
michael@0 545 (PORT_Strncmp(line+8,lib,lib_len) == 0)))) {
michael@0 546
michael@0 547 /* yup, we don't need to save any more data, */
michael@0 548 PORT_Free(block);
michael@0 549 block=NULL;
michael@0 550 /* we don't need to collect more of this block */
michael@0 551 skip = PR_TRUE;
michael@0 552 /* we don't need to continue searching for the block */
michael@0 553 found =PR_TRUE;
michael@0 554 continue;
michael@0 555 }
michael@0 556 /* not our match, continue to collect data in this block */
michael@0 557 block = nssutil_DupCat(block,line);
michael@0 558 continue;
michael@0 559 }
michael@0 560 /* we've collected a block of data that wasn't the module we were
michael@0 561 * looking for, write it out */
michael@0 562 if (block) {
michael@0 563 fwrite(block, PORT_Strlen(block), 1, fd2);
michael@0 564 PORT_Free(block);
michael@0 565 block = NULL;
michael@0 566 }
michael@0 567 /* If we didn't just delete the this block, keep the blank line */
michael@0 568 if (!skip) {
michael@0 569 fputs(line,fd2);
michael@0 570 }
michael@0 571 /* we are definately not in a deleted block anymore */
michael@0 572 skip = PR_FALSE;
michael@0 573 }
michael@0 574 fclose(fd);
michael@0 575 fclose(fd2);
michael@0 576 if (found) {
michael@0 577 /* rename dbname2 to dbname */
michael@0 578 PR_Delete(dbname);
michael@0 579 PR_Rename(dbname2,dbname);
michael@0 580 } else {
michael@0 581 PR_Delete(dbname2);
michael@0 582 }
michael@0 583 PORT_Free(dbname2);
michael@0 584 PORT_Free(lib);
michael@0 585 PORT_Free(name);
michael@0 586 PORT_Free(block);
michael@0 587 return SECSuccess;
michael@0 588
michael@0 589 loser:
michael@0 590 if (fd != NULL) {
michael@0 591 fclose(fd);
michael@0 592 }
michael@0 593 if (fd2 != NULL) {
michael@0 594 fclose(fd2);
michael@0 595 }
michael@0 596 if (dbname2) {
michael@0 597 PR_Delete(dbname2);
michael@0 598 PORT_Free(dbname2);
michael@0 599 }
michael@0 600 PORT_Free(lib);
michael@0 601 PORT_Free(name);
michael@0 602 return SECFailure;
michael@0 603 }
michael@0 604
michael@0 605 /*
michael@0 606 * Add a module to the Data base
michael@0 607 */
michael@0 608 static SECStatus
michael@0 609 nssutil_AddSecmodDBEntry(const char *appName,
michael@0 610 const char *filename, const char *dbname,
michael@0 611 char *module, PRBool rw)
michael@0 612 {
michael@0 613 os_stat_type stat_existing;
michael@0 614 os_open_permissions_type file_mode;
michael@0 615 FILE *fd = NULL;
michael@0 616 char *block = NULL;
michael@0 617 PRBool libFound = PR_FALSE;
michael@0 618
michael@0 619 if (dbname == NULL) {
michael@0 620 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 621 return SECFailure;
michael@0 622 }
michael@0 623
michael@0 624 /* can't write to a read only module */
michael@0 625 if (!rw) {
michael@0 626 PORT_SetError(SEC_ERROR_READ_ONLY);
michael@0 627 return SECFailure;
michael@0 628 }
michael@0 629
michael@0 630 /* remove the previous version if it exists */
michael@0 631 (void) nssutil_DeleteSecmodDBEntry(appName, filename, dbname, module, rw);
michael@0 632
michael@0 633 /* get the permissions of the existing file, or use the default */
michael@0 634 if (!os_stat(dbname, &stat_existing)) {
michael@0 635 file_mode = stat_existing.st_mode;
michael@0 636 } else {
michael@0 637 file_mode = os_open_permissions_default;
michael@0 638 }
michael@0 639
michael@0 640 fd = lfopen(dbname, lfopen_append, file_mode);
michael@0 641 if (fd == NULL) {
michael@0 642 return SECFailure;
michael@0 643 }
michael@0 644 module = NSSUTIL_ArgStrip(module);
michael@0 645 while (*module) {
michael@0 646 int count;
michael@0 647 char *keyEnd = PORT_Strchr(module,'=');
michael@0 648 char *value;
michael@0 649
michael@0 650 if (PORT_Strncmp(module, "library=", 8) == 0) {
michael@0 651 libFound=PR_TRUE;
michael@0 652 }
michael@0 653 if (keyEnd == NULL) {
michael@0 654 block = nssutil_DupCat(block, module);
michael@0 655 break;
michael@0 656 }
michael@0 657 block = nssutil_DupnCat(block, module, keyEnd-module+1);
michael@0 658 if (block == NULL) { goto loser; }
michael@0 659 value = NSSUTIL_ArgFetchValue(&keyEnd[1], &count);
michael@0 660 if (value) {
michael@0 661 block = nssutil_DupCat(block, NSSUTIL_ArgStrip(value));
michael@0 662 PORT_Free(value);
michael@0 663 }
michael@0 664 if (block == NULL) { goto loser; }
michael@0 665 block = nssutil_DupnCat(block, "\n", 1);
michael@0 666 module = keyEnd + 1 + count;
michael@0 667 module = NSSUTIL_ArgStrip(module);
michael@0 668 }
michael@0 669 if (block) {
michael@0 670 if (!libFound) {
michael@0 671 fprintf(fd,"library=\n");
michael@0 672 }
michael@0 673 fwrite(block, PORT_Strlen(block), 1, fd);
michael@0 674 fprintf(fd,"\n");
michael@0 675 PORT_Free(block);
michael@0 676 block = NULL;
michael@0 677 }
michael@0 678 fclose(fd);
michael@0 679 return SECSuccess;
michael@0 680
michael@0 681 loser:
michael@0 682 PORT_Free(block);
michael@0 683 fclose(fd);
michael@0 684 return SECFailure;
michael@0 685 }
michael@0 686
michael@0 687
michael@0 688 char **
michael@0 689 NSSUTIL_DoModuleDBFunction(unsigned long function,char *parameters, void *args)
michael@0 690 {
michael@0 691 char *secmod = NULL;
michael@0 692 char *appName = NULL;
michael@0 693 char *filename = NULL;
michael@0 694 NSSDBType dbType = NSS_DB_TYPE_NONE;
michael@0 695 PRBool rw;
michael@0 696 static char *success="Success";
michael@0 697 char **rvstr = NULL;
michael@0 698
michael@0 699
michael@0 700 secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName,
michael@0 701 &filename, &rw);
michael@0 702 if ((dbType == NSS_DB_TYPE_LEGACY) ||
michael@0 703 (dbType == NSS_DB_TYPE_MULTIACCESS)) {
michael@0 704 /* we can't handle the old database, only softoken can */
michael@0 705 PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
michael@0 706 rvstr = NULL;
michael@0 707 goto done;
michael@0 708 }
michael@0 709
michael@0 710 switch (function) {
michael@0 711 case SECMOD_MODULE_DB_FUNCTION_FIND:
michael@0 712 rvstr = nssutil_ReadSecmodDB(appName,filename,
michael@0 713 secmod,(char *)parameters,rw);
michael@0 714 break;
michael@0 715 case SECMOD_MODULE_DB_FUNCTION_ADD:
michael@0 716 rvstr = (nssutil_AddSecmodDBEntry(appName, filename,
michael@0 717 secmod, (char *)args, rw)
michael@0 718 == SECSuccess) ? &success: NULL;
michael@0 719 break;
michael@0 720 case SECMOD_MODULE_DB_FUNCTION_DEL:
michael@0 721 rvstr = (nssutil_DeleteSecmodDBEntry(appName, filename,
michael@0 722 secmod, (char *)args, rw)
michael@0 723 == SECSuccess) ? &success: NULL;
michael@0 724 break;
michael@0 725 case SECMOD_MODULE_DB_FUNCTION_RELEASE:
michael@0 726 rvstr = (nssutil_ReleaseSecmodDBData(appName, filename,
michael@0 727 secmod, (char **)args, rw)
michael@0 728 == SECSuccess) ? &success: NULL;
michael@0 729 break;
michael@0 730 }
michael@0 731 done:
michael@0 732 if (secmod) PR_smprintf_free(secmod);
michael@0 733 if (appName) PORT_Free(appName);
michael@0 734 if (filename) PORT_Free(filename);
michael@0 735 return rvstr;
michael@0 736 }

mercurial