security/nss/cmd/modutil/modutil.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial