Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(884)

Side by Side Diff: mozilla/security/nss/lib/util/utilmod.c

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

Powered by Google App Engine
This is Rietveld 408576698