security/nss/cmd/certutil/certutil.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/certutil/certutil.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3549 @@
     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 +/*
     1.9 +** certutil.c
    1.10 +**
    1.11 +** utility for managing certificates and the cert database
    1.12 +**
    1.13 +*/
    1.14 +#include <stdio.h>
    1.15 +#include <string.h>
    1.16 +#include <stdlib.h>
    1.17 +
    1.18 +#if defined(WIN32)
    1.19 +#include "fcntl.h"
    1.20 +#include "io.h"
    1.21 +#endif
    1.22 +
    1.23 +#include "secutil.h"
    1.24 +
    1.25 +#if defined(XP_UNIX)
    1.26 +#include <unistd.h>
    1.27 +#endif
    1.28 +
    1.29 +#include "nspr.h"
    1.30 +#include "prtypes.h"
    1.31 +#include "prtime.h"
    1.32 +#include "prlong.h"
    1.33 +
    1.34 +#include "pk11func.h"
    1.35 +#include "secasn1.h"
    1.36 +#include "cert.h"
    1.37 +#include "cryptohi.h"
    1.38 +#include "secoid.h"
    1.39 +#include "certdb.h"
    1.40 +#include "nss.h"
    1.41 +#include "certutil.h"
    1.42 +
    1.43 +#define MIN_KEY_BITS		512
    1.44 +/* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */
    1.45 +#define MAX_KEY_BITS		8192
    1.46 +#define DEFAULT_KEY_BITS	1024
    1.47 +
    1.48 +#define GEN_BREAK(e) rv=e; break;
    1.49 +
    1.50 +char *progName;
    1.51 +
    1.52 +static CERTCertificateRequest *
    1.53 +GetCertRequest(const SECItem *reqDER)
    1.54 +{
    1.55 +    CERTCertificateRequest *certReq = NULL;
    1.56 +    CERTSignedData signedData;
    1.57 +    PLArenaPool *arena = NULL;
    1.58 +    SECStatus rv;
    1.59 +
    1.60 +    do {
    1.61 +	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    1.62 +	if (arena == NULL) {
    1.63 +	    GEN_BREAK (SECFailure);
    1.64 +	}
    1.65 +	
    1.66 +        certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc
    1.67 +		  (arena, sizeof(CERTCertificateRequest));
    1.68 +        if (!certReq) { 
    1.69 +	    GEN_BREAK(SECFailure);
    1.70 +	}
    1.71 +	certReq->arena = arena;
    1.72 +
    1.73 +	/* Since cert request is a signed data, must decode to get the inner
    1.74 +	   data
    1.75 +	 */
    1.76 +	PORT_Memset(&signedData, 0, sizeof(signedData));
    1.77 +	rv = SEC_ASN1DecodeItem(arena, &signedData, 
    1.78 +		SEC_ASN1_GET(CERT_SignedDataTemplate), reqDER);
    1.79 +	if (rv) {
    1.80 +	    break;
    1.81 +	}
    1.82 +	rv = SEC_ASN1DecodeItem(arena, certReq, 
    1.83 +		SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
    1.84 +	if (rv) {
    1.85 +	    break;
    1.86 +	}
    1.87 +   	rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, 
    1.88 +		&certReq->subjectPublicKeyInfo, NULL /* wincx */);
    1.89 +   } while (0);
    1.90 +
    1.91 +   if (rv) {
    1.92 +   	SECU_PrintError(progName, "bad certificate request\n");
    1.93 +   	if (arena) {
    1.94 +   	    PORT_FreeArena(arena, PR_FALSE);
    1.95 +   	}
    1.96 +   	certReq = NULL;
    1.97 +   }
    1.98 +
    1.99 +   return certReq;
   1.100 +}
   1.101 +
   1.102 +static SECStatus
   1.103 +AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, 
   1.104 +        const SECItem *certDER, PRBool emailcert, void *pwdata)
   1.105 +{
   1.106 +    CERTCertTrust *trust = NULL;
   1.107 +    CERTCertificate *cert = NULL;
   1.108 +    SECStatus rv;
   1.109 +
   1.110 +    do {
   1.111 +	/* Read in an ASCII cert and return a CERTCertificate */
   1.112 +	cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len);
   1.113 +	if (!cert) {
   1.114 +	    SECU_PrintError(progName, "could not decode certificate");
   1.115 +	    GEN_BREAK(SECFailure);
   1.116 +	}
   1.117 +
   1.118 +	/* Create a cert trust */
   1.119 +	trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
   1.120 +	if (!trust) {
   1.121 +	    SECU_PrintError(progName, "unable to allocate cert trust");
   1.122 +	    GEN_BREAK(SECFailure);
   1.123 +	}
   1.124 +
   1.125 +	rv = CERT_DecodeTrustString(trust, trusts);
   1.126 +	if (rv) {
   1.127 +	    SECU_PrintError(progName, "unable to decode trust string");
   1.128 +	    GEN_BREAK(SECFailure);
   1.129 +	}
   1.130 +
   1.131 +	rv =  PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
   1.132 +	if (rv != SECSuccess) {
   1.133 +	    /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have 
   1.134 +	     * been coded to take a password arg. */
   1.135 +	    if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
   1.136 +		rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   1.137 +		if (rv != SECSuccess) {
   1.138 +                    SECU_PrintError(progName, 
   1.139 +				"could not authenticate to token %s.",
   1.140 +				PK11_GetTokenName(slot));
   1.141 +		    GEN_BREAK(SECFailure);
   1.142 +		}
   1.143 +		rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, 
   1.144 +				     name, PR_FALSE);
   1.145 +	    }
   1.146 +	    if (rv != SECSuccess) {
   1.147 +		SECU_PrintError(progName, 
   1.148 +			"could not add certificate to token or database");
   1.149 +		GEN_BREAK(SECFailure);
   1.150 +	    }
   1.151 +	}
   1.152 +
   1.153 +	rv = CERT_ChangeCertTrust(handle, cert, trust);
   1.154 +	if (rv != SECSuccess) {
   1.155 +	    if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
   1.156 +		rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   1.157 +		if (rv != SECSuccess) {
   1.158 +                    SECU_PrintError(progName, 
   1.159 +				"could not authenticate to token %s.",
   1.160 +				PK11_GetTokenName(slot));
   1.161 +		    GEN_BREAK(SECFailure);
   1.162 +		}
   1.163 +		rv = CERT_ChangeCertTrust(handle, cert, trust);
   1.164 +	    }
   1.165 +	    if (rv != SECSuccess) {
   1.166 +		SECU_PrintError(progName, 
   1.167 +			"could not change trust on certificate");
   1.168 +		GEN_BREAK(SECFailure);
   1.169 +	    }
   1.170 +	}
   1.171 +
   1.172 +	if ( emailcert ) {
   1.173 +	    CERT_SaveSMimeProfile(cert, NULL, pwdata);
   1.174 +	}
   1.175 +
   1.176 +    } while (0);
   1.177 +
   1.178 +    CERT_DestroyCertificate (cert);
   1.179 +    PORT_Free(trust);
   1.180 +
   1.181 +    return rv;
   1.182 +}
   1.183 +
   1.184 +static SECStatus
   1.185 +CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
   1.186 +        SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, 
   1.187 +	const char *emailAddrs, const char *dnsNames,
   1.188 +        certutilExtnList extnList, const char *extGeneric,
   1.189 +        /*out*/ SECItem *result)
   1.190 +{
   1.191 +    CERTSubjectPublicKeyInfo *spki;
   1.192 +    CERTCertificateRequest *cr;
   1.193 +    SECItem *encoding;
   1.194 +    SECOidTag signAlgTag;
   1.195 +    SECStatus rv;
   1.196 +    PLArenaPool *arena;
   1.197 +    void *extHandle;
   1.198 +    SECItem signedReq = { siBuffer, NULL, 0 };
   1.199 +
   1.200 +    /* Create info about public key */
   1.201 +    spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
   1.202 +    if (!spki) {
   1.203 +	SECU_PrintError(progName, "unable to create subject public key");
   1.204 +	return SECFailure;
   1.205 +    }
   1.206 +    
   1.207 +    /* Generate certificate request */
   1.208 +    cr = CERT_CreateCertificateRequest(subject, spki, NULL);
   1.209 +    SECKEY_DestroySubjectPublicKeyInfo(spki);
   1.210 +    if (!cr) {
   1.211 +	SECU_PrintError(progName, "unable to make certificate request");
   1.212 +	return SECFailure;
   1.213 +    }
   1.214 +
   1.215 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.216 +    if ( !arena ) {
   1.217 +	SECU_PrintError(progName, "out of memory");
   1.218 +	return SECFailure;
   1.219 +    }
   1.220 +    
   1.221 +    extHandle = CERT_StartCertificateRequestAttributes(cr);
   1.222 +    if (extHandle == NULL) {
   1.223 +        PORT_FreeArena (arena, PR_FALSE);
   1.224 +	return SECFailure;
   1.225 +    }
   1.226 +    if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric)
   1.227 +                  != SECSuccess) {
   1.228 +        PORT_FreeArena (arena, PR_FALSE);
   1.229 +        return SECFailure;
   1.230 +    }
   1.231 +    CERT_FinishExtensions(extHandle);
   1.232 +    CERT_FinishCertificateRequestAttributes(cr);
   1.233 +
   1.234 +    /* Der encode the request */
   1.235 +    encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
   1.236 +                                  SEC_ASN1_GET(CERT_CertificateRequestTemplate));
   1.237 +    CERT_DestroyCertificateRequest(cr);
   1.238 +    if (encoding == NULL) {
   1.239 +	PORT_FreeArena (arena, PR_FALSE);
   1.240 +	SECU_PrintError(progName, "der encoding of request failed");
   1.241 +	return SECFailure;
   1.242 +    }
   1.243 +
   1.244 +    /* Sign the request */
   1.245 +    signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
   1.246 +    if (signAlgTag == SEC_OID_UNKNOWN) {
   1.247 +	PORT_FreeArena (arena, PR_FALSE);
   1.248 +	SECU_PrintError(progName, "unknown Key or Hash type");
   1.249 +	return SECFailure;
   1.250 +    }
   1.251 +
   1.252 +    rv = SEC_DerSignData(arena, &signedReq, encoding->data, encoding->len,
   1.253 +			  privk, signAlgTag);
   1.254 +    if (rv) {
   1.255 +	PORT_FreeArena (arena, PR_FALSE);
   1.256 +	SECU_PrintError(progName, "signing of data failed");
   1.257 +	return SECFailure;
   1.258 +    }
   1.259 +
   1.260 +    /* Encode request in specified format */
   1.261 +    if (ascii) {
   1.262 +	char *obuf;
   1.263 +	char *header, *name, *email, *org, *state, *country;
   1.264 +
   1.265 +	obuf = BTOA_ConvertItemToAscii(&signedReq);
   1.266 +	if (!obuf) {
   1.267 +	    goto oom;
   1.268 +	}
   1.269 +
   1.270 +	name = CERT_GetCommonName(subject);
   1.271 +	if (!name) {
   1.272 +	    name = PORT_Strdup("(not specified)");
   1.273 +	}
   1.274 +
   1.275 +	if (!phone)
   1.276 +	    phone = strdup("(not specified)");
   1.277 +
   1.278 +	email = CERT_GetCertEmailAddress(subject);
   1.279 +	if (!email)
   1.280 +	    email = PORT_Strdup("(not specified)");
   1.281 +
   1.282 +	org = CERT_GetOrgName(subject);
   1.283 +	if (!org)
   1.284 +	    org = PORT_Strdup("(not specified)");
   1.285 +
   1.286 +	state = CERT_GetStateName(subject);
   1.287 +	if (!state)
   1.288 +	    state = PORT_Strdup("(not specified)");
   1.289 +
   1.290 +	country = CERT_GetCountryName(subject);
   1.291 +	if (!country)
   1.292 +	    country = PORT_Strdup("(not specified)");
   1.293 +
   1.294 +	header = PR_smprintf(
   1.295 +	    "\nCertificate request generated by Netscape certutil\n"
   1.296 +	    "Phone: %s\n\n"
   1.297 +	    "Common Name: %s\n"
   1.298 +	    "Email: %s\n"
   1.299 +	    "Organization: %s\n"
   1.300 +	    "State: %s\n"
   1.301 +	    "Country: %s\n\n"
   1.302 +	    "%s\n",
   1.303 +	    phone, name, email, org, state, country, NS_CERTREQ_HEADER);
   1.304 +
   1.305 +	PORT_Free(name);
   1.306 +	PORT_Free(email);
   1.307 +	PORT_Free(org);
   1.308 +	PORT_Free(state);
   1.309 +	PORT_Free(country);
   1.310 +
   1.311 +	if (header) {
   1.312 +	    char * trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER);
   1.313 +	    if (trailer) {
   1.314 +		PRUint32 headerLen = PL_strlen(header);
   1.315 +		PRUint32 obufLen = PL_strlen(obuf);
   1.316 +		PRUint32 trailerLen = PL_strlen(trailer);
   1.317 +		SECITEM_AllocItem(NULL, result,
   1.318 +				  headerLen + obufLen + trailerLen);
   1.319 +		if (result->data) {
   1.320 +		    PORT_Memcpy(result->data, header, headerLen);
   1.321 +		    PORT_Memcpy(result->data + headerLen, obuf, obufLen);
   1.322 +		    PORT_Memcpy(result->data + headerLen + obufLen,
   1.323 +				trailer, trailerLen);
   1.324 +		}
   1.325 +		PR_smprintf_free(trailer);
   1.326 +	    }
   1.327 +	    PR_smprintf_free(header);
   1.328 +	}
   1.329 +    } else {
   1.330 +	(void) SECITEM_CopyItem(NULL, result, &signedReq);
   1.331 +    }
   1.332 +
   1.333 +    if (!result->data) {
   1.334 +oom:    SECU_PrintError(progName, "out of memory");
   1.335 +	PORT_SetError(SEC_ERROR_NO_MEMORY);
   1.336 +	rv = SECFailure;
   1.337 +    }
   1.338 +
   1.339 +    PORT_FreeArena (arena, PR_FALSE);
   1.340 +    return rv;
   1.341 +}
   1.342 +
   1.343 +static SECStatus 
   1.344 +ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot,
   1.345 +			char *name, char *trusts, void *pwdata)
   1.346 +{
   1.347 +    SECStatus rv;
   1.348 +    CERTCertificate *cert;
   1.349 +    CERTCertTrust *trust;
   1.350 +    
   1.351 +    cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
   1.352 +    if (!cert) {
   1.353 +	SECU_PrintError(progName, "could not find certificate named \"%s\"",
   1.354 +			name);
   1.355 +	return SECFailure;
   1.356 +    }
   1.357 +
   1.358 +    trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
   1.359 +    if (!trust) {
   1.360 +	SECU_PrintError(progName, "unable to allocate cert trust");
   1.361 +	return SECFailure;
   1.362 +    }
   1.363 +
   1.364 +    /* This function only decodes these characters: pPwcTCu, */
   1.365 +    rv = CERT_DecodeTrustString(trust, trusts);
   1.366 +    if (rv) {
   1.367 +	SECU_PrintError(progName, "unable to decode trust string");
   1.368 +	return SECFailure;
   1.369 +    }
   1.370 +
   1.371 +    /* CERT_ChangeCertTrust API does not have a way to pass in
   1.372 +     * a context, so NSS can't prompt for the password if it needs to.
   1.373 +     * check to see if the failure was token not logged in and 
   1.374 +     * log in if need be. */
   1.375 +    rv = CERT_ChangeCertTrust(handle, cert, trust);
   1.376 +    if (rv != SECSuccess) {
   1.377 +	if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
   1.378 +	    rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   1.379 +	    if (rv != SECSuccess) {
   1.380 +		SECU_PrintError(progName, "could not authenticate to token %s.",
   1.381 +                                PK11_GetTokenName(slot));
   1.382 +		return SECFailure;
   1.383 +	    }
   1.384 +	    rv = CERT_ChangeCertTrust(handle, cert, trust);
   1.385 +	}
   1.386 +	if (rv != SECSuccess) {
   1.387 +	    SECU_PrintError(progName, "unable to modify trust attributes");
   1.388 +	    return SECFailure;
   1.389 +	}
   1.390 +    }
   1.391 +    CERT_DestroyCertificate(cert);
   1.392 +
   1.393 +    return SECSuccess;
   1.394 +}
   1.395 +
   1.396 +static SECStatus
   1.397 +DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii)
   1.398 +{
   1.399 +    CERTCertificate *the_cert;
   1.400 +    CERTCertificateList *chain;
   1.401 +    int i, j;
   1.402 +    the_cert = SECU_FindCertByNicknameOrFilename(handle, name,
   1.403 +                                                 ascii, NULL);
   1.404 +    if (!the_cert) {
   1.405 +	SECU_PrintError(progName, "Could not find: %s\n", name);
   1.406 +	return SECFailure;
   1.407 +    }
   1.408 +    chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE);
   1.409 +    CERT_DestroyCertificate(the_cert);
   1.410 +    if (!chain) {
   1.411 +	SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
   1.412 +	return SECFailure;
   1.413 +    }
   1.414 +    for (i=chain->len-1; i>=0; i--) {
   1.415 +	CERTCertificate *c;
   1.416 +	c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
   1.417 +	for (j=i; j<chain->len-1; j++) printf("  ");
   1.418 +	printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
   1.419 +	CERT_DestroyCertificate(c);
   1.420 +    }
   1.421 +    CERT_DestroyCertificateList(chain);
   1.422 +    return SECSuccess;
   1.423 +}
   1.424 +
   1.425 +static SECStatus
   1.426 +outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
   1.427 +                      SECItem *extensionOID, PRFileDesc *outfile)
   1.428 +{
   1.429 +    SECItem data;
   1.430 +    PRInt32 numBytes;
   1.431 +    SECStatus rv = SECFailure;
   1.432 +    if (extensionOID) {
   1.433 +	int i;
   1.434 +	PRBool found = PR_FALSE;
   1.435 +	for (i=0; the_cert->extensions[i] != NULL; i++) {
   1.436 +	    CERTCertExtension *extension = the_cert->extensions[i];
   1.437 +	    if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) {
   1.438 +		found = PR_TRUE;
   1.439 +		numBytes = PR_Write(outfile, extension->value.data,
   1.440 +				    extension->value.len);
   1.441 +		rv = SECSuccess;
   1.442 +		if (numBytes != (PRInt32) extension->value.len) {
   1.443 +		    SECU_PrintSystemError(progName, "error writing extension");
   1.444 +		    rv = SECFailure;
   1.445 +		}
   1.446 +		rv = SECSuccess;
   1.447 +		break;
   1.448 +	    }
   1.449 +	}
   1.450 +	if (!found) {
   1.451 +	    SECU_PrintSystemError(progName, "extension not found");
   1.452 +	    rv = SECFailure;
   1.453 +	}
   1.454 +    } else {
   1.455 +	data.data = the_cert->derCert.data;
   1.456 +	data.len = the_cert->derCert.len;
   1.457 +	if (ascii) {
   1.458 +	    PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, 
   1.459 +		    BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
   1.460 +	    rv = SECSuccess;
   1.461 +	} else if (raw) {
   1.462 +	    numBytes = PR_Write(outfile, data.data, data.len);
   1.463 +	    rv = SECSuccess;
   1.464 +	    if (numBytes != (PRInt32) data.len) {
   1.465 +		SECU_PrintSystemError(progName, "error writing raw cert");
   1.466 +		rv = SECFailure;
   1.467 +	    }
   1.468 +	} else {
   1.469 +	    rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
   1.470 +	    if (rv != SECSuccess) {
   1.471 +		SECU_PrintError(progName, "problem printing certificate");
   1.472 +	    }
   1.473 +	}
   1.474 +    }
   1.475 +    return rv;
   1.476 +}
   1.477 +
   1.478 +static SECStatus
   1.479 +listCerts(CERTCertDBHandle *handle, char *name, char *email,
   1.480 +	  PK11SlotInfo *slot, PRBool raw, PRBool ascii,
   1.481 +	  SECItem *extensionOID,
   1.482 +	  PRFileDesc *outfile, void *pwarg)
   1.483 +{
   1.484 +    SECStatus rv = SECFailure;
   1.485 +    CERTCertList *certs;
   1.486 +    CERTCertListNode *node;
   1.487 +
   1.488 +    /* List certs on a non-internal slot. */
   1.489 +    if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
   1.490 +        SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, pwarg);
   1.491 +        if (newrv != SECSuccess) {
   1.492 +            SECU_PrintError(progName, "could not authenticate to token %s.",
   1.493 +                            PK11_GetTokenName(slot));
   1.494 +            return SECFailure;
   1.495 +        }
   1.496 +    }
   1.497 +    if (name) {
   1.498 +	CERTCertificate *the_cert =
   1.499 +            SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL);
   1.500 +        if (!the_cert) {
   1.501 +            SECU_PrintError(progName, "Could not find cert: %s\n", name);
   1.502 +            return SECFailure;
   1.503 +        }
   1.504 +	/* Here, we have one cert with the desired nickname or email 
   1.505 +	 * address.  Now, we will attempt to get a list of ALL certs 
   1.506 +	 * with the same subject name as the cert we have.  That list 
   1.507 +	 * should contain, at a minimum, the one cert we have already found.
   1.508 +	 * If the list of certs is empty (NULL), the libraries have failed.
   1.509 +	 */
   1.510 +	certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject,
   1.511 +		PR_Now(), PR_FALSE);
   1.512 +	CERT_DestroyCertificate(the_cert);
   1.513 +	if (!certs) {
   1.514 +	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.515 +	    SECU_PrintError(progName, "problem printing certificates");
   1.516 +	    return SECFailure;
   1.517 +	}
   1.518 +	for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
   1.519 +						node = CERT_LIST_NEXT(node)) {
   1.520 +	    rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
   1.521 +                                       outfile);
   1.522 +	    if (rv != SECSuccess) {
   1.523 +		break;
   1.524 +	    }
   1.525 +	}
   1.526 +    } else if (email) {
   1.527 +	certs = PK11_FindCertsFromEmailAddress(email, NULL);
   1.528 +	if (!certs) {
   1.529 +	    SECU_PrintError(progName, 
   1.530 +			"Could not find certificates for email address: %s\n", 
   1.531 +			email);
   1.532 +	    return SECFailure;
   1.533 +	}
   1.534 +	for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
   1.535 +						node = CERT_LIST_NEXT(node)) {
   1.536 +	    rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
   1.537 +                                       outfile);
   1.538 +	    if (rv != SECSuccess) {
   1.539 +		break;
   1.540 +	    }
   1.541 +	}
   1.542 +    } else {
   1.543 +	certs = PK11_ListCertsInSlot(slot);
   1.544 +	if (certs) {
   1.545 +	    for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
   1.546 +						node = CERT_LIST_NEXT(node)) {
   1.547 +		SECU_PrintCertNickname(node,stdout);
   1.548 +	    }
   1.549 +	    rv = SECSuccess;
   1.550 +	}
   1.551 +    }
   1.552 +    if (certs) {
   1.553 +        CERT_DestroyCertList(certs);
   1.554 +    }
   1.555 +    if (rv) {
   1.556 +	SECU_PrintError(progName, "problem printing certificate nicknames");
   1.557 +	return SECFailure;
   1.558 +    }
   1.559 +
   1.560 +    return SECSuccess;	/* not rv ?? */
   1.561 +}
   1.562 +
   1.563 +static SECStatus
   1.564 +ListCerts(CERTCertDBHandle *handle, char *nickname, char *email, 
   1.565 +          PK11SlotInfo *slot, PRBool raw, PRBool ascii,
   1.566 +	  SECItem *extensionOID,
   1.567 +	  PRFileDesc *outfile, secuPWData *pwdata)
   1.568 +{
   1.569 +    SECStatus rv;
   1.570 +
   1.571 +    if (!ascii && !raw && !nickname && !email) {
   1.572 +        PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
   1.573 +                   "Certificate Nickname", "Trust Attributes", "",
   1.574 +                   "SSL,S/MIME,JAR/XPI");
   1.575 +    }
   1.576 +    if (slot == NULL) {
   1.577 +	CERTCertList *list;
   1.578 +	CERTCertListNode *node;
   1.579 +
   1.580 +	list = PK11_ListCerts(PK11CertListAll, pwdata);
   1.581 +	for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
   1.582 +	     node = CERT_LIST_NEXT(node)) {
   1.583 +	    SECU_PrintCertNickname(node, stdout);
   1.584 +	}
   1.585 +	CERT_DestroyCertList(list);
   1.586 +	return SECSuccess;
   1.587 +    } 
   1.588 +    rv = listCerts(handle, nickname, email, slot, raw, ascii,
   1.589 +                   extensionOID, outfile, pwdata);
   1.590 +    return rv;
   1.591 +}
   1.592 +
   1.593 +static SECStatus 
   1.594 +DeleteCert(CERTCertDBHandle *handle, char *name)
   1.595 +{
   1.596 +    SECStatus rv;
   1.597 +    CERTCertificate *cert;
   1.598 +
   1.599 +    cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
   1.600 +    if (!cert) {
   1.601 +	SECU_PrintError(progName, "could not find certificate named \"%s\"",
   1.602 +			name);
   1.603 +	return SECFailure;
   1.604 +    }
   1.605 +
   1.606 +    rv = SEC_DeletePermCertificate(cert);
   1.607 +    CERT_DestroyCertificate(cert);
   1.608 +    if (rv) {
   1.609 +	SECU_PrintError(progName, "unable to delete certificate");
   1.610 +    }
   1.611 +    return rv;
   1.612 +}
   1.613 +
   1.614 +static SECStatus
   1.615 +ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
   1.616 +             char *certUsage, PRBool checkSig, PRBool logit,
   1.617 +             PRBool ascii, secuPWData *pwdata)
   1.618 +{
   1.619 +    SECStatus rv;
   1.620 +    CERTCertificate *cert = NULL;
   1.621 +    PRTime timeBoundary;
   1.622 +    SECCertificateUsage usage;
   1.623 +    CERTVerifyLog reallog;
   1.624 +    CERTVerifyLog *log = NULL;
   1.625 +
   1.626 +    if (!certUsage) {
   1.627 +	    PORT_SetError (SEC_ERROR_INVALID_ARGS);
   1.628 +	    return (SECFailure);
   1.629 +    }
   1.630 +    
   1.631 +    switch (*certUsage) {
   1.632 +	case 'O':
   1.633 +	    usage = certificateUsageStatusResponder;
   1.634 +	    break;
   1.635 +	case 'L':
   1.636 +	    usage = certificateUsageSSLCA;
   1.637 +	    break;
   1.638 +	case 'A':
   1.639 +	    usage = certificateUsageAnyCA;
   1.640 +	    break;
   1.641 +	case 'Y':
   1.642 +	    usage = certificateUsageVerifyCA;
   1.643 +	    break;
   1.644 +	case 'C':
   1.645 +	    usage = certificateUsageSSLClient;
   1.646 +	    break;
   1.647 +	case 'V':
   1.648 +	    usage = certificateUsageSSLServer;
   1.649 +	    break;
   1.650 +	case 'S':
   1.651 +	    usage = certificateUsageEmailSigner;
   1.652 +	    break;
   1.653 +	case 'R':
   1.654 +	    usage = certificateUsageEmailRecipient;
   1.655 +	    break;
   1.656 +	case 'J':
   1.657 +	    usage = certificateUsageObjectSigner;
   1.658 +	    break;
   1.659 +	default:
   1.660 +	    PORT_SetError (SEC_ERROR_INVALID_ARGS);
   1.661 +	    return (SECFailure);
   1.662 +    }
   1.663 +    do {
   1.664 +	cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii,
   1.665 +                                                 NULL);
   1.666 +	if (!cert) {
   1.667 +	    SECU_PrintError(progName, "could not find certificate named \"%s\"",
   1.668 +			    name);
   1.669 +	    GEN_BREAK (SECFailure)
   1.670 +	}
   1.671 +
   1.672 +	if (date != NULL) {
   1.673 +	    rv = DER_AsciiToTime(&timeBoundary, date);
   1.674 +	    if (rv) {
   1.675 +		SECU_PrintError(progName, "invalid input date");
   1.676 +		GEN_BREAK (SECFailure)
   1.677 +	    }
   1.678 +	} else {
   1.679 +	    timeBoundary = PR_Now();
   1.680 +	}
   1.681 +
   1.682 +	if ( logit ) {
   1.683 +	    log = &reallog;
   1.684 +	    
   1.685 +	    log->count = 0;
   1.686 +	    log->head = NULL;
   1.687 +	    log->tail = NULL;
   1.688 +	    log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.689 +	    if ( log->arena == NULL ) {
   1.690 +		SECU_PrintError(progName, "out of memory");
   1.691 +		GEN_BREAK (SECFailure)
   1.692 +	    }
   1.693 +	}
   1.694 + 
   1.695 +	rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
   1.696 +			     timeBoundary, pwdata, log, &usage);
   1.697 +	if ( log ) {
   1.698 +	    if ( log->head == NULL ) {
   1.699 +		fprintf(stdout, "%s: certificate is valid\n", progName);
   1.700 +		GEN_BREAK (SECSuccess)
   1.701 +	    } else {
   1.702 +		char *name;
   1.703 +		CERTVerifyLogNode *node;
   1.704 +		
   1.705 +		node = log->head;
   1.706 +		while ( node ) {
   1.707 +		    if ( node->cert->nickname != NULL ) {
   1.708 +			name = node->cert->nickname;
   1.709 +		    } else {
   1.710 +			name = node->cert->subjectName;
   1.711 +		    }
   1.712 +		    fprintf(stderr, "%s : %s\n", name, 
   1.713 +		    	SECU_Strerror(node->error));
   1.714 +		    CERT_DestroyCertificate(node->cert);
   1.715 +		    node = node->next;
   1.716 +		}
   1.717 +	    }
   1.718 +	} else {
   1.719 +	    if (rv != SECSuccess) {
   1.720 +		PRErrorCode perr = PORT_GetError();
   1.721 +		fprintf(stdout, "%s: certificate is invalid: %s\n",
   1.722 +			progName, SECU_Strerror(perr));
   1.723 +		GEN_BREAK (SECFailure)
   1.724 +	    }
   1.725 +	    fprintf(stdout, "%s: certificate is valid\n", progName);
   1.726 +	    GEN_BREAK (SECSuccess)
   1.727 +	}
   1.728 +    } while (0);
   1.729 +
   1.730 +    if (cert) {
   1.731 +        CERT_DestroyCertificate(cert);
   1.732 +    }
   1.733 +
   1.734 +    return (rv);
   1.735 +}
   1.736 +
   1.737 +static PRBool
   1.738 +ItemIsPrintableASCII(const SECItem * item)
   1.739 +{
   1.740 +    unsigned char *src = item->data;
   1.741 +    unsigned int   len = item->len;
   1.742 +    while (len-- > 0) {
   1.743 +        unsigned char uc = *src++;
   1.744 +	if (uc < 0x20 || uc > 0x7e) 
   1.745 +	    return PR_FALSE;
   1.746 +    }
   1.747 +    return PR_TRUE;
   1.748 +}
   1.749 +
   1.750 +/* Caller ensures that dst is at least item->len*2+1 bytes long */
   1.751 +static void
   1.752 +SECItemToHex(const SECItem * item, char * dst)
   1.753 +{
   1.754 +    if (dst && item && item->data) {
   1.755 +	unsigned char * src = item->data;
   1.756 +	unsigned int    len = item->len;
   1.757 +	for (; len > 0; --len, dst += 2) {
   1.758 +	    sprintf(dst, "%02x", *src++);
   1.759 +	}
   1.760 +	*dst = '\0';
   1.761 +    }
   1.762 +}
   1.763 +
   1.764 +static const char * const keyTypeName[] = {
   1.765 +  "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec" };
   1.766 +
   1.767 +#define MAX_CKA_ID_BIN_LEN 20
   1.768 +#define MAX_CKA_ID_STR_LEN 40
   1.769 +
   1.770 +/* print key number, key ID (in hex or ASCII), key label (nickname) */
   1.771 +static SECStatus
   1.772 +PrintKey(PRFileDesc *out, const char *nickName, int count, 
   1.773 +         SECKEYPrivateKey *key, void *pwarg)
   1.774 +{
   1.775 +    SECItem * ckaID;
   1.776 +    char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
   1.777 +
   1.778 +    pwarg = NULL;
   1.779 +    ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key);
   1.780 +    if (!ckaID) {
   1.781 +	strcpy(ckaIDbuf, "(no CKA_ID)");
   1.782 +    } else if (ItemIsPrintableASCII(ckaID)) {
   1.783 +	int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
   1.784 +	ckaIDbuf[0] = '"';
   1.785 +	memcpy(ckaIDbuf + 1, ckaID->data, len);
   1.786 +	ckaIDbuf[1 + len] = '"';
   1.787 +	ckaIDbuf[2 + len] = '\0';
   1.788 +    } else {
   1.789 +    	/* print ckaid in hex */
   1.790 +	SECItem idItem = *ckaID;
   1.791 +	if (idItem.len > MAX_CKA_ID_BIN_LEN)
   1.792 +	    idItem.len = MAX_CKA_ID_BIN_LEN;
   1.793 +        SECItemToHex(&idItem, ckaIDbuf);
   1.794 +    }
   1.795 +
   1.796 +    PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count, 
   1.797 +               keyTypeName[key->keyType], ckaIDbuf, nickName);
   1.798 +    SECITEM_ZfreeItem(ckaID, PR_TRUE);
   1.799 +
   1.800 +    return SECSuccess;
   1.801 +}
   1.802 +
   1.803 +/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
   1.804 +static SECStatus
   1.805 +ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType, 
   1.806 +               void *pwarg)
   1.807 +{
   1.808 +    SECKEYPrivateKeyList *list;
   1.809 +    SECKEYPrivateKeyListNode *node;
   1.810 +    int count = 0;
   1.811 +
   1.812 +    if (PK11_NeedLogin(slot)) {
   1.813 +        SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
   1.814 +        if (rv != SECSuccess) {
   1.815 +            SECU_PrintError(progName, "could not authenticate to token %s.",
   1.816 +                            PK11_GetTokenName(slot));
   1.817 +            return SECFailure;
   1.818 +        }
   1.819 +    }
   1.820 +
   1.821 +    if (nickName && nickName[0]) 
   1.822 +	list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
   1.823 +    else
   1.824 +	list = PK11_ListPrivateKeysInSlot(slot);
   1.825 +    if (list == NULL) {
   1.826 +	SECU_PrintError(progName, "problem listing keys");
   1.827 +	return SECFailure;
   1.828 +    }
   1.829 +    for (node=PRIVKEY_LIST_HEAD(list); 
   1.830 +             !PRIVKEY_LIST_END(node,list);
   1.831 +	 node=PRIVKEY_LIST_NEXT(node)) {
   1.832 +	char * keyName;
   1.833 +	static const char orphan[] = { "(orphan)" };
   1.834 +
   1.835 +	if (keyType != nullKey && keyType != node->key->keyType)
   1.836 +	    continue;
   1.837 +        keyName = PK11_GetPrivateKeyNickname(node->key);
   1.838 +	if (!keyName || !keyName[0]) {
   1.839 +	    /* Try extra hard to find nicknames for keys that lack them. */
   1.840 +	    CERTCertificate * cert;
   1.841 +	    PORT_Free((void *)keyName);
   1.842 +	    keyName = NULL;
   1.843 +	    cert = PK11_GetCertFromPrivateKey(node->key);
   1.844 +	    if (cert) {
   1.845 +		if (cert->nickname && cert->nickname[0]) {
   1.846 +		    keyName = PORT_Strdup(cert->nickname);
   1.847 +		} else if (cert->emailAddr && cert->emailAddr[0]) {
   1.848 +		    keyName = PORT_Strdup(cert->emailAddr);
   1.849 +		}
   1.850 +		CERT_DestroyCertificate(cert);
   1.851 +	    }
   1.852 +	}
   1.853 +	if (nickName) {
   1.854 +	    if (!keyName || PL_strcmp(keyName,nickName)) {
   1.855 +		/* PKCS#11 module returned unwanted keys */
   1.856 +	        PORT_Free((void *)keyName);
   1.857 +		continue;
   1.858 +	    }
   1.859 +	}
   1.860 +	if (!keyName)
   1.861 +	    keyName = (char *)orphan;
   1.862 +
   1.863 +	PrintKey(PR_STDOUT, keyName, count, node->key, pwarg);
   1.864 +
   1.865 +	if (keyName != (char *)orphan)
   1.866 +	    PORT_Free((void *)keyName);
   1.867 +	count++;
   1.868 +    }
   1.869 +    SECKEY_DestroyPrivateKeyList(list);
   1.870 +
   1.871 +    if (count == 0) {
   1.872 +	PR_fprintf(PR_STDOUT, "%s: no keys found\n", progName);
   1.873 +	return SECFailure;
   1.874 +    }
   1.875 +    return SECSuccess;
   1.876 +}
   1.877 +
   1.878 +/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
   1.879 +static SECStatus
   1.880 +ListKeys(PK11SlotInfo *slot, const char *nickName, int index, 
   1.881 +         KeyType keyType, PRBool dopriv, secuPWData *pwdata)
   1.882 +{
   1.883 +    SECStatus rv = SECFailure;
   1.884 +    static const char fmt[] = \
   1.885 +    	"%s: Checking token \"%.33s\" in slot \"%.65s\"\n";
   1.886 +
   1.887 +    if (slot == NULL) {
   1.888 +	PK11SlotList *list;
   1.889 +	PK11SlotListElement *le;
   1.890 +
   1.891 +	list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,pwdata);
   1.892 +	if (list) {
   1.893 +	    for (le = list->head; le; le = le->next) {
   1.894 +		PR_fprintf(PR_STDOUT, fmt, progName, 
   1.895 +			   PK11_GetTokenName(le->slot), 
   1.896 +			   PK11_GetSlotName(le->slot));
   1.897 +		rv &= ListKeysInSlot(le->slot,nickName,keyType,pwdata);
   1.898 +	    }
   1.899 +	    PK11_FreeSlotList(list);
   1.900 +	}
   1.901 +    } else {
   1.902 +	PR_fprintf(PR_STDOUT, fmt, progName, PK11_GetTokenName(slot), 
   1.903 +	           PK11_GetSlotName(slot));
   1.904 +	rv = ListKeysInSlot(slot,nickName,keyType,pwdata);
   1.905 +    }
   1.906 +    return rv;
   1.907 +}
   1.908 +
   1.909 +static SECStatus
   1.910 +DeleteKey(char *nickname, secuPWData *pwdata)
   1.911 +{
   1.912 +    SECStatus rv;
   1.913 +    CERTCertificate *cert;
   1.914 +    PK11SlotInfo *slot;
   1.915 +
   1.916 +    slot = PK11_GetInternalKeySlot();
   1.917 +    if (PK11_NeedLogin(slot)) {
   1.918 +        SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   1.919 +        if (rv != SECSuccess) {
   1.920 +            SECU_PrintError(progName, "could not authenticate to token %s.",
   1.921 +                            PK11_GetTokenName(slot));
   1.922 +            return SECFailure;
   1.923 +        }
   1.924 +    }
   1.925 +    cert = PK11_FindCertFromNickname(nickname, pwdata);
   1.926 +    if (!cert) {
   1.927 +	PK11_FreeSlot(slot);
   1.928 +	return SECFailure;
   1.929 +    }
   1.930 +    rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
   1.931 +    if (rv != SECSuccess) {
   1.932 +	SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
   1.933 +    }
   1.934 +    CERT_DestroyCertificate(cert);
   1.935 +    PK11_FreeSlot(slot);
   1.936 +    return rv;
   1.937 +}
   1.938 +
   1.939 +
   1.940 +/*
   1.941 + *  L i s t M o d u l e s
   1.942 + *
   1.943 + *  Print a list of the PKCS11 modules that are
   1.944 + *  available. This is useful for smartcard people to
   1.945 + *  make sure they have the drivers loaded.
   1.946 + *
   1.947 + */
   1.948 +static SECStatus
   1.949 +ListModules(void)
   1.950 +{
   1.951 +    PK11SlotList *list;
   1.952 +    PK11SlotListElement *le;
   1.953 +
   1.954 +    /* get them all! */
   1.955 +    list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL);
   1.956 +    if (list == NULL) return SECFailure;
   1.957 +
   1.958 +    /* look at each slot*/
   1.959 +    for (le = list->head ; le; le = le->next) {
   1.960 +      printf ("\n");
   1.961 +      printf ("    slot: %s\n", PK11_GetSlotName(le->slot));
   1.962 +      printf ("   token: %s\n", PK11_GetTokenName(le->slot));
   1.963 +    }
   1.964 +    PK11_FreeSlotList(list);
   1.965 +
   1.966 +    return SECSuccess;
   1.967 +}
   1.968 +
   1.969 +static void 
   1.970 +PrintSyntax(char *progName)
   1.971 +{
   1.972 +#define FPS fprintf(stderr, 
   1.973 +    FPS "Type %s -H for more detailed descriptions\n", progName);
   1.974 +    FPS "Usage:  %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName);
   1.975 +    FPS "Usage:  %s -T [-d certdir] [-P dbprefix] [-h token-name]\n"
   1.976 +	"\t\t [-f pwfile] [-0 SSO-password]\n", progName);
   1.977 +    FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", 
   1.978 +    	progName);
   1.979 +    FPS "\t%s -B -i batch-file\n", progName);
   1.980 +    FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
   1.981 +	"\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
   1.982 +        "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n"
   1.983 +        "\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n"
   1.984 +        "\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n"
   1.985 +        "\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n"
   1.986 +        "\t\t [-8 dns-names] [-a]\n",
   1.987 +	progName);
   1.988 +    FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
   1.989 +    FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", 
   1.990 +	progName);
   1.991 +    FPS "\t%s -F -n nickname [-d certdir] [-P dbprefix]\n", 
   1.992 +	progName);
   1.993 +    FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n" 
   1.994 +	"\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
   1.995 +    FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
   1.996 +	"\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
   1.997 +#ifndef NSS_DISABLE_ECC
   1.998 +    FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
   1.999 +	"\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
  1.1000 +    FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n", 
  1.1001 +	progName);
  1.1002 +#else
  1.1003 +    FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n", 
  1.1004 +	progName);
  1.1005 +#endif /* NSS_DISABLE_ECC */
  1.1006 +    FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
  1.1007 +    FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
  1.1008 +	progName);
  1.1009 +    FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
  1.1010 +    FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
  1.1011 +    FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
  1.1012 +    FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
  1.1013 +	progName);
  1.1014 +    FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
  1.1015 +    FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
  1.1016 +    FPS "\t%s -L [-n cert-name] [--email email-address] [-X] [-r] [-a]\n",
  1.1017 +	progName);
  1.1018 +    FPS "\t\t [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
  1.1019 +    FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
  1.1020 +	progName);
  1.1021 +    FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName);
  1.1022 +    FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
  1.1023 +	"\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile] [-g key-size]\n",
  1.1024 +	progName);
  1.1025 +    FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
  1.1026 +	"\t\t[-X] [-d certdir] [-P dbprefix]\n",
  1.1027 +	progName);
  1.1028 +    FPS "Usage:  %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
  1.1029 +	progName);
  1.1030 +    FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x]  -t trustargs\n"
  1.1031 +	"\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
  1.1032 +        "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
  1.1033 +	"\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n"
  1.1034 +        "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
  1.1035 +        "\t\t [-8 DNS-names]\n"
  1.1036 +        "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
  1.1037 +        "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
  1.1038 +	"\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
  1.1039 +    FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
  1.1040 +    exit(1);
  1.1041 +}
  1.1042 +
  1.1043 +enum usage_level {
  1.1044 +    usage_all = 0, usage_selected = 1
  1.1045 +};
  1.1046 +
  1.1047 +static void luCommonDetailsAE();
  1.1048 +
  1.1049 +static void luA(enum usage_level ul, const char *command)
  1.1050 +{
  1.1051 +    int is_my_command = (command && 0 == strcmp(command, "A"));
  1.1052 +    if (ul == usage_all || !command || is_my_command)
  1.1053 +    FPS "%-15s Add a certificate to the database        (create if needed)\n",
  1.1054 +        "-A");
  1.1055 +    if (ul == usage_selected && !is_my_command)
  1.1056 +        return;
  1.1057 +    if (ul == usage_all) {
  1.1058 +    FPS "%-20s\n", "   All options under -E apply");
  1.1059 +    }
  1.1060 +    else {
  1.1061 +        luCommonDetailsAE();
  1.1062 +    }
  1.1063 +}
  1.1064 +
  1.1065 +static void luB(enum usage_level ul, const char *command)
  1.1066 +{
  1.1067 +    int is_my_command = (command && 0 == strcmp(command, "B"));
  1.1068 +    if (ul == usage_all || !command || is_my_command)
  1.1069 +    FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
  1.1070 +    if (ul == usage_selected && !is_my_command)
  1.1071 +        return;
  1.1072 +    FPS "%-20s Specify the batch file\n", "   -i batch-file");
  1.1073 +}
  1.1074 +
  1.1075 +static void luE(enum usage_level ul, const char *command)
  1.1076 +{
  1.1077 +    int is_my_command = (command && 0 == strcmp(command, "E"));
  1.1078 +    if (ul == usage_all || !command || is_my_command)
  1.1079 +    FPS "%-15s Add an Email certificate to the database (create if needed)\n",
  1.1080 +        "-E");
  1.1081 +    if (ul == usage_selected && !is_my_command)
  1.1082 +        return;
  1.1083 +    luCommonDetailsAE();
  1.1084 +}
  1.1085 +
  1.1086 +static void luCommonDetailsAE()
  1.1087 +{
  1.1088 +    FPS "%-20s Specify the nickname of the certificate to add\n",
  1.1089 +        "   -n cert-name");
  1.1090 +    FPS "%-20s Set the certificate trust attributes:\n",
  1.1091 +        "   -t trustargs");
  1.1092 +    FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
  1.1093 +    FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
  1.1094 +    FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
  1.1095 +    FPS "%-25s P \t trusted peer\n", "");
  1.1096 +    FPS "%-25s c \t valid CA\n", "");
  1.1097 +    FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
  1.1098 +    FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
  1.1099 +    FPS "%-25s u \t user cert\n", "");
  1.1100 +    FPS "%-25s w \t send warning\n", "");
  1.1101 +    FPS "%-25s g \t make step-up cert\n", "");
  1.1102 +    FPS "%-20s Specify the password file\n",
  1.1103 +        "   -f pwfile");
  1.1104 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1105 +        "   -d certdir");
  1.1106 +    FPS "%-20s Cert & Key database prefix\n",
  1.1107 +        "   -P dbprefix");
  1.1108 +    FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
  1.1109 +        "   -a");
  1.1110 +    FPS "%-20s Specify the certificate file (default is stdin)\n",
  1.1111 +        "   -i input");
  1.1112 +    FPS "\n");
  1.1113 +}
  1.1114 +
  1.1115 +static void luC(enum usage_level ul, const char *command)
  1.1116 +{
  1.1117 +    int is_my_command = (command && 0 == strcmp(command, "C"));
  1.1118 +    if (ul == usage_all || !command || is_my_command)
  1.1119 +    FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
  1.1120 +        "-C");
  1.1121 +    if (ul == usage_selected && !is_my_command)
  1.1122 +        return;
  1.1123 +    FPS "%-20s The nickname of the issuer cert\n",
  1.1124 +        "   -c issuer-name");
  1.1125 +    FPS "%-20s The BINARY certificate request file\n",
  1.1126 +        "   -i cert-request ");
  1.1127 +    FPS "%-20s Output binary cert to this file (default is stdout)\n",
  1.1128 +        "   -o output-cert");
  1.1129 +    FPS "%-20s Self sign\n",
  1.1130 +        "   -x");
  1.1131 +    FPS "%-20s Cert serial number\n",
  1.1132 +        "   -m serial-number");
  1.1133 +    FPS "%-20s Time Warp\n",
  1.1134 +        "   -w warp-months");
  1.1135 +    FPS "%-20s Months valid (default is 3)\n",
  1.1136 +        "   -v months-valid");
  1.1137 +    FPS "%-20s Specify the password file\n",
  1.1138 +        "   -f pwfile");
  1.1139 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1140 +        "   -d certdir");
  1.1141 +    FPS "%-20s Cert & Key database prefix\n",
  1.1142 +        "   -P dbprefix");
  1.1143 +    FPS "%-20s \n"
  1.1144 +              "%-20s Create key usage extension. Possible keywords:\n"
  1.1145 +              "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
  1.1146 +              "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
  1.1147 +              "%-20s \"crlSigning\", \"critical\"\n",
  1.1148 +        "   -1 | --keyUsage keyword,keyword,...", "", "", "", "");
  1.1149 +    FPS "%-20s Create basic constraint extension\n",
  1.1150 +        "   -2 ");
  1.1151 +    FPS "%-20s Create authority key ID extension\n",
  1.1152 +        "   -3 ");
  1.1153 +    FPS "%-20s Create crl distribution point extension\n",
  1.1154 +        "   -4 ");
  1.1155 +    FPS "%-20s \n"
  1.1156 +              "%-20s Create netscape cert type extension. Possible keywords:\n"
  1.1157 +              "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
  1.1158 +              "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
  1.1159 +        "   -5 | --nsCertType keyword,keyword,... ", "", "", "");
  1.1160 +    FPS "%-20s \n"
  1.1161 +              "%-20s Create extended key usage extension. Possible keywords:\n"
  1.1162 +              "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
  1.1163 +              "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
  1.1164 +              "%-20s \"stepUp\", \"msTrustListSign\", \"critical\"\n",
  1.1165 +        "   -6 | --extKeyUsage keyword,keyword,...", "", "", "", "");
  1.1166 +    FPS "%-20s Create an email subject alt name extension\n",
  1.1167 +        "   -7 emailAddrs");
  1.1168 +    FPS "%-20s Create an dns subject alt name extension\n",
  1.1169 +        "   -8 dnsNames");
  1.1170 +    FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
  1.1171 +        "   -a");
  1.1172 +    FPS "\n");
  1.1173 +}
  1.1174 +
  1.1175 +static void luG(enum usage_level ul, const char *command)
  1.1176 +{
  1.1177 +    int is_my_command = (command && 0 == strcmp(command, "G"));
  1.1178 +    if (ul == usage_all || !command || is_my_command)
  1.1179 +    FPS "%-15s Generate a new key pair\n",
  1.1180 +        "-G");
  1.1181 +    if (ul == usage_selected && !is_my_command)
  1.1182 +        return;
  1.1183 +    FPS "%-20s Name of token in which to generate key (default is internal)\n",
  1.1184 +        "   -h token-name");
  1.1185 +#ifndef NSS_DISABLE_ECC
  1.1186 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
  1.1187 +        "   -k key-type");
  1.1188 +    FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
  1.1189 +        "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1.1190 +#else
  1.1191 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
  1.1192 +        "   -k key-type");
  1.1193 +    FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n",
  1.1194 +        "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1.1195 +#endif /* NSS_DISABLE_ECC */
  1.1196 +    FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
  1.1197 +        "   -y exp");
  1.1198 +    FPS "%-20s Specify the password file\n",
  1.1199 +        "   -f password-file");
  1.1200 +    FPS "%-20s Specify the noise file to be used\n",
  1.1201 +        "   -z noisefile");
  1.1202 +    FPS "%-20s read PQG value from pqgfile (dsa only)\n",
  1.1203 +        "   -q pqgfile");
  1.1204 +#ifndef NSS_DISABLE_ECC
  1.1205 +    FPS "%-20s Elliptic curve name (ec only)\n",
  1.1206 +        "   -q curve-name");
  1.1207 +    FPS "%-20s One of nistp256, nistp384, nistp521\n", "");
  1.1208 +#ifdef NSS_ECC_MORE_THAN_SUITE_B
  1.1209 +    FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
  1.1210 +    FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
  1.1211 +    FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
  1.1212 +    FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
  1.1213 +    FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
  1.1214 +    FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
  1.1215 +    FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
  1.1216 +    FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
  1.1217 +    FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
  1.1218 +    FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
  1.1219 +    FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
  1.1220 +    FPS "%-20s c2tnb191v2, c2tnb191v3,  \n", "");
  1.1221 +    FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
  1.1222 +    FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
  1.1223 +    FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
  1.1224 +    FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
  1.1225 +    FPS "%-20s sect131r1, sect131r2\n", "");
  1.1226 +#endif /* NSS_ECC_MORE_THAN_SUITE_B */
  1.1227 +#endif
  1.1228 +    FPS "%-20s Key database directory (default is ~/.netscape)\n",
  1.1229 +        "   -d keydir");
  1.1230 +    FPS "%-20s Cert & Key database prefix\n",
  1.1231 +        "   -P dbprefix");
  1.1232 +    FPS "%-20s\n"
  1.1233 +        "%-20s PKCS #11 key Attributes.\n",
  1.1234 +        "   --keyAttrFlags attrflags", "");
  1.1235 +    FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
  1.1236 +    FPS "%-20s selected from the following list of choices:\n", "");
  1.1237 +    FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
  1.1238 +    FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
  1.1239 +    FPS "%-20s\n",
  1.1240 +        "   --keyOpFlagsOn opflags");
  1.1241 +    FPS "%-20s\n"
  1.1242 +        "%-20s PKCS #11 key Operation Flags.\n",
  1.1243 +        "   --keyOpFlagsOff opflags", "");
  1.1244 +    FPS "%-20s Comma separated list of one or more of the following:\n", "");
  1.1245 +    FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
  1.1246 +    FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
  1.1247 +    FPS "\n");
  1.1248 +}
  1.1249 +
  1.1250 +static void luD(enum usage_level ul, const char *command)
  1.1251 +{
  1.1252 +    int is_my_command = (command && 0 == strcmp(command, "D"));
  1.1253 +    if (ul == usage_all || !command || is_my_command)
  1.1254 +    FPS "%-15s Delete a certificate from the database\n",
  1.1255 +        "-D");
  1.1256 +    if (ul == usage_selected && !is_my_command)
  1.1257 +        return;
  1.1258 +    FPS "%-20s The nickname of the cert to delete\n",
  1.1259 +        "   -n cert-name");
  1.1260 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1261 +        "   -d certdir");
  1.1262 +    FPS "%-20s Cert & Key database prefix\n",
  1.1263 +        "   -P dbprefix");
  1.1264 +    FPS "\n");
  1.1265 +
  1.1266 +}
  1.1267 +
  1.1268 +static void luF(enum usage_level ul, const char *command)
  1.1269 +{
  1.1270 +    int is_my_command = (command && 0 == strcmp(command, "F"));
  1.1271 +    if (ul == usage_all || !command || is_my_command)
  1.1272 +    FPS "%-15s Delete a key from the database\n",
  1.1273 +        "-F");
  1.1274 +    if (ul == usage_selected && !is_my_command)
  1.1275 +        return;
  1.1276 +    FPS "%-20s The nickname of the key to delete\n",
  1.1277 +        "   -n cert-name");
  1.1278 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1279 +        "   -d certdir");
  1.1280 +    FPS "%-20s Cert & Key database prefix\n",
  1.1281 +        "   -P dbprefix");
  1.1282 +    FPS "\n");
  1.1283 +
  1.1284 +}
  1.1285 +
  1.1286 +static void luU(enum usage_level ul, const char *command)
  1.1287 +{
  1.1288 +    int is_my_command = (command && 0 == strcmp(command, "U"));
  1.1289 +    if (ul == usage_all || !command || is_my_command)
  1.1290 +    FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
  1.1291 +        "-U");
  1.1292 +    if (ul == usage_selected && !is_my_command)
  1.1293 +        return;
  1.1294 +    FPS "%-20s Module database directory (default is '~/.netscape')\n",
  1.1295 +        "   -d moddir");
  1.1296 +    FPS "%-20s Cert & Key database prefix\n",
  1.1297 +        "   -P dbprefix");
  1.1298 +    FPS "%-20s force the database to open R/W\n",
  1.1299 +        "   -X");
  1.1300 +    FPS "\n");
  1.1301 +
  1.1302 +}
  1.1303 +
  1.1304 +static void luK(enum usage_level ul, const char *command)
  1.1305 +{
  1.1306 +    int is_my_command = (command && 0 == strcmp(command, "K"));
  1.1307 +    if (ul == usage_all || !command || is_my_command)
  1.1308 +    FPS "%-15s List all private keys\n",
  1.1309 +        "-K");
  1.1310 +    if (ul == usage_selected && !is_my_command)
  1.1311 +        return;
  1.1312 +    FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
  1.1313 +        "   -h token-name ");
  1.1314 +
  1.1315 +    FPS "%-20s Key type (\"all\" (default), \"dsa\","
  1.1316 +#ifndef NSS_DISABLE_ECC
  1.1317 +                                                    " \"ec\","
  1.1318 +#endif
  1.1319 +                                                    " \"rsa\")\n",
  1.1320 +        "   -k key-type");
  1.1321 +    FPS "%-20s The nickname of the key or associated certificate\n",
  1.1322 +        "   -n name");
  1.1323 +    FPS "%-20s Specify the password file\n",
  1.1324 +        "   -f password-file");
  1.1325 +    FPS "%-20s Key database directory (default is ~/.netscape)\n",
  1.1326 +        "   -d keydir");
  1.1327 +    FPS "%-20s Cert & Key database prefix\n",
  1.1328 +        "   -P dbprefix");
  1.1329 +    FPS "%-20s force the database to open R/W\n",
  1.1330 +        "   -X");
  1.1331 +    FPS "\n");
  1.1332 +}
  1.1333 +
  1.1334 +static void luL(enum usage_level ul, const char *command)
  1.1335 +{
  1.1336 +    int is_my_command = (command && 0 == strcmp(command, "L"));
  1.1337 +    if (ul == usage_all || !command || is_my_command)
  1.1338 +    FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
  1.1339 +        "-L");
  1.1340 +    if (ul == usage_selected && !is_my_command)
  1.1341 +        return;
  1.1342 +    FPS "%-20s Pretty print named cert (list all if unspecified)\n",
  1.1343 +        "   -n cert-name");
  1.1344 +    FPS "%-20s \n"
  1.1345 +              "%-20s Pretty print cert with email address (list all if unspecified)\n",
  1.1346 +        "   --email email-address", "");
  1.1347 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1348 +        "   -d certdir");
  1.1349 +    FPS "%-20s Cert & Key database prefix\n",
  1.1350 +        "   -P dbprefix");
  1.1351 +    FPS "%-20s force the database to open R/W\n",
  1.1352 +        "   -X");
  1.1353 +    FPS "%-20s For single cert, print binary DER encoding\n",
  1.1354 +        "   -r");
  1.1355 +    FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
  1.1356 +        "   -a");
  1.1357 +    FPS "%-20s \n"
  1.1358 +              "%-20s For single cert, print binary DER encoding of extension OID\n",
  1.1359 +        "   --dump-ext-val OID", "");
  1.1360 +    FPS "\n");
  1.1361 +}
  1.1362 +
  1.1363 +static void luM(enum usage_level ul, const char *command)
  1.1364 +{
  1.1365 +    int is_my_command = (command && 0 == strcmp(command, "M"));
  1.1366 +    if (ul == usage_all || !command || is_my_command)
  1.1367 +    FPS "%-15s Modify trust attributes of certificate\n",
  1.1368 +        "-M");
  1.1369 +    if (ul == usage_selected && !is_my_command)
  1.1370 +        return;
  1.1371 +    FPS "%-20s The nickname of the cert to modify\n",
  1.1372 +        "   -n cert-name");
  1.1373 +    FPS "%-20s Set the certificate trust attributes (see -A above)\n",
  1.1374 +        "   -t trustargs");
  1.1375 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1376 +        "   -d certdir");
  1.1377 +    FPS "%-20s Cert & Key database prefix\n",
  1.1378 +        "   -P dbprefix");
  1.1379 +    FPS "\n");
  1.1380 +}
  1.1381 +
  1.1382 +static void luN(enum usage_level ul, const char *command)
  1.1383 +{
  1.1384 +    int is_my_command = (command && 0 == strcmp(command, "N"));
  1.1385 +    if (ul == usage_all || !command || is_my_command)
  1.1386 +    FPS "%-15s Create a new certificate database\n",
  1.1387 +        "-N");
  1.1388 +    if (ul == usage_selected && !is_my_command)
  1.1389 +        return;
  1.1390 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1391 +        "   -d certdir");
  1.1392 +    FPS "%-20s Cert & Key database prefix\n",
  1.1393 +        "   -P dbprefix");
  1.1394 +    FPS "%-20s use empty password when creating a new database\n",
  1.1395 +        "   --empty-password");
  1.1396 +    FPS "\n");
  1.1397 +}
  1.1398 +
  1.1399 +static void luT(enum usage_level ul, const char *command)
  1.1400 +{
  1.1401 +    int is_my_command = (command && 0 == strcmp(command, "T"));
  1.1402 +    if (ul == usage_all || !command || is_my_command)
  1.1403 +    FPS "%-15s Reset the Key database or token\n",
  1.1404 +        "-T");
  1.1405 +    if (ul == usage_selected && !is_my_command)
  1.1406 +        return;
  1.1407 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1408 +        "   -d certdir");
  1.1409 +    FPS "%-20s Cert & Key database prefix\n",
  1.1410 +        "   -P dbprefix");
  1.1411 +    FPS "%-20s Token to reset (default is internal)\n",
  1.1412 +        "   -h token-name");
  1.1413 +    FPS "%-20s Set token's Site Security Officer password\n",
  1.1414 +        "   -0 SSO-password");
  1.1415 +    FPS "\n");
  1.1416 +}
  1.1417 +
  1.1418 +static void luO(enum usage_level ul, const char *command)
  1.1419 +{
  1.1420 +    int is_my_command = (command && 0 == strcmp(command, "O"));
  1.1421 +    if (ul == usage_all || !command || is_my_command)
  1.1422 +    FPS "%-15s Print the chain of a certificate\n",
  1.1423 +        "-O");
  1.1424 +    if (ul == usage_selected && !is_my_command)
  1.1425 +        return;
  1.1426 +    FPS "%-20s The nickname of the cert to modify\n",
  1.1427 +        "   -n cert-name");
  1.1428 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1429 +        "   -d certdir");
  1.1430 +    FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
  1.1431 +        "   -a");
  1.1432 +    FPS "%-20s Cert & Key database prefix\n",
  1.1433 +        "   -P dbprefix");
  1.1434 +    FPS "%-20s force the database to open R/W\n",
  1.1435 +        "   -X");
  1.1436 +    FPS "\n");
  1.1437 +}
  1.1438 +
  1.1439 +static void luR(enum usage_level ul, const char *command)
  1.1440 +{
  1.1441 +    int is_my_command = (command && 0 == strcmp(command, "R"));
  1.1442 +    if (ul == usage_all || !command || is_my_command)
  1.1443 +    FPS "%-15s Generate a certificate request (stdout)\n",
  1.1444 +        "-R");
  1.1445 +    if (ul == usage_selected && !is_my_command)
  1.1446 +        return;
  1.1447 +    FPS "%-20s Specify the subject name (using RFC1485)\n",
  1.1448 +        "   -s subject");
  1.1449 +    FPS "%-20s Output the cert request to this file\n",
  1.1450 +        "   -o output-req");
  1.1451 +#ifndef NSS_DISABLE_ECC
  1.1452 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
  1.1453 +#else
  1.1454 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
  1.1455 +#endif /* NSS_DISABLE_ECC */
  1.1456 +        "   -k key-type-or-id");
  1.1457 +    FPS "%-20s or nickname of the cert key to use \n",
  1.1458 +        "");
  1.1459 +    FPS "%-20s Name of token in which to generate key (default is internal)\n",
  1.1460 +        "   -h token-name");
  1.1461 +    FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
  1.1462 +        "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1.1463 +    FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
  1.1464 +        "   -q pqgfile");
  1.1465 +#ifndef NSS_DISABLE_ECC
  1.1466 +    FPS "%-20s Elliptic curve name (ec only)\n",
  1.1467 +        "   -q curve-name");
  1.1468 +    FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
  1.1469 +        "");
  1.1470 +#endif /* NSS_DISABLE_ECC */
  1.1471 +    FPS "%-20s Specify the password file\n",
  1.1472 +        "   -f pwfile");
  1.1473 +    FPS "%-20s Key database directory (default is ~/.netscape)\n",
  1.1474 +        "   -d keydir");
  1.1475 +    FPS "%-20s Cert & Key database prefix\n",
  1.1476 +        "   -P dbprefix");
  1.1477 +    FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
  1.1478 +        "   -p phone");
  1.1479 +    FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
  1.1480 +        "   -a");
  1.1481 +    FPS "%-20s \n",
  1.1482 +        "   See -S for available extension options");
  1.1483 +    FPS "%-20s \n",
  1.1484 +        "   See -G for available key flag options");
  1.1485 +    FPS "\n");
  1.1486 +}
  1.1487 +
  1.1488 +static void luV(enum usage_level ul, const char *command)
  1.1489 +{
  1.1490 +    int is_my_command = (command && 0 == strcmp(command, "V"));
  1.1491 +    if (ul == usage_all || !command || is_my_command)
  1.1492 +    FPS "%-15s Validate a certificate\n",
  1.1493 +        "-V");
  1.1494 +    if (ul == usage_selected && !is_my_command)
  1.1495 +        return;
  1.1496 +    FPS "%-20s The nickname of the cert to Validate\n",
  1.1497 +        "   -n cert-name");
  1.1498 +    FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
  1.1499 +        "   -b time");
  1.1500 +    FPS "%-20s Check certificate signature \n",
  1.1501 +        "   -e ");   
  1.1502 +    FPS "%-20s Specify certificate usage:\n", "   -u certusage");
  1.1503 +    FPS "%-25s C \t SSL Client\n", "");
  1.1504 +    FPS "%-25s V \t SSL Server\n", "");
  1.1505 +    FPS "%-25s L \t SSL CA\n", "");
  1.1506 +    FPS "%-25s A \t Any CA\n", "");
  1.1507 +    FPS "%-25s Y \t Verify CA\n", "");
  1.1508 +    FPS "%-25s S \t Email signer\n", "");
  1.1509 +    FPS "%-25s R \t Email Recipient\n", "");   
  1.1510 +    FPS "%-25s O \t OCSP status responder\n", "");   
  1.1511 +    FPS "%-25s J \t Object signer\n", "");   
  1.1512 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1513 +        "   -d certdir");
  1.1514 +    FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
  1.1515 +        "   -a");
  1.1516 +    FPS "%-20s Cert & Key database prefix\n",
  1.1517 +        "   -P dbprefix");
  1.1518 +    FPS "%-20s force the database to open R/W\n",
  1.1519 +        "   -X");
  1.1520 +    FPS "\n");
  1.1521 +}
  1.1522 +
  1.1523 +static void luW(enum usage_level ul, const char *command)
  1.1524 +{
  1.1525 +    int is_my_command = (command && 0 == strcmp(command, "W"));
  1.1526 +    if (ul == usage_all || !command || is_my_command)
  1.1527 +    FPS "%-15s Change the key database password\n",
  1.1528 +        "-W");
  1.1529 +    if (ul == usage_selected && !is_my_command)
  1.1530 +        return;
  1.1531 +    FPS "%-20s cert and key database directory\n",
  1.1532 +        "   -d certdir");
  1.1533 +    FPS "%-20s Specify a file with the current password\n",
  1.1534 +        "   -f pwfile");
  1.1535 +    FPS "%-20s Specify a file with the new password in two lines\n",
  1.1536 +        "   -@ newpwfile");
  1.1537 +    FPS "\n");
  1.1538 +}
  1.1539 +
  1.1540 +static void luUpgradeMerge(enum usage_level ul, const char *command)
  1.1541 +{
  1.1542 +    int is_my_command = (command && 0 == strcmp(command, "upgrade-merge"));
  1.1543 +    if (ul == usage_all || !command || is_my_command)
  1.1544 +    FPS "%-15s Upgrade an old database and merge it into a new one\n",
  1.1545 +        "--upgrade-merge");
  1.1546 +    if (ul == usage_selected && !is_my_command)
  1.1547 +        return;
  1.1548 +    FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
  1.1549 +        "   -d certdir");
  1.1550 +    FPS "%-20s Cert & Key database prefix of the target database\n",
  1.1551 +        "   -P dbprefix");
  1.1552 +    FPS "%-20s Specify the password file for the target database\n",
  1.1553 +        "   -f pwfile");
  1.1554 +    FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
  1.1555 +        "   --source-dir certdir", "");
  1.1556 +    FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
  1.1557 +        "   --source-prefix dbprefix", "");
  1.1558 +    FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
  1.1559 +        "   --upgrade-id uniqueID", "");
  1.1560 +    FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
  1.1561 +        "   --upgrade-token-name name", "");
  1.1562 +    FPS "%-20s Specify the password file for the upgrade database\n",
  1.1563 +        "   -@ pwfile");
  1.1564 +    FPS "\n");
  1.1565 +}
  1.1566 +
  1.1567 +static void luMerge(enum usage_level ul, const char *command)
  1.1568 +{
  1.1569 +    int is_my_command = (command && 0 == strcmp(command, "merge"));
  1.1570 +    if (ul == usage_all || !command || is_my_command)
  1.1571 +    FPS "%-15s Merge source database into the target database\n",
  1.1572 +        "--merge");
  1.1573 +    if (ul == usage_selected && !is_my_command)
  1.1574 +        return;
  1.1575 +    FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
  1.1576 +        "   -d certdir");
  1.1577 +    FPS "%-20s Cert & Key database prefix of the target database\n",
  1.1578 +        "   -P dbprefix");
  1.1579 +    FPS "%-20s Specify the password file for the target database\n",
  1.1580 +        "   -f pwfile");
  1.1581 +    FPS "%-20s \n%-20s Cert database directory of the source database\n",
  1.1582 +        "   --source-dir certdir", "");
  1.1583 +    FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
  1.1584 +        "   --source-prefix dbprefix", "");
  1.1585 +    FPS "%-20s Specify the password file for the source database\n",
  1.1586 +        "   -@ pwfile");
  1.1587 +    FPS "\n");
  1.1588 +}
  1.1589 +
  1.1590 +static void luS(enum usage_level ul, const char *command)
  1.1591 +{
  1.1592 +    int is_my_command = (command && 0 == strcmp(command, "S"));
  1.1593 +    if (ul == usage_all || !command || is_my_command)
  1.1594 +    FPS "%-15s Make a certificate and add to database\n",
  1.1595 +        "-S");
  1.1596 +    if (ul == usage_selected && !is_my_command)
  1.1597 +        return;
  1.1598 +    FPS "%-20s Specify the nickname of the cert\n",
  1.1599 +        "   -n key-name");
  1.1600 +    FPS "%-20s Specify the subject name (using RFC1485)\n",
  1.1601 +        "   -s subject");
  1.1602 +    FPS "%-20s The nickname of the issuer cert\n",
  1.1603 +        "   -c issuer-name");
  1.1604 +    FPS "%-20s Set the certificate trust attributes (see -A above)\n",
  1.1605 +        "   -t trustargs");
  1.1606 +#ifndef NSS_DISABLE_ECC
  1.1607 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
  1.1608 +#else
  1.1609 +    FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
  1.1610 +#endif /* NSS_DISABLE_ECC */
  1.1611 +        "   -k key-type-or-id");
  1.1612 +    FPS "%-20s Name of token in which to generate key (default is internal)\n",
  1.1613 +        "   -h token-name");
  1.1614 +    FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
  1.1615 +        "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1.1616 +    FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
  1.1617 +        "   -q pqgfile");
  1.1618 +#ifndef NSS_DISABLE_ECC
  1.1619 +    FPS "%-20s Elliptic curve name (ec only)\n",
  1.1620 +        "   -q curve-name");
  1.1621 +    FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
  1.1622 +        "");
  1.1623 +#endif /* NSS_DISABLE_ECC */
  1.1624 +    FPS "%-20s Self sign\n",
  1.1625 +        "   -x");
  1.1626 +    FPS "%-20s Cert serial number\n",
  1.1627 +        "   -m serial-number");
  1.1628 +    FPS "%-20s Time Warp\n",
  1.1629 +        "   -w warp-months");
  1.1630 +    FPS "%-20s Months valid (default is 3)\n",
  1.1631 +        "   -v months-valid");
  1.1632 +    FPS "%-20s Specify the password file\n",
  1.1633 +        "   -f pwfile");
  1.1634 +    FPS "%-20s Cert database directory (default is ~/.netscape)\n",
  1.1635 +        "   -d certdir");
  1.1636 +    FPS "%-20s Cert & Key database prefix\n",
  1.1637 +        "   -P dbprefix");
  1.1638 +    FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
  1.1639 +        "   -p phone");
  1.1640 +    FPS "%-20s Create key usage extension\n",
  1.1641 +        "   -1 ");
  1.1642 +    FPS "%-20s Create basic constraint extension\n",
  1.1643 +        "   -2 ");
  1.1644 +    FPS "%-20s Create authority key ID extension\n",
  1.1645 +        "   -3 ");
  1.1646 +    FPS "%-20s Create crl distribution point extension\n",
  1.1647 +        "   -4 ");
  1.1648 +    FPS "%-20s Create netscape cert type extension\n",
  1.1649 +        "   -5 ");
  1.1650 +    FPS "%-20s Create extended key usage extension\n",
  1.1651 +        "   -6 ");
  1.1652 +    FPS "%-20s Create an email subject alt name extension\n",
  1.1653 +        "   -7 emailAddrs ");
  1.1654 +    FPS "%-20s Create a DNS subject alt name extension\n",
  1.1655 +        "   -8 DNS-names");
  1.1656 +    FPS "%-20s Create an Authority Information Access extension\n",
  1.1657 +        "   --extAIA ");
  1.1658 +    FPS "%-20s Create a Subject Information Access extension\n",
  1.1659 +        "   --extSIA ");
  1.1660 +    FPS "%-20s Create a Certificate Policies extension\n",
  1.1661 +        "   --extCP ");
  1.1662 +    FPS "%-20s Create a Policy Mappings extension\n",
  1.1663 +        "   --extPM ");
  1.1664 +    FPS "%-20s Create a Policy Constraints extension\n",
  1.1665 +        "   --extPC ");
  1.1666 +    FPS "%-20s Create an Inhibit Any Policy extension\n",
  1.1667 +        "   --extIA ");
  1.1668 +    FPS "%-20s Create a subject key ID extension\n",
  1.1669 +        "   --extSKID ");
  1.1670 +    FPS "%-20s \n",
  1.1671 +        "   See -G for available key flag options");
  1.1672 +    FPS "%-20s Create a name constraints extension\n",
  1.1673 +        "   --extNC ");
  1.1674 +    FPS "%-20s \n"
  1.1675 +        "%-20s Create a Subject Alt Name extension with one or multiple names\n",
  1.1676 +	"   --extSAN type:name[,type:name]...", "");
  1.1677 +    FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
  1.1678 +    FPS "%-20s         other, registerid, rfc822, uri, x400, x400addr\n", "");
  1.1679 +    FPS "%-20s \n"
  1.1680 +        "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
  1.1681 +	"%-20s by loading their encodings from external files.\n",
  1.1682 +        "   --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
  1.1683 +    FPS "%-20s - OID (example): 1.2.3.4\n", "");
  1.1684 +    FPS "%-20s - critical-flag: critical or not-critical\n", "");
  1.1685 +    FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
  1.1686 +    FPS "\n");
  1.1687 +}
  1.1688 +
  1.1689 +static void LongUsage(char *progName, enum usage_level ul, const char *command)
  1.1690 +{
  1.1691 +    luA(ul, command);
  1.1692 +    luB(ul, command);
  1.1693 +    luE(ul, command);
  1.1694 +    luC(ul, command);
  1.1695 +    luG(ul, command);
  1.1696 +    luD(ul, command);
  1.1697 +    luF(ul, command);
  1.1698 +    luU(ul, command);
  1.1699 +    luK(ul, command);
  1.1700 +    luL(ul, command);
  1.1701 +    luM(ul, command);
  1.1702 +    luN(ul, command);
  1.1703 +    luT(ul, command);
  1.1704 +    luO(ul, command);
  1.1705 +    luR(ul, command);
  1.1706 +    luV(ul, command);
  1.1707 +    luW(ul, command);
  1.1708 +    luUpgradeMerge(ul, command);
  1.1709 +    luMerge(ul, command);
  1.1710 +    luS(ul, command);
  1.1711 +#undef FPS
  1.1712 +}
  1.1713 +
  1.1714 +static void
  1.1715 +Usage(char *progName)
  1.1716 +{
  1.1717 +    PR_fprintf(PR_STDERR,
  1.1718 +        "%s - Utility to manipulate NSS certificate databases\n\n"
  1.1719 +        "Usage:  %s <command> -d <database-directory> <options>\n\n"
  1.1720 +        "Valid commands:\n", progName, progName);
  1.1721 +    LongUsage(progName, usage_selected, NULL);
  1.1722 +    PR_fprintf(PR_STDERR, "\n"
  1.1723 +        "%s -H <command> : Print available options for the given command\n"
  1.1724 +        "%s -H : Print complete help output of all commands and options\n"
  1.1725 +        "%s --syntax : Print a short summary of all commands and options\n",
  1.1726 +        progName, progName, progName);
  1.1727 +    exit(1);
  1.1728 +}
  1.1729 +
  1.1730 +static CERTCertificate *
  1.1731 +MakeV1Cert(	CERTCertDBHandle *	handle, 
  1.1732 +		CERTCertificateRequest *req,
  1.1733 +	    	char *			issuerNickName, 
  1.1734 +		PRBool 			selfsign, 
  1.1735 +		unsigned int 		serialNumber,
  1.1736 +		int 			warpmonths,
  1.1737 +                int                     validityMonths)
  1.1738 +{
  1.1739 +    CERTCertificate *issuerCert = NULL;
  1.1740 +    CERTValidity *validity;
  1.1741 +    CERTCertificate *cert = NULL;
  1.1742 +    PRExplodedTime printableTime;
  1.1743 +    PRTime now, after;
  1.1744 +
  1.1745 +    if ( !selfsign ) {
  1.1746 +	issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
  1.1747 +	if (!issuerCert) {
  1.1748 +	    SECU_PrintError(progName, "could not find certificate named \"%s\"",
  1.1749 +			    issuerNickName);
  1.1750 +	    return NULL;
  1.1751 +	}
  1.1752 +    }
  1.1753 +
  1.1754 +    now = PR_Now();
  1.1755 +    PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  1.1756 +    if ( warpmonths ) {
  1.1757 +	printableTime.tm_month += warpmonths;
  1.1758 +	now = PR_ImplodeTime (&printableTime);
  1.1759 +	PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  1.1760 +    }
  1.1761 +    printableTime.tm_month += validityMonths;
  1.1762 +    after = PR_ImplodeTime (&printableTime);
  1.1763 +
  1.1764 +    /* note that the time is now in micro-second unit */
  1.1765 +    validity = CERT_CreateValidity (now, after);
  1.1766 +    if (validity) {
  1.1767 +        cert = CERT_CreateCertificate(serialNumber, 
  1.1768 +				      (selfsign ? &req->subject 
  1.1769 +				                : &issuerCert->subject), 
  1.1770 +	                              validity, req);
  1.1771 +    
  1.1772 +        CERT_DestroyValidity(validity);
  1.1773 +    }
  1.1774 +    if ( issuerCert ) {
  1.1775 +	CERT_DestroyCertificate (issuerCert);
  1.1776 +    }
  1.1777 +    
  1.1778 +    return(cert);
  1.1779 +}
  1.1780 +
  1.1781 +static SECStatus
  1.1782 +SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, 
  1.1783 +         SECOidTag hashAlgTag,
  1.1784 +         SECKEYPrivateKey *privKey, char *issuerNickName,
  1.1785 +         int certVersion, void *pwarg)
  1.1786 +{
  1.1787 +    SECItem der;
  1.1788 +    SECKEYPrivateKey *caPrivateKey = NULL;    
  1.1789 +    SECStatus rv;
  1.1790 +    PLArenaPool *arena;
  1.1791 +    SECOidTag algID;
  1.1792 +    void *dummy;
  1.1793 +
  1.1794 +    if( !selfsign ) {
  1.1795 +      CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
  1.1796 +      if( (CERTCertificate *)NULL == issuer ) {
  1.1797 +        SECU_PrintError(progName, "unable to find issuer with nickname %s", 
  1.1798 +	                issuerNickName);
  1.1799 +        return SECFailure;
  1.1800 +      }
  1.1801 +
  1.1802 +      privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
  1.1803 +      CERT_DestroyCertificate(issuer);
  1.1804 +      if (caPrivateKey == NULL) {
  1.1805 +	SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
  1.1806 +	return SECFailure;
  1.1807 +      }
  1.1808 +    }
  1.1809 +	
  1.1810 +    arena = cert->arena;
  1.1811 +
  1.1812 +    algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag);
  1.1813 +    if (algID == SEC_OID_UNKNOWN) {
  1.1814 +	fprintf(stderr, "Unknown key or hash type for issuer.");
  1.1815 +	rv = SECFailure;
  1.1816 +	goto done;
  1.1817 +    }
  1.1818 +
  1.1819 +    rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
  1.1820 +    if (rv != SECSuccess) {
  1.1821 +	fprintf(stderr, "Could not set signature algorithm id.");
  1.1822 +	goto done;
  1.1823 +    }
  1.1824 +
  1.1825 +    switch(certVersion) {
  1.1826 +      case (SEC_CERTIFICATE_VERSION_1):
  1.1827 +        /* The initial version for x509 certificates is version one
  1.1828 +         * and this default value must be an implicit DER encoding. */
  1.1829 +        cert->version.data = NULL;
  1.1830 +        cert->version.len = 0;
  1.1831 +        break;
  1.1832 +      case (SEC_CERTIFICATE_VERSION_2):
  1.1833 +      case (SEC_CERTIFICATE_VERSION_3):
  1.1834 +      case 3: /* unspecified format (would be version 4 certificate). */
  1.1835 +        *(cert->version.data) = certVersion;
  1.1836 +        cert->version.len = 1;
  1.1837 +        break;
  1.1838 +      default:
  1.1839 +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.1840 +        return SECFailure;
  1.1841 +    }
  1.1842 +
  1.1843 +    der.len = 0;
  1.1844 +    der.data = NULL;
  1.1845 +    dummy = SEC_ASN1EncodeItem (arena, &der, cert,
  1.1846 +			 	SEC_ASN1_GET(CERT_CertificateTemplate));
  1.1847 +    if (!dummy) {
  1.1848 +	fprintf (stderr, "Could not encode certificate.\n");
  1.1849 +	rv = SECFailure;
  1.1850 +	goto done;
  1.1851 +    }
  1.1852 +
  1.1853 +    rv = SEC_DerSignData(arena, &cert->derCert, der.data, der.len, privKey, algID);
  1.1854 +    if (rv != SECSuccess) {
  1.1855 +	fprintf (stderr, "Could not sign encoded certificate data.\n");
  1.1856 +	/* result allocated out of the arena, it will be freed
  1.1857 +	 * when the arena is freed */
  1.1858 +	goto done;
  1.1859 +    }
  1.1860 +done:
  1.1861 +    if (caPrivateKey) {
  1.1862 +	SECKEY_DestroyPrivateKey(caPrivateKey);
  1.1863 +    }
  1.1864 +    return rv;
  1.1865 +}
  1.1866 +
  1.1867 +static SECStatus
  1.1868 +CreateCert(
  1.1869 +	CERTCertDBHandle *handle, 
  1.1870 +	PK11SlotInfo *slot,
  1.1871 +	char *  issuerNickName, 
  1.1872 +	const SECItem * certReqDER,
  1.1873 +	SECKEYPrivateKey **selfsignprivkey,
  1.1874 +	void 	*pwarg,
  1.1875 +	SECOidTag hashAlgTag,
  1.1876 +	unsigned int serialNumber, 
  1.1877 +	int     warpmonths,
  1.1878 +	int     validityMonths,
  1.1879 +	const char *emailAddrs,
  1.1880 +	const char *dnsNames,
  1.1881 +	PRBool ascii,
  1.1882 +	PRBool  selfsign,
  1.1883 +	certutilExtnList extnList,
  1.1884 +	const char *extGeneric,
  1.1885 +        int certVersion,
  1.1886 +	SECItem * certDER)
  1.1887 +{
  1.1888 +    void *	extHandle;
  1.1889 +    CERTCertificate *subjectCert 	= NULL;
  1.1890 +    CERTCertificateRequest *certReq	= NULL;
  1.1891 +    SECStatus 	rv 			= SECSuccess;
  1.1892 +    CERTCertExtension **CRexts;
  1.1893 +
  1.1894 +    do {
  1.1895 +	/* Create a certrequest object from the input cert request der */
  1.1896 +	certReq = GetCertRequest(certReqDER);
  1.1897 +	if (certReq == NULL) {
  1.1898 +	    GEN_BREAK (SECFailure)
  1.1899 +	}
  1.1900 +
  1.1901 +	subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign,
  1.1902 +				  serialNumber, warpmonths, validityMonths);
  1.1903 +	if (subjectCert == NULL) {
  1.1904 +	    GEN_BREAK (SECFailure)
  1.1905 +	}
  1.1906 +        
  1.1907 +        
  1.1908 +	extHandle = CERT_StartCertExtensions (subjectCert);
  1.1909 +	if (extHandle == NULL) {
  1.1910 +	    GEN_BREAK (SECFailure)
  1.1911 +	}
  1.1912 +        
  1.1913 +        rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
  1.1914 +        if (rv != SECSuccess) {
  1.1915 +	    GEN_BREAK (SECFailure)
  1.1916 +	}
  1.1917 +        
  1.1918 +        if (certReq->attributes != NULL &&
  1.1919 +	    certReq->attributes[0] != NULL &&
  1.1920 +	    certReq->attributes[0]->attrType.data != NULL &&
  1.1921 +	    certReq->attributes[0]->attrType.len   > 0    &&
  1.1922 +            SECOID_FindOIDTag(&certReq->attributes[0]->attrType)
  1.1923 +                == SEC_OID_PKCS9_EXTENSION_REQUEST) {
  1.1924 +            rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
  1.1925 +            if (rv != SECSuccess)
  1.1926 +                break;
  1.1927 +            rv = CERT_MergeExtensions(extHandle, CRexts);
  1.1928 +            if (rv != SECSuccess)
  1.1929 +                break;
  1.1930 +        }
  1.1931 +
  1.1932 +	CERT_FinishExtensions(extHandle);
  1.1933 +
  1.1934 +	/* self-signing a cert request, find the private key */
  1.1935 +	if (selfsign && *selfsignprivkey == NULL) {
  1.1936 +	    *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg);
  1.1937 +	    if (!*selfsignprivkey) {
  1.1938 +		fprintf(stderr, "Failed to locate private key.\n");
  1.1939 +		rv = SECFailure;
  1.1940 +		break;
  1.1941 +	    }
  1.1942 +	}
  1.1943 +
  1.1944 +	rv = SignCert(handle, subjectCert, selfsign, hashAlgTag,
  1.1945 +		      *selfsignprivkey, issuerNickName,
  1.1946 +                      certVersion, pwarg);
  1.1947 +	if (rv != SECSuccess)
  1.1948 +	    break;
  1.1949 +
  1.1950 +	rv = SECFailure;
  1.1951 +	if (ascii) {
  1.1952 +	    char * asciiDER = BTOA_DataToAscii(subjectCert->derCert.data,
  1.1953 +					       subjectCert->derCert.len);
  1.1954 +	    if (asciiDER) {
  1.1955 +	        char * wrapped = PR_smprintf("%s\n%s\n%s\n",
  1.1956 +					     NS_CERT_HEADER,
  1.1957 +					     asciiDER,
  1.1958 +					     NS_CERT_TRAILER);
  1.1959 +	        if (wrapped) {
  1.1960 +		    PRUint32 wrappedLen = PL_strlen(wrapped);
  1.1961 +		    if (SECITEM_AllocItem(NULL, certDER, wrappedLen)) {
  1.1962 +		        PORT_Memcpy(certDER->data, wrapped, wrappedLen);
  1.1963 +		        rv = SECSuccess;
  1.1964 +		    }
  1.1965 +		    PR_smprintf_free(wrapped);
  1.1966 +	        }
  1.1967 +		PORT_Free(asciiDER);
  1.1968 +	    }
  1.1969 +	} else {
  1.1970 +	    rv = SECITEM_CopyItem(NULL, certDER, &subjectCert->derCert);
  1.1971 +	}
  1.1972 +    } while (0);
  1.1973 +    CERT_DestroyCertificateRequest (certReq);
  1.1974 +    CERT_DestroyCertificate (subjectCert);
  1.1975 +    if (rv != SECSuccess) {
  1.1976 +	PRErrorCode  perr = PR_GetError();
  1.1977 +        fprintf(stderr, "%s: unable to create cert (%s)\n", progName,
  1.1978 +               SECU_Strerror(perr));
  1.1979 +    }
  1.1980 +    return (rv);
  1.1981 +}
  1.1982 +
  1.1983 +
  1.1984 +/*
  1.1985 + * map a class to a user presentable string
  1.1986 + */
  1.1987 +static const char *objClassArray[] = {
  1.1988 +   "Data",
  1.1989 +   "Certificate",
  1.1990 +   "Public Key",
  1.1991 +   "Private Key",
  1.1992 +   "Secret Key",
  1.1993 +   "Hardware Feature",
  1.1994 +   "Domain Parameters",
  1.1995 +   "Mechanism"
  1.1996 +};
  1.1997 +
  1.1998 +static const char *objNSSClassArray[] = {
  1.1999 +   "CKO_NSS",
  1.2000 +   "Crl",
  1.2001 +   "SMIME Record",
  1.2002 +   "Trust",
  1.2003 +   "Builtin Root List"
  1.2004 +};
  1.2005 +
  1.2006 +
  1.2007 +const char *
  1.2008 +getObjectClass(CK_ULONG classType)
  1.2009 +{
  1.2010 +    static char buf[sizeof(CK_ULONG)*2+3];
  1.2011 +
  1.2012 +    if (classType <= CKO_MECHANISM) {
  1.2013 +	return objClassArray[classType];
  1.2014 +    }
  1.2015 +    if (classType >= CKO_NSS && classType <= CKO_NSS_BUILTIN_ROOT_LIST) {
  1.2016 +	return objNSSClassArray[classType - CKO_NSS];
  1.2017 +    }
  1.2018 +    sprintf(buf, "0x%lx", classType);
  1.2019 +    return buf;
  1.2020 +}
  1.2021 +
  1.2022 +typedef struct {
  1.2023 +    char *name;
  1.2024 +    int  nameSize;
  1.2025 +    CK_ULONG value;
  1.2026 +} flagArray;
  1.2027 +
  1.2028 +#define NAME_SIZE(x) #x,sizeof(#x)-1
  1.2029 +
  1.2030 +flagArray opFlagsArray[] =
  1.2031 +{
  1.2032 +    {NAME_SIZE(encrypt), CKF_ENCRYPT},
  1.2033 +    {NAME_SIZE(decrypt), CKF_DECRYPT},
  1.2034 +    {NAME_SIZE(sign), CKF_SIGN},
  1.2035 +    {NAME_SIZE(sign_recover), CKF_SIGN_RECOVER},
  1.2036 +    {NAME_SIZE(verify), CKF_VERIFY},
  1.2037 +    {NAME_SIZE(verify_recover), CKF_VERIFY_RECOVER},
  1.2038 +    {NAME_SIZE(wrap), CKF_WRAP},
  1.2039 +    {NAME_SIZE(unwrap), CKF_UNWRAP},
  1.2040 +    {NAME_SIZE(derive), CKF_DERIVE},
  1.2041 +};
  1.2042 +
  1.2043 +int opFlagsCount = sizeof(opFlagsArray)/sizeof(flagArray);
  1.2044 +
  1.2045 +flagArray attrFlagsArray[] =
  1.2046 +{
  1.2047 +    {NAME_SIZE(token), PK11_ATTR_TOKEN},
  1.2048 +    {NAME_SIZE(session), PK11_ATTR_SESSION},
  1.2049 +    {NAME_SIZE(private), PK11_ATTR_PRIVATE},
  1.2050 +    {NAME_SIZE(public), PK11_ATTR_PUBLIC},
  1.2051 +    {NAME_SIZE(modifiable), PK11_ATTR_MODIFIABLE},
  1.2052 +    {NAME_SIZE(unmodifiable), PK11_ATTR_UNMODIFIABLE},
  1.2053 +    {NAME_SIZE(sensitive), PK11_ATTR_SENSITIVE},
  1.2054 +    {NAME_SIZE(insensitive), PK11_ATTR_INSENSITIVE},
  1.2055 +    {NAME_SIZE(extractable), PK11_ATTR_EXTRACTABLE},
  1.2056 +    {NAME_SIZE(unextractable), PK11_ATTR_UNEXTRACTABLE}
  1.2057 +
  1.2058 +};
  1.2059 +
  1.2060 +int attrFlagsCount = sizeof(attrFlagsArray)/sizeof(flagArray);
  1.2061 +
  1.2062 +#define MAX_STRING 30
  1.2063 +CK_ULONG
  1.2064 +GetFlags(char *flagsString, flagArray *flagArray, int count)
  1.2065 +{
  1.2066 +   CK_ULONG flagsValue = strtol(flagsString, NULL, 0);
  1.2067 +   int i;
  1.2068 +
  1.2069 +   if ((flagsValue != 0) || (*flagsString == 0)) {
  1.2070 +	return flagsValue;
  1.2071 +   }
  1.2072 +   while (*flagsString) {
  1.2073 +	for (i=0; i < count; i++) {
  1.2074 +	    if (strncmp(flagsString, flagArray[i].name, flagArray[i].nameSize) 
  1.2075 +								== 0) {
  1.2076 +		flagsValue |= flagArray[i].value;
  1.2077 +		flagsString += flagArray[i].nameSize;
  1.2078 +		if (*flagsString != 0) {
  1.2079 +		    flagsString++;
  1.2080 +		}
  1.2081 +		break;
  1.2082 +	    }
  1.2083 +	}
  1.2084 +	if (i == count) {
  1.2085 +	    char name[MAX_STRING];
  1.2086 +	    char *tok;
  1.2087 +
  1.2088 +	    strncpy(name,flagsString, MAX_STRING);
  1.2089 +	    name[MAX_STRING-1] = 0;
  1.2090 +	    tok = strchr(name, ',');
  1.2091 +	    if (tok) {
  1.2092 +		*tok = 0;
  1.2093 +	    }
  1.2094 +	    fprintf(stderr,"Unknown flag (%s)\n",name);
  1.2095 +	    tok = strchr(flagsString, ',');
  1.2096 +	    if (tok == NULL)  {
  1.2097 +		break;
  1.2098 +	    }
  1.2099 +	    flagsString = tok+1;
  1.2100 +	}
  1.2101 +    }
  1.2102 +    return flagsValue;
  1.2103 +}
  1.2104 +
  1.2105 +CK_FLAGS
  1.2106 +GetOpFlags(char *flags)
  1.2107 +{
  1.2108 +    return GetFlags(flags, opFlagsArray, opFlagsCount);
  1.2109 +}
  1.2110 +
  1.2111 +PK11AttrFlags
  1.2112 +GetAttrFlags(char *flags)
  1.2113 +{
  1.2114 +    return GetFlags(flags, attrFlagsArray, attrFlagsCount);
  1.2115 +}
  1.2116 +
  1.2117 +char *mkNickname(unsigned char *data, int len)
  1.2118 +{
  1.2119 +   char *nick = PORT_Alloc(len+1);
  1.2120 +   if (!nick) {
  1.2121 +	return nick;
  1.2122 +   }
  1.2123 +   PORT_Memcpy(nick, data, len);
  1.2124 +   nick[len] = 0;
  1.2125 +   return nick;
  1.2126 +}
  1.2127 +
  1.2128 +/*
  1.2129 + * dump a PK11_MergeTokens error log to the console
  1.2130 + */
  1.2131 +void
  1.2132 +DumpMergeLog(const char *progname, PK11MergeLog *log)
  1.2133 +{
  1.2134 +    PK11MergeLogNode *node;
  1.2135 +
  1.2136 +    for (node = log->head; node; node = node->next) {
  1.2137 +	SECItem  attrItem;
  1.2138 +	char *nickname = NULL;
  1.2139 +	const char *objectClass = NULL;
  1.2140 +	SECStatus rv;
  1.2141 +
  1.2142 +	attrItem.data = NULL;
  1.2143 +	rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object, 
  1.2144 +				   CKA_LABEL, &attrItem);
  1.2145 +	if (rv == SECSuccess) {
  1.2146 +	    nickname = mkNickname(attrItem.data, attrItem.len);
  1.2147 +	    PORT_Free(attrItem.data);
  1.2148 +	}
  1.2149 +	attrItem.data = NULL;
  1.2150 +	rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object, 
  1.2151 +				   CKA_CLASS, &attrItem);
  1.2152 +	if (rv == SECSuccess) {
  1.2153 +	     if (attrItem.len == sizeof(CK_ULONG)) {
  1.2154 +		objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
  1.2155 +	     }
  1.2156 +	     PORT_Free(attrItem.data);
  1.2157 +	}
  1.2158 +
  1.2159 +	fprintf(stderr, "%s: Could not merge object %s (type %s): %s\n",
  1.2160 +		progName,
  1.2161 +		nickname ? nickname : "unnamed",
  1.2162 +		objectClass ? objectClass : "unknown",
  1.2163 +		SECU_Strerror(node->error));
  1.2164 +
  1.2165 +	if (nickname) {
  1.2166 +	    PORT_Free(nickname);
  1.2167 +	}
  1.2168 +    }
  1.2169 +}
  1.2170 +
  1.2171 +/*  Certutil commands  */
  1.2172 +enum {
  1.2173 +    cmd_AddCert = 0,
  1.2174 +    cmd_CreateNewCert,
  1.2175 +    cmd_DeleteCert,
  1.2176 +    cmd_AddEmailCert,
  1.2177 +    cmd_DeleteKey,
  1.2178 +    cmd_GenKeyPair,
  1.2179 +    cmd_PrintHelp,
  1.2180 +    cmd_PrintSyntax,
  1.2181 +    cmd_ListKeys,
  1.2182 +    cmd_ListCerts,
  1.2183 +    cmd_ModifyCertTrust,
  1.2184 +    cmd_NewDBs,
  1.2185 +    cmd_DumpChain,
  1.2186 +    cmd_CertReq,
  1.2187 +    cmd_CreateAndAddCert,
  1.2188 +    cmd_TokenReset,
  1.2189 +    cmd_ListModules,
  1.2190 +    cmd_CheckCertValidity,
  1.2191 +    cmd_ChangePassword,
  1.2192 +    cmd_Version,
  1.2193 +    cmd_Batch,
  1.2194 +    cmd_Merge,
  1.2195 +    cmd_UpgradeMerge, /* test only */
  1.2196 +    max_cmd
  1.2197 +};
  1.2198 +
  1.2199 +/*  Certutil options */
  1.2200 +enum certutilOpts {
  1.2201 +    opt_SSOPass = 0,
  1.2202 +    opt_AddKeyUsageExt,
  1.2203 +    opt_AddBasicConstraintExt,
  1.2204 +    opt_AddAuthorityKeyIDExt,
  1.2205 +    opt_AddCRLDistPtsExt,
  1.2206 +    opt_AddNSCertTypeExt,
  1.2207 +    opt_AddExtKeyUsageExt,
  1.2208 +    opt_ExtendedEmailAddrs,
  1.2209 +    opt_ExtendedDNSNames,
  1.2210 +    opt_ASCIIForIO,
  1.2211 +    opt_ValidityTime,
  1.2212 +    opt_IssuerName,
  1.2213 +    opt_CertDir,
  1.2214 +    opt_VerifySig,
  1.2215 +    opt_PasswordFile,
  1.2216 +    opt_KeySize,
  1.2217 +    opt_TokenName,
  1.2218 +    opt_InputFile,
  1.2219 +    opt_Emailaddress,
  1.2220 +    opt_KeyIndex,
  1.2221 +    opt_KeyType,
  1.2222 +    opt_DetailedInfo,
  1.2223 +    opt_SerialNumber,
  1.2224 +    opt_Nickname,
  1.2225 +    opt_OutputFile,
  1.2226 +    opt_PhoneNumber,
  1.2227 +    opt_DBPrefix,
  1.2228 +    opt_PQGFile,
  1.2229 +    opt_BinaryDER,
  1.2230 +    opt_Subject,
  1.2231 +    opt_Trust,
  1.2232 +    opt_Usage,
  1.2233 +    opt_Validity,
  1.2234 +    opt_OffsetMonths,
  1.2235 +    opt_SelfSign,
  1.2236 +    opt_RW,
  1.2237 +    opt_Exponent,
  1.2238 +    opt_NoiseFile,
  1.2239 +    opt_Hash,
  1.2240 +    opt_NewPasswordFile,
  1.2241 +    opt_AddAuthInfoAccExt,
  1.2242 +    opt_AddSubjInfoAccExt,
  1.2243 +    opt_AddCertPoliciesExt,
  1.2244 +    opt_AddPolicyMapExt,
  1.2245 +    opt_AddPolicyConstrExt,
  1.2246 +    opt_AddInhibAnyExt,
  1.2247 +    opt_AddNameConstraintsExt,
  1.2248 +    opt_AddSubjectKeyIDExt,
  1.2249 +    opt_AddCmdKeyUsageExt,
  1.2250 +    opt_AddCmdNSCertTypeExt,
  1.2251 +    opt_AddCmdExtKeyUsageExt,
  1.2252 +    opt_SourceDir,
  1.2253 +    opt_SourcePrefix,
  1.2254 +    opt_UpgradeID,
  1.2255 +    opt_UpgradeTokenName,
  1.2256 +    opt_KeyOpFlagsOn,
  1.2257 +    opt_KeyOpFlagsOff,
  1.2258 +    opt_KeyAttrFlags,
  1.2259 +    opt_EmptyPassword,
  1.2260 +    opt_CertVersion,
  1.2261 +    opt_AddSubjectAltNameExt,
  1.2262 +    opt_DumpExtensionValue,
  1.2263 +    opt_GenericExtensions,
  1.2264 +    opt_Help
  1.2265 +};
  1.2266 +
  1.2267 +static const
  1.2268 +secuCommandFlag commands_init[] =
  1.2269 +{
  1.2270 +	{ /* cmd_AddCert             */  'A', PR_FALSE, 0, PR_FALSE },
  1.2271 +	{ /* cmd_CreateNewCert       */  'C', PR_FALSE, 0, PR_FALSE },
  1.2272 +	{ /* cmd_DeleteCert          */  'D', PR_FALSE, 0, PR_FALSE },
  1.2273 +	{ /* cmd_AddEmailCert        */  'E', PR_FALSE, 0, PR_FALSE },
  1.2274 +	{ /* cmd_DeleteKey           */  'F', PR_FALSE, 0, PR_FALSE },
  1.2275 +	{ /* cmd_GenKeyPair          */  'G', PR_FALSE, 0, PR_FALSE },
  1.2276 +	{ /* cmd_PrintHelp           */  'H', PR_FALSE, 0, PR_FALSE, "help" },
  1.2277 +        { /* cmd_PrintSyntax         */   0,  PR_FALSE, 0, PR_FALSE,
  1.2278 +                                                   "syntax" },
  1.2279 +	{ /* cmd_ListKeys            */  'K', PR_FALSE, 0, PR_FALSE },
  1.2280 +	{ /* cmd_ListCerts           */  'L', PR_FALSE, 0, PR_FALSE },
  1.2281 +	{ /* cmd_ModifyCertTrust     */  'M', PR_FALSE, 0, PR_FALSE },
  1.2282 +	{ /* cmd_NewDBs              */  'N', PR_FALSE, 0, PR_FALSE },
  1.2283 +	{ /* cmd_DumpChain           */  'O', PR_FALSE, 0, PR_FALSE },
  1.2284 +	{ /* cmd_CertReq             */  'R', PR_FALSE, 0, PR_FALSE },
  1.2285 +	{ /* cmd_CreateAndAddCert    */  'S', PR_FALSE, 0, PR_FALSE },
  1.2286 +	{ /* cmd_TokenReset          */  'T', PR_FALSE, 0, PR_FALSE },
  1.2287 +	{ /* cmd_ListModules         */  'U', PR_FALSE, 0, PR_FALSE },
  1.2288 +	{ /* cmd_CheckCertValidity   */  'V', PR_FALSE, 0, PR_FALSE },
  1.2289 +	{ /* cmd_ChangePassword      */  'W', PR_FALSE, 0, PR_FALSE },
  1.2290 +	{ /* cmd_Version             */  'Y', PR_FALSE, 0, PR_FALSE },
  1.2291 +	{ /* cmd_Batch               */  'B', PR_FALSE, 0, PR_FALSE },
  1.2292 +	{ /* cmd_Merge               */   0,  PR_FALSE, 0, PR_FALSE, "merge" },
  1.2293 +	{ /* cmd_UpgradeMerge        */   0,  PR_FALSE, 0, PR_FALSE, 
  1.2294 +                                                   "upgrade-merge" }
  1.2295 +};
  1.2296 +#define NUM_COMMANDS ((sizeof commands_init) / (sizeof commands_init[0]))
  1.2297 + 
  1.2298 +static const 
  1.2299 +secuCommandFlag options_init[] =
  1.2300 +{
  1.2301 +	{ /* opt_SSOPass             */  '0', PR_TRUE,  0, PR_FALSE },
  1.2302 +	{ /* opt_AddKeyUsageExt      */  '1', PR_FALSE, 0, PR_FALSE },
  1.2303 +	{ /* opt_AddBasicConstraintExt*/ '2', PR_FALSE, 0, PR_FALSE },
  1.2304 +	{ /* opt_AddAuthorityKeyIDExt*/  '3', PR_FALSE, 0, PR_FALSE },
  1.2305 +	{ /* opt_AddCRLDistPtsExt    */  '4', PR_FALSE, 0, PR_FALSE },
  1.2306 +	{ /* opt_AddNSCertTypeExt    */  '5', PR_FALSE, 0, PR_FALSE },
  1.2307 +	{ /* opt_AddExtKeyUsageExt   */  '6', PR_FALSE, 0, PR_FALSE },
  1.2308 +	{ /* opt_ExtendedEmailAddrs  */  '7', PR_TRUE,  0, PR_FALSE },
  1.2309 +	{ /* opt_ExtendedDNSNames    */  '8', PR_TRUE,  0, PR_FALSE },
  1.2310 +	{ /* opt_ASCIIForIO          */  'a', PR_FALSE, 0, PR_FALSE },
  1.2311 +	{ /* opt_ValidityTime        */  'b', PR_TRUE,  0, PR_FALSE },
  1.2312 +	{ /* opt_IssuerName          */  'c', PR_TRUE,  0, PR_FALSE },
  1.2313 +	{ /* opt_CertDir             */  'd', PR_TRUE,  0, PR_FALSE },
  1.2314 +	{ /* opt_VerifySig           */  'e', PR_FALSE, 0, PR_FALSE },
  1.2315 +	{ /* opt_PasswordFile        */  'f', PR_TRUE,  0, PR_FALSE },
  1.2316 +	{ /* opt_KeySize             */  'g', PR_TRUE,  0, PR_FALSE },
  1.2317 +	{ /* opt_TokenName           */  'h', PR_TRUE,  0, PR_FALSE },
  1.2318 +	{ /* opt_InputFile           */  'i', PR_TRUE,  0, PR_FALSE },
  1.2319 +	{ /* opt_Emailaddress        */  0,   PR_TRUE,  0, PR_FALSE, "email" },
  1.2320 +	{ /* opt_KeyIndex            */  'j', PR_TRUE,  0, PR_FALSE },
  1.2321 +	{ /* opt_KeyType             */  'k', PR_TRUE,  0, PR_FALSE },
  1.2322 +	{ /* opt_DetailedInfo        */  'l', PR_FALSE, 0, PR_FALSE },
  1.2323 +	{ /* opt_SerialNumber        */  'm', PR_TRUE,  0, PR_FALSE },
  1.2324 +	{ /* opt_Nickname            */  'n', PR_TRUE,  0, PR_FALSE },
  1.2325 +	{ /* opt_OutputFile          */  'o', PR_TRUE,  0, PR_FALSE },
  1.2326 +	{ /* opt_PhoneNumber         */  'p', PR_TRUE,  0, PR_FALSE },
  1.2327 +	{ /* opt_DBPrefix            */  'P', PR_TRUE,  0, PR_FALSE },
  1.2328 +	{ /* opt_PQGFile             */  'q', PR_TRUE,  0, PR_FALSE },
  1.2329 +	{ /* opt_BinaryDER           */  'r', PR_FALSE, 0, PR_FALSE },
  1.2330 +	{ /* opt_Subject             */  's', PR_TRUE,  0, PR_FALSE },
  1.2331 +	{ /* opt_Trust               */  't', PR_TRUE,  0, PR_FALSE },
  1.2332 +	{ /* opt_Usage               */  'u', PR_TRUE,  0, PR_FALSE },
  1.2333 +	{ /* opt_Validity            */  'v', PR_TRUE,  0, PR_FALSE },
  1.2334 +	{ /* opt_OffsetMonths        */  'w', PR_TRUE,  0, PR_FALSE },
  1.2335 +	{ /* opt_SelfSign            */  'x', PR_FALSE, 0, PR_FALSE },
  1.2336 +	{ /* opt_RW                  */  'X', PR_FALSE, 0, PR_FALSE },
  1.2337 +	{ /* opt_Exponent            */  'y', PR_TRUE,  0, PR_FALSE },
  1.2338 +	{ /* opt_NoiseFile           */  'z', PR_TRUE,  0, PR_FALSE },
  1.2339 +	{ /* opt_Hash                */  'Z', PR_TRUE,  0, PR_FALSE },
  1.2340 +	{ /* opt_NewPasswordFile     */  '@', PR_TRUE,  0, PR_FALSE },
  1.2341 +	{ /* opt_AddAuthInfoAccExt   */  0,   PR_FALSE, 0, PR_FALSE, "extAIA" },
  1.2342 +	{ /* opt_AddSubjInfoAccExt   */  0,   PR_FALSE, 0, PR_FALSE, "extSIA" },
  1.2343 +	{ /* opt_AddCertPoliciesExt  */  0,   PR_FALSE, 0, PR_FALSE, "extCP" },
  1.2344 +	{ /* opt_AddPolicyMapExt     */  0,   PR_FALSE, 0, PR_FALSE, "extPM" },
  1.2345 +	{ /* opt_AddPolicyConstrExt  */  0,   PR_FALSE, 0, PR_FALSE, "extPC" },
  1.2346 +	{ /* opt_AddInhibAnyExt      */  0,   PR_FALSE, 0, PR_FALSE, "extIA" },
  1.2347 +	{ /* opt_AddNameConstraintsExt*/ 0,   PR_FALSE, 0, PR_FALSE, "extNC" },
  1.2348 +	{ /* opt_AddSubjectKeyIDExt  */  0,   PR_FALSE, 0, PR_FALSE, 
  1.2349 +						   "extSKID" },
  1.2350 +	{ /* opt_AddCmdKeyUsageExt   */  0,   PR_TRUE,  0, PR_FALSE,
  1.2351 +                                                   "keyUsage" },
  1.2352 +	{ /* opt_AddCmdNSCertTypeExt */   0,   PR_TRUE,  0, PR_FALSE,
  1.2353 +                                                   "nsCertType" },
  1.2354 +	{ /* opt_AddCmdExtKeyUsageExt*/  0,   PR_TRUE,  0, PR_FALSE,
  1.2355 +                                                   "extKeyUsage" },
  1.2356 +
  1.2357 +	{ /* opt_SourceDir           */  0,   PR_TRUE,  0, PR_FALSE,
  1.2358 +                                                   "source-dir"},
  1.2359 +	{ /* opt_SourcePrefix        */  0,   PR_TRUE,  0, PR_FALSE, 
  1.2360 +						   "source-prefix"},
  1.2361 +	{ /* opt_UpgradeID           */  0,   PR_TRUE,  0, PR_FALSE, 
  1.2362 +                                                   "upgrade-id"},
  1.2363 +	{ /* opt_UpgradeTokenName    */  0,   PR_TRUE,  0, PR_FALSE, 
  1.2364 +                                                   "upgrade-token-name"},
  1.2365 +	{ /* opt_KeyOpFlagsOn        */  0,   PR_TRUE, 0, PR_FALSE, 
  1.2366 +                                                   "keyOpFlagsOn"},
  1.2367 +	{ /* opt_KeyOpFlagsOff       */  0,   PR_TRUE, 0, PR_FALSE, 
  1.2368 +                                                   "keyOpFlagsOff"},
  1.2369 +	{ /* opt_KeyAttrFlags        */  0,   PR_TRUE, 0, PR_FALSE, 
  1.2370 +                                                   "keyAttrFlags"},
  1.2371 +	{ /* opt_EmptyPassword       */  0,   PR_FALSE, 0, PR_FALSE, 
  1.2372 +                                                   "empty-password"},
  1.2373 +        { /* opt_CertVersion         */  0,   PR_FALSE, 0, PR_FALSE,
  1.2374 +                                                   "certVersion"},
  1.2375 +	{ /* opt_AddSubjectAltExt    */  0,   PR_TRUE,  0, PR_FALSE, "extSAN"},
  1.2376 +	{ /* opt_DumpExtensionValue  */  0,   PR_TRUE, 0, PR_FALSE, 
  1.2377 +                                                   "dump-ext-val"},
  1.2378 +	{ /* opt_GenericExtensions   */  0,   PR_TRUE, 0, PR_FALSE, 
  1.2379 +                                                   "extGeneric"},
  1.2380 +};
  1.2381 +#define NUM_OPTIONS ((sizeof options_init)  / (sizeof options_init[0]))
  1.2382 +
  1.2383 +static secuCommandFlag certutil_commands[NUM_COMMANDS];
  1.2384 +static secuCommandFlag certutil_options [NUM_OPTIONS ];
  1.2385 +
  1.2386 +static const secuCommand certutil = {
  1.2387 +    NUM_COMMANDS, 
  1.2388 +    NUM_OPTIONS, 
  1.2389 +    certutil_commands, 
  1.2390 +    certutil_options
  1.2391 +};
  1.2392 +
  1.2393 +static certutilExtnList certutil_extns;
  1.2394 +
  1.2395 +static int 
  1.2396 +certutil_main(int argc, char **argv, PRBool initialize)
  1.2397 +{
  1.2398 +    CERTCertDBHandle *certHandle;
  1.2399 +    PK11SlotInfo *slot = NULL;
  1.2400 +    CERTName *  subject         = 0;
  1.2401 +    PRFileDesc *inFile          = PR_STDIN;
  1.2402 +    PRFileDesc *outFile         = PR_STDOUT;
  1.2403 +    SECItem     certReqDER      = { siBuffer, NULL, 0 };
  1.2404 +    SECItem     certDER         = { siBuffer, NULL, 0 };
  1.2405 +    char *      slotname        = "internal";
  1.2406 +    char *      certPrefix      = "";
  1.2407 +    char *      sourceDir       = "";
  1.2408 +    char *      srcCertPrefix   = "";
  1.2409 +    char *      upgradeID        = "";
  1.2410 +    char *      upgradeTokenName     = "";
  1.2411 +    KeyType     keytype         = rsaKey;
  1.2412 +    char *      name            = NULL;
  1.2413 +    char *      email            = NULL;
  1.2414 +    char *      keysource       = NULL;
  1.2415 +    SECOidTag   hashAlgTag      = SEC_OID_UNKNOWN;
  1.2416 +    int	        keysize	        = DEFAULT_KEY_BITS;
  1.2417 +    int         publicExponent  = 0x010001;
  1.2418 +    int         certVersion     = SEC_CERTIFICATE_VERSION_3;
  1.2419 +    unsigned int serialNumber   = 0;
  1.2420 +    int         warpmonths      = 0;
  1.2421 +    int         validityMonths  = 3;
  1.2422 +    int         commandsEntered = 0;
  1.2423 +    char        commandToRun    = '\0';
  1.2424 +    secuPWData  pwdata          = { PW_NONE, 0 };
  1.2425 +    secuPWData  pwdata2         = { PW_NONE, 0 };
  1.2426 +    PRBool      readOnly        = PR_FALSE;
  1.2427 +    PRBool      initialized     = PR_FALSE;
  1.2428 +    CK_FLAGS    keyOpFlagsOn = 0;
  1.2429 +    CK_FLAGS    keyOpFlagsOff = 0;
  1.2430 +    PK11AttrFlags    keyAttrFlags = 
  1.2431 +		PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE;
  1.2432 +
  1.2433 +    SECKEYPrivateKey *privkey = NULL;
  1.2434 +    SECKEYPublicKey *pubkey = NULL;
  1.2435 +
  1.2436 +    int i;
  1.2437 +    SECStatus rv;
  1.2438 +
  1.2439 +    progName = PORT_Strrchr(argv[0], '/');
  1.2440 +    progName = progName ? progName+1 : argv[0];
  1.2441 +    memcpy(certutil_commands, commands_init, sizeof commands_init);
  1.2442 +    memcpy(certutil_options,  options_init,  sizeof options_init);
  1.2443 +
  1.2444 +    rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
  1.2445 +
  1.2446 +    if (rv != SECSuccess)
  1.2447 +	Usage(progName);
  1.2448 +
  1.2449 +    if (certutil.commands[cmd_PrintSyntax].activated) {
  1.2450 +        PrintSyntax(progName);
  1.2451 +    }
  1.2452 +
  1.2453 +    if (certutil.commands[cmd_PrintHelp].activated) {
  1.2454 +        int i;
  1.2455 +        char buf[2];
  1.2456 +        const char *command = NULL;
  1.2457 +        for (i = 0; i < max_cmd; i++) {
  1.2458 +            if (i == cmd_PrintHelp)
  1.2459 +                continue;
  1.2460 +            if (certutil.commands[i].activated) {
  1.2461 +                if (certutil.commands[i].flag) {
  1.2462 +                    buf[0] = certutil.commands[i].flag;
  1.2463 +                    buf[1] = 0;
  1.2464 +                    command = buf;
  1.2465 +                }
  1.2466 +                else {
  1.2467 +                    command = certutil.commands[i].longform;
  1.2468 +                }
  1.2469 +                break;
  1.2470 +            }
  1.2471 +        }
  1.2472 +	LongUsage(progName, (command ? usage_selected : usage_all), command);
  1.2473 +        exit(1);
  1.2474 +    }
  1.2475 +
  1.2476 +    if (certutil.options[opt_PasswordFile].arg) {
  1.2477 +	pwdata.source = PW_FROMFILE;
  1.2478 +	pwdata.data = certutil.options[opt_PasswordFile].arg;
  1.2479 +    }
  1.2480 +    if (certutil.options[opt_NewPasswordFile].arg) {
  1.2481 +	pwdata2.source = PW_FROMFILE;
  1.2482 +	pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
  1.2483 +    }
  1.2484 +
  1.2485 +    if (certutil.options[opt_CertDir].activated)
  1.2486 +	SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
  1.2487 +
  1.2488 +    if (certutil.options[opt_SourceDir].activated)
  1.2489 +	sourceDir = certutil.options[opt_SourceDir].arg;
  1.2490 +
  1.2491 +    if (certutil.options[opt_UpgradeID].activated)
  1.2492 +	upgradeID = certutil.options[opt_UpgradeID].arg;
  1.2493 +
  1.2494 +    if (certutil.options[opt_UpgradeTokenName].activated)
  1.2495 +	upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
  1.2496 +
  1.2497 +    if (certutil.options[opt_KeySize].activated) {
  1.2498 +	keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);
  1.2499 +	if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {
  1.2500 +	    PR_fprintf(PR_STDERR, 
  1.2501 +                       "%s -g:  Keysize must be between %d and %d.\n",
  1.2502 +		       progName, MIN_KEY_BITS, MAX_KEY_BITS);
  1.2503 +	    return 255;
  1.2504 +	}
  1.2505 +#ifndef NSS_DISABLE_ECC
  1.2506 +	if (keytype == ecKey) {
  1.2507 +	    PR_fprintf(PR_STDERR, "%s -g:  Not for ec keys.\n", progName);
  1.2508 +	    return 255;
  1.2509 +	}
  1.2510 +#endif /* NSS_DISABLE_ECC */
  1.2511 +
  1.2512 +    }
  1.2513 +
  1.2514 +    /*  -h specify token name  */
  1.2515 +    if (certutil.options[opt_TokenName].activated) {
  1.2516 +	if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
  1.2517 +	    slotname = NULL;
  1.2518 +	else
  1.2519 +	    slotname = PL_strdup(certutil.options[opt_TokenName].arg);
  1.2520 +    }
  1.2521 +
  1.2522 +    /*  -Z hash type  */
  1.2523 +    if (certutil.options[opt_Hash].activated) {
  1.2524 +	char * arg = certutil.options[opt_Hash].arg;
  1.2525 +        hashAlgTag = SECU_StringToSignatureAlgTag(arg);
  1.2526 +        if (hashAlgTag == SEC_OID_UNKNOWN) {
  1.2527 +	    PR_fprintf(PR_STDERR, "%s -Z:  %s is not a recognized type.\n",
  1.2528 +	               progName, arg);
  1.2529 +	    return 255;
  1.2530 +	}
  1.2531 +    }
  1.2532 +
  1.2533 +    /*  -k key type  */
  1.2534 +    if (certutil.options[opt_KeyType].activated) {
  1.2535 +	char * arg = certutil.options[opt_KeyType].arg;
  1.2536 +	if (PL_strcmp(arg, "rsa") == 0) {
  1.2537 +	    keytype = rsaKey;
  1.2538 +	} else if (PL_strcmp(arg, "dsa") == 0) {
  1.2539 +	    keytype = dsaKey;
  1.2540 +#ifndef NSS_DISABLE_ECC
  1.2541 +	} else if (PL_strcmp(arg, "ec") == 0) {
  1.2542 +	    keytype = ecKey;
  1.2543 +#endif /* NSS_DISABLE_ECC */
  1.2544 +	} else if (PL_strcmp(arg, "all") == 0) {
  1.2545 +	    keytype = nullKey;
  1.2546 +	} else {
  1.2547 +	    /* use an existing private/public key pair */
  1.2548 +	    keysource = arg;
  1.2549 +	}
  1.2550 +    } else if (certutil.commands[cmd_ListKeys].activated) {
  1.2551 +	keytype = nullKey;
  1.2552 +    }
  1.2553 +
  1.2554 +    if (certutil.options[opt_KeyOpFlagsOn].activated) {
  1.2555 +	keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
  1.2556 +    }
  1.2557 +    if (certutil.options[opt_KeyOpFlagsOff].activated) {
  1.2558 +	keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
  1.2559 +	keyOpFlagsOn &=~keyOpFlagsOff; /* make off override on */
  1.2560 +    }
  1.2561 +    if (certutil.options[opt_KeyAttrFlags].activated) {
  1.2562 +	keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
  1.2563 +    }
  1.2564 +
  1.2565 +    /*  -m serial number */
  1.2566 +    if (certutil.options[opt_SerialNumber].activated) {
  1.2567 +	int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg);
  1.2568 +	if (sn < 0) {
  1.2569 +	    PR_fprintf(PR_STDERR, "%s -m:  %s is not a valid serial number.\n",
  1.2570 +	               progName, certutil.options[opt_SerialNumber].arg);
  1.2571 +	    return 255;
  1.2572 +	}
  1.2573 +	serialNumber = sn;
  1.2574 +    }
  1.2575 +
  1.2576 +    /*  -P certdb name prefix */
  1.2577 +    if (certutil.options[opt_DBPrefix].activated) {
  1.2578 +        if (certutil.options[opt_DBPrefix].arg) {
  1.2579 +            certPrefix = strdup(certutil.options[opt_DBPrefix].arg);
  1.2580 +        } else {
  1.2581 +            Usage(progName);
  1.2582 +        }
  1.2583 +    }
  1.2584 +
  1.2585 +    /*  --source-prefix certdb name prefix */
  1.2586 +    if (certutil.options[opt_SourcePrefix].activated) {
  1.2587 +        if (certutil.options[opt_SourcePrefix].arg) {
  1.2588 +            srcCertPrefix = strdup(certutil.options[opt_SourcePrefix].arg);
  1.2589 +        } else {
  1.2590 +            Usage(progName);
  1.2591 +        }
  1.2592 +    }
  1.2593 +
  1.2594 +    /*  -q PQG file or curve name */
  1.2595 +    if (certutil.options[opt_PQGFile].activated) {
  1.2596 +#ifndef NSS_DISABLE_ECC
  1.2597 +	if ((keytype != dsaKey) && (keytype != ecKey)) {
  1.2598 +	    PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys" \
  1.2599 +		       " (-k dsa) or a named curve for EC keys (-k ec)\n)",
  1.2600 +	               progName);
  1.2601 +#else   /* } */
  1.2602 +	if (keytype != dsaKey) {
  1.2603 +	    PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)",
  1.2604 +	               progName);
  1.2605 +#endif /* NSS_DISABLE_ECC */
  1.2606 +	    return 255;
  1.2607 +	}
  1.2608 +    }
  1.2609 +
  1.2610 +    /*  -s subject name  */
  1.2611 +    if (certutil.options[opt_Subject].activated) {
  1.2612 +	subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
  1.2613 +	if (!subject) {
  1.2614 +	    PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n",
  1.2615 +	               progName, certutil.options[opt_Subject].arg);
  1.2616 +	    return 255;
  1.2617 +	}
  1.2618 +    }
  1.2619 +
  1.2620 +    /*  -v validity period  */
  1.2621 +    if (certutil.options[opt_Validity].activated) {
  1.2622 +	validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg);
  1.2623 +	if (validityMonths < 0) {
  1.2624 +	    PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n",
  1.2625 +	               progName, certutil.options[opt_Validity].arg);
  1.2626 +	    return 255;
  1.2627 +	}
  1.2628 +    }
  1.2629 +
  1.2630 +    /*  -w warp months  */
  1.2631 +    if (certutil.options[opt_OffsetMonths].activated)
  1.2632 +	warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);
  1.2633 +
  1.2634 +    /*  -y public exponent (for RSA)  */
  1.2635 +    if (certutil.options[opt_Exponent].activated) {
  1.2636 +	publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg);
  1.2637 +	if ((publicExponent != 3) &&
  1.2638 +	    (publicExponent != 17) &&
  1.2639 +	    (publicExponent != 65537)) {
  1.2640 +	    PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.", 
  1.2641 +	                           progName, publicExponent);
  1.2642 +	    PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n");
  1.2643 +	    return 255;
  1.2644 +	}
  1.2645 +    }
  1.2646 +
  1.2647 +    /*  --certVersion */
  1.2648 +    if (certutil.options[opt_CertVersion].activated) {
  1.2649 +        certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg);
  1.2650 +        if (certVersion < 1 || certVersion > 4) {
  1.2651 +            PR_fprintf(PR_STDERR, "%s -certVersion: incorrect certificate version %d.",
  1.2652 +                                   progName, certVersion);
  1.2653 +            PR_fprintf(PR_STDERR, "Must be 1, 2, 3 or 4.\n");
  1.2654 +            return 255;
  1.2655 +        }
  1.2656 +        certVersion = certVersion - 1;
  1.2657 +    }
  1.2658 +
  1.2659 +
  1.2660 +    /*  Check number of commands entered.  */
  1.2661 +    commandsEntered = 0;
  1.2662 +    for (i=0; i< certutil.numCommands; i++) {
  1.2663 +	if (certutil.commands[i].activated) {
  1.2664 +	    commandToRun = certutil.commands[i].flag;
  1.2665 +	    commandsEntered++;
  1.2666 +	}
  1.2667 +	if (commandsEntered > 1)
  1.2668 +	    break;
  1.2669 +    }
  1.2670 +    if (commandsEntered > 1) {
  1.2671 +	PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
  1.2672 +	PR_fprintf(PR_STDERR, "You entered: ");
  1.2673 +	for (i=0; i< certutil.numCommands; i++) {
  1.2674 +	    if (certutil.commands[i].activated)
  1.2675 +		PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);
  1.2676 +	}
  1.2677 +	PR_fprintf(PR_STDERR, "\n");
  1.2678 +	return 255;
  1.2679 +    }
  1.2680 +    if (commandsEntered == 0) {
  1.2681 +	Usage(progName);
  1.2682 +    }
  1.2683 +
  1.2684 +    if (certutil.commands[cmd_ListCerts].activated ||
  1.2685 +         certutil.commands[cmd_PrintHelp].activated ||
  1.2686 +         certutil.commands[cmd_ListKeys].activated ||
  1.2687 +         certutil.commands[cmd_ListModules].activated ||
  1.2688 +         certutil.commands[cmd_CheckCertValidity].activated ||
  1.2689 +         certutil.commands[cmd_Version].activated ) {
  1.2690 +	readOnly = !certutil.options[opt_RW].activated;
  1.2691 +    }
  1.2692 +
  1.2693 +    /*  -A, -D, -F, -M, -S, -V, and all require -n  */
  1.2694 +    if ((certutil.commands[cmd_AddCert].activated ||
  1.2695 +         certutil.commands[cmd_DeleteCert].activated ||
  1.2696 +         certutil.commands[cmd_DeleteKey].activated ||
  1.2697 +	 certutil.commands[cmd_DumpChain].activated ||
  1.2698 +         certutil.commands[cmd_ModifyCertTrust].activated ||
  1.2699 +         certutil.commands[cmd_CreateAndAddCert].activated ||
  1.2700 +         certutil.commands[cmd_CheckCertValidity].activated) &&
  1.2701 +        !certutil.options[opt_Nickname].activated) {
  1.2702 +	PR_fprintf(PR_STDERR, 
  1.2703 +	          "%s -%c: nickname is required for this command (-n).\n",
  1.2704 +	           progName, commandToRun);
  1.2705 +	return 255;
  1.2706 +    }
  1.2707 +
  1.2708 +    /*  -A, -E, -M, -S require trust  */
  1.2709 +    if ((certutil.commands[cmd_AddCert].activated ||
  1.2710 +         certutil.commands[cmd_AddEmailCert].activated ||
  1.2711 +         certutil.commands[cmd_ModifyCertTrust].activated ||
  1.2712 +         certutil.commands[cmd_CreateAndAddCert].activated) &&
  1.2713 +        !certutil.options[opt_Trust].activated) {
  1.2714 +	PR_fprintf(PR_STDERR, 
  1.2715 +	          "%s -%c: trust is required for this command (-t).\n",
  1.2716 +	           progName, commandToRun);
  1.2717 +	return 255;
  1.2718 +    }
  1.2719 +
  1.2720 +    /*  if -L is given raw, ascii or dump mode, it must be for only one cert. */
  1.2721 +    if (certutil.commands[cmd_ListCerts].activated &&
  1.2722 +        (certutil.options[opt_ASCIIForIO].activated ||
  1.2723 +         certutil.options[opt_DumpExtensionValue].activated ||
  1.2724 +         certutil.options[opt_BinaryDER].activated) &&
  1.2725 +        !certutil.options[opt_Nickname].activated) {
  1.2726 +	PR_fprintf(PR_STDERR, 
  1.2727 +	        "%s: nickname is required to dump cert in raw or ascii mode.\n",
  1.2728 +	           progName);
  1.2729 +	return 255;
  1.2730 +    }
  1.2731 +    
  1.2732 +    /*  -L can only be in (raw || ascii).  */
  1.2733 +    if (certutil.commands[cmd_ListCerts].activated &&
  1.2734 +        certutil.options[opt_ASCIIForIO].activated &&
  1.2735 +        certutil.options[opt_BinaryDER].activated) {
  1.2736 +	PR_fprintf(PR_STDERR, 
  1.2737 +	           "%s: cannot specify both -r and -a when dumping cert.\n",
  1.2738 +	           progName);
  1.2739 +	return 255;
  1.2740 +    }
  1.2741 +
  1.2742 +    /*  If making a cert request, need a subject.  */
  1.2743 +    if ((certutil.commands[cmd_CertReq].activated ||
  1.2744 +         certutil.commands[cmd_CreateAndAddCert].activated) &&
  1.2745 +        !(certutil.options[opt_Subject].activated || keysource)) {
  1.2746 +	PR_fprintf(PR_STDERR, 
  1.2747 +	           "%s -%c: subject is required to create a cert request.\n",
  1.2748 +	           progName, commandToRun);
  1.2749 +	return 255;
  1.2750 +    }
  1.2751 +
  1.2752 +    /*  If making a cert, need a serial number.  */
  1.2753 +    if ((certutil.commands[cmd_CreateNewCert].activated ||
  1.2754 +         certutil.commands[cmd_CreateAndAddCert].activated) &&
  1.2755 +         !certutil.options[opt_SerialNumber].activated) {
  1.2756 +	/*  Make a default serial number from the current time.  */
  1.2757 +	PRTime now = PR_Now();
  1.2758 +	LL_USHR(now, now, 19);
  1.2759 +	LL_L2UI(serialNumber, now);
  1.2760 +    }
  1.2761 +
  1.2762 +    /*  Validation needs the usage to validate for.  */
  1.2763 +    if (certutil.commands[cmd_CheckCertValidity].activated &&
  1.2764 +        !certutil.options[opt_Usage].activated) {
  1.2765 +	PR_fprintf(PR_STDERR, 
  1.2766 +	           "%s -V: specify a usage to validate the cert for (-u).\n",
  1.2767 +	           progName);
  1.2768 +	return 255;
  1.2769 +    }
  1.2770 +
  1.2771 +    /* Upgrade/Merge needs a source database and a upgrade id. */
  1.2772 +    if (certutil.commands[cmd_UpgradeMerge].activated &&
  1.2773 +        !(certutil.options[opt_SourceDir].activated &&
  1.2774 +          certutil.options[opt_UpgradeID].activated)) {
  1.2775 +
  1.2776 +	PR_fprintf(PR_STDERR, 
  1.2777 +	           "%s --upgrade-merge: specify an upgrade database directory "
  1.2778 +		   "(--source-dir) and\n"
  1.2779 +                   "   an upgrade ID (--upgrade-id).\n",
  1.2780 +	           progName);
  1.2781 +	return 255;
  1.2782 +    }
  1.2783 +
  1.2784 +    /* Merge needs a source database */
  1.2785 +    if (certutil.commands[cmd_Merge].activated &&
  1.2786 +        !certutil.options[opt_SourceDir].activated) {
  1.2787 +
  1.2788 +
  1.2789 +	PR_fprintf(PR_STDERR, 
  1.2790 +	           "%s --merge: specify an source database directory "
  1.2791 +		   "(--source-dir)\n",
  1.2792 +	           progName);
  1.2793 +	return 255;
  1.2794 +    }
  1.2795 +
  1.2796 +    
  1.2797 +    /*  To make a cert, need either a issuer or to self-sign it.  */
  1.2798 +    if (certutil.commands[cmd_CreateAndAddCert].activated &&
  1.2799 +	!(certutil.options[opt_IssuerName].activated ||
  1.2800 +          certutil.options[opt_SelfSign].activated)) {
  1.2801 +	PR_fprintf(PR_STDERR,
  1.2802 +	           "%s -S: must specify issuer (-c) or self-sign (-x).\n",
  1.2803 +	           progName);
  1.2804 +	return 255;
  1.2805 +    }
  1.2806 +
  1.2807 +    /*  Using slotname == NULL for listing keys and certs on all slots, 
  1.2808 +     *  but only that. */
  1.2809 +    if (!(certutil.commands[cmd_ListKeys].activated ||
  1.2810 +	  certutil.commands[cmd_DumpChain].activated ||
  1.2811 +    	  certutil.commands[cmd_ListCerts].activated) && slotname == NULL) {
  1.2812 +	PR_fprintf(PR_STDERR,
  1.2813 +	           "%s -%c: cannot use \"-h all\" for this command.\n",
  1.2814 +	           progName, commandToRun);
  1.2815 +	return 255;
  1.2816 +    }
  1.2817 +
  1.2818 +    /*  Using keytype == nullKey for list all key types, but only that.  */
  1.2819 +    if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
  1.2820 +	PR_fprintf(PR_STDERR,
  1.2821 +	           "%s -%c: cannot use \"-k all\" for this command.\n",
  1.2822 +	           progName, commandToRun);
  1.2823 +	return 255;
  1.2824 +    }
  1.2825 +
  1.2826 +    /*  Open the input file.  */
  1.2827 +    if (certutil.options[opt_InputFile].activated) {
  1.2828 +	inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0);
  1.2829 +	if (!inFile) {
  1.2830 +	    PR_fprintf(PR_STDERR,
  1.2831 +	               "%s:  unable to open \"%s\" for reading (%ld, %ld).\n",
  1.2832 +	               progName, certutil.options[opt_InputFile].arg,
  1.2833 +	               PR_GetError(), PR_GetOSError());
  1.2834 +	    return 255;
  1.2835 +	}
  1.2836 +    }
  1.2837 +
  1.2838 +    /*  Open the output file.  */
  1.2839 +    if (certutil.options[opt_OutputFile].activated) {
  1.2840 +	outFile = PR_Open(certutil.options[opt_OutputFile].arg, 
  1.2841 +                          PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660);
  1.2842 +	if (!outFile) {
  1.2843 +	    PR_fprintf(PR_STDERR,
  1.2844 +	               "%s:  unable to open \"%s\" for writing (%ld, %ld).\n",
  1.2845 +	               progName, certutil.options[opt_OutputFile].arg,
  1.2846 +	               PR_GetError(), PR_GetOSError());
  1.2847 +	    return 255;
  1.2848 +	}
  1.2849 +    }
  1.2850 +
  1.2851 +    name = SECU_GetOptionArg(&certutil, opt_Nickname);
  1.2852 +    email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
  1.2853 +
  1.2854 +    PK11_SetPasswordFunc(SECU_GetModulePassword);
  1.2855 +
  1.2856 +    if (PR_TRUE == initialize) {
  1.2857 +        /*  Initialize NSPR and NSS.  */
  1.2858 +        PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  1.2859 +	if (!certutil.commands[cmd_UpgradeMerge].activated) {
  1.2860 +            rv = NSS_Initialize(SECU_ConfigDirectory(NULL), 
  1.2861 +			    certPrefix, certPrefix,
  1.2862 +                            "secmod.db", readOnly ? NSS_INIT_READONLY: 0);
  1.2863 +	} else {
  1.2864 +            rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL), 
  1.2865 +			    certPrefix, certPrefix, "secmod.db",
  1.2866 +			    sourceDir, srcCertPrefix, srcCertPrefix, 
  1.2867 +			    upgradeID, upgradeTokenName,
  1.2868 +                            readOnly ? NSS_INIT_READONLY: 0);
  1.2869 +	}
  1.2870 +        if (rv != SECSuccess) {
  1.2871 +	    SECU_PrintPRandOSError(progName);
  1.2872 +	    rv = SECFailure;
  1.2873 +	    goto shutdown;
  1.2874 +        }
  1.2875 +        initialized = PR_TRUE;
  1.2876 +    	SECU_RegisterDynamicOids();
  1.2877 +    }
  1.2878 +    certHandle = CERT_GetDefaultCertDB();
  1.2879 +
  1.2880 +    if (certutil.commands[cmd_Version].activated) {
  1.2881 +	printf("Certificate database content version: command not implemented.\n");
  1.2882 +    }
  1.2883 +
  1.2884 +    if (PL_strcmp(slotname, "internal") == 0)
  1.2885 +	slot = PK11_GetInternalKeySlot();
  1.2886 +    else if (slotname != NULL)
  1.2887 +	slot = PK11_FindSlotByName(slotname);
  1.2888 +
  1.2889 +    if ( !slot && (certutil.commands[cmd_NewDBs].activated ||
  1.2890 +         certutil.commands[cmd_ModifyCertTrust].activated  || 
  1.2891 +         certutil.commands[cmd_ChangePassword].activated   ||
  1.2892 +         certutil.commands[cmd_TokenReset].activated       ||
  1.2893 +         certutil.commands[cmd_CreateAndAddCert].activated ||
  1.2894 +         certutil.commands[cmd_AddCert].activated          ||
  1.2895 +         certutil.commands[cmd_Merge].activated          ||
  1.2896 +         certutil.commands[cmd_UpgradeMerge].activated          ||
  1.2897 +         certutil.commands[cmd_AddEmailCert].activated)) {
  1.2898 +      
  1.2899 +         SECU_PrintError(progName, "could not find the slot %s",slotname);
  1.2900 +         rv = SECFailure;
  1.2901 +         goto shutdown;
  1.2902 +    }
  1.2903 +
  1.2904 +    /*  If creating new database, initialize the password.  */
  1.2905 +    if (certutil.commands[cmd_NewDBs].activated) {
  1.2906 +	if(certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot)))
  1.2907 +	    PK11_InitPin(slot, (char*)NULL, "");
  1.2908 +	else
  1.2909 +	    SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
  1.2910 +				certutil.options[opt_NewPasswordFile].arg);
  1.2911 +    }
  1.2912 +
  1.2913 +    /* walk through the upgrade merge if necessary.
  1.2914 +     * This option is more to test what some applications will want to do
  1.2915 +     * to do an automatic upgrade. The --merge command is more useful for
  1.2916 +     * the general case where 2 database need to be merged together.
  1.2917 +     */
  1.2918 +    if (certutil.commands[cmd_UpgradeMerge].activated) {
  1.2919 +	if (*upgradeTokenName == 0) {
  1.2920 +	    upgradeTokenName = upgradeID;
  1.2921 +	}
  1.2922 +	if (!PK11_IsInternal(slot)) {
  1.2923 +	    fprintf(stderr, "Only internal DB's can be upgraded\n");
  1.2924 +	    rv = SECSuccess;
  1.2925 +	    goto shutdown;
  1.2926 +	}
  1.2927 +	if (!PK11_IsRemovable(slot)) {
  1.2928 +	    printf("database already upgraded.\n");
  1.2929 +	    rv = SECSuccess;
  1.2930 +	    goto shutdown;
  1.2931 +	}
  1.2932 +	if (!PK11_NeedLogin(slot)) {
  1.2933 +	    printf("upgrade complete!\n");
  1.2934 +	    rv = SECSuccess;
  1.2935 +	    goto shutdown;
  1.2936 +	}
  1.2937 +	/* authenticate to the old DB if necessary */
  1.2938 +	if (PORT_Strcmp(PK11_GetTokenName(slot), upgradeTokenName) ==  0) {
  1.2939 +	    /* if we need a password, supply it. This will be the password
  1.2940 +	     * for the old database */
  1.2941 +	    rv = PK11_Authenticate(slot, PR_FALSE, &pwdata2);
  1.2942 +	    if (rv != SECSuccess) {
  1.2943 +         	SECU_PrintError(progName, "Could not get password for %s",
  1.2944 +				upgradeTokenName);
  1.2945 +		goto shutdown;
  1.2946 +	    }
  1.2947 +	    /* 
  1.2948 +	     * if we succeeded above, but still aren't logged in, that means
  1.2949 +	     * we just supplied the password for the old database. We may
  1.2950 +	     * need the password for the new database. NSS will automatically
  1.2951 +	     * change the token names at this point
  1.2952 +	     */
  1.2953 +	    if (PK11_IsLoggedIn(slot, &pwdata)) {
  1.2954 +		printf("upgrade complete!\n");
  1.2955 +		rv = SECSuccess;
  1.2956 +		goto shutdown;
  1.2957 +	    }
  1.2958 + 	}
  1.2959 +
  1.2960 +	/* call PK11_IsPresent to update our cached token information */
  1.2961 +	if (!PK11_IsPresent(slot)) {
  1.2962 +	    /* this shouldn't happen. We call isPresent to force a token
  1.2963 +	     * info update */
  1.2964 +	    fprintf(stderr, "upgrade/merge internal error\n");
  1.2965 +	    rv = SECFailure;
  1.2966 +	    goto shutdown;
  1.2967 +	}
  1.2968 +
  1.2969 +	/* the token is now set to the state of the source database,
  1.2970 +	 * if we need a password for it, PK11_Authenticate will 
  1.2971 +	 * automatically prompt us */
  1.2972 +	rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
  1.2973 +	if (rv == SECSuccess) {
  1.2974 +	    printf("upgrade complete!\n");
  1.2975 +	} else {
  1.2976 +            SECU_PrintError(progName, "Could not get password for %s",
  1.2977 +				PK11_GetTokenName(slot));
  1.2978 +	}
  1.2979 +	goto shutdown;
  1.2980 +    }
  1.2981 +
  1.2982 +    /*
  1.2983 +     * merge 2 databases.
  1.2984 +     */
  1.2985 +    if (certutil.commands[cmd_Merge].activated) {
  1.2986 +	PK11SlotInfo *sourceSlot = NULL;
  1.2987 +	PK11MergeLog *log;
  1.2988 +	char *modspec = PR_smprintf(
  1.2989 +		"configDir='%s' certPrefix='%s' tokenDescription='%s'",
  1.2990 +		sourceDir, srcCertPrefix, 
  1.2991 +		*upgradeTokenName ? upgradeTokenName : "Source Database");
  1.2992 +
  1.2993 +	if (!modspec) {
  1.2994 +	    rv = SECFailure;
  1.2995 +	    goto shutdown;
  1.2996 +	}
  1.2997 +
  1.2998 +	sourceSlot = SECMOD_OpenUserDB(modspec);
  1.2999 +	PR_smprintf_free(modspec);
  1.3000 +	if (!sourceSlot) {
  1.3001 +	    SECU_PrintError(progName, "couldn't open source database");
  1.3002 +	    rv = SECFailure;
  1.3003 +	    goto shutdown;
  1.3004 +	}
  1.3005 +
  1.3006 +	rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
  1.3007 +	if (rv != SECSuccess) {
  1.3008 +	    SECU_PrintError(progName, "Couldn't get password for %s",
  1.3009 +					PK11_GetTokenName(slot));
  1.3010 +	    goto merge_fail;
  1.3011 +	}
  1.3012 +
  1.3013 +	rv = PK11_Authenticate(sourceSlot, PR_FALSE, &pwdata2);
  1.3014 +	if (rv != SECSuccess) {
  1.3015 +	    SECU_PrintError(progName, "Couldn't get password for %s",
  1.3016 +					PK11_GetTokenName(sourceSlot));
  1.3017 +	    goto merge_fail;
  1.3018 +	}
  1.3019 +
  1.3020 +	log = PK11_CreateMergeLog();
  1.3021 +	if (!log) {
  1.3022 +	    rv = SECFailure;
  1.3023 +	    SECU_PrintError(progName, "couldn't create error log");
  1.3024 +	    goto merge_fail;
  1.3025 +	}
  1.3026 +
  1.3027 +	rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
  1.3028 +	if (rv != SECSuccess) {
  1.3029 +	    DumpMergeLog(progName, log);
  1.3030 +	}
  1.3031 +	PK11_DestroyMergeLog(log);
  1.3032 +
  1.3033 +merge_fail:
  1.3034 +	SECMOD_CloseUserDB(sourceSlot);
  1.3035 +	PK11_FreeSlot(sourceSlot);
  1.3036 +	goto shutdown;
  1.3037 +    }
  1.3038 +
  1.3039 +    /* The following 8 options are mutually exclusive with all others. */
  1.3040 +
  1.3041 +    /*  List certs (-L)  */
  1.3042 +    if (certutil.commands[cmd_ListCerts].activated) {
  1.3043 +	if (certutil.options[opt_DumpExtensionValue].activated) {
  1.3044 +	    const char *oid_str;
  1.3045 +	    SECItem oid_item;
  1.3046 +            SECStatus srv;
  1.3047 +	    oid_item.data = NULL;
  1.3048 +	    oid_item.len = 0;
  1.3049 +	    oid_str = certutil.options[opt_DumpExtensionValue].arg;
  1.3050 +	    srv = GetOidFromString(NULL, &oid_item, oid_str, strlen(oid_str));
  1.3051 +	    if (srv != SECSuccess) {
  1.3052 +         	SECU_PrintError(progName, "malformed extension OID %s",
  1.3053 +				oid_str);
  1.3054 +		goto shutdown;
  1.3055 +	    }
  1.3056 +	    rv = ListCerts(certHandle, name, email, slot,
  1.3057 +			   PR_TRUE /*binary*/, PR_FALSE /*ascii*/,
  1.3058 +			   &oid_item,
  1.3059 +			   outFile, &pwdata);
  1.3060 +	} else {
  1.3061 +	    rv = ListCerts(certHandle, name, email, slot,
  1.3062 +			   certutil.options[opt_BinaryDER].activated,
  1.3063 +			   certutil.options[opt_ASCIIForIO].activated,
  1.3064 +			   NULL, outFile, &pwdata);
  1.3065 +	}
  1.3066 +	goto shutdown;
  1.3067 +    }
  1.3068 +    if (certutil.commands[cmd_DumpChain].activated) {
  1.3069 +	rv = DumpChain(certHandle, name,
  1.3070 +                       certutil.options[opt_ASCIIForIO].activated);
  1.3071 +	goto shutdown;
  1.3072 +    }
  1.3073 +    /*  XXX needs work  */
  1.3074 +    /*  List keys (-K)  */
  1.3075 +    if (certutil.commands[cmd_ListKeys].activated) {
  1.3076 +	rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/,
  1.3077 +	              &pwdata);
  1.3078 +	goto shutdown;
  1.3079 +    }
  1.3080 +    /*  List modules (-U)  */
  1.3081 +    if (certutil.commands[cmd_ListModules].activated) {
  1.3082 +	rv = ListModules();
  1.3083 +	goto shutdown;
  1.3084 +    }
  1.3085 +    /*  Delete cert (-D)  */
  1.3086 +    if (certutil.commands[cmd_DeleteCert].activated) {
  1.3087 +	rv = DeleteCert(certHandle, name);
  1.3088 +	goto shutdown;
  1.3089 +    }
  1.3090 +    /*  Delete key (-F)  */
  1.3091 +    if (certutil.commands[cmd_DeleteKey].activated) {
  1.3092 +	rv = DeleteKey(name, &pwdata);
  1.3093 +	goto shutdown;
  1.3094 +    }
  1.3095 +    /*  Modify trust attribute for cert (-M)  */
  1.3096 +    if (certutil.commands[cmd_ModifyCertTrust].activated) {
  1.3097 +	rv = ChangeTrustAttributes(certHandle, slot, name, 
  1.3098 +	                           certutil.options[opt_Trust].arg, &pwdata);
  1.3099 +	goto shutdown;
  1.3100 +    }
  1.3101 +    /*  Change key db password (-W) (future - change pw to slot?)  */
  1.3102 +    if (certutil.commands[cmd_ChangePassword].activated) {
  1.3103 +	rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
  1.3104 +				certutil.options[opt_NewPasswordFile].arg);
  1.3105 +	goto shutdown;
  1.3106 +    }
  1.3107 +    /*  Reset the a token */
  1.3108 +    if (certutil.commands[cmd_TokenReset].activated) {
  1.3109 +	char *sso_pass = "";
  1.3110 +
  1.3111 +	if (certutil.options[opt_SSOPass].activated) {
  1.3112 +	    sso_pass = certutil.options[opt_SSOPass].arg;
  1.3113 + 	}
  1.3114 +	rv = PK11_ResetToken(slot,sso_pass);
  1.3115 +
  1.3116 +	goto shutdown;
  1.3117 +    }
  1.3118 +    /*  Check cert validity against current time (-V)  */
  1.3119 +    if (certutil.commands[cmd_CheckCertValidity].activated) {
  1.3120 +	/* XXX temporary hack for fips - must log in to get priv key */
  1.3121 +	if (certutil.options[opt_VerifySig].activated) {
  1.3122 +	    if (slot && PK11_NeedLogin(slot)) {
  1.3123 +                SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, &pwdata);
  1.3124 +                if (newrv != SECSuccess) {
  1.3125 +                    SECU_PrintError(progName, "could not authenticate to token %s.",
  1.3126 +                                    PK11_GetTokenName(slot));
  1.3127 +                    goto shutdown;
  1.3128 +                }
  1.3129 +            }
  1.3130 +	}
  1.3131 +	rv = ValidateCert(certHandle, name, 
  1.3132 +	                  certutil.options[opt_ValidityTime].arg,
  1.3133 +			  certutil.options[opt_Usage].arg,
  1.3134 +			  certutil.options[opt_VerifySig].activated,
  1.3135 +			  certutil.options[opt_DetailedInfo].activated,
  1.3136 +			  certutil.options[opt_ASCIIForIO].activated,
  1.3137 +	                  &pwdata);
  1.3138 +	if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS)
  1.3139 +            SECU_PrintError(progName, "validation failed");
  1.3140 +	goto shutdown;
  1.3141 +    }
  1.3142 +
  1.3143 +    /*
  1.3144 +     *  Key generation
  1.3145 +     */
  1.3146 +
  1.3147 +    /*  These commands may require keygen.  */
  1.3148 +    if (certutil.commands[cmd_CertReq].activated ||
  1.3149 +        certutil.commands[cmd_CreateAndAddCert].activated ||
  1.3150 +	certutil.commands[cmd_GenKeyPair].activated) {
  1.3151 +	if (keysource) {
  1.3152 +	    CERTCertificate *keycert;
  1.3153 +	    keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource);
  1.3154 +	    if (!keycert) {
  1.3155 +		keycert = PK11_FindCertFromNickname(keysource, NULL);
  1.3156 +		if (!keycert) {
  1.3157 +		    SECU_PrintError(progName,
  1.3158 +			    "%s is neither a key-type nor a nickname", keysource);
  1.3159 +		    return SECFailure;
  1.3160 +		}
  1.3161 +	    }
  1.3162 +	    privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
  1.3163 +	    if (privkey)
  1.3164 +		pubkey = CERT_ExtractPublicKey(keycert);
  1.3165 +	    if (!pubkey) {
  1.3166 +		SECU_PrintError(progName,
  1.3167 +				"Could not get keys from cert %s", keysource);
  1.3168 +		rv = SECFailure;
  1.3169 +		CERT_DestroyCertificate(keycert);
  1.3170 +		goto shutdown;
  1.3171 +	    }
  1.3172 +	    keytype = privkey->keyType;
  1.3173 +	    /* On CertReq for renewal if no subject has been
  1.3174 +	     * specified obtain it from the certificate. 
  1.3175 +	     */
  1.3176 +	    if (certutil.commands[cmd_CertReq].activated && !subject) {
  1.3177 +	        subject = CERT_AsciiToName(keycert->subjectName);
  1.3178 +	        if (!subject) {
  1.3179 +	            SECU_PrintError(progName,
  1.3180 +			"Could not get subject from certificate %s", keysource);
  1.3181 +	            CERT_DestroyCertificate(keycert);
  1.3182 +	            rv = SECFailure;
  1.3183 +	            goto shutdown;
  1.3184 +	        }
  1.3185 +	    }
  1.3186 +	    CERT_DestroyCertificate(keycert);
  1.3187 +	} else {
  1.3188 +	    privkey = 
  1.3189 +		CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
  1.3190 +					    publicExponent, 
  1.3191 +					    certutil.options[opt_NoiseFile].arg,
  1.3192 +					    &pubkey, 
  1.3193 +					    certutil.options[opt_PQGFile].arg,
  1.3194 +					    keyAttrFlags,
  1.3195 +					    keyOpFlagsOn,
  1.3196 +					    keyOpFlagsOff,
  1.3197 +					    &pwdata);
  1.3198 +	    if (privkey == NULL) {
  1.3199 +		SECU_PrintError(progName, "unable to generate key(s)\n");
  1.3200 +		rv = SECFailure;
  1.3201 +		goto shutdown;
  1.3202 +	    }
  1.3203 +	}
  1.3204 +	privkey->wincx = &pwdata;
  1.3205 +	PORT_Assert(pubkey != NULL);
  1.3206 +
  1.3207 +	/*  If all that was needed was keygen, exit.  */
  1.3208 +	if (certutil.commands[cmd_GenKeyPair].activated) {
  1.3209 +	    rv = SECSuccess;
  1.3210 +	    goto shutdown;
  1.3211 +	}
  1.3212 +    }
  1.3213 +
  1.3214 +    /* If we need a list of extensions convert the flags into list format */
  1.3215 +    if (certutil.commands[cmd_CertReq].activated ||
  1.3216 +        certutil.commands[cmd_CreateAndAddCert].activated ||
  1.3217 +        certutil.commands[cmd_CreateNewCert].activated) {
  1.3218 +        certutil_extns[ext_keyUsage].activated =
  1.3219 +            certutil.options[opt_AddCmdKeyUsageExt].activated;
  1.3220 +        if (!certutil_extns[ext_keyUsage].activated) {
  1.3221 +            certutil_extns[ext_keyUsage].activated =
  1.3222 +                certutil.options[opt_AddKeyUsageExt].activated;
  1.3223 +        } else {
  1.3224 +            certutil_extns[ext_keyUsage].arg =
  1.3225 +                certutil.options[opt_AddCmdKeyUsageExt].arg;
  1.3226 +        }
  1.3227 +        certutil_extns[ext_basicConstraint].activated =
  1.3228 +				certutil.options[opt_AddBasicConstraintExt].activated;
  1.3229 +        certutil_extns[ext_nameConstraints].activated =
  1.3230 +                                certutil.options[opt_AddNameConstraintsExt].activated;
  1.3231 +        certutil_extns[ext_authorityKeyID].activated =
  1.3232 +				certutil.options[opt_AddAuthorityKeyIDExt].activated;
  1.3233 +        certutil_extns[ext_subjectKeyID].activated =
  1.3234 +				certutil.options[opt_AddSubjectKeyIDExt].activated;
  1.3235 +        certutil_extns[ext_CRLDistPts].activated =
  1.3236 +				certutil.options[opt_AddCRLDistPtsExt].activated;
  1.3237 +        certutil_extns[ext_NSCertType].activated =
  1.3238 +            certutil.options[opt_AddCmdNSCertTypeExt].activated;
  1.3239 +        if (!certutil_extns[ext_NSCertType].activated) {
  1.3240 +            certutil_extns[ext_NSCertType].activated =
  1.3241 +                certutil.options[opt_AddNSCertTypeExt].activated;
  1.3242 +        } else {
  1.3243 +            certutil_extns[ext_NSCertType].arg =
  1.3244 +                certutil.options[opt_AddCmdNSCertTypeExt].arg;
  1.3245 +        }
  1.3246 +
  1.3247 +        certutil_extns[ext_extKeyUsage].activated =
  1.3248 +            certutil.options[opt_AddCmdExtKeyUsageExt].activated;
  1.3249 +        if (!certutil_extns[ext_extKeyUsage].activated) {
  1.3250 +            certutil_extns[ext_extKeyUsage].activated =
  1.3251 +                certutil.options[opt_AddExtKeyUsageExt].activated;
  1.3252 +        } else {
  1.3253 +            certutil_extns[ext_extKeyUsage].arg =
  1.3254 +                certutil.options[opt_AddCmdExtKeyUsageExt].arg;
  1.3255 +        }
  1.3256 +        certutil_extns[ext_subjectAltName].activated =
  1.3257 +                certutil.options[opt_AddSubjectAltNameExt].activated;
  1.3258 +        if (certutil_extns[ext_subjectAltName].activated) {
  1.3259 +            certutil_extns[ext_subjectAltName].arg =
  1.3260 +                certutil.options[opt_AddSubjectAltNameExt].arg;
  1.3261 +        }
  1.3262 +
  1.3263 +        certutil_extns[ext_authInfoAcc].activated =
  1.3264 +				certutil.options[opt_AddAuthInfoAccExt].activated;
  1.3265 +        certutil_extns[ext_subjInfoAcc].activated =
  1.3266 +				certutil.options[opt_AddSubjInfoAccExt].activated;
  1.3267 +        certutil_extns[ext_certPolicies].activated =
  1.3268 +				certutil.options[opt_AddCertPoliciesExt].activated;
  1.3269 +        certutil_extns[ext_policyMappings].activated =
  1.3270 +				certutil.options[opt_AddPolicyMapExt].activated;
  1.3271 +        certutil_extns[ext_policyConstr].activated =
  1.3272 +				certutil.options[opt_AddPolicyConstrExt].activated;
  1.3273 +        certutil_extns[ext_inhibitAnyPolicy].activated =
  1.3274 +				certutil.options[opt_AddInhibAnyExt].activated;
  1.3275 +    }
  1.3276 +
  1.3277 +    /* -A -C or -E    Read inFile */
  1.3278 +    if (certutil.commands[cmd_CreateNewCert].activated ||
  1.3279 +	certutil.commands[cmd_AddCert].activated ||
  1.3280 +	certutil.commands[cmd_AddEmailCert].activated) {
  1.3281 +	PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
  1.3282 +	rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
  1.3283 +				  certutil.options[opt_ASCIIForIO].activated,
  1.3284 +				  PR_TRUE);
  1.3285 +	if (rv)
  1.3286 +	    goto shutdown;
  1.3287 +    }
  1.3288 +
  1.3289 +    /*
  1.3290 +     *  Certificate request
  1.3291 +     */
  1.3292 +
  1.3293 +    /*  Make a cert request (-R).  */
  1.3294 +    if (certutil.commands[cmd_CertReq].activated) {
  1.3295 +	rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
  1.3296 +	             certutil.options[opt_PhoneNumber].arg,
  1.3297 +	             certutil.options[opt_ASCIIForIO].activated,
  1.3298 +		     certutil.options[opt_ExtendedEmailAddrs].arg,
  1.3299 +		     certutil.options[opt_ExtendedDNSNames].arg,
  1.3300 +                     certutil_extns,
  1.3301 +		     (certutil.options[opt_GenericExtensions].activated ?
  1.3302 +		         certutil.options[opt_GenericExtensions].arg : NULL),
  1.3303 +                     &certReqDER);
  1.3304 +	if (rv)
  1.3305 +	    goto shutdown;
  1.3306 +	privkey->wincx = &pwdata;
  1.3307 +    }
  1.3308 +
  1.3309 +    /*
  1.3310 +     *  Certificate creation
  1.3311 +     */
  1.3312 +
  1.3313 +    /*  If making and adding a cert, create a cert request file first without
  1.3314 +     *  any extensions, then load it with the command line extensions
  1.3315 +     *  and output the cert to another file.
  1.3316 +     */
  1.3317 +    if (certutil.commands[cmd_CreateAndAddCert].activated) {
  1.3318 +	static certutilExtnList nullextnlist = {{PR_FALSE, NULL}};
  1.3319 +	rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
  1.3320 +	             certutil.options[opt_PhoneNumber].arg,
  1.3321 +		     PR_FALSE, /* do not BASE64-encode regardless of -a option */
  1.3322 +		     NULL,
  1.3323 +		     NULL,
  1.3324 +                     nullextnlist,
  1.3325 +		     (certutil.options[opt_GenericExtensions].activated ?
  1.3326 +		         certutil.options[opt_GenericExtensions].arg : NULL),
  1.3327 +		     &certReqDER);
  1.3328 +	if (rv) 
  1.3329 +	    goto shutdown;
  1.3330 +	privkey->wincx = &pwdata;
  1.3331 +    }
  1.3332 +
  1.3333 +    /*  Create a certificate (-C or -S).  */
  1.3334 +    if (certutil.commands[cmd_CreateAndAddCert].activated ||
  1.3335 +         certutil.commands[cmd_CreateNewCert].activated) {
  1.3336 +	rv = CreateCert(certHandle, slot,
  1.3337 +	                certutil.options[opt_IssuerName].arg,
  1.3338 +			&certReqDER, &privkey, &pwdata, hashAlgTag,
  1.3339 +	                serialNumber, warpmonths, validityMonths,
  1.3340 +		        certutil.options[opt_ExtendedEmailAddrs].arg,
  1.3341 +		        certutil.options[opt_ExtendedDNSNames].arg,
  1.3342 +		        certutil.options[opt_ASCIIForIO].activated &&
  1.3343 +			    certutil.commands[cmd_CreateNewCert].activated,
  1.3344 +	                certutil.options[opt_SelfSign].activated,
  1.3345 +	                certutil_extns,
  1.3346 +			(certutil.options[opt_GenericExtensions].activated ?
  1.3347 +			    certutil.options[opt_GenericExtensions].arg : NULL),
  1.3348 +                        certVersion,
  1.3349 +			&certDER);
  1.3350 +	if (rv) 
  1.3351 +	    goto shutdown;
  1.3352 +    }
  1.3353 +
  1.3354 +    /* 
  1.3355 +     * Adding a cert to the database (or slot)
  1.3356 +     */
  1.3357 +
  1.3358 +    /* -A -E or -S    Add the cert to the DB */
  1.3359 +    if (certutil.commands[cmd_CreateAndAddCert].activated ||
  1.3360 +         certutil.commands[cmd_AddCert].activated ||
  1.3361 +	 certutil.commands[cmd_AddEmailCert].activated) {
  1.3362 +	if (strstr(certutil.options[opt_Trust].arg, "u")) {
  1.3363 +	    fprintf(stderr, "Notice: Trust flag u is set automatically if the "
  1.3364 +			    "private key is present.\n");
  1.3365 +	}
  1.3366 +	rv = AddCert(slot, certHandle, name, 
  1.3367 +	             certutil.options[opt_Trust].arg,
  1.3368 +	             &certDER,
  1.3369 +	             certutil.commands[cmd_AddEmailCert].activated,&pwdata);
  1.3370 +	if (rv) 
  1.3371 +	    goto shutdown;
  1.3372 +    }
  1.3373 +
  1.3374 +    if (certutil.commands[cmd_CertReq].activated ||
  1.3375 +	certutil.commands[cmd_CreateNewCert].activated) {
  1.3376 +	SECItem * item = certutil.commands[cmd_CertReq].activated ? &certReqDER
  1.3377 +								  : &certDER;
  1.3378 +	PRInt32 written = PR_Write(outFile, item->data, item->len);
  1.3379 +	if (written < 0 || (PRUint32) written != item->len) {
  1.3380 +	    rv = SECFailure;
  1.3381 +	}
  1.3382 +    }
  1.3383 +
  1.3384 +shutdown:
  1.3385 +    if (slot) {
  1.3386 +	PK11_FreeSlot(slot);
  1.3387 +    }
  1.3388 +    if (privkey) {
  1.3389 +	SECKEY_DestroyPrivateKey(privkey);
  1.3390 +    }
  1.3391 +    if (pubkey) {
  1.3392 +	SECKEY_DestroyPublicKey(pubkey);
  1.3393 +    }
  1.3394 +    if (subject) {
  1.3395 +	CERT_DestroyName(subject);
  1.3396 +    }
  1.3397 +    if (name) {
  1.3398 +	PL_strfree(name);
  1.3399 +    }
  1.3400 +    if (inFile && inFile != PR_STDIN) {
  1.3401 +	PR_Close(inFile);
  1.3402 +    }
  1.3403 +    if (outFile && outFile != PR_STDOUT) {
  1.3404 +	PR_Close(outFile);
  1.3405 +    }
  1.3406 +    SECITEM_FreeItem(&certReqDER, PR_FALSE);
  1.3407 +    SECITEM_FreeItem(&certDER, PR_FALSE);
  1.3408 +    if (pwdata.data && pwdata.source == PW_PLAINTEXT) {
  1.3409 +	/* Allocated by a PL_strdup call in SECU_GetModulePassword. */
  1.3410 +	PL_strfree(pwdata.data);
  1.3411 +    }
  1.3412 +
  1.3413 +    /* Open the batch command file.
  1.3414 +     *
  1.3415 +     * - If -B <command line> option is specified, the contents in the
  1.3416 +     * command file will be interpreted as subsequent certutil
  1.3417 +     * commands to be executed in the current certutil process
  1.3418 +     * context after the current certutil command has been executed.
  1.3419 +     * - Each line in the command file consists of the command
  1.3420 +     * line arguments for certutil.
  1.3421 +     * - The -d <configdir> option will be ignored if specified in the
  1.3422 +     * command file.
  1.3423 +     * - Quoting with double quote characters ("...") is supported
  1.3424 +     * to allow white space in a command line argument.  The
  1.3425 +     * double quote character cannot be escaped and quoting cannot
  1.3426 +     * be nested in this version.
  1.3427 +     * - each line in the batch file is limited to 512 characters
  1.3428 +    */
  1.3429 +
  1.3430 +    if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) {
  1.3431 +	FILE* batchFile = NULL;
  1.3432 +        char *nextcommand = NULL;
  1.3433 +	PRInt32 cmd_len = 0, buf_size = 0;
  1.3434 +	static const int increment = 512;
  1.3435 +
  1.3436 +        if (!certutil.options[opt_InputFile].activated ||
  1.3437 +            !certutil.options[opt_InputFile].arg) {
  1.3438 +	    PR_fprintf(PR_STDERR,
  1.3439 +	               "%s:  no batch input file specified.\n",
  1.3440 +	               progName);
  1.3441 +	    return 255;
  1.3442 +        }
  1.3443 +        batchFile = fopen(certutil.options[opt_InputFile].arg, "r");
  1.3444 +        if (!batchFile) {
  1.3445 +	    PR_fprintf(PR_STDERR,
  1.3446 +	               "%s:  unable to open \"%s\" for reading (%ld, %ld).\n",
  1.3447 +	               progName, certutil.options[opt_InputFile].arg,
  1.3448 +	               PR_GetError(), PR_GetOSError());
  1.3449 +	    return 255;
  1.3450 +        }
  1.3451 +        /* read and execute command-lines in a loop */
  1.3452 +        while ( SECSuccess == rv ) {
  1.3453 +            PRBool invalid = PR_FALSE;
  1.3454 +            int newargc = 2;
  1.3455 +            char* space = NULL;
  1.3456 +            char* nextarg = NULL;
  1.3457 +            char** newargv = NULL;
  1.3458 +            char* crlf;
  1.3459 +
  1.3460 +	    if (cmd_len + increment > buf_size) {
  1.3461 +	        char * new_buf;
  1.3462 +		buf_size += increment;
  1.3463 +	        new_buf = PORT_Realloc(nextcommand, buf_size);
  1.3464 +		if (!new_buf) {
  1.3465 +		    PR_fprintf(PR_STDERR, "%s: PORT_Realloc(%ld) failed\n",
  1.3466 +			       progName, buf_size);
  1.3467 +		    break;
  1.3468 +		}
  1.3469 +		nextcommand = new_buf;
  1.3470 +		nextcommand[cmd_len] = '\0';
  1.3471 +	    }
  1.3472 +	    if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) {
  1.3473 +		break;
  1.3474 +	    }
  1.3475 +            crlf = PORT_Strrchr(nextcommand, '\n');
  1.3476 +            if (crlf) {
  1.3477 +                *crlf = '\0';
  1.3478 +            }
  1.3479 +	    cmd_len = strlen(nextcommand);
  1.3480 +	    if (cmd_len && nextcommand[cmd_len - 1] == '\\') {
  1.3481 +	        nextcommand[--cmd_len] = '\0';
  1.3482 +		continue;
  1.3483 +	    }
  1.3484 +
  1.3485 +            /* we now need to split the command into argc / argv format */
  1.3486 +
  1.3487 +            newargv = PORT_Alloc(sizeof(char*)*(newargc+1));
  1.3488 +            newargv[0] = progName;
  1.3489 +            newargv[1] = nextcommand;
  1.3490 +            nextarg = nextcommand;
  1.3491 +            while ((space = PORT_Strpbrk(nextarg, " \f\n\r\t\v")) ) {
  1.3492 +                while (isspace(*space) ) {
  1.3493 +                    *space = '\0';
  1.3494 +                    space ++;
  1.3495 +                }
  1.3496 +                if (*space == '\0') {
  1.3497 +                    break;
  1.3498 +                } else if (*space != '\"') {
  1.3499 +                    nextarg = space;
  1.3500 +                } else {
  1.3501 +                    char* closingquote = strchr(space+1, '\"');
  1.3502 +                    if (closingquote) {
  1.3503 +                        *closingquote = '\0';
  1.3504 +                        space++;
  1.3505 +                        nextarg = closingquote+1;
  1.3506 +                    } else {
  1.3507 +                        invalid = PR_TRUE;
  1.3508 +                        nextarg = space;
  1.3509 +                    }
  1.3510 +                }
  1.3511 +                newargc++;
  1.3512 +                newargv = PORT_Realloc(newargv, sizeof(char*)*(newargc+1));
  1.3513 +                newargv[newargc-1] = space;
  1.3514 +            }
  1.3515 +            newargv[newargc] = NULL;
  1.3516 +            
  1.3517 +            /* invoke next command */
  1.3518 +            if (PR_TRUE == invalid) {
  1.3519 +                PR_fprintf(PR_STDERR, "Missing closing quote in batch command :\n%s\nNot executed.\n",
  1.3520 +                           nextcommand);
  1.3521 +                rv = SECFailure;
  1.3522 +            } else {
  1.3523 +                if (0 != certutil_main(newargc, newargv, PR_FALSE) )
  1.3524 +                    rv = SECFailure;
  1.3525 +            }
  1.3526 +            PORT_Free(newargv);
  1.3527 +	    cmd_len = 0;
  1.3528 +	    nextcommand[0] = '\0';
  1.3529 +        }
  1.3530 +	PORT_Free(nextcommand);
  1.3531 +        fclose(batchFile);
  1.3532 +    }
  1.3533 +
  1.3534 +    if ((initialized == PR_TRUE) && NSS_Shutdown() != SECSuccess) {
  1.3535 +        exit(1);
  1.3536 +    }
  1.3537 +    if (rv == SECSuccess) {
  1.3538 +	return 0;
  1.3539 +    } else {
  1.3540 +	return 255;
  1.3541 +    }
  1.3542 +}
  1.3543 +
  1.3544 +int
  1.3545 +main(int argc, char **argv)
  1.3546 +{
  1.3547 +    int rv = certutil_main(argc, argv, PR_TRUE);
  1.3548 +    PL_ArenaFinish();
  1.3549 +    PR_Cleanup();
  1.3550 +    return rv;
  1.3551 +}
  1.3552 +

mercurial