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