nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / cmd / modutil / modutil.c
blobc91c5eebd93f7ff936dc085343dec4602f5e477c
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 /* To edit this file, set TABSTOPS to 4 spaces.
38 * This is not the normal NSS convention.
41 #include "modutil.h"
42 #include "install.h"
43 #include <plstr.h>
44 #include "certdb.h" /* for CERT_DB_FILE_VERSION */
45 #include "nss.h"
47 static void install_error(char *message);
48 static char* PR_fgets(char *buf, int size, PRFileDesc *file);
49 static char *progName;
52 /* This enum must be kept in sync with the commandNames list */
53 typedef enum {
54 NO_COMMAND,
55 ADD_COMMAND,
56 CHANGEPW_COMMAND,
57 CREATE_COMMAND,
58 DEFAULT_COMMAND,
59 DELETE_COMMAND,
60 DISABLE_COMMAND,
61 ENABLE_COMMAND,
62 FIPS_COMMAND,
63 JAR_COMMAND,
64 LIST_COMMAND,
65 RAW_LIST_COMMAND,
66 RAW_ADD_COMMAND,
67 CHKFIPS_COMMAND,
68 UNDEFAULT_COMMAND
69 } Command;
71 /* This list must be kept in sync with the Command enum */
72 static char *commandNames[] = {
73 "(no command)",
74 "-add",
75 "-changepw",
76 "-create",
77 "-default",
78 "-delete",
79 "-disable",
80 "-enable",
81 "-fips",
82 "-jar",
83 "-list",
84 "-rawlist",
85 "-rawadd",
86 "-chkfips",
87 "-undefault"
91 /* this enum must be kept in sync with the optionStrings list */
92 typedef enum {
93 ADD_ARG=0,
94 RAW_ADD_ARG,
95 CHANGEPW_ARG,
96 CIPHERS_ARG,
97 CREATE_ARG,
98 DBDIR_ARG,
99 DBPREFIX_ARG,
100 DEFAULT_ARG,
101 DELETE_ARG,
102 DISABLE_ARG,
103 ENABLE_ARG,
104 FIPS_ARG,
105 FORCE_ARG,
106 JAR_ARG,
107 LIBFILE_ARG,
108 LIST_ARG,
109 RAW_LIST_ARG,
110 MECHANISMS_ARG,
111 NEWPWFILE_ARG,
112 PWFILE_ARG,
113 SLOT_ARG,
114 UNDEFAULT_ARG,
115 INSTALLDIR_ARG,
116 TEMPDIR_ARG,
117 SECMOD_ARG,
118 NOCERTDB_ARG,
119 STRING_ARG,
120 CHKFIPS_ARG,
122 NUM_ARGS /* must be last */
123 } Arg;
125 /* This list must be kept in sync with the Arg enum */
126 static char *optionStrings[] = {
127 "-add",
128 "-rawadd",
129 "-changepw",
130 "-ciphers",
131 "-create",
132 "-dbdir",
133 "-dbprefix",
134 "-default",
135 "-delete",
136 "-disable",
137 "-enable",
138 "-fips",
139 "-force",
140 "-jar",
141 "-libfile",
142 "-list",
143 "-rawlist",
144 "-mechanisms",
145 "-newpwfile",
146 "-pwfile",
147 "-slot",
148 "-undefault",
149 "-installdir",
150 "-tempdir",
151 "-secmod",
152 "-nocertdb",
153 "-string",
154 "-chkfips",
157 /* Increment i if doing so would have i still be less than j. If you
158 are able to do this, return 0. Otherwise return 1. */
159 #define TRY_INC(i,j) ( ((i+1)<j) ? (++i, 0) : 1 )
161 /********************************************************************
163 * file-wide variables obtained from the command line
165 static Command command = NO_COMMAND;
166 static char* pwFile = NULL;
167 static char* newpwFile = NULL;
168 static char* moduleName = NULL;
169 static char* moduleSpec = NULL;
170 static char* slotName = NULL;
171 static char* secmodName = NULL;
172 static char* tokenName = NULL;
173 static char* libFile = NULL;
174 static char* dbdir = NULL;
175 static char* dbprefix = "";
176 static char* secmodString = NULL;
177 static char* mechanisms = NULL;
178 static char* ciphers = NULL;
179 static char* fipsArg = NULL;
180 static char* jarFile = NULL;
181 static char* installDir = NULL;
182 static char* tempDir = NULL;
183 static short force = 0;
184 static PRBool nocertdb = PR_FALSE;
186 /*******************************************************************
188 * p a r s e _ a r g s
190 static Error
191 parse_args(int argc, char *argv[])
193 int i;
194 char *arg;
195 int optionType;
197 /* Loop over all arguments */
198 for(i=1; i < argc; i++) {
199 arg = argv[i];
201 /* Make sure this is an option and not some floating argument */
202 if(arg[0] != '-') {
203 PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
204 return UNEXPECTED_ARG_ERR;
207 /* Find which option this is */
208 for(optionType=0; optionType < NUM_ARGS; optionType++) {
209 if(! strcmp(arg, optionStrings[optionType])) {
210 break;
214 /* Deal with this specific option */
215 switch(optionType) {
216 case NUM_ARGS:
217 default:
218 PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
219 return UNKNOWN_OPTION_ERR;
220 break;
221 case ADD_ARG:
222 if(command != NO_COMMAND) {
223 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
224 return MULTIPLE_COMMAND_ERR;
226 command = ADD_COMMAND;
227 if(TRY_INC(i, argc)) {
228 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
229 return OPTION_NEEDS_ARG_ERR;
231 moduleName = argv[i];
232 break;
233 case CHANGEPW_ARG:
234 if(command != NO_COMMAND) {
235 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
236 return MULTIPLE_COMMAND_ERR;
238 command = CHANGEPW_COMMAND;
239 if(TRY_INC(i, argc)) {
240 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
241 return OPTION_NEEDS_ARG_ERR;
243 tokenName = argv[i];
244 break;
245 case CIPHERS_ARG:
246 if(ciphers != NULL) {
247 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
248 return DUPLICATE_OPTION_ERR;
250 if(TRY_INC(i, argc)) {
251 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
252 return OPTION_NEEDS_ARG_ERR;
254 ciphers = argv[i];
255 break;
256 case CREATE_ARG:
257 if(command != NO_COMMAND) {
258 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
259 return MULTIPLE_COMMAND_ERR;
261 command = CREATE_COMMAND;
262 break;
263 case DBDIR_ARG:
264 if(dbdir != NULL) {
265 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
266 return DUPLICATE_OPTION_ERR;
268 if(TRY_INC(i, argc)) {
269 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
270 return OPTION_NEEDS_ARG_ERR;
272 dbdir = argv[i];
273 break;
274 case DBPREFIX_ARG:
275 if(TRY_INC(i, argc)) {
276 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
277 return OPTION_NEEDS_ARG_ERR;
279 dbprefix = argv[i];
280 break;
281 case UNDEFAULT_ARG:
282 case DEFAULT_ARG:
283 if(command != NO_COMMAND) {
284 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
285 return MULTIPLE_COMMAND_ERR;
287 if(optionType == DEFAULT_ARG) {
288 command = DEFAULT_COMMAND;
289 } else {
290 command = UNDEFAULT_COMMAND;
292 if(TRY_INC(i, argc)) {
293 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
294 return OPTION_NEEDS_ARG_ERR;
296 moduleName = argv[i];
297 break;
298 case DELETE_ARG:
299 if(command != NO_COMMAND) {
300 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
301 return MULTIPLE_COMMAND_ERR;
303 command = DELETE_COMMAND;
304 if(TRY_INC(i, argc)) {
305 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
306 return OPTION_NEEDS_ARG_ERR;
308 moduleName = argv[i];
309 break;
310 case DISABLE_ARG:
311 if(command != NO_COMMAND) {
312 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
313 return MULTIPLE_COMMAND_ERR;
315 command = DISABLE_COMMAND;
316 if(TRY_INC(i, argc)) {
317 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
318 return OPTION_NEEDS_ARG_ERR;
320 moduleName = argv[i];
321 break;
322 case ENABLE_ARG:
323 if(command != NO_COMMAND) {
324 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
325 return MULTIPLE_COMMAND_ERR;
327 command = ENABLE_COMMAND;
328 if(TRY_INC(i, argc)) {
329 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
330 return OPTION_NEEDS_ARG_ERR;
332 moduleName = argv[i];
333 break;
334 case FIPS_ARG:
335 if(command != NO_COMMAND) {
336 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
337 return MULTIPLE_COMMAND_ERR;
339 command = FIPS_COMMAND;
340 if(TRY_INC(i, argc)) {
341 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
342 return OPTION_NEEDS_ARG_ERR;
344 fipsArg = argv[i];
345 break;
346 case CHKFIPS_ARG:
347 if(command != NO_COMMAND) {
348 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
349 return MULTIPLE_COMMAND_ERR;
351 command = CHKFIPS_COMMAND;
352 if(TRY_INC(i, argc)) {
353 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
354 return OPTION_NEEDS_ARG_ERR;
356 fipsArg = argv[i];
357 break;
358 case FORCE_ARG:
359 force = 1;
360 break;
361 case NOCERTDB_ARG:
362 nocertdb = PR_TRUE;
363 break;
364 case INSTALLDIR_ARG:
365 if(installDir != NULL) {
366 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
367 return DUPLICATE_OPTION_ERR;
369 if(TRY_INC(i, argc)) {
370 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
371 return OPTION_NEEDS_ARG_ERR;
373 installDir = argv[i];
374 break;
375 case TEMPDIR_ARG:
376 if(tempDir != NULL) {
377 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
378 return DUPLICATE_OPTION_ERR;
380 if(TRY_INC(i, argc)) {
381 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
382 return OPTION_NEEDS_ARG_ERR;
384 tempDir = argv[i];
385 break;
386 case JAR_ARG:
387 if(command != NO_COMMAND) {
388 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
389 return MULTIPLE_COMMAND_ERR;
391 command = JAR_COMMAND;
392 if(TRY_INC(i, argc)) {
393 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
394 return OPTION_NEEDS_ARG_ERR;
396 jarFile = argv[i];
397 break;
398 case LIBFILE_ARG:
399 if(libFile != NULL) {
400 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
401 return DUPLICATE_OPTION_ERR;
403 if(TRY_INC(i, argc)) {
404 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
405 return OPTION_NEEDS_ARG_ERR;
407 libFile = argv[i];
408 break;
409 case LIST_ARG:
410 if(command != NO_COMMAND) {
411 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
412 return MULTIPLE_COMMAND_ERR;
414 command = LIST_COMMAND;
415 /* This option may or may not have an argument */
416 if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
417 moduleName = argv[++i];
419 break;
420 case RAW_LIST_ARG:
421 if(command != NO_COMMAND) {
422 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
423 return MULTIPLE_COMMAND_ERR;
425 command = RAW_LIST_COMMAND;
426 /* This option may or may not have an argument */
427 if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
428 moduleName = argv[++i];
430 break;
431 case RAW_ADD_ARG:
432 if(command != NO_COMMAND) {
433 PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
434 return MULTIPLE_COMMAND_ERR;
436 command = RAW_ADD_COMMAND;
437 if(TRY_INC(i, argc)) {
438 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
439 return OPTION_NEEDS_ARG_ERR;
441 moduleSpec = argv[i];
442 break;
443 case MECHANISMS_ARG:
444 if(mechanisms != NULL) {
445 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
446 return DUPLICATE_OPTION_ERR;
448 if(TRY_INC(i, argc)) {
449 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
450 return OPTION_NEEDS_ARG_ERR;
452 mechanisms = argv[i];
453 break;
454 case NEWPWFILE_ARG:
455 if(newpwFile != NULL) {
456 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
457 return DUPLICATE_OPTION_ERR;
459 if(TRY_INC(i, argc)) {
460 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
461 return OPTION_NEEDS_ARG_ERR;
463 newpwFile = argv[i];
464 break;
465 case PWFILE_ARG:
466 if(pwFile != NULL) {
467 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
468 return DUPLICATE_OPTION_ERR;
470 if(TRY_INC(i, argc)) {
471 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
472 return OPTION_NEEDS_ARG_ERR;
474 pwFile = argv[i];
475 break;
476 case SLOT_ARG:
477 if(slotName != NULL) {
478 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
479 return DUPLICATE_OPTION_ERR;
481 if(TRY_INC(i, argc)) {
482 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
483 return OPTION_NEEDS_ARG_ERR;
485 slotName = argv[i];
486 break;
487 case SECMOD_ARG:
488 if(secmodName != NULL) {
489 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
490 return DUPLICATE_OPTION_ERR;
492 if(TRY_INC(i, argc)) {
493 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
494 return OPTION_NEEDS_ARG_ERR;
496 secmodName = argv[i];
497 break;
498 case STRING_ARG:
499 if(secmodString != NULL) {
500 PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
501 return DUPLICATE_OPTION_ERR;
503 if(TRY_INC(i, argc)) {
504 PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
505 return OPTION_NEEDS_ARG_ERR;
507 secmodString = argv[i];
508 break;
511 return SUCCESS;
514 /************************************************************************
516 * v e r i f y _ p a r a m s
518 static Error
519 verify_params()
521 switch(command) {
522 case ADD_COMMAND:
523 if(libFile == NULL) {
524 PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
525 commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
526 return MISSING_PARAM_ERR;
528 break;
529 case CHANGEPW_COMMAND:
530 break;
531 case CREATE_COMMAND:
532 break;
533 case DELETE_COMMAND:
534 break;
535 case DISABLE_COMMAND:
536 break;
537 case ENABLE_COMMAND:
538 break;
539 case FIPS_COMMAND:
540 case CHKFIPS_COMMAND:
541 if(PL_strcasecmp(fipsArg, "true") &&
542 PL_strcasecmp(fipsArg, "false")) {
543 PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
544 return INVALID_FIPS_ARG;
546 break;
547 case JAR_COMMAND:
548 if(installDir == NULL) {
549 PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
550 commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
551 return MISSING_PARAM_ERR;
553 break;
554 case LIST_COMMAND:
555 case RAW_LIST_COMMAND:
556 break;
557 case RAW_ADD_COMMAND:
558 break;
559 case UNDEFAULT_COMMAND:
560 case DEFAULT_COMMAND:
561 if(mechanisms == NULL) {
562 PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
563 commandNames[command], optionStrings[MECHANISMS_ARG]);
564 return MISSING_PARAM_ERR;
566 break;
567 default:
568 /* Ignore this here */
569 break;
572 return SUCCESS;
575 /********************************************************************
577 * i n i t _ c r y p t o
579 * Does crypto initialization that all commands will require.
580 * If -nocertdb option is specified, don't open key or cert db (we don't
581 * need them if we aren't going to be verifying signatures). This is
582 * because serverland doesn't always have cert and key database files
583 * available.
585 * This function is ill advised. Names and locations of databases are
586 * private to NSS proper. Such functions only confuse other users.
589 static Error
590 check_crypto(PRBool create, PRBool readOnly)
592 char *dir;
593 char *moddbname=NULL;
594 Error retval;
595 static const char multiaccess[] = { "multiaccess:" };
597 dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */
598 if (dir[0] == '\0') {
599 PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
600 retval=NO_DBDIR_ERR;
601 goto loser;
603 if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) {
604 /* won't attempt to handle the multiaccess case. */
605 return SUCCESS;
607 #ifdef notdef
608 /* Make sure db directory exists and is readable */
609 if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
610 PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
611 retval = DIR_DOESNT_EXIST_ERR;
612 goto loser;
613 } else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
614 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
615 retval = DIR_NOT_READABLE_ERR;
616 goto loser;
619 if (secmodName == NULL) {
620 secmodName = "secmod.db";
623 moddbname = PR_smprintf("%s/%s", dir, secmodName);
624 if (!moddbname)
625 return OUT_OF_MEM_ERR;
627 /* Check for the proper permissions on databases */
628 if(create) {
629 /* Make sure dbs don't already exist, and the directory is
630 writeable */
631 if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
632 PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
633 moddbname);
634 retval=FILE_ALREADY_EXISTS_ERR;
635 goto loser;
636 } else
637 if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
638 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
639 retval=DIR_NOT_WRITEABLE_ERR;
640 goto loser;
642 } else {
643 /* Make sure dbs are readable and writeable */
644 if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
645 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
646 retval=FILE_NOT_READABLE_ERR;
647 goto loser;
650 /* Check for write access if we'll be making changes */
651 if( !readOnly ) {
652 if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
653 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
654 moddbname);
655 retval=FILE_NOT_WRITEABLE_ERR;
656 goto loser;
659 PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
660 SECU_ConfigDirectory(NULL));
662 #endif
663 retval=SUCCESS;
664 loser:
665 if (moddbname) {
666 PR_Free(moddbname);
668 return retval;
671 static Error
672 init_crypto(PRBool create, PRBool readOnly)
675 PRUint32 flags = 0;
676 SECStatus rv;
677 Error retval;
678 /* Open/create key database */
680 if (readOnly) flags |= NSS_INIT_READONLY;
681 if (nocertdb) flags |= NSS_INIT_NOCERTDB;
682 rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
683 secmodName, flags);
684 if (rv != SECSuccess) {
685 SECU_PrintPRandOSError(progName);
686 retval=NSS_INITIALIZE_FAILED_ERR;
687 } else
688 retval=SUCCESS;
690 return retval;
693 /*************************************************************************
695 * u s a g e
697 static void
698 usage()
700 PR_fprintf(PR_STDOUT,
701 "\nNetscape Cryptographic Module Utility\n"
702 "Usage: modutil [command] [options]\n\n"
703 " COMMANDS\n"
704 "---------------------------------------------------------------------------\n"
705 "-add MODULE_NAME Add the named module to the module database\n"
706 " -libfile LIBRARY_FILE The name of the file (.so or .dll)\n"
707 " containing the implementation of PKCS #11\n"
708 " [-ciphers CIPHER_LIST] Enable the given ciphers on this module\n"
709 " [-mechanisms MECHANISM_LIST] Make the module a default provider of the\n"
710 " given mechanisms\n"
711 " [-string CONFIG_STRING] Pass a configuration string to this module\n"
712 "-changepw TOKEN Change the password on the named token\n"
713 " [-pwfile FILE] The old password is in this file\n"
714 " [-newpwfile FILE] The new password is in this file\n"
715 "-chkfips [ true | false ] If true, verify FIPS mode. If false,\n"
716 " verify not FIPS mode\n"
717 "-create Create a new set of security databases\n"
718 "-default MODULE Make the given module a default provider\n"
719 " -mechanisms MECHANISM_LIST of the given mechanisms\n"
720 " [-slot SLOT] limit change to only the given slot\n"
721 "-delete MODULE Remove the named module from the module\n"
722 " database\n"
723 "-disable MODULE Disable the named module\n"
724 " [-slot SLOT] Disable only the named slot on the module\n"
725 "-enable MODULE Enable the named module\n"
726 " [-slot SLOT] Enable only the named slot on the module\n"
727 "-fips [ true | false ] If true, enable FIPS mode. If false,\n"
728 " disable FIPS mode\n"
729 "-force Do not run interactively\n"
730 "-jar JARFILE Install a PKCS #11 module from the given\n"
731 " JAR file in the PKCS #11 JAR format\n"
732 " -installdir DIR Use DIR as the root directory of the\n"
733 " installation\n"
734 " [-tempdir DIR] Use DIR as the temporary installation\n"
735 " directory. If not specified, the current\n"
736 " directory is used\n"
737 "-list [MODULE] Lists information about the specified module\n"
738 " or about all modules if none is specified\n"
739 "-rawadd MODULESPEC Add module spec string to secmod DB\n"
740 "-rawlist [MODULE] Display module spec(s) for one or all\n"
741 " loadable modules\n"
742 "-undefault MODULE The given module is NOT a default provider\n"
743 " -mechanisms MECHANISM_LIST of the listed mechanisms\n"
744 " [-slot SLOT] limit change to only the given slot\n"
745 "---------------------------------------------------------------------------\n"
746 "\n"
747 " OPTIONS\n"
748 "---------------------------------------------------------------------------\n"
749 "-dbdir DIR Directory DIR contains the security databases\n"
750 "-dbprefix prefix Prefix for the security databases\n"
751 "-nocertdb Do not load certificate or key databases. No\n"
752 " verification will be performed on JAR files.\n"
753 "-secmod secmodName Name of the security modules file\n"
754 "---------------------------------------------------------------------------\n"
755 "\n"
756 "Mechanism lists are colon-separated. The following mechanisms are recognized:\n"
757 "RSA, DSA, DH, RC2, RC4, RC5, AES, CAMELLIA, DES, MD2, MD5, SHA1, SHA256, SHA512,\n"
758 "SSL, TLS, RANDOM, and FRIENDLY\n"
759 "\n"
760 "Cipher lists are colon-separated. The following ciphers are recognized:\n"
761 "\n"
762 "\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n"
767 /*************************************************************************
769 * m a i n
772 main(int argc, char *argv[])
774 int errcode = SUCCESS;
775 PRBool createdb, readOnly;
776 #define STDINBUF_SIZE 80
777 char stdinbuf[STDINBUF_SIZE];
779 progName = strrchr(argv[0], '/');
780 progName = progName ? progName+1 : argv[0];
783 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
785 if(parse_args(argc, argv) != SUCCESS) {
786 usage();
787 errcode = INVALID_USAGE_ERR;
788 goto loser;
791 if(verify_params() != SUCCESS) {
792 usage();
793 errcode = INVALID_USAGE_ERR;
794 goto loser;
797 if(command==NO_COMMAND) {
798 PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
799 usage();
800 errcode = INVALID_USAGE_ERR;
801 goto loser;
804 /* Set up crypto stuff */
805 createdb = command==CREATE_COMMAND;
806 readOnly = ((command == LIST_COMMAND) ||
807 (command == CHKFIPS_COMMAND) ||
808 (command == RAW_LIST_COMMAND));
810 /* Make sure browser is not running if we're writing to a database */
811 /* Do this before initializing crypto */
812 if(!readOnly && !force) {
813 char *response;
815 PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
816 if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
817 PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
818 errcode = STDIN_READ_ERR;
819 goto loser;
821 if( (response=strtok(stdinbuf, " \r\n\t")) ) {
822 if(!PL_strcasecmp(response, "q")) {
823 PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
824 errcode = SUCCESS;
825 goto loser;
828 PR_fprintf(PR_STDOUT, "\n");
831 errcode = check_crypto(createdb, readOnly);
832 if( errcode != SUCCESS) {
833 goto loser;
836 if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
837 if(!moduleName) {
838 char *readOnlyStr, *noCertDBStr, *sep;
839 if (!secmodName) secmodName="secmod.db";
840 if (!dbprefix) dbprefix = "";
841 sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
842 readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ;
843 noCertDBStr = nocertdb ? "noCertDB" : "";
844 SECU_ConfigDirectory(dbdir);
846 moduleName=PR_smprintf(
847 "name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s "
848 "keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,"
849 "moduleDBOnly,critical\"",
850 SECU_ConfigDirectory(NULL),dbprefix,dbprefix,
851 secmodName, readOnlyStr,sep, noCertDBStr);
853 if (command == RAW_LIST_COMMAND) {
854 errcode = RawListModule(moduleName);
855 } else {
856 PORT_Assert(moduleSpec);
857 errcode = RawAddModule(moduleName,moduleSpec);
859 goto loser;
862 errcode = init_crypto(createdb, readOnly);
863 if( errcode != SUCCESS) {
864 goto loser;
867 /* Execute the command */
868 switch(command) {
869 case ADD_COMMAND:
870 errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
871 break;
872 case CHANGEPW_COMMAND:
873 errcode = ChangePW(tokenName, pwFile, newpwFile);
874 break;
875 case CREATE_COMMAND:
876 /* The work was already done in init_crypto() */
877 break;
878 case DEFAULT_COMMAND:
879 errcode = SetDefaultModule(moduleName, slotName, mechanisms);
880 break;
881 case DELETE_COMMAND:
882 errcode = DeleteModule(moduleName);
883 break;
884 case DISABLE_COMMAND:
885 errcode = EnableModule(moduleName, slotName, PR_FALSE);
886 break;
887 case ENABLE_COMMAND:
888 errcode = EnableModule(moduleName, slotName, PR_TRUE);
889 break;
890 case FIPS_COMMAND:
891 errcode = FipsMode(fipsArg);
892 break;
893 case CHKFIPS_COMMAND:
894 errcode = ChkFipsMode(fipsArg);
895 break;
896 case JAR_COMMAND:
897 Pk11Install_SetErrorHandler(install_error);
898 errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
899 PR_STDOUT, force, nocertdb);
900 break;
901 case LIST_COMMAND:
902 if(moduleName) {
903 errcode = ListModule(moduleName);
904 } else {
905 errcode = ListModules();
907 break;
908 case UNDEFAULT_COMMAND:
909 errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
910 break;
911 default:
912 PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
913 errcode = INVALID_USAGE_ERR;
914 break;
917 if (NSS_Shutdown() != SECSuccess) {
918 exit(1);
921 loser:
922 PR_Cleanup();
923 return errcode;
926 /************************************************************************
928 * i n s t a l l _ e r r o r
930 * Callback function to handle errors in PK11 JAR file installation.
932 static void
933 install_error(char *message)
935 PR_fprintf(PR_STDERR, "Install error: %s\n", message);
938 /*************************************************************************
940 * o u t _ o f _ m e m o r y
942 void
943 out_of_memory(void)
945 PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
946 exit(OUT_OF_MEM_ERR);
950 /**************************************************************************
952 * P R _ f g e t s
954 * fgets implemented with NSPR.
956 static char*
957 PR_fgets(char *buf, int size, PRFileDesc *file)
959 int i;
960 int status;
961 char c;
963 i=0;
964 while(i < size-1) {
965 status = PR_Read(file, (void*) &c, 1);
966 if(status==-1) {
967 return NULL;
968 } else if(status==0) {
969 break;
971 buf[i++] = c;
972 if(c=='\n') {
973 break;
976 buf[i]='\0';
978 return buf;