mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 03:30:17 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
889 lines
22 KiB
C
889 lines
22 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "nss.h"
|
|
#include "secutil.h"
|
|
#include "pk11pub.h"
|
|
#include "cert.h"
|
|
|
|
typedef struct commandDescriptStr {
|
|
int required;
|
|
char *arg;
|
|
char *des;
|
|
} commandDescript;
|
|
|
|
enum optionNames {
|
|
opt_liborder = 0,
|
|
opt_mainDB,
|
|
opt_lib1DB,
|
|
opt_lib2DB,
|
|
opt_mainRO,
|
|
opt_lib1RO,
|
|
opt_lib2RO,
|
|
opt_mainCMD,
|
|
opt_lib1CMD,
|
|
opt_lib2CMD,
|
|
opt_mainTokNam,
|
|
opt_lib1TokNam,
|
|
opt_lib2TokNam,
|
|
opt_oldStyle,
|
|
opt_verbose,
|
|
opt_summary,
|
|
opt_help,
|
|
opt_last
|
|
};
|
|
|
|
|
|
static const
|
|
secuCommandFlag options_init[] =
|
|
{
|
|
{ /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" },
|
|
{ /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" },
|
|
{ /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" },
|
|
{ /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" },
|
|
{ /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" },
|
|
{ /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" },
|
|
{ /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" },
|
|
{ /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" },
|
|
{ /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" },
|
|
{ /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" },
|
|
{ /* opt_mainTokNam */'t', PR_TRUE, 0, PR_FALSE, "main_token_name" },
|
|
{ /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" },
|
|
{ /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" },
|
|
{ /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" },
|
|
{ /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" },
|
|
{ /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" },
|
|
{ /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" }
|
|
};
|
|
|
|
static const
|
|
commandDescript options_des[] =
|
|
{
|
|
{ /* opt_liborder */ PR_FALSE, "initOrder",
|
|
" Specifies the order of NSS initialization and shutdown. Order is\n"
|
|
" given as a string where each character represents either an init or\n"
|
|
" a shutdown of the main program or one of the 2 test libraries\n"
|
|
" (library 1 and library 2). The valid characters are as follows:\n"
|
|
" M Init the main program\n 1 Init library 1\n"
|
|
" 2 Init library 2\n"
|
|
" m Shutdown the main program\n i Shutdown library 1\n"
|
|
" z Shutdown library 2\n" },
|
|
{ /* opt_mainDB */ PR_TRUE, "nss_db",
|
|
" Specified the directory to open the nss database for the main\n"
|
|
" program. Must be specified if \"M\" is given in the order string\n"},
|
|
{ /* opt_lib1DB */ PR_FALSE, "nss_db",
|
|
" Specified the directory to open the nss database for library 1.\n"
|
|
" Must be specified if \"1\" is given in the order string\n"},
|
|
{ /* opt_lib2DB */ PR_FALSE, "nss_db",
|
|
" Specified the directory to open the nss database for library 2.\n"
|
|
" Must be specified if \"2\" is given in the order string\n"},
|
|
{ /* opt_mainRO */ PR_FALSE, NULL,
|
|
" Open the main program's database read only.\n" },
|
|
{ /* opt_lib1RO */ PR_FALSE, NULL,
|
|
" Open library 1's database read only.\n" },
|
|
{ /* opt_lib2RO */ PR_FALSE, NULL,
|
|
" Open library 2's database read only.\n" },
|
|
{ /* opt_mainCMD */ PR_FALSE, "nss_command",
|
|
" Specifies the NSS command to execute in the main program.\n"
|
|
" Valid commands are: \n"
|
|
" key_slot, list_slots, list_certs, add_cert, none.\n"
|
|
" Default is \"none\".\n" },
|
|
{ /* opt_lib1CMD */ PR_FALSE, "nss_command",
|
|
" Specifies the NSS command to execute in library 1.\n" },
|
|
{ /* opt_lib2CMD */ PR_FALSE, "nss_command",
|
|
" Specifies the NSS command to execute in library 2.\n" },
|
|
{ /* opt_mainTokNam */PR_FALSE, "token_name",
|
|
" Specifies the name of PKCS11 token for the main program's "
|
|
"database.\n" },
|
|
{ /* opt_lib1TokNam */PR_FALSE, "token_name",
|
|
" Specifies the name of PKCS11 token for library 1's database.\n" },
|
|
{ /* opt_lib2TokNam */PR_FALSE, "token_name",
|
|
" Specifies the name of PKCS11 token for library 2's database.\n" },
|
|
{ /* opt_oldStype */ PR_FALSE, NULL,
|
|
" Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
|
|
" program.\n" },
|
|
{ /* opt_verbose */ PR_FALSE, NULL,
|
|
" Noisily output status to standard error\n" },
|
|
{ /* opt_summarize */ PR_FALSE, NULL,
|
|
"report a summary of the test results\n" },
|
|
{ /* opt_help */ PR_FALSE, NULL, " give this message\n" }
|
|
};
|
|
|
|
/*
|
|
* output our short help (table driven). (does not exit).
|
|
*/
|
|
static void
|
|
short_help(const char *prog)
|
|
{
|
|
int count = opt_last;
|
|
int i,words_found;
|
|
|
|
/* make sure all the tables are up to date before we allow compiles to
|
|
* succeed */
|
|
PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) == opt_last);
|
|
PR_STATIC_ASSERT(sizeof(options_init)/sizeof(secuCommandFlag) ==
|
|
sizeof(options_des)/sizeof(commandDescript));
|
|
|
|
/* print the base usage */
|
|
fprintf(stderr,"usage: %s ",prog);
|
|
for (i=0, words_found=0; i < count; i++) {
|
|
if (!options_des[i].required) {
|
|
fprintf(stderr,"[");
|
|
}
|
|
if (options_init[i].longform) {
|
|
fprintf(stderr, "--%s", options_init[i].longform);
|
|
words_found++;
|
|
} else {
|
|
fprintf(stderr, "-%c", options_init[i].flag);
|
|
}
|
|
if (options_init[i].needsArg) {
|
|
if (options_des[i].arg) {
|
|
fprintf(stderr," %s",options_des[i].arg);
|
|
} else {
|
|
fprintf(stderr," arg");
|
|
}
|
|
words_found++;
|
|
}
|
|
if (!options_des[i].required) {
|
|
fprintf(stderr,"]");
|
|
}
|
|
if (i < count-1 ) {
|
|
if (words_found >= 5) {
|
|
fprintf(stderr,"\n ");
|
|
words_found=0;
|
|
} else {
|
|
fprintf(stderr," ");
|
|
}
|
|
}
|
|
}
|
|
fprintf(stderr,"\n");
|
|
}
|
|
|
|
/*
|
|
* print out long help. like short_help, this does not exit
|
|
*/
|
|
static void
|
|
long_help(const char *prog)
|
|
{
|
|
int i;
|
|
int count = opt_last;
|
|
|
|
short_help(prog);
|
|
/* print the option descriptions */
|
|
fprintf(stderr,"\n");
|
|
for (i=0; i < count; i++) {
|
|
fprintf(stderr," ");
|
|
if (options_init[i].flag) {
|
|
fprintf(stderr, "-%c", options_init[i].flag);
|
|
if (options_init[i].longform) {
|
|
fprintf(stderr,",");
|
|
}
|
|
}
|
|
if (options_init[i].longform) {
|
|
fprintf(stderr,"--%s", options_init[i].longform);
|
|
}
|
|
if (options_init[i].needsArg) {
|
|
if (options_des[i].arg) {
|
|
fprintf(stderr," %s",options_des[i].arg);
|
|
} else {
|
|
fprintf(stderr," arg");
|
|
}
|
|
if (options_init[i].arg) {
|
|
fprintf(stderr," (default = \"%s\")",options_init[i].arg);
|
|
}
|
|
}
|
|
fprintf(stderr,"\n%s",options_des[i].des);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* record summary data
|
|
*/
|
|
struct bufferData {
|
|
char * data; /* lowest address of the buffer */
|
|
char * next; /* pointer to the next element on the buffer */
|
|
int len; /* length of the buffer */
|
|
};
|
|
|
|
/* our actual buffer. If data is NULL, then all append ops
|
|
* except are noops */
|
|
static struct bufferData buffer= { NULL, NULL, 0 };
|
|
|
|
#define CHUNK_SIZE 1000
|
|
|
|
/*
|
|
* get our initial data. and set the buffer variables up. on failure,
|
|
* just don't initialize the buffer.
|
|
*/
|
|
static void
|
|
initBuffer(void)
|
|
{
|
|
buffer.data = PORT_Alloc(CHUNK_SIZE);
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
buffer.next = buffer.data;
|
|
buffer.len = CHUNK_SIZE;
|
|
}
|
|
|
|
/*
|
|
* grow the buffer. If we can't get more data, record a 'D' in the second
|
|
* to last record and allow the rest of the data to overwrite the last
|
|
* element.
|
|
*/
|
|
static void
|
|
growBuffer(void)
|
|
{
|
|
char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE);
|
|
if (!new) {
|
|
buffer.data[buffer.len-2] = 'D'; /* signal malloc failure in summary */
|
|
/* buffer must always point to good memory if it exists */
|
|
buffer.next = buffer.data + (buffer.len -1);
|
|
return;
|
|
}
|
|
buffer.next = new + (buffer.next-buffer.data);
|
|
buffer.data = new;
|
|
buffer.len += CHUNK_SIZE;
|
|
}
|
|
|
|
/*
|
|
* append a label, doubles as appending a single character.
|
|
*/
|
|
static void
|
|
appendLabel(char label)
|
|
{
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
|
|
*buffer.next++ = label;
|
|
if (buffer.data+buffer.len >= buffer.next) {
|
|
growBuffer();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* append a string onto the buffer. The result will be <string>
|
|
*/
|
|
static void
|
|
appendString(char *string)
|
|
{
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
|
|
appendLabel('<');
|
|
while (*string) {
|
|
appendLabel(*string++);
|
|
}
|
|
appendLabel('>');
|
|
}
|
|
|
|
/*
|
|
* append a bool, T= true, F=false
|
|
*/
|
|
static void
|
|
appendBool(PRBool bool)
|
|
{
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
|
|
if (bool) {
|
|
appendLabel('t');
|
|
} else {
|
|
appendLabel('f');
|
|
}
|
|
}
|
|
|
|
/*
|
|
* append a single hex nibble.
|
|
*/
|
|
static void
|
|
appendHex(unsigned char nibble)
|
|
{
|
|
if (nibble <= 9) {
|
|
appendLabel('0'+nibble);
|
|
} else {
|
|
appendLabel('a'+nibble-10);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* append a 32 bit integer (even on a 64 bit platform).
|
|
* for simplicity append it as a hex value, full extension with 0x prefix.
|
|
*/
|
|
static void
|
|
appendInt(unsigned int value)
|
|
{
|
|
int i;
|
|
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
|
|
appendLabel('0');
|
|
appendLabel('x');
|
|
value = value & 0xffffffff; /* only look at the buttom 8 bytes */
|
|
for (i=0; i < 8; i++) {
|
|
appendHex(value >> 28 );
|
|
value = value << 4;
|
|
}
|
|
}
|
|
|
|
/* append a trust flag */
|
|
static void
|
|
appendFlags(unsigned int flag)
|
|
{
|
|
char trust[10];
|
|
char *cp=trust;
|
|
|
|
trust[0] = 0;
|
|
printflags(trust, flag);
|
|
while (*cp) {
|
|
appendLabel(*cp++);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* dump our buffer out with a result= flag so we can find it easily.
|
|
* free the buffer as a side effect.
|
|
*/
|
|
static void
|
|
dumpBuffer(void)
|
|
{
|
|
if (!buffer.data) {
|
|
return;
|
|
}
|
|
|
|
appendLabel(0); /* terminate */
|
|
printf("\nresult=%s\n",buffer.data);
|
|
PORT_Free(buffer.data);
|
|
buffer.data = buffer.next = NULL;
|
|
buffer.len = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* usage, like traditional usage, automatically exit
|
|
*/
|
|
static void
|
|
usage(const char *prog)
|
|
{
|
|
short_help(prog);
|
|
dumpBuffer();
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
* like usage, except prints the long version of help
|
|
*/
|
|
static void
|
|
usage_long(const char *prog)
|
|
{
|
|
long_help(prog);
|
|
dumpBuffer();
|
|
exit(1);
|
|
}
|
|
|
|
static const char *
|
|
bool2String(PRBool bool)
|
|
{
|
|
return bool ? "true" : "false";
|
|
}
|
|
|
|
/*
|
|
* print out interesting info about the given slot
|
|
*/
|
|
void
|
|
print_slot(PK11SlotInfo *slot, int log)
|
|
{
|
|
if (log) {
|
|
fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
|
|
PK11_GetSlotName(slot), PK11_GetTokenName(slot),
|
|
bool2String(PK11_IsPresent(slot)),
|
|
bool2String(PK11_IsReadOnly(slot)));
|
|
}
|
|
appendLabel('S');
|
|
appendString(PK11_GetTokenName(slot));
|
|
appendBool(PK11_IsPresent(slot));
|
|
appendBool(PK11_IsReadOnly(slot));
|
|
}
|
|
|
|
/*
|
|
* list all our slots
|
|
*/
|
|
void
|
|
do_list_slots(const char *progName, int log)
|
|
{
|
|
PK11SlotList *list;
|
|
PK11SlotListElement *le;
|
|
|
|
list= PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
|
|
if (list == NULL) {
|
|
fprintf(stderr,"ERROR: no tokens found %s\n",
|
|
SECU_Strerror(PORT_GetError()));
|
|
appendLabel('S');
|
|
appendString("none");
|
|
return;
|
|
}
|
|
|
|
for (le= PK11_GetFirstSafe(list); le;
|
|
le = PK11_GetNextSafe(list,le,PR_TRUE)) {
|
|
print_slot(le->slot, log);
|
|
}
|
|
PK11_FreeSlotList(list);
|
|
}
|
|
|
|
static PRBool
|
|
sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
|
|
{
|
|
char *commonNameA, *commonNameB;
|
|
int ret;
|
|
|
|
commonNameA = CERT_GetCommonName(&certa->subject);
|
|
commonNameB = CERT_GetCommonName(&certb->subject);
|
|
|
|
if (commonNameA == NULL) {
|
|
PORT_Free(commonNameB);
|
|
return PR_TRUE;
|
|
}
|
|
if (commonNameB == NULL) {
|
|
PORT_Free(commonNameA);
|
|
return PR_FALSE;
|
|
}
|
|
ret = PORT_Strcmp(commonNameA,commonNameB);
|
|
PORT_Free(commonNameA);
|
|
PORT_Free(commonNameB);
|
|
return (ret < 0) ? PR_TRUE: PR_FALSE;
|
|
}
|
|
|
|
/*
|
|
* list all the certs
|
|
*/
|
|
void
|
|
do_list_certs(const char *progName, int log)
|
|
{
|
|
CERTCertList *list;
|
|
CERTCertList *sorted;
|
|
CERTCertListNode *node;
|
|
CERTCertTrust trust;
|
|
unsigned int i;
|
|
|
|
list = PK11_ListCerts(PK11CertListUnique, NULL);
|
|
if (list == NULL) {
|
|
fprintf(stderr,"ERROR: no certs found %s\n",
|
|
SECU_Strerror(PORT_GetError()));
|
|
appendLabel('C');
|
|
appendString("none");
|
|
return;
|
|
}
|
|
|
|
sorted = CERT_NewCertList();
|
|
if (sorted == NULL) {
|
|
fprintf(stderr,"ERROR: no certs found %s\n",
|
|
SECU_Strerror(PORT_GetError()));
|
|
appendLabel('C');
|
|
appendLabel('E');
|
|
appendInt(PORT_GetError());
|
|
return;
|
|
}
|
|
|
|
/* sort the list */
|
|
for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node,list);
|
|
node = CERT_LIST_NEXT(node)) {
|
|
CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL);
|
|
}
|
|
|
|
|
|
for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node,sorted);
|
|
node = CERT_LIST_NEXT(node)) {
|
|
CERTCertificate *cert = node->cert;
|
|
char *commonName;
|
|
|
|
SECU_PrintCertNickname(node, stderr);
|
|
if (log) {
|
|
fprintf(stderr, "* Slot=%s*\n", cert->slot ?
|
|
PK11_GetTokenName(cert->slot) : "none");
|
|
fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
|
|
fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
|
|
fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
|
|
fprintf(stderr, "* SN=");
|
|
for (i=0; i < cert->serialNumber.len; i++) {
|
|
if (i!=0) fprintf(stderr,":");
|
|
fprintf(stderr, "%02x",cert->serialNumber.data[0]);
|
|
}
|
|
fprintf(stderr," *\n");
|
|
}
|
|
appendLabel('C');
|
|
commonName = CERT_GetCommonName(&cert->subject);
|
|
appendString(commonName?commonName:"*NoName*");
|
|
PORT_Free(commonName);
|
|
if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
|
|
appendFlags(trust.sslFlags);
|
|
appendFlags(trust.emailFlags);
|
|
appendFlags(trust.objectSigningFlags);
|
|
}
|
|
}
|
|
CERT_DestroyCertList(list);
|
|
|
|
}
|
|
|
|
/*
|
|
* need to implement yet... try to add a new certificate
|
|
*/
|
|
void
|
|
do_add_cert(const char *progName, int log)
|
|
{
|
|
PORT_Assert(/* do_add_cert not implemented */ 0);
|
|
}
|
|
|
|
/*
|
|
* display the current key slot
|
|
*/
|
|
void
|
|
do_key_slot(const char *progName, int log)
|
|
{
|
|
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
|
|
if (!slot) {
|
|
fprintf(stderr,"ERROR: no internal key slot found %s\n",
|
|
SECU_Strerror(PORT_GetError()));
|
|
appendLabel('K');
|
|
appendLabel('S');
|
|
appendString("none");
|
|
}
|
|
print_slot(slot, log);
|
|
PK11_FreeSlot(slot);
|
|
}
|
|
|
|
/*
|
|
* execute some NSS command.
|
|
*/
|
|
void
|
|
do_command(const char *label, int initialized, secuCommandFlag *command,
|
|
const char *progName, int log)
|
|
{
|
|
char * command_string;
|
|
if (!initialized) {
|
|
return;
|
|
}
|
|
|
|
if (command->activated) {
|
|
command_string = command->arg;
|
|
} else {
|
|
command_string = "none";
|
|
}
|
|
|
|
if (log) {
|
|
fprintf(stderr, "*Executing nss command \"%s\" for %s*\n",
|
|
command_string,label);
|
|
}
|
|
|
|
/* do something */
|
|
if (PORT_Strcasecmp(command_string, "list_slots") == 0) {
|
|
do_list_slots(progName, log);
|
|
} else if (PORT_Strcasecmp(command_string, "list_certs") == 0) {
|
|
do_list_certs(progName, log);
|
|
} else if (PORT_Strcasecmp(command_string, "add_cert") == 0) {
|
|
do_add_cert(progName, log);
|
|
} else if (PORT_Strcasecmp(command_string, "key_slot") == 0) {
|
|
do_key_slot(progName, log);
|
|
} else if (PORT_Strcasecmp(command_string, "none") != 0) {
|
|
fprintf(stderr, ">> Unknown command (%s)\n", command_string);
|
|
appendLabel('E');
|
|
appendString("bc");
|
|
usage_long(progName);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* functions do handle
|
|
* different library initializations.
|
|
*/
|
|
static int main_initialized;
|
|
static int lib1_initialized;
|
|
static int lib2_initialized;
|
|
|
|
void
|
|
main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
|
|
int readOnly, const char *progName, int log)
|
|
{
|
|
SECStatus rv;
|
|
if (log) {
|
|
fprintf(stderr,"*NSS_Init for the main program*\n");
|
|
}
|
|
appendLabel('M');
|
|
if (!db->activated) {
|
|
fprintf(stderr, ">> No main_db has been specified\n");
|
|
usage(progName);
|
|
}
|
|
if (main_initialized) {
|
|
fprintf(stderr,"Warning: Second initialization of Main\n");
|
|
appendLabel('E');
|
|
appendString("2M");
|
|
}
|
|
if (tokNam->activated) {
|
|
PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg,
|
|
NULL, NULL, NULL, NULL, 0, 0);
|
|
}
|
|
rv = NSS_Initialize(db->arg, "", "", "",
|
|
NSS_INIT_NOROOTINIT|(readOnly?NSS_INIT_READONLY:0));
|
|
if (rv != SECSuccess) {
|
|
appendLabel('E');
|
|
appendInt(PORT_GetError());
|
|
fprintf(stderr,">> %s\n", SECU_Strerror(PORT_GetError()));
|
|
dumpBuffer();
|
|
exit(1);
|
|
}
|
|
main_initialized = 1;
|
|
}
|
|
|
|
void
|
|
main_Do(secuCommandFlag *command, const char *progName, int log)
|
|
{
|
|
do_command("main", main_initialized, command, progName, log);
|
|
}
|
|
|
|
void
|
|
main_Shutdown(int old_style, const char *progName, int log)
|
|
{
|
|
SECStatus rv;
|
|
appendLabel('N');
|
|
if (log) {
|
|
fprintf(stderr,"*NSS_Shutdown for the main program*\n");
|
|
}
|
|
if (!main_initialized) {
|
|
fprintf(stderr,"Warning: Main shutdown without corresponding init\n");
|
|
}
|
|
if (old_style) {
|
|
rv = NSS_Shutdown();
|
|
} else {
|
|
rv = NSS_ShutdownContext(NULL);
|
|
}
|
|
fprintf(stderr, "Shutdown main state = %d\n", rv);
|
|
if (rv != SECSuccess) {
|
|
appendLabel('E');
|
|
appendInt(PORT_GetError());
|
|
fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
|
|
}
|
|
main_initialized = 0;
|
|
}
|
|
|
|
/* common library init */
|
|
NSSInitContext *
|
|
lib_Init(const char *lableString, char label, int initialized,
|
|
secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
|
|
const char *progName, int log)
|
|
{
|
|
NSSInitContext *ctxt;
|
|
NSSInitParameters initStrings;
|
|
NSSInitParameters *initStringPtr = NULL;
|
|
|
|
appendLabel(label);
|
|
if (log) {
|
|
fprintf(stderr,"*NSS_Init for %s*\n", lableString);
|
|
}
|
|
|
|
if (!db->activated) {
|
|
fprintf(stderr, ">> No %s_db has been specified\n", lableString);
|
|
usage(progName);
|
|
}
|
|
if (initialized) {
|
|
fprintf(stderr,"Warning: Second initialization of %s\n", lableString);
|
|
}
|
|
if (tokNam->activated) {
|
|
PORT_Memset(&initStrings, 0, sizeof(initStrings));
|
|
initStrings.length = sizeof(initStrings);
|
|
initStrings.dbTokenDescription = tokNam->arg;
|
|
initStringPtr = &initStrings;
|
|
}
|
|
ctxt = NSS_InitContext(db->arg, "", "", "", initStringPtr,
|
|
NSS_INIT_NOROOTINIT|(readonly?NSS_INIT_READONLY:0));
|
|
if (ctxt == NULL) {
|
|
appendLabel('E');
|
|
appendInt(PORT_GetError());
|
|
fprintf(stderr,">> %s\n",SECU_Strerror(PORT_GetError()));
|
|
dumpBuffer();
|
|
exit(1);
|
|
}
|
|
return ctxt;
|
|
}
|
|
|
|
/* common library shutdown */
|
|
void
|
|
lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
|
|
int initialize, const char *progName, int log)
|
|
{
|
|
SECStatus rv;
|
|
appendLabel(label);
|
|
if (log) {
|
|
fprintf(stderr,"*NSS_Shutdown for %s\n*", labelString);
|
|
}
|
|
if (!initialize) {
|
|
fprintf(stderr,"Warning: %s shutdown without corresponding init\n",
|
|
labelString);
|
|
}
|
|
rv = NSS_ShutdownContext(ctx);
|
|
fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv);
|
|
if (rv != SECSuccess) {
|
|
appendLabel('E');
|
|
appendInt(PORT_GetError());
|
|
fprintf(stderr,"ERROR: %s\n", SECU_Strerror(PORT_GetError()));
|
|
}
|
|
}
|
|
|
|
|
|
static NSSInitContext *lib1_context;
|
|
static NSSInitContext *lib2_context;
|
|
void
|
|
lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
|
|
int readOnly, const char *progName, int log)
|
|
{
|
|
lib1_context = lib_Init("lib1", '1', lib1_initialized, db, tokNam,
|
|
readOnly, progName, log);
|
|
lib1_initialized = 1;
|
|
}
|
|
|
|
void
|
|
lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
|
|
int readOnly, const char *progName, int log)
|
|
{
|
|
lib2_context = lib_Init("lib2", '2', lib2_initialized,
|
|
db, tokNam, readOnly, progName, log);
|
|
lib2_initialized = 1;
|
|
}
|
|
|
|
void
|
|
lib1_Do(secuCommandFlag *command, const char *progName, int log)
|
|
{
|
|
do_command("lib1", lib1_initialized, command, progName, log);
|
|
}
|
|
|
|
void
|
|
lib2_Do(secuCommandFlag *command, const char *progName, int log)
|
|
{
|
|
do_command("lib2", lib2_initialized, command, progName, log);
|
|
}
|
|
|
|
void
|
|
lib1_Shutdown(const char *progName, int log)
|
|
{
|
|
lib_Shutdown("lib1", 'I', lib1_context, lib1_initialized, progName, log);
|
|
lib1_initialized = 0;
|
|
/* don't clear lib1_Context, so we can test multiple attempts to close
|
|
* the same context produces correct errors*/
|
|
}
|
|
|
|
void
|
|
lib2_Shutdown(const char *progName, int log)
|
|
{
|
|
lib_Shutdown("lib2", 'Z', lib2_context, lib2_initialized, progName, log);
|
|
lib2_initialized = 0;
|
|
/* don't clear lib2_Context, so we can test multiple attempts to close
|
|
* the same context produces correct errors*/
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
SECStatus rv;
|
|
secuCommand libinit;
|
|
char *progName;
|
|
char *order;
|
|
secuCommandFlag *options;
|
|
int log = 0;
|
|
|
|
progName = strrchr(argv[0], '/');
|
|
progName = progName ? progName+1 : argv[0];
|
|
|
|
libinit.numCommands = 0;
|
|
libinit.commands = 0;
|
|
libinit.numOptions = opt_last;
|
|
options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init));
|
|
if (options == NULL) {
|
|
fprintf(stderr, ">> %s:Not enough free memory to run command\n",
|
|
progName);
|
|
exit(1);
|
|
}
|
|
PORT_Memcpy(options, options_init, sizeof(options_init));
|
|
libinit.options = options;
|
|
|
|
rv = SECU_ParseCommandLine(argc, argv, progName, & libinit);
|
|
if (rv != SECSuccess) {
|
|
usage(progName);
|
|
}
|
|
|
|
if (libinit.options[opt_help].activated) {
|
|
long_help(progName);
|
|
exit (0);
|
|
}
|
|
|
|
log = libinit.options[opt_verbose].activated;
|
|
if (libinit.options[opt_summary].activated) {
|
|
initBuffer();
|
|
}
|
|
|
|
order = libinit.options[opt_liborder].arg;
|
|
if (!order) {
|
|
usage(progName);
|
|
}
|
|
|
|
if (log) {
|
|
fprintf(stderr,"* initializing with order \"%s\"*\n", order);
|
|
}
|
|
|
|
for (;*order; order++) {
|
|
switch (*order) {
|
|
case 'M':
|
|
main_Init(&libinit.options[opt_mainDB],
|
|
&libinit.options[opt_mainTokNam],
|
|
libinit.options[opt_mainRO].activated,
|
|
progName, log);
|
|
break;
|
|
case '1':
|
|
lib1_Init(&libinit.options[opt_lib1DB],
|
|
&libinit.options[opt_lib1TokNam],
|
|
libinit.options[opt_lib1RO].activated,
|
|
progName,log);
|
|
break;
|
|
case '2':
|
|
lib2_Init(&libinit.options[opt_lib2DB],
|
|
&libinit.options[opt_lib2TokNam],
|
|
libinit.options[opt_lib2RO].activated,
|
|
progName,log);
|
|
break;
|
|
case 'm':
|
|
main_Shutdown(libinit.options[opt_oldStyle].activated,
|
|
progName, log);
|
|
break;
|
|
case 'i':
|
|
lib1_Shutdown(progName, log);
|
|
break;
|
|
case 'z':
|
|
lib2_Shutdown(progName, log);
|
|
break;
|
|
default:
|
|
fprintf(stderr,">> Unknown init/shutdown command \"%c\"", *order);
|
|
usage_long(progName);
|
|
}
|
|
main_Do(&libinit.options[opt_mainCMD], progName, log);
|
|
lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
|
|
lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
|
|
}
|
|
|
|
if (NSS_IsInitialized()) {
|
|
appendLabel('X');
|
|
fprintf(stderr, "Warning: NSS is initialized\n");
|
|
}
|
|
dumpBuffer();
|
|
|
|
exit(0);
|
|
}
|
|
|