security/nss/cmd/modutil/modutil.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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/. */
     5 /* To edit this file, set TABSTOPS to 4 spaces. 
     6  * This is not the normal NSS convention. 
     7  */
     9 #include "modutil.h"
    10 #include "install.h"
    11 #include <plstr.h>
    12 #include "certdb.h" /* for CERT_DB_FILE_VERSION */
    13 #include "nss.h"
    15 static void install_error(char *message);
    16 static char* PR_fgets(char *buf, int size, PRFileDesc *file);
    17 static char *progName;
    20 /* This enum must be kept in sync with the commandNames list */
    21 typedef enum {
    22 	NO_COMMAND,
    23 	ADD_COMMAND,
    24 	CHANGEPW_COMMAND,
    25 	CREATE_COMMAND,
    26 	DEFAULT_COMMAND,
    27 	DELETE_COMMAND,
    28 	DISABLE_COMMAND,
    29 	ENABLE_COMMAND,
    30 	FIPS_COMMAND,
    31 	JAR_COMMAND,
    32 	LIST_COMMAND,
    33 	RAW_LIST_COMMAND,
    34 	RAW_ADD_COMMAND,
    35 	CHKFIPS_COMMAND,
    36 	UNDEFAULT_COMMAND
    37 } Command;
    39 /* This list must be kept in sync with the Command enum */
    40 static char *commandNames[] = {
    41 	"(no command)",
    42 	"-add",
    43 	"-changepw",
    44 	"-create",
    45 	"-default",
    46 	"-delete",
    47 	"-disable",
    48 	"-enable",
    49 	"-fips",
    50 	"-jar",
    51 	"-list",
    52 	"-rawlist",
    53 	"-rawadd",
    54 	"-chkfips",
    55 	"-undefault"
    56 };
    59 /* this enum must be kept in sync with the optionStrings list */
    60 typedef enum {
    61 	ADD_ARG=0,
    62 	RAW_ADD_ARG,
    63 	CHANGEPW_ARG,
    64 	CIPHERS_ARG,
    65 	CREATE_ARG,
    66 	DBDIR_ARG,
    67 	DBPREFIX_ARG,
    68 	DEFAULT_ARG,
    69 	DELETE_ARG,
    70 	DISABLE_ARG,
    71 	ENABLE_ARG,
    72 	FIPS_ARG,
    73 	FORCE_ARG,
    74 	JAR_ARG,
    75 	LIBFILE_ARG,
    76 	LIST_ARG,
    77 	RAW_LIST_ARG,
    78 	MECHANISMS_ARG,
    79 	NEWPWFILE_ARG,
    80 	PWFILE_ARG,
    81 	SLOT_ARG,
    82 	UNDEFAULT_ARG,
    83 	INSTALLDIR_ARG,
    84 	TEMPDIR_ARG,
    85 	SECMOD_ARG,
    86 	NOCERTDB_ARG,
    87 	STRING_ARG,
    88 	CHKFIPS_ARG,
    90 	NUM_ARGS	/* must be last */
    91 } Arg;
    93 /* This list must be kept in sync with the Arg enum */
    94 static char *optionStrings[] = {
    95 	"-add",
    96 	"-rawadd",
    97 	"-changepw",
    98 	"-ciphers",
    99 	"-create",
   100 	"-dbdir",
   101 	"-dbprefix",
   102 	"-default",
   103 	"-delete",
   104 	"-disable",
   105 	"-enable",
   106 	"-fips",
   107 	"-force",
   108 	"-jar",
   109 	"-libfile",
   110 	"-list",
   111 	"-rawlist",
   112 	"-mechanisms",
   113 	"-newpwfile",
   114 	"-pwfile",
   115 	"-slot",
   116 	"-undefault",
   117 	"-installdir",
   118 	"-tempdir",
   119 	"-secmod",
   120 	"-nocertdb",
   121 	"-string",
   122 	"-chkfips",
   123 };
   125 /* Increment i if doing so would have i still be less than j.  If you
   126    are able to do this, return 0.  Otherwise return 1. */
   127 #define TRY_INC(i,j)  ( ((i+1)<j) ? (++i, 0) : 1 )
   129 /********************************************************************
   130  *
   131  * file-wide variables obtained from the command line
   132  */
   133 static Command command = NO_COMMAND;
   134 static char* pwFile = NULL;
   135 static char* newpwFile = NULL;
   136 static char* moduleName = NULL;
   137 static char* moduleSpec = NULL;
   138 static char* slotName = NULL;
   139 static char* secmodName = NULL;
   140 static char* tokenName = NULL;
   141 static char* libFile = NULL;
   142 static char* dbdir = NULL;
   143 static char* dbprefix = "";
   144 static char* secmodString = NULL;
   145 static char* mechanisms = NULL;
   146 static char* ciphers = NULL;
   147 static char* fipsArg = NULL;
   148 static char* jarFile = NULL;
   149 static char* installDir = NULL;
   150 static char* tempDir = NULL;
   151 static short force = 0;
   152 static PRBool nocertdb = PR_FALSE;
   154 /*******************************************************************
   155  *
   156  * p a r s e _ a r g s
   157  */
   158 static Error
   159 parse_args(int argc, char *argv[])
   160 {
   161 	int i;
   162 	char *arg;
   163 	int optionType;
   165 	/* Loop over all arguments */
   166 	for(i=1; i < argc; i++) {
   167 		arg = argv[i];
   169 		/* Make sure this is an option and not some floating argument */
   170 		if(arg[0] != '-') {
   171 			PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
   172 			return UNEXPECTED_ARG_ERR;
   173 		}
   175 		/* Find which option this is */
   176 		for(optionType=0; optionType < NUM_ARGS; optionType++) {
   177 			if(! strcmp(arg, optionStrings[optionType])) {
   178 				break;
   179 			}
   180 		}
   182 		/* Deal with this specific option */
   183 		switch(optionType) {
   184 		case NUM_ARGS:
   185 		default:
   186 			PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
   187 			return UNKNOWN_OPTION_ERR;
   188 			break;
   189 		case ADD_ARG:
   190 			if(command != NO_COMMAND) {
   191 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   192 				return MULTIPLE_COMMAND_ERR;
   193 			}
   194 			command = ADD_COMMAND;
   195 			if(TRY_INC(i, argc)) {
   196 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   197 				return OPTION_NEEDS_ARG_ERR;
   198 			}
   199 			moduleName = argv[i];
   200 			break;
   201 		case CHANGEPW_ARG:
   202 			if(command != NO_COMMAND) {
   203 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   204 				return MULTIPLE_COMMAND_ERR;
   205 			}
   206 			command = CHANGEPW_COMMAND;
   207 			if(TRY_INC(i, argc)) {
   208 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   209 				return OPTION_NEEDS_ARG_ERR;
   210 			}
   211 			tokenName = argv[i];
   212 			break;
   213 		case CIPHERS_ARG:
   214 			if(ciphers != NULL) {
   215 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   216 				return DUPLICATE_OPTION_ERR;
   217 			}
   218 			if(TRY_INC(i, argc)) {
   219 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   220 				return OPTION_NEEDS_ARG_ERR;
   221 			}
   222 			ciphers = argv[i];
   223 			break;
   224 		case CREATE_ARG:
   225 			if(command != NO_COMMAND) {
   226 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   227 				return MULTIPLE_COMMAND_ERR;
   228 			}
   229 			command = CREATE_COMMAND;
   230 			break;
   231 		case DBDIR_ARG:
   232 			if(dbdir != NULL) {
   233 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   234 				return DUPLICATE_OPTION_ERR;
   235 			}
   236 			if(TRY_INC(i, argc)) {
   237 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   238 				return OPTION_NEEDS_ARG_ERR;
   239 			}
   240 			dbdir = argv[i];
   241 			break;
   242 		case DBPREFIX_ARG:
   243 			if(TRY_INC(i, argc)) {
   244 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   245 				return OPTION_NEEDS_ARG_ERR;
   246 			}
   247 			dbprefix = argv[i];
   248 			break;
   249 		case UNDEFAULT_ARG:
   250 		case DEFAULT_ARG:
   251 			if(command != NO_COMMAND) {
   252 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   253 				return MULTIPLE_COMMAND_ERR;
   254 			}
   255 			if(optionType == DEFAULT_ARG) {
   256 				command = DEFAULT_COMMAND;
   257 			} else {
   258 				command = UNDEFAULT_COMMAND;
   259 			}
   260 			if(TRY_INC(i, argc)) {
   261 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   262 				return OPTION_NEEDS_ARG_ERR;
   263 			}
   264 			moduleName = argv[i];
   265 			break;
   266 		case DELETE_ARG:
   267 			if(command != NO_COMMAND) {
   268 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   269 				return MULTIPLE_COMMAND_ERR;
   270 			}
   271 			command = DELETE_COMMAND;
   272 			if(TRY_INC(i, argc)) {
   273 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   274 				return OPTION_NEEDS_ARG_ERR;
   275 			}
   276 			moduleName = argv[i];
   277 			break;
   278 		case DISABLE_ARG:
   279 			if(command != NO_COMMAND) {
   280 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   281 				return MULTIPLE_COMMAND_ERR;
   282 			}
   283 			command = DISABLE_COMMAND;
   284 			if(TRY_INC(i, argc)) {
   285 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   286 				return OPTION_NEEDS_ARG_ERR;
   287 			}
   288 			moduleName = argv[i];
   289 			break;
   290 		case ENABLE_ARG:
   291 			if(command != NO_COMMAND) {
   292 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   293 				return MULTIPLE_COMMAND_ERR;
   294 			}
   295 			command = ENABLE_COMMAND;
   296 			if(TRY_INC(i, argc)) {
   297 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   298 				return OPTION_NEEDS_ARG_ERR;
   299 			}
   300 			moduleName = argv[i];
   301 			break;
   302 		case FIPS_ARG:
   303 			if(command != NO_COMMAND) {
   304 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   305 				return MULTIPLE_COMMAND_ERR;
   306 			}
   307 			command = FIPS_COMMAND;
   308 			if(TRY_INC(i, argc)) {
   309 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   310 				return OPTION_NEEDS_ARG_ERR;
   311 			}
   312 			fipsArg = argv[i];
   313 			break;
   314 		case CHKFIPS_ARG:
   315 			if(command != NO_COMMAND) {
   316 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   317 				return MULTIPLE_COMMAND_ERR;
   318 			}
   319 			command = CHKFIPS_COMMAND;
   320 			if(TRY_INC(i, argc)) {
   321 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   322 				return OPTION_NEEDS_ARG_ERR;
   323 			}
   324 			fipsArg = argv[i];
   325 			break;
   326 		case FORCE_ARG:
   327 			force = 1;
   328 			break;
   329 		case NOCERTDB_ARG:
   330 			nocertdb = PR_TRUE;
   331 			break;
   332 		case INSTALLDIR_ARG:
   333 			if(installDir != NULL) {
   334 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   335 				return DUPLICATE_OPTION_ERR;
   336 			}
   337 			if(TRY_INC(i, argc)) {
   338 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   339 				return OPTION_NEEDS_ARG_ERR;
   340 			}
   341 			installDir = argv[i];
   342 			break;
   343 		case TEMPDIR_ARG:
   344 			if(tempDir != NULL) {
   345 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   346 				return DUPLICATE_OPTION_ERR;
   347 			}
   348 			if(TRY_INC(i, argc)) {
   349 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   350 				return OPTION_NEEDS_ARG_ERR;
   351 			}
   352 			tempDir = argv[i];
   353 			break;
   354 		case JAR_ARG:
   355 			if(command != NO_COMMAND) {
   356 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   357 				return MULTIPLE_COMMAND_ERR;
   358 			}
   359 			command = JAR_COMMAND;
   360 			if(TRY_INC(i, argc)) {
   361 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   362 				return OPTION_NEEDS_ARG_ERR;
   363 			}
   364 			jarFile = argv[i];
   365 			break;
   366 		case LIBFILE_ARG:
   367 			if(libFile != NULL) {
   368 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   369 				return DUPLICATE_OPTION_ERR;
   370 			}
   371 			if(TRY_INC(i, argc)) {
   372 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   373 				return OPTION_NEEDS_ARG_ERR;
   374 			}
   375 			libFile = argv[i];
   376 			break;
   377 		case LIST_ARG:
   378 			if(command != NO_COMMAND) {
   379 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   380 				return MULTIPLE_COMMAND_ERR;
   381 			}
   382 			command = LIST_COMMAND;
   383 			/* This option may or may not have an argument */
   384 			if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
   385 				moduleName = argv[++i];
   386 			}
   387 			break;
   388 		case RAW_LIST_ARG:
   389 			if(command != NO_COMMAND) {
   390 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   391 				return MULTIPLE_COMMAND_ERR;
   392 			}
   393 			command = RAW_LIST_COMMAND;
   394 			/* This option may or may not have an argument */
   395 			if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
   396 				moduleName = argv[++i];
   397 			}
   398 			break;
   399 		case RAW_ADD_ARG:
   400 			if(command != NO_COMMAND) {
   401 				PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
   402 				return MULTIPLE_COMMAND_ERR;
   403 			}
   404 			command = RAW_ADD_COMMAND;
   405 			if(TRY_INC(i, argc)) {
   406 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   407 				return OPTION_NEEDS_ARG_ERR;
   408 			}
   409 			moduleSpec = argv[i];
   410 			break;
   411 		case MECHANISMS_ARG:
   412 			if(mechanisms != NULL) {
   413 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   414 				return DUPLICATE_OPTION_ERR;
   415 			}
   416 			if(TRY_INC(i, argc)) {
   417 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   418 				return OPTION_NEEDS_ARG_ERR;
   419 			}
   420 			mechanisms = argv[i];
   421 			break;
   422 		case NEWPWFILE_ARG:
   423 			if(newpwFile != NULL) {
   424 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   425 				return DUPLICATE_OPTION_ERR;
   426 			}
   427 			if(TRY_INC(i, argc)) {
   428 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   429 				return OPTION_NEEDS_ARG_ERR;
   430 			}
   431 			newpwFile = argv[i];
   432 			break;
   433 		case PWFILE_ARG:
   434 			if(pwFile != NULL) {
   435 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   436 				return DUPLICATE_OPTION_ERR;
   437 			}
   438 			if(TRY_INC(i, argc)) {
   439 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   440 				return OPTION_NEEDS_ARG_ERR;
   441 			}
   442 			pwFile = argv[i];
   443 			break;
   444 		case SLOT_ARG:
   445 			if(slotName != NULL) {
   446 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   447 				return DUPLICATE_OPTION_ERR;
   448 			}
   449 			if(TRY_INC(i, argc)) {
   450 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   451 				return OPTION_NEEDS_ARG_ERR;
   452 			}
   453 			slotName = argv[i];
   454 			break;
   455 		case SECMOD_ARG:
   456 			if(secmodName != NULL) {
   457 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   458 				return DUPLICATE_OPTION_ERR;
   459 			}
   460 			if(TRY_INC(i, argc)) {
   461 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   462 				return OPTION_NEEDS_ARG_ERR;
   463 			}
   464 			secmodName = argv[i];
   465 			break;
   466 		case STRING_ARG:
   467 			if(secmodString != NULL) {
   468 				PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
   469 				return DUPLICATE_OPTION_ERR;
   470 			}
   471 			if(TRY_INC(i, argc)) {
   472 				PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
   473 				return OPTION_NEEDS_ARG_ERR;
   474 			}
   475 			secmodString = argv[i];
   476 			break;
   477 		}
   478 	}
   479 	return SUCCESS;
   480 }
   482 /************************************************************************
   483  *
   484  * v e r i f y _ p a r a m s
   485  */
   486 static Error
   487 verify_params()
   488 {
   489 	switch(command) {
   490 	case ADD_COMMAND:
   491 		if(libFile == NULL) {
   492 			PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
   493 				commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
   494 			return MISSING_PARAM_ERR;
   495 		}
   496 		break;
   497 	case CHANGEPW_COMMAND:
   498 		break;
   499 	case CREATE_COMMAND:
   500 		break;
   501 	case DELETE_COMMAND:
   502 		break;
   503 	case DISABLE_COMMAND:
   504 		break;
   505 	case ENABLE_COMMAND:
   506 		break;
   507 	case FIPS_COMMAND:
   508 	case CHKFIPS_COMMAND:
   509 		if(PL_strcasecmp(fipsArg, "true") &&
   510 			PL_strcasecmp(fipsArg, "false")) {
   511 			PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
   512 			return INVALID_FIPS_ARG;
   513 		}
   514 		break;
   515 	case JAR_COMMAND:
   516 		if(installDir == NULL) {
   517 			PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
   518 				commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
   519 			return MISSING_PARAM_ERR;
   520 		}
   521 		break;
   522 	case LIST_COMMAND:
   523 	case RAW_LIST_COMMAND:
   524 		break;
   525 	case RAW_ADD_COMMAND:
   526 		break;
   527 	case UNDEFAULT_COMMAND:
   528 	case DEFAULT_COMMAND:
   529 		if(mechanisms == NULL) {
   530 			PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
   531 				commandNames[command], optionStrings[MECHANISMS_ARG]);
   532 			return MISSING_PARAM_ERR;
   533 		}
   534 		break;
   535 	default:
   536 		/* Ignore this here */
   537 		break;
   538 	}
   540 	return SUCCESS;
   541 }
   543 /********************************************************************
   544  *
   545  * i n i t _ c r y p t o
   546  *
   547  * Does crypto initialization that all commands will require.
   548  * If -nocertdb option is specified, don't open key or cert db (we don't
   549  * need them if we aren't going to be verifying signatures).  This is
   550  * because serverland doesn't always have cert and key database files
   551  * available.
   552  *
   553  * This function is ill advised. Names and locations of databases are
   554  * private to NSS proper. Such functions only confuse other users.
   555  *
   556  */
   557 static Error
   558 check_crypto(PRBool create, PRBool readOnly)
   559 {
   560 	char *dir;
   561 	char *moddbname=NULL;
   562 	Error retval;
   563 	static const char multiaccess[] = { "multiaccess:" };
   565 	dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */
   566 	if (dir[0] == '\0') {
   567 		PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
   568 		retval=NO_DBDIR_ERR;
   569 		goto loser;
   570 	}
   571 	if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) {
   572 		/* won't attempt to handle the multiaccess case. */
   573 		return SUCCESS;
   574 	}
   575 #ifdef notdef
   576 	/* Make sure db directory exists and is readable */
   577 	if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
   578 		PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
   579 		retval = DIR_DOESNT_EXIST_ERR;
   580 		goto loser;
   581 	} else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
   582 		PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
   583 		retval = DIR_NOT_READABLE_ERR;
   584 		goto loser;
   585 	}
   587 	if (secmodName == NULL) {
   588 		secmodName = "secmod.db";
   589 	}
   591 	moddbname = PR_smprintf("%s/%s", dir, secmodName);
   592 	if (!moddbname)
   593 	    return OUT_OF_MEM_ERR;
   595 	/* Check for the proper permissions on databases */
   596 	if(create) {
   597 		/* Make sure dbs don't already exist, and the directory is
   598 			writeable */
   599 		if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
   600 			PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
   601 			           moddbname);
   602 			retval=FILE_ALREADY_EXISTS_ERR;
   603 			goto loser;
   604 		} else 
   605 		if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
   606 			PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
   607 			retval=DIR_NOT_WRITEABLE_ERR;
   608 			goto loser;
   609 		}
   610 	} else {
   611 		/* Make sure dbs are readable and writeable */
   612 		if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
   613 			PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
   614 			retval=FILE_NOT_READABLE_ERR;
   615 			goto loser;
   616 		}
   618 		/* Check for write access if we'll be making changes */
   619 		if( !readOnly ) {
   620 			if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
   621 				PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
   622 							moddbname);
   623 				retval=FILE_NOT_WRITEABLE_ERR;
   624 				goto loser;
   625 			}
   626 		}
   627 		PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
   628 		  SECU_ConfigDirectory(NULL));
   629 	}
   630 #endif
   631 	retval=SUCCESS;
   632 loser:
   633 	if (moddbname) {
   634 		PR_Free(moddbname);
   635 	}
   636 	return retval;
   637 }
   639 static Error
   640 init_crypto(PRBool create, PRBool readOnly)
   641 {
   643 	PRUint32  flags = 0;
   644 	SECStatus rv;
   645 	Error     retval;
   646 	/* Open/create key database */
   648 	if (readOnly) flags |= NSS_INIT_READONLY;
   649 	if (nocertdb) flags |= NSS_INIT_NOCERTDB;
   650 	rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
   651 		       secmodName, flags);
   652 	if (rv != SECSuccess) {
   653 		SECU_PrintPRandOSError(progName);
   654 		retval=NSS_INITIALIZE_FAILED_ERR;
   655 	} else 
   656 		retval=SUCCESS;
   658 	return retval;
   659 }
   661 /*************************************************************************
   662  *
   663  * u s a g e
   664  */
   665 static void
   666 usage()
   667 {
   668 	PR_fprintf(PR_STDOUT,
   669 "\nNetscape Cryptographic Module Utility\n"
   670 "Usage: modutil [command] [options]\n\n"
   671 "                            COMMANDS\n"
   672 "---------------------------------------------------------------------------\n"
   673 "-add MODULE_NAME                 Add the named module to the module database\n"
   674 "   -libfile LIBRARY_FILE         The name of the file (.so or .dll)\n"
   675 "                                 containing the implementation of PKCS #11\n"
   676 "   [-ciphers CIPHER_LIST]        Enable the given ciphers on this module\n"
   677 "   [-mechanisms MECHANISM_LIST]  Make the module a default provider of the\n"
   678 "                                 given mechanisms\n"
   679 "   [-string CONFIG_STRING]       Pass a configuration string to this module\n"
   680 "-changepw TOKEN                  Change the password on the named token\n"
   681 "   [-pwfile FILE]                The old password is in this file\n"
   682 "   [-newpwfile FILE]             The new password is in this file\n"
   683 "-chkfips [ true | false ]        If true, verify  FIPS mode.  If false,\n"
   684 "                                 verify not FIPS mode\n"
   685 "-create                          Create a new set of security databases\n"
   686 "-default MODULE                  Make the given module a default provider\n"
   687 "   -mechanisms MECHANISM_LIST    of the given mechanisms\n"
   688 "   [-slot SLOT]                  limit change to only the given slot\n"
   689 "-delete MODULE                   Remove the named module from the module\n"
   690 "                                 database\n"
   691 "-disable MODULE                  Disable the named module\n"
   692 "   [-slot SLOT]                  Disable only the named slot on the module\n"
   693 "-enable MODULE                   Enable the named module\n"
   694 "   [-slot SLOT]                  Enable only the named slot on the module\n"
   695 "-fips [ true | false ]           If true, enable FIPS mode.  If false,\n"
   696 "                                 disable FIPS mode\n"
   697 "-force                           Do not run interactively\n"
   698 "-jar JARFILE                     Install a PKCS #11 module from the given\n"
   699 "                                 JAR file in the PKCS #11 JAR format\n"
   700 "   -installdir DIR               Use DIR as the root directory of the\n"
   701 "                                 installation\n"
   702 "   [-tempdir DIR]                Use DIR as the temporary installation\n"
   703 "                                 directory. If not specified, the current\n"
   704 "                                 directory is used\n"
   705 "-list [MODULE]                   Lists information about the specified module\n"
   706 "                                 or about all modules if none is specified\n"
   707 "-rawadd MODULESPEC               Add module spec string to secmod DB\n"
   708 "-rawlist [MODULE]                Display module spec(s) for one or all\n"
   709 "                                 loadable modules\n"
   710 "-undefault MODULE                The given module is NOT a default provider\n"
   711 "   -mechanisms MECHANISM_LIST    of the listed mechanisms\n"
   712 "   [-slot SLOT]                  limit change to only the given slot\n"
   713 "---------------------------------------------------------------------------\n"
   714 "\n"
   715 "                             OPTIONS\n"
   716 "---------------------------------------------------------------------------\n"
   717 "-dbdir DIR                       Directory DIR contains the security databases\n"
   718 "-dbprefix prefix                 Prefix for the security databases\n"
   719 "-nocertdb                        Do not load certificate or key databases. No\n"
   720 "                                 verification will be performed on JAR files.\n"
   721 "-secmod secmodName               Name of the security modules file\n"
   722 "---------------------------------------------------------------------------\n"
   723 "\n"
   724 "Mechanism lists are colon-separated.  The following mechanisms are recognized:\n"
   725 "RSA, DSA, DH, RC2, RC4, RC5, AES, CAMELLIA, DES, MD2, MD5, SHA1, SHA256, SHA512,\n"
   726 "SSL, TLS, RANDOM, and FRIENDLY\n"
   727 "\n"
   728 "Cipher lists are colon-separated.  The following ciphers are recognized:\n"
   729 "\n"
   730 "\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n"
   731 );
   733 }
   735 /*************************************************************************
   736  *
   737  * m a i n
   738  */
   739 int
   740 main(int argc, char *argv[])
   741 {
   742 	int errcode = SUCCESS;
   743 	PRBool createdb, readOnly;
   744 #define STDINBUF_SIZE 80
   745 	char stdinbuf[STDINBUF_SIZE];
   747 	progName = strrchr(argv[0], '/');
   748 	progName = progName ? progName+1 : argv[0];
   751 	PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   753 	if(parse_args(argc, argv) != SUCCESS) {
   754 		usage();
   755 		errcode = INVALID_USAGE_ERR;
   756 		goto loser;
   757 	}
   759 	if(verify_params() != SUCCESS) {
   760 		usage();
   761 		errcode = INVALID_USAGE_ERR;
   762 		goto loser;
   763 	}
   765 	if(command==NO_COMMAND) {
   766 		PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
   767 		usage();
   768 		errcode = INVALID_USAGE_ERR;
   769 		goto loser;
   770 	}
   772 	/* Set up crypto stuff */
   773 	createdb = command==CREATE_COMMAND;
   774 	readOnly = ((command == LIST_COMMAND) || 
   775 	            (command == CHKFIPS_COMMAND) ||
   776 	            (command == RAW_LIST_COMMAND));
   778 	/* Make sure browser is not running if we're writing to a database */
   779 	/* Do this before initializing crypto */
   780 	if(!readOnly && !force) {
   781 		char *response;
   783 		PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
   784 		if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
   785 			PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
   786 			errcode = STDIN_READ_ERR;
   787 			goto loser;
   788 		}
   789 		if( (response=strtok(stdinbuf, " \r\n\t")) ) {
   790 			if(!PL_strcasecmp(response, "q")) {
   791 				PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
   792 				errcode = SUCCESS;
   793 				goto loser;
   794 			}
   795 		}
   796 		PR_fprintf(PR_STDOUT, "\n");
   797 	}
   799 	errcode = check_crypto(createdb, readOnly);
   800 	if( errcode != SUCCESS) {
   801 		goto loser;
   802 	}
   804 	if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
   805 		if(!moduleName) {
   806 			char *readOnlyStr, *noCertDBStr, *sep;
   807 			if (!secmodName) secmodName="secmod.db";
   808 			if (!dbprefix) dbprefix = "";
   809 			sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
   810 			readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ;
   811 			noCertDBStr = nocertdb ? "noCertDB" : "";
   812 			SECU_ConfigDirectory(dbdir);
   814 			moduleName=PR_smprintf(
   815     "name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s "
   816     "keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,"
   817     "moduleDBOnly,critical\"",
   818 			                       SECU_ConfigDirectory(NULL),dbprefix,dbprefix,
   819 			                       secmodName, readOnlyStr,sep, noCertDBStr);
   820 		}
   821 		if (command == RAW_LIST_COMMAND) {
   822 			errcode = RawListModule(moduleName);
   823 		} else {
   824 			PORT_Assert(moduleSpec);
   825 			errcode = RawAddModule(moduleName,moduleSpec);
   826 		}
   827 		goto loser;
   828 	}
   830 	errcode = init_crypto(createdb, readOnly);
   831 	if( errcode != SUCCESS) {
   832 		goto loser;
   833 	}
   835 	errcode = LoadMechanismList();
   836 	if (errcode != SUCCESS) {
   837 		goto loser;
   838 	}
   840 	/* Execute the command */
   841 	switch(command) {
   842 	case ADD_COMMAND:
   843 		errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
   844 		break;
   845 	case CHANGEPW_COMMAND:
   846 		errcode = ChangePW(tokenName, pwFile, newpwFile);
   847 		break;
   848 	case CREATE_COMMAND:
   849 		/* The work was already done in init_crypto() */
   850 		break;
   851 	case DEFAULT_COMMAND:
   852 		errcode = SetDefaultModule(moduleName, slotName, mechanisms);
   853 		break;
   854 	case DELETE_COMMAND:
   855 		errcode = DeleteModule(moduleName);
   856 		break;
   857 	case DISABLE_COMMAND:
   858 		errcode = EnableModule(moduleName, slotName, PR_FALSE);
   859 		break;
   860 	case ENABLE_COMMAND:
   861 		errcode = EnableModule(moduleName, slotName, PR_TRUE);
   862 		break;
   863 	case FIPS_COMMAND:
   864 		errcode = FipsMode(fipsArg);
   865 		break;
   866 	case CHKFIPS_COMMAND:
   867 		errcode = ChkFipsMode(fipsArg);
   868 		break;
   869 	case JAR_COMMAND:
   870 		Pk11Install_SetErrorHandler(install_error);
   871 		errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
   872 		                                PR_STDOUT, force, nocertdb);
   873 		break;
   874 	case LIST_COMMAND:
   875 		if(moduleName) {
   876 			errcode = ListModule(moduleName);
   877 		} else {
   878 			errcode = ListModules();
   879 		}
   880 		break;
   881 	case UNDEFAULT_COMMAND:
   882 		errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
   883 		break;
   884 	default:
   885 		PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
   886 		errcode = INVALID_USAGE_ERR;
   887 		break;
   888 	}
   890 	if (NSS_Shutdown() != SECSuccess) {
   891 		exit(1);
   892 	}
   894 loser:
   895 	PR_Cleanup();
   896 	return errcode;
   897 }
   899 /************************************************************************
   900  *
   901  * i n s t a l l _ e r r o r
   902  *
   903  * Callback function to handle errors in PK11 JAR file installation.
   904  */
   905 static void
   906 install_error(char *message)
   907 {
   908 	PR_fprintf(PR_STDERR, "Install error: %s\n", message);
   909 }
   911 /*************************************************************************
   912  *
   913  * o u t _ o f _ m e m o r y
   914  */
   915 void
   916 out_of_memory(void)
   917 {
   918 	PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
   919 	exit(OUT_OF_MEM_ERR);
   920 }
   923 /**************************************************************************
   924  *
   925  * P R _ f g e t s
   926  *
   927  * fgets implemented with NSPR.
   928  */
   929 static char*
   930 PR_fgets(char *buf, int size, PRFileDesc *file)
   931 {
   932 	int i;
   933 	int status;
   934 	char c;
   936 	i=0;
   937 	while(i < size-1) {
   938 		status = PR_Read(file, (void*) &c, 1);
   939 		if(status==-1) {
   940 			return NULL;
   941 		} else if(status==0) {
   942 			break;
   943 		}
   944 		buf[i++] = c;
   945 		if(c=='\n') {
   946 			break;
   947 		}
   948 	}
   949 	buf[i]='\0';
   951 	return buf;
   952 }

mercurial