char buffer[513]; PRErrorCode err    = PR_GetError(); PRInt32     errLen = PR_GetErrorTextLength(); if (errLen > 0 && errLen < sizeof buffer) PR_GetErrorText(buffer); SECU_PrintError(progName, "NSS_Initialize failed"); if (errLen > 0 && errLen < sizeof buffer) PR_fprintf(PR_STDERR, "\t%s\n", buffer);
SECU_PrintPRandOSError(progName);
main(int argc, char **argv){    CERTCertDBHandle *certHandle;    PK11SlotInfo *slot = NULL;    CERTName *  subject         = 0;    PRFileDesc *inFile          = 0;    PRFileDesc *outFile         = 0;    char *      certfile        = "tempcert";    char *      certreqfile     = "tempcertreq";    char *      slotname        = "internal";    char *      certPrefix      = "";    KeyType     keytype         = rsaKey;    /*char *	keyslot	        = NULL;*/    /*char *      keynickname     = NULL;*/    char *      name            = NULL;    int	        keysize	        = DEFAULT_KEY_BITS;    int         publicExponent  = 0x010001;    int         serialNumber    = 0;    int         warpmonths      = 0;    int         validitylength  = 0;    int         commandsEntered = 0;    char        commandToRun    = '\0';    secuPWData  pwdata          = { PW_NONE, 0 };    SECKEYPrivateKey *privkey;    SECKEYPublicKey *pubkey = NULL;    int i;    SECStatus rv;    secuCommand certutil;    certutil.numCommands = sizeof(certutil_commands) / sizeof(secuCommandFlag);    certutil.numOptions = sizeof(certutil_options) / sizeof(secuCommandFlag);    certutil.commands = certutil_commands;    certutil.options = certutil_options;    progName = strrchr(argv[0], '/');    progName = progName ? progName+1 : argv[0];    rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);    if (rv != SECSuccess)	Usage(progName);    if (certutil.commands[cmd_PrintHelp].activated)	LongUsage(progName);    if (certutil.options[opt_PasswordFile].arg) {	pwdata.source = PW_FROMFILE;	pwdata.data = certutil.options[opt_PasswordFile].arg;    }    if (certutil.options[opt_CertDir].activated)	SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);    if (certutil.options[opt_KeySize].activated) {	keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);	if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {	    PR_fprintf(PR_STDERR,                        "%s -g:  Keysize must be between %d and %d.\n",	               MIN_KEY_BITS, MAX_KEY_BITS);	    return -1;	}    }    /*  -h specify token name  */    if (certutil.options[opt_TokenName].activated) {	if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)	    slotname = NULL;	else	    slotname = PL_strdup(certutil.options[opt_TokenName].arg);    }    /*  -k key type  */    if (certutil.options[opt_KeyType].activated) {	if (PL_strcmp(certutil.options[opt_KeyType].arg, "rsa") == 0) {	    keytype = rsaKey;	} else if (PL_strcmp(certutil.options[opt_KeyType].arg, "dsa") == 0) {	    keytype = dsaKey;	} else if (PL_strcmp(certutil.options[opt_KeyType].arg, "all") == 0) {	    keytype = nullKey;	} else {	    PR_fprintf(PR_STDERR, "%s -k:  %s is not a recognized type.\n",	               progName, certutil.options[opt_KeyType].arg);	    return -1;	}    }    /*  -m serial number */    if (certutil.options[opt_SerialNumber].activated) {	serialNumber = PORT_Atoi(certutil.options[opt_SerialNumber].arg);	if (serialNumber < 0) {	    PR_fprintf(PR_STDERR, "%s -m:  %s is not a valid serial number.\n",	               progName, certutil.options[opt_SerialNumber].arg);	    return -1;	}    }    /*  -P certdb name prefix */    if (certutil.options[opt_DBPrefix].activated)	certPrefix = strdup(certutil.options[opt_DBPrefix].arg);    /*  -q PQG file  */    if (certutil.options[opt_PQGFile].activated) {	if (keytype != dsaKey) {	    PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)",	               progName);	    return -1;	}    }    /*  -s subject name  */    if (certutil.options[opt_Subject].activated) {	subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);	if (!subject) {	    PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n",	               progName, certutil.options[opt_Subject].arg);	    return -1;	}    }    /*  -v validity period  */    if (certutil.options[opt_Validity].activated) {	validitylength = PORT_Atoi(certutil.options[opt_Validity].arg);	if (validitylength < 0) {	    PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n",	               progName, certutil.options[opt_Validity].arg);	    return -1;	}    }    /*  -w warp months  */    if (certutil.options[opt_OffsetMonths].activated)	warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);    /*  -y public exponent (for RSA)  */    if (certutil.options[opt_Exponent].activated) {	publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg);	if ((publicExponent != 3) &&	    (publicExponent != 17) &&	    (publicExponent != 65537)) {	    PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.", 	                           progName, publicExponent);	    PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n");	    return -1;	}    }    /*  Check number of commands entered.  */    commandsEntered = 0;    for (i=0; i< certutil.numCommands; i++) {	if (certutil.commands[i].activated) {	    commandToRun = certutil.commands[i].flag;	    commandsEntered++;	}	if (commandsEntered > 1)	    break;    }    if (commandsEntered > 1) {	PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);	PR_fprintf(PR_STDERR, "You entered: ");	for (i=0; i< certutil.numCommands; i++) {	    if (certutil.commands[i].activated)		PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);	}	PR_fprintf(PR_STDERR, "\n");	return -1;    }    if (commandsEntered == 0) {	PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName);	Usage(progName);    }    /*  -A, -D, -F, -M, -S, -V, and all require -n  */    if ((certutil.commands[cmd_AddCert].activated ||         certutil.commands[cmd_DeleteCert].activated ||         certutil.commands[cmd_DeleteKey].activated ||         certutil.commands[cmd_ModifyCertTrust].activated ||         certutil.commands[cmd_CreateAndAddCert].activated ||         certutil.commands[cmd_CheckCertValidity].activated) &&        !certutil.options[opt_Nickname].activated) {	PR_fprintf(PR_STDERR, 	          "%s -%c: nickname is required for this command (-n).\n",	           progName, commandToRun);	return -1;    }    /*  -A, -E, -M, -S require trust  */    if ((certutil.commands[cmd_AddCert].activated ||         certutil.commands[cmd_AddEmailCert].activated ||         certutil.commands[cmd_ModifyCertTrust].activated ||         certutil.commands[cmd_CreateAndAddCert].activated) &&        !certutil.options[opt_Trust].activated) {	PR_fprintf(PR_STDERR, 	          "%s -%c: trust is required for this command (-t).\n",	           progName, commandToRun);	return -1;    }    /*  if -L is given raw or ascii mode, it must be for only one cert.  */    if (certutil.commands[cmd_ListCerts].activated &&        (certutil.options[opt_ASCIIForIO].activated ||         certutil.options[opt_BinaryDER].activated) &&        !certutil.options[opt_Nickname].activated) {	PR_fprintf(PR_STDERR, 	        "%s: nickname is required to dump cert in raw or ascii mode.\n",	           progName);	return -1;    }        /*  -L can only be in (raw || ascii).  */    if (certutil.commands[cmd_ListCerts].activated &&        certutil.options[opt_ASCIIForIO].activated &&        certutil.options[opt_BinaryDER].activated) {	PR_fprintf(PR_STDERR, 	           "%s: cannot specify both -r and -a when dumping cert.\n",	           progName);	return -1;    }    /*  If making a cert request, need a subject.  */    if ((certutil.commands[cmd_CertReq].activated ||         certutil.commands[cmd_CreateAndAddCert].activated) &&        !certutil.options[opt_Subject].activated) {	PR_fprintf(PR_STDERR, 	           "%s -%c: subject is required to create a cert request.\n",	           progName, commandToRun);	return -1;    }    /*  If making a cert, need a serial number.  */    if ((certutil.commands[cmd_CreateNewCert].activated ||         certutil.commands[cmd_CreateAndAddCert].activated) &&         !certutil.options[opt_SerialNumber].activated) {	/*  Make a default serial number from the current time.  */	PRTime now = PR_Now();	serialNumber = LL_L2UI(serialNumber, now);    }    /*  Validation needs the usage to validate for.  */    if (certutil.commands[cmd_CheckCertValidity].activated &&        !certutil.options[opt_Usage].activated) {	PR_fprintf(PR_STDERR, 	           "%s -V: specify a usage to validate the cert for (-u).\n",	           progName);	return -1;    }        /*  To make a cert, need either a issuer or to self-sign it.  */    if (certutil.commands[cmd_CreateAndAddCert].activated &&	!(certutil.options[opt_IssuerName].activated ||          certutil.options[opt_SelfSign].activated)) {	PR_fprintf(PR_STDERR,	           "%s -S: must specify issuer (-c) or self-sign (-x).\n",	           progName);	return -1;    }    /*  Using slotname == NULL for listing keys and certs on all slots,      *  but only that. */    if (!(certutil.commands[cmd_ListKeys].activated ||    	  certutil.commands[cmd_ListCerts].activated) && slotname == NULL) {	PR_fprintf(PR_STDERR,	           "%s -%c: cannot use \"-h all\" for this command.\n",	           progName, commandToRun);	return -1;    }    /*  Using keytype == nullKey for list all key types, but only that.  */    if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {	PR_fprintf(PR_STDERR,	           "%s -%c: cannot use \"-k all\" for this command.\n",	           progName, commandToRun);	return -1;    }    /*  -S  open outFile, temporary file for cert request.  */    if (certutil.commands[cmd_CreateAndAddCert].activated) {	outFile = PR_Open(certreqfile, PR_RDWR | PR_CREATE_FILE, 00660);	if (!outFile) {	    PR_fprintf(PR_STDERR, 		       "%s -o: unable to open \"%s\" for writing (%ld, %ld)\n",		       progName, certreqfile,		       PR_GetError(), PR_GetOSError());	    return -1;	}    }    /*  Open the input file.  */    if (certutil.options[opt_InputFile].activated) {	inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0);	if (!inFile) {	    PR_fprintf(PR_STDERR,	               "%s:  unable to open \"%s\" for reading (%ld, %ld).\n",	               progName, certutil.options[opt_InputFile].arg,	               PR_GetError(), PR_GetOSError());	    return -1;	}    }    /*  Open the output file.  */    if (certutil.options[opt_OutputFile].activated && !outFile) {	outFile = PR_Open(certutil.options[opt_OutputFile].arg,                           PR_CREATE_FILE | PR_RDWR, 00660);	if (!outFile) {	    PR_fprintf(PR_STDERR,	               "%s:  unable to open \"%s\" for writing (%ld, %ld).\n",	               progName, certutil.options[opt_OutputFile].arg,	               PR_GetError(), PR_GetOSError());	    return -1;	}    }    name = SECU_GetOptionArg(&certutil, opt_Nickname);    PK11_SetPasswordFunc(SECU_GetModulePassword);    /*  Initialize NSPR and NSS.  */    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);    rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,                        "secmod.db", PR_FALSE);    if (rv != SECSuccess) {	char buffer[513];	PRErrorCode err    = PR_GetError();	PRInt32     errLen = PR_GetErrorTextLength();	if (errLen > 0 && errLen < sizeof buffer)	    PR_GetErrorText(buffer);	SECU_PrintError(progName, "NSS_Initialize failed");	if (errLen > 0 && errLen < sizeof buffer)	    PR_fprintf(PR_STDERR, "\t%s\n", buffer);	return -1;    }    certHandle = CERT_GetDefaultCertDB();    if (certutil.commands[cmd_Version].activated) {	int version = CERT_GetDBContentVersion(certHandle);	printf("Certificate database content version:  %d\n", version);    }    if (PL_strcmp(slotname, "internal") == 0)	slot = PK11_GetInternalKeySlot();    else if (slotname != NULL)	slot = PK11_FindSlotByName(slotname);    /*  If creating new database, initialize the password.  */    if (certutil.commands[cmd_NewDBs].activated) {	SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);    }    /* The following 8 options are mutually exclusive with all others. */    /*  List certs (-L)  */    if (certutil.commands[cmd_ListCerts].activated) {	rv = ListCerts(certHandle, name, slot,	               certutil.options[opt_BinaryDER].activated,	               certutil.options[opt_ASCIIForIO].activated,                        (outFile) ? outFile : PR_STDOUT,		       certutil.options[opt_PasswordFile].arg);	return !rv - 1;    }    /*  XXX needs work  */    /*  List keys (-K)  */    if (certutil.commands[cmd_ListKeys].activated) {	rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/,		       certutil.options[opt_PasswordFile].arg);	return !rv - 1;    }    /*  List modules (-U)  */    if (certutil.commands[cmd_ListModules].activated) {	rv = ListModules();	return !rv - 1;    }    /*  Delete cert (-D)  */    if (certutil.commands[cmd_DeleteCert].activated) {	rv = DeleteCert(certHandle, name);	return !rv - 1;    }#ifdef notdef    /*  Delete key (-F)  */    if (certutil.commands[cmd_DeleteKey].activated) {	rv = DeleteKey(keyHandle, name);	return !rv - 1;    }#endif    /*  Modify trust attribute for cert (-M)  */    if (certutil.commands[cmd_ModifyCertTrust].activated) {	rv = ChangeTrustAttributes(certHandle, name, 	                           certutil.options[opt_Trust].arg);	return !rv - 1;    }    /*  Change key db password (-W) (future - change pw to slot?)  */    if (certutil.commands[cmd_ChangePassword].activated) {	rv = SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);	return !rv - 1;    }    /*  Check cert validity against current time (-V)  */    if (certutil.commands[cmd_CheckCertValidity].activated) {	rv = ValidateCert(certHandle, name, 	                  certutil.options[opt_ValidityTime].arg,			  certutil.options[opt_Usage].arg,			  certutil.options[opt_VerifySig].activated,			  certutil.options[opt_DetailedInfo].activated);	return !rv - 1;    }    /*     *  Key generation     */    /*  These commands require keygen.  */    if (certutil.commands[cmd_CertReq].activated ||        certutil.commands[cmd_CreateAndAddCert].activated ||	certutil.commands[cmd_GenKeyPair].activated) {	/*  XXX Give it a nickname.  */	privkey = 	    CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,	                                publicExponent, 	                                certutil.options[opt_NoiseFile].arg,	                                &pubkey, 	                                certutil.options[opt_PQGFile].arg,	                                certutil.options[opt_PasswordFile].arg);	if (privkey == NULL) {	    SECU_PrintError(progName, "unable to generate key(s)\n");	    return -1;	}	PORT_Assert(pubkey != NULL);	/*  If all that was needed was keygen, exit.  */	if (certutil.commands[cmd_GenKeyPair].activated) {	    return SECSuccess;	}    }    /*     *  Certificate request     */    /*  Make a cert request (-R or -S).  */    if (certutil.commands[cmd_CreateAndAddCert].activated ||         certutil.commands[cmd_CertReq].activated) {	rv = CertReq(privkey, pubkey, keytype, subject,	             certutil.options[opt_PhoneNumber].arg,	             certutil.options[opt_ASCIIForIO].activated,		     outFile ? outFile : PR_STDOUT);	if (rv) 	    return -1;    }    /*     *  Certificate creation     */    /*  If making and adding a cert, load the cert request file     *  and output the cert to another file.     */    if (certutil.commands[cmd_CreateAndAddCert].activated) {	PR_Close(outFile);	inFile  = PR_Open(certreqfile, PR_RDONLY, 0);	if (!inFile) {	    PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",                       certreqfile, PR_GetError(), PR_GetOSError());	    return -1;	}	outFile = PR_Open(certfile, PR_RDWR | PR_CREATE_FILE, 00660);	if (!outFile) {	    PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",                       certfile, PR_GetError(), PR_GetOSError());	    return -1;	}    }    /*  Create a certificate (-C or -S).  */    if (certutil.commands[cmd_CreateAndAddCert].activated ||         certutil.commands[cmd_CreateNewCert].activated) {	rv = CreateCert(certHandle, 	                certutil.options[opt_IssuerName].arg,	                inFile, outFile, privkey, &pwdata,	                serialNumber, warpmonths, validitylength,	                certutil.options[opt_SelfSign].activated,	                certutil.options[opt_AddKeyUsageExt].activated,	                certutil.options[opt_AddExtKeyUsageExt].activated,	                certutil.options[opt_AddBasicConstraintExt].activated,	                certutil.options[opt_AddAuthorityKeyIDExt].activated,	                certutil.options[opt_AddCRLDistPtsExt].activated,	                certutil.options[opt_AddNSCertTypeExt].activated);	if (rv) 	    return -1;    }    /*      * Adding a cert to the database (or slot)     */     if (certutil.commands[cmd_CreateAndAddCert].activated) { 	PR_Close(inFile);	PR_Close(outFile);	inFile = PR_Open(certfile, PR_RDONLY, 0);	if (!inFile) {	    PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",                       certfile, PR_GetError(), PR_GetOSError());	    return -1;	}    }    if (certutil.commands[cmd_CreateAndAddCert].activated ||         certutil.commands[cmd_AddCert].activated ||	 certutil.commands[cmd_AddEmailCert].activated) {	rv = AddCert(slot, certHandle, name, 	             certutil.options[opt_Trust].arg,	             inFile, 	             certutil.options[opt_ASCIIForIO].activated,	             certutil.commands[cmd_AddEmailCert].activated);	if (rv) 	    return -1;    }    if (certutil.commands[cmd_CreateAndAddCert].activated) {	PR_Close(inFile);	PR_Delete(certfile);	PR_Delete(certreqfile);    }    if ( certHandle ) {	CERT_ClosePermCertDB(certHandle);    }    return rv;  }