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 +