1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/multinit/multinit.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,909 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <stdio.h> 1.9 +#include <string.h> 1.10 +#include <stdlib.h> 1.11 +#include "nss.h" 1.12 +#include "secutil.h" 1.13 +#include "pk11pub.h" 1.14 +#include "cert.h" 1.15 + 1.16 +typedef struct commandDescriptStr { 1.17 + int required; 1.18 + char *arg; 1.19 + char *des; 1.20 +} commandDescript; 1.21 + 1.22 +enum optionNames { 1.23 + opt_liborder = 0, 1.24 + opt_mainDB, 1.25 + opt_lib1DB, 1.26 + opt_lib2DB, 1.27 + opt_mainRO, 1.28 + opt_lib1RO, 1.29 + opt_lib2RO, 1.30 + opt_mainCMD, 1.31 + opt_lib1CMD, 1.32 + opt_lib2CMD, 1.33 + opt_mainTokNam, 1.34 + opt_lib1TokNam, 1.35 + opt_lib2TokNam, 1.36 + opt_oldStyle, 1.37 + opt_verbose, 1.38 + opt_summary, 1.39 + opt_help, 1.40 + opt_last 1.41 +}; 1.42 + 1.43 + 1.44 +static const 1.45 +secuCommandFlag options_init[] = 1.46 +{ 1.47 + { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" }, 1.48 + { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" }, 1.49 + { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" }, 1.50 + { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" }, 1.51 + { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" }, 1.52 + { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" }, 1.53 + { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" }, 1.54 + { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" }, 1.55 + { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" }, 1.56 + { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" }, 1.57 + { /* opt_mainTokNam */'t', PR_TRUE, 0, PR_FALSE, "main_token_name" }, 1.58 + { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" }, 1.59 + { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" }, 1.60 + { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" }, 1.61 + { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" }, 1.62 + { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" }, 1.63 + { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" } 1.64 +}; 1.65 + 1.66 +static const 1.67 +commandDescript options_des[] = 1.68 +{ 1.69 + { /* opt_liborder */ PR_FALSE, "initOrder", 1.70 + " Specifies the order of NSS initialization and shutdown. Order is\n" 1.71 + " given as a string where each character represents either an init or\n" 1.72 + " a shutdown of the main program or one of the 2 test libraries\n" 1.73 + " (library 1 and library 2). The valid characters are as follows:\n" 1.74 + " M Init the main program\n 1 Init library 1\n" 1.75 + " 2 Init library 2\n" 1.76 + " m Shutdown the main program\n i Shutdown library 1\n" 1.77 + " z Shutdown library 2\n" }, 1.78 + { /* opt_mainDB */ PR_TRUE, "nss_db", 1.79 + " Specified the directory to open the nss database for the main\n" 1.80 + " program. Must be specified if \"M\" is given in the order string\n"}, 1.81 + { /* opt_lib1DB */ PR_FALSE, "nss_db", 1.82 + " Specified the directory to open the nss database for library 1.\n" 1.83 + " Must be specified if \"1\" is given in the order string\n"}, 1.84 + { /* opt_lib2DB */ PR_FALSE, "nss_db", 1.85 + " Specified the directory to open the nss database for library 2.\n" 1.86 + " Must be specified if \"2\" is given in the order string\n"}, 1.87 + { /* opt_mainRO */ PR_FALSE, NULL, 1.88 + " Open the main program's database read only.\n" }, 1.89 + { /* opt_lib1RO */ PR_FALSE, NULL, 1.90 + " Open library 1's database read only.\n" }, 1.91 + { /* opt_lib2RO */ PR_FALSE, NULL, 1.92 + " Open library 2's database read only.\n" }, 1.93 + { /* opt_mainCMD */ PR_FALSE, "nss_command", 1.94 + " Specifies the NSS command to execute in the main program.\n" 1.95 + " Valid commands are: \n" 1.96 + " key_slot, list_slots, list_certs, add_cert, none.\n" 1.97 + " Default is \"none\".\n" }, 1.98 + { /* opt_lib1CMD */ PR_FALSE, "nss_command", 1.99 + " Specifies the NSS command to execute in library 1.\n" }, 1.100 + { /* opt_lib2CMD */ PR_FALSE, "nss_command", 1.101 + " Specifies the NSS command to execute in library 2.\n" }, 1.102 + { /* opt_mainTokNam */PR_FALSE, "token_name", 1.103 + " Specifies the name of PKCS11 token for the main program's " 1.104 + "database.\n" }, 1.105 + { /* opt_lib1TokNam */PR_FALSE, "token_name", 1.106 + " Specifies the name of PKCS11 token for library 1's database.\n" }, 1.107 + { /* opt_lib2TokNam */PR_FALSE, "token_name", 1.108 + " Specifies the name of PKCS11 token for library 2's database.\n" }, 1.109 + { /* opt_oldStype */ PR_FALSE, NULL, 1.110 + " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n" 1.111 + " program.\n" }, 1.112 + { /* opt_verbose */ PR_FALSE, NULL, 1.113 + " Noisily output status to standard error\n" }, 1.114 + { /* opt_summarize */ PR_FALSE, NULL, 1.115 + "report a summary of the test results\n" }, 1.116 + { /* opt_help */ PR_FALSE, NULL, " give this message\n" } 1.117 +}; 1.118 + 1.119 +/* 1.120 + * output our short help (table driven). (does not exit). 1.121 + */ 1.122 +static void 1.123 +short_help(const char *prog) 1.124 +{ 1.125 + int count = opt_last; 1.126 + int i,words_found; 1.127 + 1.128 + /* make sure all the tables are up to date before we allow compiles to 1.129 + * succeed */ 1.130 + PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) == opt_last); 1.131 + PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) == 1.132 + sizeof(options_des)/sizeof(commandDescript)); 1.133 + 1.134 + /* print the base usage */ 1.135 + fprintf(stderr,"usage: %s ",prog); 1.136 + for (i=0, words_found=0; i < count; i++) { 1.137 + if (!options_des[i].required) { 1.138 + fprintf(stderr,"["); 1.139 + } 1.140 + if (options_init[i].longform) { 1.141 + fprintf(stderr, "--%s", options_init[i].longform); 1.142 + words_found++; 1.143 + } else { 1.144 + fprintf(stderr, "-%c", options_init[i].flag); 1.145 + } 1.146 + if (options_init[i].needsArg) { 1.147 + if (options_des[i].arg) { 1.148 + fprintf(stderr," %s",options_des[i].arg); 1.149 + } else { 1.150 + fprintf(stderr," arg"); 1.151 + } 1.152 + words_found++; 1.153 + } 1.154 + if (!options_des[i].required) { 1.155 + fprintf(stderr,"]"); 1.156 + } 1.157 + if (i < count-1 ) { 1.158 + if (words_found >= 5) { 1.159 + fprintf(stderr,"\n "); 1.160 + words_found=0; 1.161 + } else { 1.162 + fprintf(stderr," "); 1.163 + } 1.164 + } 1.165 + } 1.166 + fprintf(stderr,"\n"); 1.167 +} 1.168 + 1.169 +/* 1.170 + * print out long help. like short_help, this does not exit 1.171 + */ 1.172 +static void 1.173 +long_help(const char *prog) 1.174 +{ 1.175 + int i; 1.176 + int count = opt_last; 1.177 + 1.178 + short_help(prog); 1.179 + /* print the option descriptions */ 1.180 + fprintf(stderr,"\n"); 1.181 + for (i=0; i < count; i++) { 1.182 + fprintf(stderr," "); 1.183 + if (options_init[i].flag) { 1.184 + fprintf(stderr, "-%c", options_init[i].flag); 1.185 + if (options_init[i].longform) { 1.186 + fprintf(stderr,","); 1.187 + } 1.188 + } 1.189 + if (options_init[i].longform) { 1.190 + fprintf(stderr,"--%s", options_init[i].longform); 1.191 + } 1.192 + if (options_init[i].needsArg) { 1.193 + if (options_des[i].arg) { 1.194 + fprintf(stderr," %s",options_des[i].arg); 1.195 + } else { 1.196 + fprintf(stderr," arg"); 1.197 + } 1.198 + if (options_init[i].arg) { 1.199 + fprintf(stderr," (default = \"%s\")",options_init[i].arg); 1.200 + } 1.201 + } 1.202 + fprintf(stderr,"\n%s",options_des[i].des); 1.203 + } 1.204 +} 1.205 + 1.206 +/* 1.207 + * record summary data 1.208 + */ 1.209 +struct bufferData { 1.210 + char * data; /* lowest address of the buffer */ 1.211 + char * next; /* pointer to the next element on the buffer */ 1.212 + int len; /* length of the buffer */ 1.213 +}; 1.214 + 1.215 +/* our actual buffer. If data is NULL, then all append ops 1.216 + * except are noops */ 1.217 +static struct bufferData buffer= { NULL, NULL, 0 }; 1.218 + 1.219 +#define CHUNK_SIZE 1000 1.220 + 1.221 +/* 1.222 + * get our initial data. and set the buffer variables up. on failure, 1.223 + * just don't initialize the buffer. 1.224 + */ 1.225 +static void 1.226 +initBuffer(void) 1.227 +{ 1.228 + buffer.data = PORT_Alloc(CHUNK_SIZE); 1.229 + if (!buffer.data) { 1.230 + return; 1.231 + } 1.232 + buffer.next = buffer.data; 1.233 + buffer.len = CHUNK_SIZE; 1.234 +} 1.235 + 1.236 +/* 1.237 + * grow the buffer. If we can't get more data, record a 'D' in the second 1.238 + * to last record and allow the rest of the data to overwrite the last 1.239 + * element. 1.240 + */ 1.241 +static void 1.242 +growBuffer(void) 1.243 +{ 1.244 + char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE); 1.245 + if (!new) { 1.246 + buffer.data[buffer.len-2] = 'D'; /* signal malloc failure in summary */ 1.247 + /* buffer must always point to good memory if it exists */ 1.248 + buffer.next = buffer.data + (buffer.len -1); 1.249 + return; 1.250 + } 1.251 + buffer.next = new + (buffer.next-buffer.data); 1.252 + buffer.data = new; 1.253 + buffer.len += CHUNK_SIZE; 1.254 +} 1.255 + 1.256 +/* 1.257 + * append a label, doubles as appending a single character. 1.258 + */ 1.259 +static void 1.260 +appendLabel(char label) 1.261 +{ 1.262 + if (!buffer.data) { 1.263 + return; 1.264 + } 1.265 + 1.266 + *buffer.next++ = label; 1.267 + if (buffer.data+buffer.len >= buffer.next) { 1.268 + growBuffer(); 1.269 + } 1.270 +} 1.271 + 1.272 +/* 1.273 + * append a string onto the buffer. The result will be <string> 1.274 + */ 1.275 +static void 1.276 +appendString(char *string) 1.277 +{ 1.278 + if (!buffer.data) { 1.279 + return; 1.280 + } 1.281 + 1.282 + appendLabel('<'); 1.283 + while (*string) { 1.284 + appendLabel(*string++); 1.285 + } 1.286 + appendLabel('>'); 1.287 +} 1.288 + 1.289 +/* 1.290 + * append a bool, T= true, F=false 1.291 + */ 1.292 +static void 1.293 +appendBool(PRBool bool) 1.294 +{ 1.295 + if (!buffer.data) { 1.296 + return; 1.297 + } 1.298 + 1.299 + if (bool) { 1.300 + appendLabel('t'); 1.301 + } else { 1.302 + appendLabel('f'); 1.303 + } 1.304 +} 1.305 + 1.306 +/* 1.307 + * append a single hex nibble. 1.308 + */ 1.309 +static void 1.310 +appendHex(unsigned char nibble) 1.311 +{ 1.312 + if (nibble <= 9) { 1.313 + appendLabel('0'+nibble); 1.314 + } else { 1.315 + appendLabel('a'+nibble-10); 1.316 + } 1.317 +} 1.318 + 1.319 +/* 1.320 + * append a secitem as colon separated hex bytes. 1.321 + */ 1.322 +static void 1.323 +appendItem(SECItem *item) 1.324 +{ 1.325 + int i; 1.326 + 1.327 + if (!buffer.data) { 1.328 + return; 1.329 + } 1.330 + 1.331 + appendLabel(':'); 1.332 + for (i=0; i < item->len; i++) { 1.333 + unsigned char byte=item->data[i]; 1.334 + appendHex(byte >> 4); 1.335 + appendHex(byte & 0xf); 1.336 + appendLabel(':'); 1.337 + } 1.338 +} 1.339 + 1.340 +/* 1.341 + * append a 32 bit integer (even on a 64 bit platform). 1.342 + * for simplicity append it as a hex value, full extension with 0x prefix. 1.343 + */ 1.344 +static void 1.345 +appendInt(unsigned int value) 1.346 +{ 1.347 + int i; 1.348 + 1.349 + if (!buffer.data) { 1.350 + return; 1.351 + } 1.352 + 1.353 + appendLabel('0'); 1.354 + appendLabel('x'); 1.355 + value = value & 0xffffffff; /* only look at the buttom 8 bytes */ 1.356 + for (i=0; i < 8; i++) { 1.357 + appendHex(value >> 28 ); 1.358 + value = value << 4; 1.359 + } 1.360 +} 1.361 + 1.362 +/* append a trust flag */ 1.363 +static void 1.364 +appendFlags(unsigned int flag) 1.365 +{ 1.366 + char trust[10]; 1.367 + char *cp=trust; 1.368 + 1.369 + trust[0] = 0; 1.370 + printflags(trust, flag); 1.371 + while (*cp) { 1.372 + appendLabel(*cp++); 1.373 + } 1.374 +} 1.375 + 1.376 +/* 1.377 + * dump our buffer out with a result= flag so we can find it easily. 1.378 + * free the buffer as a side effect. 1.379 + */ 1.380 +static void 1.381 +dumpBuffer(void) 1.382 +{ 1.383 + if (!buffer.data) { 1.384 + return; 1.385 + } 1.386 + 1.387 + appendLabel(0); /* terminate */ 1.388 + printf("\nresult=%s\n",buffer.data); 1.389 + PORT_Free(buffer.data); 1.390 + buffer.data = buffer.next = NULL; 1.391 + buffer.len = 0; 1.392 +} 1.393 + 1.394 + 1.395 +/* 1.396 + * usage, like traditional usage, automatically exit 1.397 + */ 1.398 +static void 1.399 +usage(const char *prog) 1.400 +{ 1.401 + short_help(prog); 1.402 + dumpBuffer(); 1.403 + exit(1); 1.404 +} 1.405 + 1.406 +/* 1.407 + * like usage, except prints the long version of help 1.408 + */ 1.409 +static void 1.410 +usage_long(const char *prog) 1.411 +{ 1.412 + long_help(prog); 1.413 + dumpBuffer(); 1.414 + exit(1); 1.415 +} 1.416 + 1.417 +static const char * 1.418 +bool2String(PRBool bool) 1.419 +{ 1.420 + return bool ? "true" : "false"; 1.421 +} 1.422 + 1.423 +/* 1.424 + * print out interesting info about the given slot 1.425 + */ 1.426 +void 1.427 +print_slot(PK11SlotInfo *slot, int log) 1.428 +{ 1.429 + if (log) { 1.430 + fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n", 1.431 + PK11_GetSlotName(slot), PK11_GetTokenName(slot), 1.432 + bool2String(PK11_IsPresent(slot)), 1.433 + bool2String(PK11_IsReadOnly(slot))); 1.434 + } 1.435 + appendLabel('S'); 1.436 + appendString(PK11_GetTokenName(slot)); 1.437 + appendBool(PK11_IsPresent(slot)); 1.438 + appendBool(PK11_IsReadOnly(slot)); 1.439 +} 1.440 + 1.441 +/* 1.442 + * list all our slots 1.443 + */ 1.444 +void 1.445 +do_list_slots(const char *progName, int log) 1.446 +{ 1.447 + PK11SlotList *list; 1.448 + PK11SlotListElement *le; 1.449 + 1.450 + list= PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); 1.451 + if (list == NULL) { 1.452 + fprintf(stderr,"ERROR: no tokens found %s\n", 1.453 + SECU_Strerror(PORT_GetError())); 1.454 + appendLabel('S'); 1.455 + appendString("none"); 1.456 + return; 1.457 + } 1.458 + 1.459 + for (le= PK11_GetFirstSafe(list); le; 1.460 + le = PK11_GetNextSafe(list,le,PR_TRUE)) { 1.461 + print_slot(le->slot, log); 1.462 + } 1.463 + PK11_FreeSlotList(list); 1.464 +} 1.465 + 1.466 +static PRBool 1.467 +sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg) 1.468 +{ 1.469 + char *commonNameA, *commonNameB; 1.470 + int ret; 1.471 + 1.472 + commonNameA = CERT_GetCommonName(&certa->subject); 1.473 + commonNameB = CERT_GetCommonName(&certb->subject); 1.474 + 1.475 + if (commonNameA == NULL) { 1.476 + PORT_Free(commonNameB); 1.477 + return PR_TRUE; 1.478 + } 1.479 + if (commonNameB == NULL) { 1.480 + PORT_Free(commonNameA); 1.481 + return PR_FALSE; 1.482 + } 1.483 + ret = PORT_Strcmp(commonNameA,commonNameB); 1.484 + PORT_Free(commonNameA); 1.485 + PORT_Free(commonNameB); 1.486 + return (ret < 0) ? PR_TRUE: PR_FALSE; 1.487 +} 1.488 + 1.489 +/* 1.490 + * list all the certs 1.491 + */ 1.492 +void 1.493 +do_list_certs(const char *progName, int log) 1.494 +{ 1.495 + CERTCertList *list; 1.496 + CERTCertList *sorted; 1.497 + CERTCertListNode *node; 1.498 + CERTCertTrust trust; 1.499 + int i; 1.500 + 1.501 + list = PK11_ListCerts(PK11CertListUnique, NULL); 1.502 + if (list == NULL) { 1.503 + fprintf(stderr,"ERROR: no certs found %s\n", 1.504 + SECU_Strerror(PORT_GetError())); 1.505 + appendLabel('C'); 1.506 + appendString("none"); 1.507 + return; 1.508 + } 1.509 + 1.510 + sorted = CERT_NewCertList(); 1.511 + if (sorted == NULL) { 1.512 + fprintf(stderr,"ERROR: no certs found %s\n", 1.513 + SECU_Strerror(PORT_GetError())); 1.514 + appendLabel('C'); 1.515 + appendLabel('E'); 1.516 + appendInt(PORT_GetError()); 1.517 + return; 1.518 + } 1.519 + 1.520 + /* sort the list */ 1.521 + for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node,list); 1.522 + node = CERT_LIST_NEXT(node)) { 1.523 + CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL); 1.524 + } 1.525 + 1.526 + 1.527 + for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node,sorted); 1.528 + node = CERT_LIST_NEXT(node)) { 1.529 + CERTCertificate *cert = node->cert; 1.530 + char *commonName; 1.531 + 1.532 + SECU_PrintCertNickname(node, stderr); 1.533 + if (log) { 1.534 + fprintf(stderr, "* Slot=%s*\n", cert->slot ? 1.535 + PK11_GetTokenName(cert->slot) : "none"); 1.536 + fprintf(stderr, "* Nickname=%s*\n", cert->nickname); 1.537 + fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName); 1.538 + fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName); 1.539 + fprintf(stderr, "* SN="); 1.540 + for (i=0; i < cert->serialNumber.len; i++) { 1.541 + if (i!=0) fprintf(stderr,":"); 1.542 + fprintf(stderr, "%02x",cert->serialNumber.data[0]); 1.543 + } 1.544 + fprintf(stderr," *\n"); 1.545 + } 1.546 + appendLabel('C'); 1.547 + commonName = CERT_GetCommonName(&cert->subject); 1.548 + appendString(commonName?commonName:"*NoName*"); 1.549 + PORT_Free(commonName); 1.550 + if (CERT_GetCertTrust(cert, &trust) == SECSuccess) { 1.551 + appendFlags(trust.sslFlags); 1.552 + appendFlags(trust.emailFlags); 1.553 + appendFlags(trust.objectSigningFlags); 1.554 + } 1.555 + } 1.556 + CERT_DestroyCertList(list); 1.557 + 1.558 +} 1.559 + 1.560 +/* 1.561 + * need to implement yet... try to add a new certificate 1.562 + */ 1.563 +void 1.564 +do_add_cert(const char *progName, int log) 1.565 +{ 1.566 + PORT_Assert(/* do_add_cert not implemented */ 0); 1.567 +} 1.568 + 1.569 +/* 1.570 + * display the current key slot 1.571 + */ 1.572 +void 1.573 +do_key_slot(const char *progName, int log) 1.574 +{ 1.575 + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 1.576 + if (!slot) { 1.577 + fprintf(stderr,"ERROR: no internal key slot found %s\n", 1.578 + SECU_Strerror(PORT_GetError())); 1.579 + appendLabel('K'); 1.580 + appendLabel('S'); 1.581 + appendString("none"); 1.582 + } 1.583 + print_slot(slot, log); 1.584 + PK11_FreeSlot(slot); 1.585 +} 1.586 + 1.587 +/* 1.588 + * execute some NSS command. 1.589 + */ 1.590 +void 1.591 +do_command(const char *label, int initialized, secuCommandFlag *command, 1.592 + const char *progName, int log) 1.593 +{ 1.594 + char * command_string; 1.595 + if (!initialized) { 1.596 + return; 1.597 + } 1.598 + 1.599 + if (command->activated) { 1.600 + command_string = command->arg; 1.601 + } else { 1.602 + command_string = "none"; 1.603 + } 1.604 + 1.605 + if (log) { 1.606 + fprintf(stderr, "*Executing nss command \"%s\" for %s*\n", 1.607 + command_string,label); 1.608 + } 1.609 + 1.610 + /* do something */ 1.611 + if (PORT_Strcasecmp(command_string, "list_slots") == 0) { 1.612 + do_list_slots(progName, log); 1.613 + } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) { 1.614 + do_list_certs(progName, log); 1.615 + } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) { 1.616 + do_add_cert(progName, log); 1.617 + } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) { 1.618 + do_key_slot(progName, log); 1.619 + } else if (PORT_Strcasecmp(command_string, "none") != 0) { 1.620 + fprintf(stderr, ">> Unknown command (%s)\n", command_string); 1.621 + appendLabel('E'); 1.622 + appendString("bc"); 1.623 + usage_long(progName); 1.624 + } 1.625 + 1.626 +} 1.627 + 1.628 + 1.629 +/* 1.630 + * functions do handle 1.631 + * different library initializations. 1.632 + */ 1.633 +static int main_initialized; 1.634 +static int lib1_initialized; 1.635 +static int lib2_initialized; 1.636 + 1.637 +void 1.638 +main_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 1.639 + int readOnly, const char *progName, int log) 1.640 +{ 1.641 + SECStatus rv; 1.642 + if (log) { 1.643 + fprintf(stderr,"*NSS_Init for the main program*\n"); 1.644 + } 1.645 + appendLabel('M'); 1.646 + if (!db->activated) { 1.647 + fprintf(stderr, ">> No main_db has been specified\n"); 1.648 + usage(progName); 1.649 + } 1.650 + if (main_initialized) { 1.651 + fprintf(stderr,"Warning: Second initialization of Main\n"); 1.652 + appendLabel('E'); 1.653 + appendString("2M"); 1.654 + } 1.655 + if (tokNam->activated) { 1.656 + PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg, 1.657 + NULL, NULL, NULL, NULL, 0, 0); 1.658 + } 1.659 + rv = NSS_Initialize(db->arg, "", "", "", 1.660 + NSS_INIT_NOROOTINIT|(readOnly?NSS_INIT_READONLY:0)); 1.661 + if (rv != SECSuccess) { 1.662 + appendLabel('E'); 1.663 + appendInt(PORT_GetError()); 1.664 + fprintf(stderr,">> %s\n", SECU_Strerror(PORT_GetError())); 1.665 + dumpBuffer(); 1.666 + exit(1); 1.667 + } 1.668 + main_initialized = 1; 1.669 +} 1.670 + 1.671 +void 1.672 +main_Do(secuCommandFlag *command, const char *progName, int log) 1.673 +{ 1.674 + do_command("main", main_initialized, command, progName, log); 1.675 +} 1.676 + 1.677 +void 1.678 +main_Shutdown(int old_style, const char *progName, int log) 1.679 +{ 1.680 + SECStatus rv; 1.681 + appendLabel('N'); 1.682 + if (log) { 1.683 + fprintf(stderr,"*NSS_Shutdown for the main program*\n"); 1.684 + } 1.685 + if (!main_initialized) { 1.686 + fprintf(stderr,"Warning: Main shutdown without corresponding init\n"); 1.687 + } 1.688 + if (old_style) { 1.689 + rv = NSS_Shutdown(); 1.690 + } else { 1.691 + rv = NSS_ShutdownContext(NULL); 1.692 + } 1.693 + fprintf(stderr, "Shutdown main state = %d\n", rv); 1.694 + if (rv != SECSuccess) { 1.695 + appendLabel('E'); 1.696 + appendInt(PORT_GetError()); 1.697 + fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError())); 1.698 + } 1.699 + main_initialized = 0; 1.700 +} 1.701 + 1.702 +/* common library init */ 1.703 +NSSInitContext * 1.704 +lib_Init(const char *lableString, char label, int initialized, 1.705 + secuCommandFlag *db, secuCommandFlag *tokNam, int readonly, 1.706 + const char *progName, int log) 1.707 +{ 1.708 + NSSInitContext *ctxt; 1.709 + NSSInitParameters initStrings; 1.710 + NSSInitParameters *initStringPtr = NULL; 1.711 + 1.712 + appendLabel(label); 1.713 + if (log) { 1.714 + fprintf(stderr,"*NSS_Init for %s*\n", lableString); 1.715 + } 1.716 + 1.717 + if (!db->activated) { 1.718 + fprintf(stderr, ">> No %s_db has been specified\n", lableString); 1.719 + usage(progName); 1.720 + } 1.721 + if (initialized) { 1.722 + fprintf(stderr,"Warning: Second initialization of %s\n", lableString); 1.723 + } 1.724 + if (tokNam->activated) { 1.725 + PORT_Memset(&initStrings, 0, sizeof(initStrings)); 1.726 + initStrings.length = sizeof(initStrings); 1.727 + initStrings.dbTokenDescription = tokNam->arg; 1.728 + initStringPtr = &initStrings; 1.729 + } 1.730 + ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr, 1.731 + NSS_INIT_NOROOTINIT|(readonly?NSS_INIT_READONLY:0)); 1.732 + if (ctxt == NULL) { 1.733 + appendLabel('E'); 1.734 + appendInt(PORT_GetError()); 1.735 + fprintf(stderr,">> %s\n",SECU_Strerror(PORT_GetError())); 1.736 + dumpBuffer(); 1.737 + exit(1); 1.738 + } 1.739 + return ctxt; 1.740 +} 1.741 + 1.742 +/* common library shutdown */ 1.743 +void 1.744 +lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx, 1.745 + int initialize, const char *progName, int log) 1.746 +{ 1.747 + SECStatus rv; 1.748 + appendLabel(label); 1.749 + if (log) { 1.750 + fprintf(stderr,"*NSS_Shutdown for %s\n*", labelString); 1.751 + } 1.752 + if (!initialize) { 1.753 + fprintf(stderr,"Warning: %s shutdown without corresponding init\n", 1.754 + labelString); 1.755 + } 1.756 + rv = NSS_ShutdownContext(ctx); 1.757 + fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv); 1.758 + if (rv != SECSuccess) { 1.759 + appendLabel('E'); 1.760 + appendInt(PORT_GetError()); 1.761 + fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError())); 1.762 + } 1.763 +} 1.764 + 1.765 + 1.766 +static NSSInitContext *lib1_context; 1.767 +static NSSInitContext *lib2_context; 1.768 +void 1.769 +lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 1.770 + int readOnly, const char *progName, int log) 1.771 +{ 1.772 + lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam, 1.773 + readOnly, progName, log); 1.774 + lib1_initialized = 1; 1.775 +} 1.776 + 1.777 +void 1.778 +lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam, 1.779 + int readOnly, const char *progName, int log) 1.780 +{ 1.781 + lib2_context = lib_Init("lib2", '2', lib2_initialized, 1.782 + db, tokNam, readOnly, progName, log); 1.783 + lib2_initialized = 1; 1.784 +} 1.785 + 1.786 +void 1.787 +lib1_Do(secuCommandFlag *command, const char *progName, int log) 1.788 +{ 1.789 + do_command("lib1", lib1_initialized, command, progName, log); 1.790 +} 1.791 + 1.792 +void 1.793 +lib2_Do(secuCommandFlag *command, const char *progName, int log) 1.794 +{ 1.795 + do_command("lib2", lib2_initialized, command, progName, log); 1.796 +} 1.797 + 1.798 +void 1.799 +lib1_Shutdown(const char *progName, int log) 1.800 +{ 1.801 + lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log); 1.802 + lib1_initialized = 0; 1.803 + /* don't clear lib1_Context, so we can test multiple attempts to close 1.804 + * the same context produces correct errors*/ 1.805 +} 1.806 + 1.807 +void 1.808 +lib2_Shutdown(const char *progName, int log) 1.809 +{ 1.810 + lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log); 1.811 + lib2_initialized = 0; 1.812 + /* don't clear lib2_Context, so we can test multiple attempts to close 1.813 + * the same context produces correct errors*/ 1.814 +} 1.815 + 1.816 +int 1.817 +main(int argc, char **argv) 1.818 +{ 1.819 + SECStatus rv; 1.820 + secuCommand libinit; 1.821 + char *progName; 1.822 + char *order; 1.823 + secuCommandFlag *options; 1.824 + int log = 0; 1.825 + 1.826 + progName = strrchr(argv[0], '/'); 1.827 + progName = progName ? progName+1 : argv[0]; 1.828 + 1.829 + libinit.numCommands = 0; 1.830 + libinit.commands = 0; 1.831 + libinit.numOptions = opt_last; 1.832 + options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init)); 1.833 + if (options == NULL) { 1.834 + fprintf(stderr, ">> %s:Not enough free memory to run command\n", 1.835 + progName); 1.836 + exit(1); 1.837 + } 1.838 + PORT_Memcpy(options, options_init, sizeof(options_init)); 1.839 + libinit.options = options; 1.840 + 1.841 + rv = SECU_ParseCommandLine(argc, argv, progName, & libinit); 1.842 + if (rv != SECSuccess) { 1.843 + usage(progName); 1.844 + } 1.845 + 1.846 + if (libinit.options[opt_help].activated) { 1.847 + long_help(progName); 1.848 + exit (0); 1.849 + } 1.850 + 1.851 + log = libinit.options[opt_verbose].activated; 1.852 + if (libinit.options[opt_summary].activated) { 1.853 + initBuffer(); 1.854 + } 1.855 + 1.856 + order = libinit.options[opt_liborder].arg; 1.857 + if (!order) { 1.858 + usage(progName); 1.859 + } 1.860 + 1.861 + if (log) { 1.862 + fprintf(stderr,"* initializing with order \"%s\"*\n", order); 1.863 + } 1.864 + 1.865 + for (;*order; order++) { 1.866 + switch (*order) { 1.867 + case 'M': 1.868 + main_Init(&libinit.options[opt_mainDB], 1.869 + &libinit.options[opt_mainTokNam], 1.870 + libinit.options[opt_mainRO].activated, 1.871 + progName, log); 1.872 + break; 1.873 + case '1': 1.874 + lib1_Init(&libinit.options[opt_lib1DB], 1.875 + &libinit.options[opt_lib1TokNam], 1.876 + libinit.options[opt_lib1RO].activated, 1.877 + progName,log); 1.878 + break; 1.879 + case '2': 1.880 + lib2_Init(&libinit.options[opt_lib2DB], 1.881 + &libinit.options[opt_lib2TokNam], 1.882 + libinit.options[opt_lib2RO].activated, 1.883 + progName,log); 1.884 + break; 1.885 + case 'm': 1.886 + main_Shutdown(libinit.options[opt_oldStyle].activated, 1.887 + progName, log); 1.888 + break; 1.889 + case 'i': 1.890 + lib1_Shutdown(progName, log); 1.891 + break; 1.892 + case 'z': 1.893 + lib2_Shutdown(progName, log); 1.894 + break; 1.895 + default: 1.896 + fprintf(stderr,">> Unknown init/shutdown command \"%c\"", *order); 1.897 + usage_long(progName); 1.898 + } 1.899 + main_Do(&libinit.options[opt_mainCMD], progName, log); 1.900 + lib1_Do(&libinit.options[opt_lib1CMD], progName, log); 1.901 + lib2_Do(&libinit.options[opt_lib2CMD], progName, log); 1.902 + } 1.903 + 1.904 + if (NSS_IsInitialized()) { 1.905 + appendLabel('X'); 1.906 + fprintf(stderr, "Warning: NSS is initialized\n"); 1.907 + } 1.908 + dumpBuffer(); 1.909 + 1.910 + exit(0); 1.911 +} 1.912 +