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 |