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.

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

mercurial