security/nss/cmd/multinit/multinit.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.

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 #include <stdio.h>
michael@0 6 #include <string.h>
michael@0 7 #include <stdlib.h>
michael@0 8 #include "nss.h"
michael@0 9 #include "secutil.h"
michael@0 10 #include "pk11pub.h"
michael@0 11 #include "cert.h"
michael@0 12
michael@0 13 typedef struct commandDescriptStr {
michael@0 14 int required;
michael@0 15 char *arg;
michael@0 16 char *des;
michael@0 17 } commandDescript;
michael@0 18
michael@0 19 enum optionNames {
michael@0 20 opt_liborder = 0,
michael@0 21 opt_mainDB,
michael@0 22 opt_lib1DB,
michael@0 23 opt_lib2DB,
michael@0 24 opt_mainRO,
michael@0 25 opt_lib1RO,
michael@0 26 opt_lib2RO,
michael@0 27 opt_mainCMD,
michael@0 28 opt_lib1CMD,
michael@0 29 opt_lib2CMD,
michael@0 30 opt_mainTokNam,
michael@0 31 opt_lib1TokNam,
michael@0 32 opt_lib2TokNam,
michael@0 33 opt_oldStyle,
michael@0 34 opt_verbose,
michael@0 35 opt_summary,
michael@0 36 opt_help,
michael@0 37 opt_last
michael@0 38 };
michael@0 39
michael@0 40
michael@0 41 static const
michael@0 42 secuCommandFlag options_init[] =
michael@0 43 {
michael@0 44 { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" },
michael@0 45 { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" },
michael@0 46 { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" },
michael@0 47 { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" },
michael@0 48 { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" },
michael@0 49 { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" },
michael@0 50 { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" },
michael@0 51 { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" },
michael@0 52 { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" },
michael@0 53 { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" },
michael@0 54 { /* opt_mainTokNam */'t', PR_TRUE, 0, PR_FALSE, "main_token_name" },
michael@0 55 { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" },
michael@0 56 { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" },
michael@0 57 { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" },
michael@0 58 { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" },
michael@0 59 { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" },
michael@0 60 { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" }
michael@0 61 };
michael@0 62
michael@0 63 static const
michael@0 64 commandDescript options_des[] =
michael@0 65 {
michael@0 66 { /* opt_liborder */ PR_FALSE, "initOrder",
michael@0 67 " Specifies the order of NSS initialization and shutdown. Order is\n"
michael@0 68 " given as a string where each character represents either an init or\n"
michael@0 69 " a shutdown of the main program or one of the 2 test libraries\n"
michael@0 70 " (library 1 and library 2). The valid characters are as follows:\n"
michael@0 71 " M Init the main program\n 1 Init library 1\n"
michael@0 72 " 2 Init library 2\n"
michael@0 73 " m Shutdown the main program\n i Shutdown library 1\n"
michael@0 74 " z Shutdown library 2\n" },
michael@0 75 { /* opt_mainDB */ PR_TRUE, "nss_db",
michael@0 76 " Specified the directory to open the nss database for the main\n"
michael@0 77 " program. Must be specified if \"M\" is given in the order string\n"},
michael@0 78 { /* opt_lib1DB */ PR_FALSE, "nss_db",
michael@0 79 " Specified the directory to open the nss database for library 1.\n"
michael@0 80 " Must be specified if \"1\" is given in the order string\n"},
michael@0 81 { /* opt_lib2DB */ PR_FALSE, "nss_db",
michael@0 82 " Specified the directory to open the nss database for library 2.\n"
michael@0 83 " Must be specified if \"2\" is given in the order string\n"},
michael@0 84 { /* opt_mainRO */ PR_FALSE, NULL,
michael@0 85 " Open the main program's database read only.\n" },
michael@0 86 { /* opt_lib1RO */ PR_FALSE, NULL,
michael@0 87 " Open library 1's database read only.\n" },
michael@0 88 { /* opt_lib2RO */ PR_FALSE, NULL,
michael@0 89 " Open library 2's database read only.\n" },
michael@0 90 { /* opt_mainCMD */ PR_FALSE, "nss_command",
michael@0 91 " Specifies the NSS command to execute in the main program.\n"
michael@0 92 " Valid commands are: \n"
michael@0 93 " key_slot, list_slots, list_certs, add_cert, none.\n"
michael@0 94 " Default is \"none\".\n" },
michael@0 95 { /* opt_lib1CMD */ PR_FALSE, "nss_command",
michael@0 96 " Specifies the NSS command to execute in library 1.\n" },
michael@0 97 { /* opt_lib2CMD */ PR_FALSE, "nss_command",
michael@0 98 " Specifies the NSS command to execute in library 2.\n" },
michael@0 99 { /* opt_mainTokNam */PR_FALSE, "token_name",
michael@0 100 " Specifies the name of PKCS11 token for the main program's "
michael@0 101 "database.\n" },
michael@0 102 { /* opt_lib1TokNam */PR_FALSE, "token_name",
michael@0 103 " Specifies the name of PKCS11 token for library 1's database.\n" },
michael@0 104 { /* opt_lib2TokNam */PR_FALSE, "token_name",
michael@0 105 " Specifies the name of PKCS11 token for library 2's database.\n" },
michael@0 106 { /* opt_oldStype */ PR_FALSE, NULL,
michael@0 107 " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
michael@0 108 " program.\n" },
michael@0 109 { /* opt_verbose */ PR_FALSE, NULL,
michael@0 110 " Noisily output status to standard error\n" },
michael@0 111 { /* opt_summarize */ PR_FALSE, NULL,
michael@0 112 "report a summary of the test results\n" },
michael@0 113 { /* opt_help */ PR_FALSE, NULL, " give this message\n" }
michael@0 114 };
michael@0 115
michael@0 116 /*
michael@0 117 * output our short help (table driven). (does not exit).
michael@0 118 */
michael@0 119 static void
michael@0 120 short_help(const char *prog)
michael@0 121 {
michael@0 122 int count = opt_last;
michael@0 123 int i,words_found;
michael@0 124
michael@0 125 /* make sure all the tables are up to date before we allow compiles to
michael@0 126 * succeed */
michael@0 127 PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) == opt_last);
michael@0 128 PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) ==
michael@0 129 sizeof(options_des)/sizeof(commandDescript));
michael@0 130
michael@0 131 /* print the base usage */
michael@0 132 fprintf(stderr,"usage: %s ",prog);
michael@0 133 for (i=0, words_found=0; i < count; i++) {
michael@0 134 if (!options_des[i].required) {
michael@0 135 fprintf(stderr,"[");
michael@0 136 }
michael@0 137 if (options_init[i].longform) {
michael@0 138 fprintf(stderr, "--%s", options_init[i].longform);
michael@0 139 words_found++;
michael@0 140 } else {
michael@0 141 fprintf(stderr, "-%c", options_init[i].flag);
michael@0 142 }
michael@0 143 if (options_init[i].needsArg) {
michael@0 144 if (options_des[i].arg) {
michael@0 145 fprintf(stderr," %s",options_des[i].arg);
michael@0 146 } else {
michael@0 147 fprintf(stderr," arg");
michael@0 148 }
michael@0 149 words_found++;
michael@0 150 }
michael@0 151 if (!options_des[i].required) {
michael@0 152 fprintf(stderr,"]");
michael@0 153 }
michael@0 154 if (i < count-1 ) {
michael@0 155 if (words_found >= 5) {
michael@0 156 fprintf(stderr,"\n ");
michael@0 157 words_found=0;
michael@0 158 } else {
michael@0 159 fprintf(stderr," ");
michael@0 160 }
michael@0 161 }
michael@0 162 }
michael@0 163 fprintf(stderr,"\n");
michael@0 164 }
michael@0 165
michael@0 166 /*
michael@0 167 * print out long help. like short_help, this does not exit
michael@0 168 */
michael@0 169 static void
michael@0 170 long_help(const char *prog)
michael@0 171 {
michael@0 172 int i;
michael@0 173 int count = opt_last;
michael@0 174
michael@0 175 short_help(prog);
michael@0 176 /* print the option descriptions */
michael@0 177 fprintf(stderr,"\n");
michael@0 178 for (i=0; i < count; i++) {
michael@0 179 fprintf(stderr," ");
michael@0 180 if (options_init[i].flag) {
michael@0 181 fprintf(stderr, "-%c", options_init[i].flag);
michael@0 182 if (options_init[i].longform) {
michael@0 183 fprintf(stderr,",");
michael@0 184 }
michael@0 185 }
michael@0 186 if (options_init[i].longform) {
michael@0 187 fprintf(stderr,"--%s", options_init[i].longform);
michael@0 188 }
michael@0 189 if (options_init[i].needsArg) {
michael@0 190 if (options_des[i].arg) {
michael@0 191 fprintf(stderr," %s",options_des[i].arg);
michael@0 192 } else {
michael@0 193 fprintf(stderr," arg");
michael@0 194 }
michael@0 195 if (options_init[i].arg) {
michael@0 196 fprintf(stderr," (default = \"%s\")",options_init[i].arg);
michael@0 197 }
michael@0 198 }
michael@0 199 fprintf(stderr,"\n%s",options_des[i].des);
michael@0 200 }
michael@0 201 }
michael@0 202
michael@0 203 /*
michael@0 204 * record summary data
michael@0 205 */
michael@0 206 struct bufferData {
michael@0 207 char * data; /* lowest address of the buffer */
michael@0 208 char * next; /* pointer to the next element on the buffer */
michael@0 209 int len; /* length of the buffer */
michael@0 210 };
michael@0 211
michael@0 212 /* our actual buffer. If data is NULL, then all append ops
michael@0 213 * except are noops */
michael@0 214 static struct bufferData buffer= { NULL, NULL, 0 };
michael@0 215
michael@0 216 #define CHUNK_SIZE 1000
michael@0 217
michael@0 218 /*
michael@0 219 * get our initial data. and set the buffer variables up. on failure,
michael@0 220 * just don't initialize the buffer.
michael@0 221 */
michael@0 222 static void
michael@0 223 initBuffer(void)
michael@0 224 {
michael@0 225 buffer.data = PORT_Alloc(CHUNK_SIZE);
michael@0 226 if (!buffer.data) {
michael@0 227 return;
michael@0 228 }
michael@0 229 buffer.next = buffer.data;
michael@0 230 buffer.len = CHUNK_SIZE;
michael@0 231 }
michael@0 232
michael@0 233 /*
michael@0 234 * grow the buffer. If we can't get more data, record a 'D' in the second
michael@0 235 * to last record and allow the rest of the data to overwrite the last
michael@0 236 * element.
michael@0 237 */
michael@0 238 static void
michael@0 239 growBuffer(void)
michael@0 240 {
michael@0 241 char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE);
michael@0 242 if (!new) {
michael@0 243 buffer.data[buffer.len-2] = 'D'; /* signal malloc failure in summary */
michael@0 244 /* buffer must always point to good memory if it exists */
michael@0 245 buffer.next = buffer.data + (buffer.len -1);
michael@0 246 return;
michael@0 247 }
michael@0 248 buffer.next = new + (buffer.next-buffer.data);
michael@0 249 buffer.data = new;
michael@0 250 buffer.len += CHUNK_SIZE;
michael@0 251 }
michael@0 252
michael@0 253 /*
michael@0 254 * append a label, doubles as appending a single character.
michael@0 255 */
michael@0 256 static void
michael@0 257 appendLabel(char label)
michael@0 258 {
michael@0 259 if (!buffer.data) {
michael@0 260 return;
michael@0 261 }
michael@0 262
michael@0 263 *buffer.next++ = label;
michael@0 264 if (buffer.data+buffer.len >= buffer.next) {
michael@0 265 growBuffer();
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 /*
michael@0 270 * append a string onto the buffer. The result will be <string>
michael@0 271 */
michael@0 272 static void
michael@0 273 appendString(char *string)
michael@0 274 {
michael@0 275 if (!buffer.data) {
michael@0 276 return;
michael@0 277 }
michael@0 278
michael@0 279 appendLabel('<');
michael@0 280 while (*string) {
michael@0 281 appendLabel(*string++);
michael@0 282 }
michael@0 283 appendLabel('>');
michael@0 284 }
michael@0 285
michael@0 286 /*
michael@0 287 * append a bool, T= true, F=false
michael@0 288 */
michael@0 289 static void
michael@0 290 appendBool(PRBool bool)
michael@0 291 {
michael@0 292 if (!buffer.data) {
michael@0 293 return;
michael@0 294 }
michael@0 295
michael@0 296 if (bool) {
michael@0 297 appendLabel('t');
michael@0 298 } else {
michael@0 299 appendLabel('f');
michael@0 300 }
michael@0 301 }
michael@0 302
michael@0 303 /*
michael@0 304 * append a single hex nibble.
michael@0 305 */
michael@0 306 static void
michael@0 307 appendHex(unsigned char nibble)
michael@0 308 {
michael@0 309 if (nibble <= 9) {
michael@0 310 appendLabel('0'+nibble);
michael@0 311 } else {
michael@0 312 appendLabel('a'+nibble-10);
michael@0 313 }
michael@0 314 }
michael@0 315
michael@0 316 /*
michael@0 317 * append a secitem as colon separated hex bytes.
michael@0 318 */
michael@0 319 static void
michael@0 320 appendItem(SECItem *item)
michael@0 321 {
michael@0 322 int i;
michael@0 323
michael@0 324 if (!buffer.data) {
michael@0 325 return;
michael@0 326 }
michael@0 327
michael@0 328 appendLabel(':');
michael@0 329 for (i=0; i < item->len; i++) {
michael@0 330 unsigned char byte=item->data[i];
michael@0 331 appendHex(byte >> 4);
michael@0 332 appendHex(byte & 0xf);
michael@0 333 appendLabel(':');
michael@0 334 }
michael@0 335 }
michael@0 336
michael@0 337 /*
michael@0 338 * append a 32 bit integer (even on a 64 bit platform).
michael@0 339 * for simplicity append it as a hex value, full extension with 0x prefix.
michael@0 340 */
michael@0 341 static void
michael@0 342 appendInt(unsigned int value)
michael@0 343 {
michael@0 344 int i;
michael@0 345
michael@0 346 if (!buffer.data) {
michael@0 347 return;
michael@0 348 }
michael@0 349
michael@0 350 appendLabel('0');
michael@0 351 appendLabel('x');
michael@0 352 value = value & 0xffffffff; /* only look at the buttom 8 bytes */
michael@0 353 for (i=0; i < 8; i++) {
michael@0 354 appendHex(value >> 28 );
michael@0 355 value = value << 4;
michael@0 356 }
michael@0 357 }
michael@0 358
michael@0 359 /* append a trust flag */
michael@0 360 static void
michael@0 361 appendFlags(unsigned int flag)
michael@0 362 {
michael@0 363 char trust[10];
michael@0 364 char *cp=trust;
michael@0 365
michael@0 366 trust[0] = 0;
michael@0 367 printflags(trust, flag);
michael@0 368 while (*cp) {
michael@0 369 appendLabel(*cp++);
michael@0 370 }
michael@0 371 }
michael@0 372
michael@0 373 /*
michael@0 374 * dump our buffer out with a result= flag so we can find it easily.
michael@0 375 * free the buffer as a side effect.
michael@0 376 */
michael@0 377 static void
michael@0 378 dumpBuffer(void)
michael@0 379 {
michael@0 380 if (!buffer.data) {
michael@0 381 return;
michael@0 382 }
michael@0 383
michael@0 384 appendLabel(0); /* terminate */
michael@0 385 printf("\nresult=%s\n",buffer.data);
michael@0 386 PORT_Free(buffer.data);
michael@0 387 buffer.data = buffer.next = NULL;
michael@0 388 buffer.len = 0;
michael@0 389 }
michael@0 390
michael@0 391
michael@0 392 /*
michael@0 393 * usage, like traditional usage, automatically exit
michael@0 394 */
michael@0 395 static void
michael@0 396 usage(const char *prog)
michael@0 397 {
michael@0 398 short_help(prog);
michael@0 399 dumpBuffer();
michael@0 400 exit(1);
michael@0 401 }
michael@0 402
michael@0 403 /*
michael@0 404 * like usage, except prints the long version of help
michael@0 405 */
michael@0 406 static void
michael@0 407 usage_long(const char *prog)
michael@0 408 {
michael@0 409 long_help(prog);
michael@0 410 dumpBuffer();
michael@0 411 exit(1);
michael@0 412 }
michael@0 413
michael@0 414 static const char *
michael@0 415 bool2String(PRBool bool)
michael@0 416 {
michael@0 417 return bool ? "true" : "false";
michael@0 418 }
michael@0 419
michael@0 420 /*
michael@0 421 * print out interesting info about the given slot
michael@0 422 */
michael@0 423 void
michael@0 424 print_slot(PK11SlotInfo *slot, int log)
michael@0 425 {
michael@0 426 if (log) {
michael@0 427 fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
michael@0 428 PK11_GetSlotName(slot), PK11_GetTokenName(slot),
michael@0 429 bool2String(PK11_IsPresent(slot)),
michael@0 430 bool2String(PK11_IsReadOnly(slot)));
michael@0 431 }
michael@0 432 appendLabel('S');
michael@0 433 appendString(PK11_GetTokenName(slot));
michael@0 434 appendBool(PK11_IsPresent(slot));
michael@0 435 appendBool(PK11_IsReadOnly(slot));
michael@0 436 }
michael@0 437
michael@0 438 /*
michael@0 439 * list all our slots
michael@0 440 */
michael@0 441 void
michael@0 442 do_list_slots(const char *progName, int log)
michael@0 443 {
michael@0 444 PK11SlotList *list;
michael@0 445 PK11SlotListElement *le;
michael@0 446
michael@0 447 list= PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
michael@0 448 if (list == NULL) {
michael@0 449 fprintf(stderr,"ERROR: no tokens found %s\n",
michael@0 450 SECU_Strerror(PORT_GetError()));
michael@0 451 appendLabel('S');
michael@0 452 appendString("none");
michael@0 453 return;
michael@0 454 }
michael@0 455
michael@0 456 for (le= PK11_GetFirstSafe(list); le;
michael@0 457 le = PK11_GetNextSafe(list,le,PR_TRUE)) {
michael@0 458 print_slot(le->slot, log);
michael@0 459 }
michael@0 460 PK11_FreeSlotList(list);
michael@0 461 }
michael@0 462
michael@0 463 static PRBool
michael@0 464 sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
michael@0 465 {
michael@0 466 char *commonNameA, *commonNameB;
michael@0 467 int ret;
michael@0 468
michael@0 469 commonNameA = CERT_GetCommonName(&certa->subject);
michael@0 470 commonNameB = CERT_GetCommonName(&certb->subject);
michael@0 471
michael@0 472 if (commonNameA == NULL) {
michael@0 473 PORT_Free(commonNameB);
michael@0 474 return PR_TRUE;
michael@0 475 }
michael@0 476 if (commonNameB == NULL) {
michael@0 477 PORT_Free(commonNameA);
michael@0 478 return PR_FALSE;
michael@0 479 }
michael@0 480 ret = PORT_Strcmp(commonNameA,commonNameB);
michael@0 481 PORT_Free(commonNameA);
michael@0 482 PORT_Free(commonNameB);
michael@0 483 return (ret < 0) ? PR_TRUE: PR_FALSE;
michael@0 484 }
michael@0 485
michael@0 486 /*
michael@0 487 * list all the certs
michael@0 488 */
michael@0 489 void
michael@0 490 do_list_certs(const char *progName, int log)
michael@0 491 {
michael@0 492 CERTCertList *list;
michael@0 493 CERTCertList *sorted;
michael@0 494 CERTCertListNode *node;
michael@0 495 CERTCertTrust trust;
michael@0 496 int i;
michael@0 497
michael@0 498 list = PK11_ListCerts(PK11CertListUnique, NULL);
michael@0 499 if (list == NULL) {
michael@0 500 fprintf(stderr,"ERROR: no certs found %s\n",
michael@0 501 SECU_Strerror(PORT_GetError()));
michael@0 502 appendLabel('C');
michael@0 503 appendString("none");
michael@0 504 return;
michael@0 505 }
michael@0 506
michael@0 507 sorted = CERT_NewCertList();
michael@0 508 if (sorted == NULL) {
michael@0 509 fprintf(stderr,"ERROR: no certs found %s\n",
michael@0 510 SECU_Strerror(PORT_GetError()));
michael@0 511 appendLabel('C');
michael@0 512 appendLabel('E');
michael@0 513 appendInt(PORT_GetError());
michael@0 514 return;
michael@0 515 }
michael@0 516
michael@0 517 /* sort the list */
michael@0 518 for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node,list);
michael@0 519 node = CERT_LIST_NEXT(node)) {
michael@0 520 CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL);
michael@0 521 }
michael@0 522
michael@0 523
michael@0 524 for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node,sorted);
michael@0 525 node = CERT_LIST_NEXT(node)) {
michael@0 526 CERTCertificate *cert = node->cert;
michael@0 527 char *commonName;
michael@0 528
michael@0 529 SECU_PrintCertNickname(node, stderr);
michael@0 530 if (log) {
michael@0 531 fprintf(stderr, "* Slot=%s*\n", cert->slot ?
michael@0 532 PK11_GetTokenName(cert->slot) : "none");
michael@0 533 fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
michael@0 534 fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
michael@0 535 fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
michael@0 536 fprintf(stderr, "* SN=");
michael@0 537 for (i=0; i < cert->serialNumber.len; i++) {
michael@0 538 if (i!=0) fprintf(stderr,":");
michael@0 539 fprintf(stderr, "%02x",cert->serialNumber.data[0]);
michael@0 540 }
michael@0 541 fprintf(stderr," *\n");
michael@0 542 }
michael@0 543 appendLabel('C');
michael@0 544 commonName = CERT_GetCommonName(&cert->subject);
michael@0 545 appendString(commonName?commonName:"*NoName*");
michael@0 546 PORT_Free(commonName);
michael@0 547 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
michael@0 548 appendFlags(trust.sslFlags);
michael@0 549 appendFlags(trust.emailFlags);
michael@0 550 appendFlags(trust.objectSigningFlags);
michael@0 551 }
michael@0 552 }
michael@0 553 CERT_DestroyCertList(list);
michael@0 554
michael@0 555 }
michael@0 556
michael@0 557 /*
michael@0 558 * need to implement yet... try to add a new certificate
michael@0 559 */
michael@0 560 void
michael@0 561 do_add_cert(const char *progName, int log)
michael@0 562 {
michael@0 563 PORT_Assert(/* do_add_cert not implemented */ 0);
michael@0 564 }
michael@0 565
michael@0 566 /*
michael@0 567 * display the current key slot
michael@0 568 */
michael@0 569 void
michael@0 570 do_key_slot(const char *progName, int log)
michael@0 571 {
michael@0 572 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
michael@0 573 if (!slot) {
michael@0 574 fprintf(stderr,"ERROR: no internal key slot found %s\n",
michael@0 575 SECU_Strerror(PORT_GetError()));
michael@0 576 appendLabel('K');
michael@0 577 appendLabel('S');
michael@0 578 appendString("none");
michael@0 579 }
michael@0 580 print_slot(slot, log);
michael@0 581 PK11_FreeSlot(slot);
michael@0 582 }
michael@0 583
michael@0 584 /*
michael@0 585 * execute some NSS command.
michael@0 586 */
michael@0 587 void
michael@0 588 do_command(const char *label, int initialized, secuCommandFlag *command,
michael@0 589 const char *progName, int log)
michael@0 590 {
michael@0 591 char * command_string;
michael@0 592 if (!initialized) {
michael@0 593 return;
michael@0 594 }
michael@0 595
michael@0 596 if (command->activated) {
michael@0 597 command_string = command->arg;
michael@0 598 } else {
michael@0 599 command_string = "none";
michael@0 600 }
michael@0 601
michael@0 602 if (log) {
michael@0 603 fprintf(stderr, "*Executing nss command \"%s\" for %s*\n",
michael@0 604 command_string,label);
michael@0 605 }
michael@0 606
michael@0 607 /* do something */
michael@0 608 if (PORT_Strcasecmp(command_string, "list_slots") == 0) {
michael@0 609 do_list_slots(progName, log);
michael@0 610 } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) {
michael@0 611 do_list_certs(progName, log);
michael@0 612 } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) {
michael@0 613 do_add_cert(progName, log);
michael@0 614 } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) {
michael@0 615 do_key_slot(progName, log);
michael@0 616 } else if (PORT_Strcasecmp(command_string, "none") != 0) {
michael@0 617 fprintf(stderr, ">> Unknown command (%s)\n", command_string);
michael@0 618 appendLabel('E');
michael@0 619 appendString("bc");
michael@0 620 usage_long(progName);
michael@0 621 }
michael@0 622
michael@0 623 }
michael@0 624
michael@0 625
michael@0 626 /*
michael@0 627 * functions do handle
michael@0 628 * different library initializations.
michael@0 629 */
michael@0 630 static int main_initialized;
michael@0 631 static int lib1_initialized;
michael@0 632 static int lib2_initialized;
michael@0 633
michael@0 634 void
michael@0 635 main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
michael@0 636 int readOnly, const char *progName, int log)
michael@0 637 {
michael@0 638 SECStatus rv;
michael@0 639 if (log) {
michael@0 640 fprintf(stderr,"*NSS_Init for the main program*\n");
michael@0 641 }
michael@0 642 appendLabel('M');
michael@0 643 if (!db->activated) {
michael@0 644 fprintf(stderr, ">> No main_db has been specified\n");
michael@0 645 usage(progName);
michael@0 646 }
michael@0 647 if (main_initialized) {
michael@0 648 fprintf(stderr,"Warning: Second initialization of Main\n");
michael@0 649 appendLabel('E');
michael@0 650 appendString("2M");
michael@0 651 }
michael@0 652 if (tokNam->activated) {
michael@0 653 PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg,
michael@0 654 NULL, NULL, NULL, NULL, 0, 0);
michael@0 655 }
michael@0 656 rv = NSS_Initialize(db->arg, "", "", "",
michael@0 657 NSS_INIT_NOROOTINIT|(readOnly?NSS_INIT_READONLY:0));
michael@0 658 if (rv != SECSuccess) {
michael@0 659 appendLabel('E');
michael@0 660 appendInt(PORT_GetError());
michael@0 661 fprintf(stderr,">> %s\n", SECU_Strerror(PORT_GetError()));
michael@0 662 dumpBuffer();
michael@0 663 exit(1);
michael@0 664 }
michael@0 665 main_initialized = 1;
michael@0 666 }
michael@0 667
michael@0 668 void
michael@0 669 main_Do(secuCommandFlag *command, const char *progName, int log)
michael@0 670 {
michael@0 671 do_command("main", main_initialized, command, progName, log);
michael@0 672 }
michael@0 673
michael@0 674 void
michael@0 675 main_Shutdown(int old_style, const char *progName, int log)
michael@0 676 {
michael@0 677 SECStatus rv;
michael@0 678 appendLabel('N');
michael@0 679 if (log) {
michael@0 680 fprintf(stderr,"*NSS_Shutdown for the main program*\n");
michael@0 681 }
michael@0 682 if (!main_initialized) {
michael@0 683 fprintf(stderr,"Warning: Main shutdown without corresponding init\n");
michael@0 684 }
michael@0 685 if (old_style) {
michael@0 686 rv = NSS_Shutdown();
michael@0 687 } else {
michael@0 688 rv = NSS_ShutdownContext(NULL);
michael@0 689 }
michael@0 690 fprintf(stderr, "Shutdown main state = %d\n", rv);
michael@0 691 if (rv != SECSuccess) {
michael@0 692 appendLabel('E');
michael@0 693 appendInt(PORT_GetError());
michael@0 694 fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
michael@0 695 }
michael@0 696 main_initialized = 0;
michael@0 697 }
michael@0 698
michael@0 699 /* common library init */
michael@0 700 NSSInitContext *
michael@0 701 lib_Init(const char *lableString, char label, int initialized,
michael@0 702 secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
michael@0 703 const char *progName, int log)
michael@0 704 {
michael@0 705 NSSInitContext *ctxt;
michael@0 706 NSSInitParameters initStrings;
michael@0 707 NSSInitParameters *initStringPtr = NULL;
michael@0 708
michael@0 709 appendLabel(label);
michael@0 710 if (log) {
michael@0 711 fprintf(stderr,"*NSS_Init for %s*\n", lableString);
michael@0 712 }
michael@0 713
michael@0 714 if (!db->activated) {
michael@0 715 fprintf(stderr, ">> No %s_db has been specified\n", lableString);
michael@0 716 usage(progName);
michael@0 717 }
michael@0 718 if (initialized) {
michael@0 719 fprintf(stderr,"Warning: Second initialization of %s\n", lableString);
michael@0 720 }
michael@0 721 if (tokNam->activated) {
michael@0 722 PORT_Memset(&initStrings, 0, sizeof(initStrings));
michael@0 723 initStrings.length = sizeof(initStrings);
michael@0 724 initStrings.dbTokenDescription = tokNam->arg;
michael@0 725 initStringPtr = &initStrings;
michael@0 726 }
michael@0 727 ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr,
michael@0 728 NSS_INIT_NOROOTINIT|(readonly?NSS_INIT_READONLY:0));
michael@0 729 if (ctxt == NULL) {
michael@0 730 appendLabel('E');
michael@0 731 appendInt(PORT_GetError());
michael@0 732 fprintf(stderr,">> %s\n",SECU_Strerror(PORT_GetError()));
michael@0 733 dumpBuffer();
michael@0 734 exit(1);
michael@0 735 }
michael@0 736 return ctxt;
michael@0 737 }
michael@0 738
michael@0 739 /* common library shutdown */
michael@0 740 void
michael@0 741 lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
michael@0 742 int initialize, const char *progName, int log)
michael@0 743 {
michael@0 744 SECStatus rv;
michael@0 745 appendLabel(label);
michael@0 746 if (log) {
michael@0 747 fprintf(stderr,"*NSS_Shutdown for %s\n*", labelString);
michael@0 748 }
michael@0 749 if (!initialize) {
michael@0 750 fprintf(stderr,"Warning: %s shutdown without corresponding init\n",
michael@0 751 labelString);
michael@0 752 }
michael@0 753 rv = NSS_ShutdownContext(ctx);
michael@0 754 fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv);
michael@0 755 if (rv != SECSuccess) {
michael@0 756 appendLabel('E');
michael@0 757 appendInt(PORT_GetError());
michael@0 758 fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
michael@0 759 }
michael@0 760 }
michael@0 761
michael@0 762
michael@0 763 static NSSInitContext *lib1_context;
michael@0 764 static NSSInitContext *lib2_context;
michael@0 765 void
michael@0 766 lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
michael@0 767 int readOnly, const char *progName, int log)
michael@0 768 {
michael@0 769 lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam,
michael@0 770 readOnly, progName, log);
michael@0 771 lib1_initialized = 1;
michael@0 772 }
michael@0 773
michael@0 774 void
michael@0 775 lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
michael@0 776 int readOnly, const char *progName, int log)
michael@0 777 {
michael@0 778 lib2_context = lib_Init("lib2", '2', lib2_initialized,
michael@0 779 db, tokNam, readOnly, progName, log);
michael@0 780 lib2_initialized = 1;
michael@0 781 }
michael@0 782
michael@0 783 void
michael@0 784 lib1_Do(secuCommandFlag *command, const char *progName, int log)
michael@0 785 {
michael@0 786 do_command("lib1", lib1_initialized, command, progName, log);
michael@0 787 }
michael@0 788
michael@0 789 void
michael@0 790 lib2_Do(secuCommandFlag *command, const char *progName, int log)
michael@0 791 {
michael@0 792 do_command("lib2", lib2_initialized, command, progName, log);
michael@0 793 }
michael@0 794
michael@0 795 void
michael@0 796 lib1_Shutdown(const char *progName, int log)
michael@0 797 {
michael@0 798 lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log);
michael@0 799 lib1_initialized = 0;
michael@0 800 /* don't clear lib1_Context, so we can test multiple attempts to close
michael@0 801 * the same context produces correct errors*/
michael@0 802 }
michael@0 803
michael@0 804 void
michael@0 805 lib2_Shutdown(const char *progName, int log)
michael@0 806 {
michael@0 807 lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log);
michael@0 808 lib2_initialized = 0;
michael@0 809 /* don't clear lib2_Context, so we can test multiple attempts to close
michael@0 810 * the same context produces correct errors*/
michael@0 811 }
michael@0 812
michael@0 813 int
michael@0 814 main(int argc, char **argv)
michael@0 815 {
michael@0 816 SECStatus rv;
michael@0 817 secuCommand libinit;
michael@0 818 char *progName;
michael@0 819 char *order;
michael@0 820 secuCommandFlag *options;
michael@0 821 int log = 0;
michael@0 822
michael@0 823 progName = strrchr(argv[0], '/');
michael@0 824 progName = progName ? progName+1 : argv[0];
michael@0 825
michael@0 826 libinit.numCommands = 0;
michael@0 827 libinit.commands = 0;
michael@0 828 libinit.numOptions = opt_last;
michael@0 829 options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init));
michael@0 830 if (options == NULL) {
michael@0 831 fprintf(stderr, ">> %s:Not enough free memory to run command\n",
michael@0 832 progName);
michael@0 833 exit(1);
michael@0 834 }
michael@0 835 PORT_Memcpy(options, options_init, sizeof(options_init));
michael@0 836 libinit.options = options;
michael@0 837
michael@0 838 rv = SECU_ParseCommandLine(argc, argv, progName, & libinit);
michael@0 839 if (rv != SECSuccess) {
michael@0 840 usage(progName);
michael@0 841 }
michael@0 842
michael@0 843 if (libinit.options[opt_help].activated) {
michael@0 844 long_help(progName);
michael@0 845 exit (0);
michael@0 846 }
michael@0 847
michael@0 848 log = libinit.options[opt_verbose].activated;
michael@0 849 if (libinit.options[opt_summary].activated) {
michael@0 850 initBuffer();
michael@0 851 }
michael@0 852
michael@0 853 order = libinit.options[opt_liborder].arg;
michael@0 854 if (!order) {
michael@0 855 usage(progName);
michael@0 856 }
michael@0 857
michael@0 858 if (log) {
michael@0 859 fprintf(stderr,"* initializing with order \"%s\"*\n", order);
michael@0 860 }
michael@0 861
michael@0 862 for (;*order; order++) {
michael@0 863 switch (*order) {
michael@0 864 case 'M':
michael@0 865 main_Init(&libinit.options[opt_mainDB],
michael@0 866 &libinit.options[opt_mainTokNam],
michael@0 867 libinit.options[opt_mainRO].activated,
michael@0 868 progName, log);
michael@0 869 break;
michael@0 870 case '1':
michael@0 871 lib1_Init(&libinit.options[opt_lib1DB],
michael@0 872 &libinit.options[opt_lib1TokNam],
michael@0 873 libinit.options[opt_lib1RO].activated,
michael@0 874 progName,log);
michael@0 875 break;
michael@0 876 case '2':
michael@0 877 lib2_Init(&libinit.options[opt_lib2DB],
michael@0 878 &libinit.options[opt_lib2TokNam],
michael@0 879 libinit.options[opt_lib2RO].activated,
michael@0 880 progName,log);
michael@0 881 break;
michael@0 882 case 'm':
michael@0 883 main_Shutdown(libinit.options[opt_oldStyle].activated,
michael@0 884 progName, log);
michael@0 885 break;
michael@0 886 case 'i':
michael@0 887 lib1_Shutdown(progName, log);
michael@0 888 break;
michael@0 889 case 'z':
michael@0 890 lib2_Shutdown(progName, log);
michael@0 891 break;
michael@0 892 default:
michael@0 893 fprintf(stderr,">> Unknown init/shutdown command \"%c\"", *order);
michael@0 894 usage_long(progName);
michael@0 895 }
michael@0 896 main_Do(&libinit.options[opt_mainCMD], progName, log);
michael@0 897 lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
michael@0 898 lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
michael@0 899 }
michael@0 900
michael@0 901 if (NSS_IsInitialized()) {
michael@0 902 appendLabel('X');
michael@0 903 fprintf(stderr, "Warning: NSS is initialized\n");
michael@0 904 }
michael@0 905 dumpBuffer();
michael@0 906
michael@0 907 exit(0);
michael@0 908 }
michael@0 909

mercurial