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