security/nss/cmd/multinit/multinit.c

changeset 0
6474c204b198
     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 +

mercurial