Bug Summary

File:s/cmd/certutil/certutil.c
Warning:line 62, column 13
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name certutil.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/certutil -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/certutil -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D NSPR20 -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/dbm -I ../../../dist/public/seccmd -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c certutil.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/*
6** certutil.c
7**
8** utility for managing certificates and the cert database
9**
10*/
11#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
14
15#if defined(WIN32)
16#include "fcntl.h"
17#include "io.h"
18#endif
19
20#include "secutil.h"
21
22#if defined(XP_UNIX1)
23#include <unistd.h>
24#endif
25
26#include "nspr.h"
27#include "prtypes.h"
28#include "prtime.h"
29#include "prlong.h"
30
31#include "pk11func.h"
32#include "secasn1.h"
33#include "cert.h"
34#include "cryptohi.h"
35#include "secoid.h"
36#include "certdb.h"
37#include "nss.h"
38#include "certutil.h"
39#include "basicutil.h"
40#include "ssl.h"
41
42#define MIN_KEY_BITS512 512
43/* MAX_KEY_BITS should agree with RSA_MAX_MODULUS_BITS in freebl */
44#define MAX_KEY_BITS8192 8192
45#define DEFAULT_KEY_BITS2048 2048
46
47#define GEN_BREAK(e)rv = e; break; \
48 rv = e; \
49 break;
50
51char *progName;
52
53static SECStatus
54ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
55 CERTCertTrust *trust, PK11SlotInfo *slot, void *pwdata)
56{
57 SECStatus rv;
58
59 rv = CERT_ChangeCertTrust(handle, cert, trust);
60 if (rv != SECSuccess) {
61 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
62 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
Value stored to 'rv' is never read
63 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
64 PK11SlotInfo *internalslot;
65 internalslot = PK11_GetInternalKeySlot();
66 rv = PK11_Authenticate(internalslot, PR_TRUE1, pwdata);
67 if (rv != SECSuccess) {
68 SECU_PrintError(progName,
69 "could not authenticate to token %s.",
70 PK11_GetTokenName(internalslot));
71 PK11_FreeSlot(internalslot);
72 return SECFailure;
73 }
74 PK11_FreeSlot(internalslot);
75 }
76 rv = CERT_ChangeCertTrust(handle, cert, trust);
77 }
78 }
79 return rv;
80}
81
82static CERTCertificateRequest *
83GetCertRequest(const SECItem *reqDER, void *pwarg)
84{
85 CERTCertificateRequest *certReq = NULL((void*)0);
86 CERTSignedData signedData;
87 PLArenaPool *arena = NULL((void*)0);
88 SECStatus rv;
89
90 do {
91 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
92 if (arena == NULL((void*)0)) {
93 GEN_BREAK(SECFailure)rv = SECFailure; break;;
94 }
95
96 certReq = (CERTCertificateRequest *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificateRequest));
97 if (!certReq) {
98 GEN_BREAK(SECFailure)rv = SECFailure; break;;
99 }
100 certReq->arena = arena;
101
102 /* Since cert request is a signed data, must decode to get the inner
103 data
104 */
105 PORT_Memsetmemset(&signedData, 0, sizeof(signedData));
106 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &signedData,
107 SEC_ASN1_GET(CERT_SignedDataTemplate)CERT_SignedDataTemplate, reqDER);
108 if (rv) {
109 break;
110 }
111 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, certReq,
112 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate, &signedData.data);
113 if (rv) {
114 break;
115 }
116 rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
117 &certReq->subjectPublicKeyInfo, pwarg);
118 } while (0);
119
120 if (rv) {
121 SECU_PrintError(progName, "bad certificate request\n");
122 if (arena) {
123 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
124 }
125 certReq = NULL((void*)0);
126 }
127
128 return certReq;
129}
130
131static SECStatus
132AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts,
133 const SECItem *certDER, PRBool emailcert, void *pwdata)
134{
135 CERTCertTrust *trust = NULL((void*)0);
136 CERTCertificate *cert = NULL((void*)0);
137 SECStatus rv;
138
139 do {
140 /* Read in an ASCII cert and return a CERTCertificate */
141 cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len);
142 if (!cert) {
143 SECU_PrintError(progName, "could not decode certificate");
144 GEN_BREAK(SECFailure)rv = SECFailure; break;;
145 }
146
147 /* Create a cert trust */
148 trust = (CERTCertTrust *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(CERTCertTrust));
149 if (!trust) {
150 SECU_PrintError(progName, "unable to allocate cert trust");
151 GEN_BREAK(SECFailure)rv = SECFailure; break;;
152 }
153
154 rv = CERT_DecodeTrustString(trust, trusts);
155 if (rv) {
156 SECU_PrintError(progName, "unable to decode trust string");
157 GEN_BREAK(SECFailure)rv = SECFailure; break;;
158 }
159
160 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE0, name, PR_FALSE0);
161 if (rv != SECSuccess) {
162 /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have
163 * been coded to take a password arg. */
164 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
165 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
166 if (rv != SECSuccess) {
167 SECU_PrintError(progName,
168 "could not authenticate to token %s.",
169 PK11_GetTokenName(slot));
170 GEN_BREAK(SECFailure)rv = SECFailure; break;;
171 }
172 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE0,
173 name, PR_FALSE0);
174 }
175 if (rv != SECSuccess) {
176 SECU_PrintError(progName,
177 "could not add certificate to token or database");
178 GEN_BREAK(SECFailure)rv = SECFailure; break;;
179 }
180 }
181 rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
182 if (rv != SECSuccess) {
183 SECU_PrintError(progName,
184 "could not change trust on certificate");
185 GEN_BREAK(SECFailure)rv = SECFailure; break;;
186 }
187
188 if (emailcert) {
189 CERT_SaveSMimeProfile(cert, NULL((void*)0), pwdata);
190 }
191
192 } while (0);
193
194 CERT_DestroyCertificate(cert);
195 PORT_FreePORT_Free_Util(trust);
196
197 return rv;
198}
199
200static SECStatus
201CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
202 SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
203 const char *emailAddrs, const char *dnsNames,
204 certutilExtnList extnList, const char *extGeneric,
205 PRBool pssCertificate, /*out*/ SECItem *result)
206{
207 CERTSubjectPublicKeyInfo *spki;
208 CERTCertificateRequest *cr;
209 SECItem *encoding;
210 SECOidTag signAlgTag;
211 SECStatus rv;
212 PLArenaPool *arena;
213 void *extHandle;
214 SECItem signedReq = { siBuffer, NULL((void*)0), 0 };
215 SECAlgorithmID signAlg;
216 SECItem *params = NULL((void*)0);
217
218 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
219 if (!arena) {
220 SECU_PrintError(progName, "out of memory");
221 return SECFailure;
222 }
223
224 /* Create info about public key */
225 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
226 if (!spki) {
227 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
228 SECU_PrintError(progName, "unable to create subject public key");
229 return SECFailure;
230 }
231
232 /* Change cert type to RSA-PSS, if desired. */
233 if (pssCertificate) {
234 params = SEC_CreateSignatureAlgorithmParameters(arena,
235 NULL((void*)0),
236 SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
237 hashAlgTag,
238 NULL((void*)0),
239 privk);
240 if (!params) {
241 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
242 SECKEY_DestroySubjectPublicKeyInfo(spki);
243 SECU_PrintError(progName, "unable to create RSA-PSS parameters");
244 return SECFailure;
245 }
246
247 spki->algorithm.parameters.data = NULL((void*)0);
248 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &spki->algorithm,
249 SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
250 hashAlgTag == SEC_OID_UNKNOWN ? NULL((void*)0) : params);
251 if (rv != SECSuccess) {
252 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
253 SECKEY_DestroySubjectPublicKeyInfo(spki);
254 SECU_PrintError(progName, "unable to set algorithm ID");
255 return SECFailure;
256 }
257 }
258
259 /* Generate certificate request */
260 cr = CERT_CreateCertificateRequest(subject, spki, NULL((void*)0));
261 SECKEY_DestroySubjectPublicKeyInfo(spki);
262 if (!cr) {
263 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
264 SECU_PrintError(progName, "unable to make certificate request");
265 return SECFailure;
266 }
267
268 extHandle = CERT_StartCertificateRequestAttributes(cr);
269 if (extHandle == NULL((void*)0)) {
270 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
271 CERT_DestroyCertificateRequest(cr);
272 return SECFailure;
273 }
274 if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric) !=
275 SECSuccess) {
276 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
277 CERT_FinishExtensions(extHandle);
278 CERT_DestroyCertificateRequest(cr);
279 return SECFailure;
280 }
281 CERT_FinishExtensions(extHandle);
282 CERT_FinishCertificateRequestAttributes(cr);
283
284 /* Der encode the request */
285 encoding = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, NULL((void*)0), cr,
286 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate);
287 CERT_DestroyCertificateRequest(cr);
288 if (encoding == NULL((void*)0)) {
289 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
290 SECU_PrintError(progName, "der encoding of request failed");
291 return SECFailure;
292 }
293
294 PORT_Memsetmemset(&signAlg, 0, sizeof(signAlg));
295 if (pssCertificate) {
296 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &signAlg,
297 SEC_OID_PKCS1_RSA_PSS_SIGNATURE, params);
298 if (rv != SECSuccess) {
299 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
300 SECU_PrintError(progName, "unable to set algorithm ID");
301 return SECFailure;
302 }
303 } else {
304 signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
305 if (signAlgTag == SEC_OID_UNKNOWN) {
306 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
307 SECU_PrintError(progName, "unknown Key or Hash type");
308 return SECFailure;
309 }
310 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &signAlg, signAlgTag, 0);
311 if (rv != SECSuccess) {
312 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
313 SECU_PrintError(progName, "unable to set algorithm ID");
314 return SECFailure;
315 }
316 }
317
318 /* Sign the request */
319 rv = SEC_DerSignDataWithAlgorithmID(arena, &signedReq,
320 encoding->data, encoding->len,
321 privk, &signAlg);
322 if (rv) {
323 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
324 SECU_PrintError(progName, "signing of data failed");
325 return SECFailure;
326 }
327
328 /* Encode request in specified format */
329 if (ascii) {
330 char *obuf;
331 char *header, *name, *email, *org, *state, *country;
332
333 obuf = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&signedReq);
334 if (!obuf) {
335 goto oom;
336 }
337
338 name = CERT_GetCommonName(subject);
339 if (!name) {
340 name = PORT_StrdupPORT_Strdup_Util("(not specified)");
341 }
342
343 if (!phone)
344 phone = "(not specified)";
345
346 email = CERT_GetCertEmailAddress(subject);
347 if (!email)
348 email = PORT_StrdupPORT_Strdup_Util("(not specified)");
349
350 org = CERT_GetOrgName(subject);
351 if (!org)
352 org = PORT_StrdupPORT_Strdup_Util("(not specified)");
353
354 state = CERT_GetStateName(subject);
355 if (!state)
356 state = PORT_StrdupPORT_Strdup_Util("(not specified)");
357
358 country = CERT_GetCountryName(subject);
359 if (!country)
360 country = PORT_StrdupPORT_Strdup_Util("(not specified)");
361
362 header = PR_smprintf(
363 "\nCertificate request generated by Netscape certutil\n"
364 "Phone: %s\n\n"
365 "Common Name: %s\n"
366 "Email: %s\n"
367 "Organization: %s\n"
368 "State: %s\n"
369 "Country: %s\n\n"
370 "%s\n",
371 phone, name, email, org, state, country, NS_CERTREQ_HEADER"-----BEGIN NEW CERTIFICATE REQUEST-----");
372
373 PORT_FreePORT_Free_Util(name);
374 PORT_FreePORT_Free_Util(email);
375 PORT_FreePORT_Free_Util(org);
376 PORT_FreePORT_Free_Util(state);
377 PORT_FreePORT_Free_Util(country);
378
379 if (header) {
380 char *trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER"-----END NEW CERTIFICATE REQUEST-----");
381 if (trailer) {
382 PRUint32 headerLen = PL_strlen(header);
383 PRUint32 obufLen = PL_strlen(obuf);
384 PRUint32 trailerLen = PL_strlen(trailer);
385 SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), result,
386 headerLen + obufLen + trailerLen);
387 if (result->data) {
388 PORT_Memcpymemcpy(result->data, header, headerLen);
389 PORT_Memcpymemcpy(result->data + headerLen, obuf, obufLen);
390 PORT_Memcpymemcpy(result->data + headerLen + obufLen,
391 trailer, trailerLen);
392 }
393 PR_smprintf_free(trailer);
394 }
395 PR_smprintf_free(header);
396 }
397 PORT_FreePORT_Free_Util(obuf);
398 } else {
399 (void)SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), result, &signedReq);
400 }
401
402 if (!result->data) {
403 oom:
404 SECU_PrintError(progName, "out of memory");
405 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
406 rv = SECFailure;
407 }
408
409 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
410 return rv;
411}
412
413static SECStatus
414ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot,
415 char *name, char *trusts, void *pwdata)
416{
417 SECStatus rv;
418 CERTCertificate *cert;
419 CERTCertTrust *trust;
420
421 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
422 if (!cert) {
423 SECU_PrintError(progName, "could not find certificate named \"%s\"",
424 name);
425 return SECFailure;
426 }
427
428 trust = (CERTCertTrust *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(CERTCertTrust));
429 if (!trust) {
430 SECU_PrintError(progName, "unable to allocate cert trust");
431 return SECFailure;
432 }
433
434 /* This function only decodes these characters: pPwcTCu, */
435 rv = CERT_DecodeTrustString(trust, trusts);
436 if (rv) {
437 SECU_PrintError(progName, "unable to decode trust string");
438 return SECFailure;
439 }
440
441 /* CERT_ChangeCertTrust API does not have a way to pass in
442 * a context, so NSS can't prompt for the password if it needs to.
443 * check to see if the failure was token not logged in and
444 * log in if need be. */
445 rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
446 if (rv != SECSuccess) {
447 SECU_PrintError(progName, "unable to modify trust attributes");
448 return SECFailure;
449 }
450 CERT_DestroyCertificate(cert);
451 PORT_FreePORT_Free_Util(trust);
452
453 return SECSuccess;
454}
455
456static SECStatus
457DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii,
458 PRBool simpleSelfSigned)
459{
460 CERTCertificate *the_cert;
461 CERTCertificateList *chain;
462 int i, j;
463 the_cert = SECU_FindCertByNicknameOrFilename(handle, name,
464 ascii, NULL((void*)0));
465 if (!the_cert) {
466 SECU_PrintError(progName, "Could not find: %s\n", name);
467 return SECFailure;
468 }
469 if (simpleSelfSigned &&
470 SECEqual == SECITEM_CompareItemSECITEM_CompareItem_Util(&the_cert->derIssuer,
471 &the_cert->derSubject)) {
472 printf("\"%s\" [%s]\n\n", the_cert->nickname, the_cert->subjectName);
473 CERT_DestroyCertificate(the_cert);
474 return SECSuccess;
475 }
476
477 chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE1);
478 CERT_DestroyCertificate(the_cert);
479 if (!chain) {
480 SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
481 return SECFailure;
482 }
483 for (i = chain->len - 1; i >= 0; i--) {
484 CERTCertificate *c;
485 c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
486 for (j = i; j < chain->len - 1; j++) {
487 printf(" ");
488 }
489 if (c) {
490 printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
491 CERT_DestroyCertificate(c);
492 } else {
493 printf("(null)\n\n");
494 }
495 }
496 CERT_DestroyCertificateList(chain);
497 return SECSuccess;
498}
499
500static SECStatus
501outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
502 SECItem *extensionOID, PRFileDesc *outfile)
503{
504 SECItem data;
505 PRInt32 numBytes;
506 SECStatus rv = SECFailure;
507 if (extensionOID) {
508 int i;
509 PRBool found = PR_FALSE0;
510 for (i = 0; the_cert->extensions[i] != NULL((void*)0); i++) {
511 CERTCertExtension *extension = the_cert->extensions[i];
512 if (SECITEM_CompareItemSECITEM_CompareItem_Util(&extension->id, extensionOID) == SECEqual) {
513 found = PR_TRUE1;
514 numBytes = PR_Write(outfile, extension->value.data,
515 extension->value.len);
516 rv = SECSuccess;
517 if (numBytes != (PRInt32)extension->value.len) {
518 SECU_PrintSystemError(progName, "error writing extension");
519 rv = SECFailure;
520 }
521 break;
522 }
523 }
524 if (!found) {
525 SECU_PrintSystemError(progName, "extension not found");
526 rv = SECFailure;
527 }
528 } else {
529 data.data = the_cert->derCert.data;
530 data.len = the_cert->derCert.len;
531 if (ascii) {
532 PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
533 BTOA_DataToAsciiBTOA_DataToAscii_Util(data.data, data.len), NS_CERT_TRAILER"-----END CERTIFICATE-----");
534 rv = SECSuccess;
535 } else if (raw) {
536 numBytes = PR_Write(outfile, data.data, data.len);
537 rv = SECSuccess;
538 if (numBytes != (PRInt32)data.len) {
539 SECU_PrintSystemError(progName, "error writing raw cert");
540 rv = SECFailure;
541 }
542 } else {
543 rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL((void*)0));
544 if (rv != SECSuccess) {
545 SECU_PrintError(progName, "problem printing certificate");
546 }
547 }
548 }
549 return rv;
550}
551
552static SECStatus
553listCerts(CERTCertDBHandle *handle, char *name, char *email,
554 PK11SlotInfo *slot, PRBool raw, PRBool ascii,
555 SECItem *extensionOID,
556 PRFileDesc *outfile, void *pwarg)
557{
558 SECStatus rv = SECFailure;
559 CERTCertList *certs;
560 CERTCertListNode *node;
561
562 /* List certs on a non-internal slot. */
563 if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
564 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
565 if (newrv != SECSuccess) {
566 SECU_PrintError(progName, "could not authenticate to token %s.",
567 PK11_GetTokenName(slot));
568 return SECFailure;
569 }
570 }
571 if (name) {
572 CERTCertificate *the_cert =
573 SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL((void*)0));
574 if (!the_cert) {
575 SECU_PrintError(progName, "Could not find cert: %s\n", name);
576 return SECFailure;
577 }
578 /* Here, we have one cert with the desired nickname or email
579 * address. Now, we will attempt to get a list of ALL certs
580 * with the same subject name as the cert we have. That list
581 * should contain, at a minimum, the one cert we have already found.
582 * If the list of certs is empty (NULL), the libraries have failed.
583 */
584 certs = CERT_CreateSubjectCertList(NULL((void*)0), handle, &the_cert->derSubject,
585 PR_Now(), PR_FALSE0);
586 CERT_DestroyCertificate(the_cert);
587 if (!certs) {
588 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
589 SECU_PrintError(progName, "problem printing certificates");
590 return SECFailure;
591 }
592 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
593 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
594 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
595 outfile);
596 if (rv != SECSuccess) {
597 break;
598 }
599 }
600 } else if (email) {
601 certs = PK11_FindCertsFromEmailAddress(email, NULL((void*)0));
602 if (!certs) {
603 SECU_PrintError(progName,
604 "Could not find certificates for email address: %s\n",
605 email);
606 return SECFailure;
607 }
608 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
609 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
610 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
611 outfile);
612 if (rv != SECSuccess) {
613 break;
614 }
615 }
616 } else {
617 certs = PK11_ListCertsInSlot(slot);
618 if (certs) {
619 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
620 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
621 SECU_PrintCertNickname(node, stdoutstdout);
622 }
623 rv = SECSuccess;
624 }
625 }
626 if (certs) {
627 CERT_DestroyCertList(certs);
628 }
629 if (rv) {
630 SECU_PrintError(progName, "problem printing certificate nicknames");
631 return SECFailure;
632 }
633
634 return SECSuccess; /* not rv ?? */
635}
636
637static SECStatus
638ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
639 PK11SlotInfo *slot, PRBool raw, PRBool ascii,
640 SECItem *extensionOID,
641 PRFileDesc *outfile, secuPWData *pwdata)
642{
643 SECStatus rv;
644
645 if (slot && PK11_NeedUserInit(slot)) {
646 printf("\nDatabase needs user init\n");
647 }
648
649 if (!ascii && !raw && !nickname && !email) {
650 PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
651 "Certificate Nickname", "Trust Attributes", "",
652 "SSL,S/MIME,JAR/XPI");
653 }
654 if (slot == NULL((void*)0)) {
655 CERTCertList *list;
656 CERTCertListNode *node;
657
658 list = PK11_ListCerts(PK11CertListAll, pwdata);
659 for (node = CERT_LIST_HEAD(list)((CERTCertListNode *)(&list->list)->next); !CERT_LIST_END(node, list)(((void *)node) == ((void *)&list->list));
660 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
661 SECU_PrintCertNickname(node, stdoutstdout);
662 }
663 CERT_DestroyCertList(list);
664 return SECSuccess;
665 }
666 rv = listCerts(handle, nickname, email, slot, raw, ascii,
667 extensionOID, outfile, pwdata);
668 return rv;
669}
670
671static SECStatus
672DeleteCert(CERTCertDBHandle *handle, char *name, void *pwdata)
673{
674 SECStatus rv;
675 CERTCertificate *cert;
676
677 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
678 if (!cert) {
679 SECU_PrintError(progName, "could not find certificate named \"%s\"",
680 name);
681 return SECFailure;
682 }
683
684 rv = SEC_DeletePermCertificate(cert);
685 CERT_DestroyCertificate(cert);
686 if (rv) {
687 SECU_PrintError(progName, "unable to delete certificate");
688 }
689 return rv;
690}
691
692static SECStatus
693RenameCert(CERTCertDBHandle *handle, char *name, char *newName, void *pwdata)
694{
695 SECStatus rv;
696 CERTCertificate *cert;
697
698 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
699 if (!cert) {
700 SECU_PrintError(progName, "could not find certificate named \"%s\"",
701 name);
702 return SECFailure;
703 }
704
705 rv = __PK11_SetCertificateNickname(cert, newName);
706 CERT_DestroyCertificate(cert);
707 if (rv) {
708 SECU_PrintError(progName, "unable to rename certificate");
709 }
710 return rv;
711}
712
713static SECStatus
714ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
715 char *certUsage, PRBool checkSig, PRBool logit,
716 PRBool ascii, secuPWData *pwdata)
717{
718 SECStatus rv;
719 CERTCertificate *cert = NULL((void*)0);
720 PRTime timeBoundary;
721 SECCertificateUsage usage;
722 CERTVerifyLog reallog;
723 CERTVerifyLog *log = NULL((void*)0);
724
725 if (!certUsage) {
726 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
727 return (SECFailure);
728 }
729
730 switch (*certUsage) {
731 case 'O':
732 usage = certificateUsageStatusResponder(0x0400);
733 break;
734 case 'L':
735 usage = certificateUsageSSLCA(0x0008);
736 break;
737 case 'A':
738 usage = certificateUsageAnyCA(0x0800);
739 break;
740 case 'Y':
741 usage = certificateUsageVerifyCA(0x0100);
742 break;
743 case 'C':
744 usage = certificateUsageSSLClient(0x0001);
745 break;
746 case 'V':
747 usage = certificateUsageSSLServer(0x0002);
748 break;
749 case 'I':
750 usage = certificateUsageIPsec(0x1000);
751 break;
752 case 'S':
753 usage = certificateUsageEmailSigner(0x0010);
754 break;
755 case 'R':
756 usage = certificateUsageEmailRecipient(0x0020);
757 break;
758 case 'J':
759 usage = certificateUsageObjectSigner(0x0040);
760 break;
761 default:
762 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
763 return (SECFailure);
764 }
765 do {
766 cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii,
767 NULL((void*)0));
768 if (!cert) {
769 SECU_PrintError(progName, "could not find certificate named \"%s\"",
770 name);
771 GEN_BREAK(SECFailure)rv = SECFailure; break;
772 }
773
774 if (date != NULL((void*)0)) {
775 rv = DER_AsciiToTimeDER_AsciiToTime_Util(&timeBoundary, date);
776 if (rv) {
777 SECU_PrintError(progName, "invalid input date");
778 GEN_BREAK(SECFailure)rv = SECFailure; break;
779 }
780 } else {
781 timeBoundary = PR_Now();
782 }
783
784 if (logit) {
785 log = &reallog;
786
787 log->count = 0;
788 log->head = NULL((void*)0);
789 log->tail = NULL((void*)0);
790 log->arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
791 if (log->arena == NULL((void*)0)) {
792 SECU_PrintError(progName, "out of memory");
793 GEN_BREAK(SECFailure)rv = SECFailure; break;
794 }
795 }
796
797 rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
798 timeBoundary, pwdata, log, &usage);
799 if (log) {
800 if (log->head == NULL((void*)0)) {
801 fprintf(stdoutstdout, "%s: certificate is valid\n", progName);
802 GEN_BREAK(SECSuccess)rv = SECSuccess; break;
803 } else {
804 char *nick;
805 CERTVerifyLogNode *node;
806
807 node = log->head;
808 while (node) {
809 if (node->cert->nickname != NULL((void*)0)) {
810 nick = node->cert->nickname;
811 } else {
812 nick = node->cert->subjectName;
813 }
814 fprintf(stderrstderr, "%s : %s\n", nick,
815 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
816 CERT_DestroyCertificate(node->cert);
817 node = node->next;
818 }
819 }
820 } else {
821 if (rv != SECSuccess) {
822 PRErrorCode perr = PORT_GetErrorPORT_GetError_Util();
823 fprintf(stdoutstdout, "%s: certificate is invalid: %s\n",
824 progName, SECU_Strerror(perr)PR_ErrorToString((perr), 0));
825 GEN_BREAK(SECFailure)rv = SECFailure; break;
826 }
827 fprintf(stdoutstdout, "%s: certificate is valid\n", progName);
828 GEN_BREAK(SECSuccess)rv = SECSuccess; break;
829 }
830 } while (0);
831
832 if (cert) {
833 CERT_DestroyCertificate(cert);
834 }
835
836 return (rv);
837}
838
839static PRBool
840ItemIsPrintableASCII(const SECItem *item)
841{
842 unsigned char *src = item->data;
843 unsigned int len = item->len;
844 while (len-- > 0) {
845 unsigned char uc = *src++;
846 if (uc < 0x20 || uc > 0x7e)
847 return PR_FALSE0;
848 }
849 return PR_TRUE1;
850}
851
852/* Caller ensures that dst is at least item->len*2+1 bytes long */
853static void
854SECItemToHex(const SECItem *item, char *dst)
855{
856 if (dst && item && item->data) {
857 unsigned char *src = item->data;
858 unsigned int len = item->len;
859 for (; len > 0; --len, dst += 2) {
860 snprintf(dst, 3, "%02x", *src++);
861 }
862 *dst = '\0';
863 }
864}
865
866static const char *const keyTypeName[] = {
867 "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec", "rsaPss", "rsaOaep"
868};
869
870#define MAX_CKA_ID_BIN_LEN20 20
871#define MAX_CKA_ID_STR_LEN40 40
872
873/* output human readable key ID in buffer, which should have at least
874 * MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */
875static void
876formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer)
877{
878 SECItem *ckaID;
879
880 ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
881 if (!ckaID) {
882 strcpy(buffer, "(no CKA_ID)");
883 } else if (ItemIsPrintableASCII(ckaID)) {
884 int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len)((40)<(ckaID->len)?(40):(ckaID->len));
885 buffer[0] = '"';
886 memcpy(buffer + 1, ckaID->data, len);
887 buffer[1 + len] = '"';
888 buffer[2 + len] = '\0';
889 } else {
890 /* print ckaid in hex */
891 SECItem idItem = *ckaID;
892 if (idItem.len > MAX_CKA_ID_BIN_LEN20)
893 idItem.len = MAX_CKA_ID_BIN_LEN20;
894 SECItemToHex(&idItem, buffer);
895 }
896 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(ckaID, PR_TRUE1);
897}
898
899/* print key number, key ID (in hex or ASCII), key label (nickname) */
900static SECStatus
901PrintKey(PRFileDesc *out, const char *nickName, int count,
902 SECKEYPrivateKey *key, void *pwarg)
903{
904 char ckaIDbuf[MAX_CKA_ID_STR_LEN40 + 4];
905 CERTCertificate *cert;
906 KeyType keyType;
907
908 formatPrivateKeyID(key, ckaIDbuf);
909 cert = PK11_GetCertFromPrivateKey(key);
910 if (cert) {
911 keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
912 CERT_DestroyCertificate(cert);
913 } else {
914 keyType = key->keyType;
915 }
916 PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
917 keyTypeName[keyType], ckaIDbuf, nickName);
918
919 return SECSuccess;
920}
921
922/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
923static SECStatus
924ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType,
925 void *pwarg)
926{
927 SECKEYPrivateKeyList *list;
928 SECKEYPrivateKeyListNode *node;
929 int count = 0;
930
931 if (PK11_NeedLogin(slot)) {
932 SECStatus rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
933 if (rv != SECSuccess) {
934 SECU_PrintError(progName, "could not authenticate to token %s.",
935 PK11_GetTokenName(slot));
936 return SECFailure;
937 }
938 }
939
940 if (nickName && nickName[0])
941 list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
942 else
943 list = PK11_ListPrivateKeysInSlot(slot);
944 if (list == NULL((void*)0)) {
945 SECU_PrintError(progName, "problem listing keys");
946 return SECFailure;
947 }
948 for (node = PRIVKEY_LIST_HEAD(list)((SECKEYPrivateKeyListNode *)(&list->list)->next);
949 !PRIVKEY_LIST_END(node, list)(((void *)node) == ((void *)&list->list));
950 node = PRIVKEY_LIST_NEXT(node)((SECKEYPrivateKeyListNode *)node->links.next)) {
951 char *keyName;
952 static const char orphan[] = { "(orphan)" };
953
954 if (keyType != nullKey && keyType != node->key->keyType)
955 continue;
956 keyName = PK11_GetPrivateKeyNickname(node->key);
957 if (!keyName || !keyName[0]) {
958 /* Try extra hard to find nicknames for keys that lack them. */
959 CERTCertificate *cert;
960 PORT_FreePORT_Free_Util((void *)keyName);
961 keyName = NULL((void*)0);
962 cert = PK11_GetCertFromPrivateKey(node->key);
963 if (cert) {
964 if (cert->nickname && cert->nickname[0]) {
965 keyName = PORT_StrdupPORT_Strdup_Util(cert->nickname);
966 } else if (cert->emailAddr && cert->emailAddr[0]) {
967 keyName = PORT_StrdupPORT_Strdup_Util(cert->emailAddr);
968 }
969 CERT_DestroyCertificate(cert);
970 }
971 }
972 if (nickName) {
973 if (!keyName || PL_strcmp(keyName, nickName)) {
974 /* PKCS#11 module returned unwanted keys */
975 PORT_FreePORT_Free_Util((void *)keyName);
976 continue;
977 }
978 }
979 if (!keyName)
980 keyName = (char *)orphan;
981
982 PrintKey(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), keyName, count, node->key, pwarg);
983
984 if (keyName != (char *)orphan)
985 PORT_FreePORT_Free_Util((void *)keyName);
986 count++;
987 }
988 SECKEY_DestroyPrivateKeyList(list);
989
990 if (count == 0) {
991 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "%s: no keys found\n", progName);
992 return SECFailure;
993 }
994 return SECSuccess;
995}
996
997/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
998static SECStatus
999ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
1000 KeyType keyType, PRBool dopriv, secuPWData *pwdata)
1001{
1002 SECStatus rv = SECFailure;
1003 static const char fmt[] =
1004 "%s: Checking token \"%.33s\" in slot \"%.65s\"\n";
1005
1006 if (slot == NULL((void*)0)) {
1007 PK11SlotList *list;
1008 PK11SlotListElement *le;
1009
1010 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, pwdata);
1011 if (list) {
1012 for (le = list->head; le; le = le->next) {
1013 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), fmt, progName,
1014 PK11_GetTokenName(le->slot),
1015 PK11_GetSlotName(le->slot));
1016 rv &= ListKeysInSlot(le->slot, nickName, keyType, pwdata);
1017 }
1018 PK11_FreeSlotList(list);
1019 }
1020 } else {
1021 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), fmt, progName, PK11_GetTokenName(slot),
1022 PK11_GetSlotName(slot));
1023 rv = ListKeysInSlot(slot, nickName, keyType, pwdata);
1024 }
1025 return rv;
1026}
1027
1028static SECStatus
1029DeleteCertAndKey(char *nickname, secuPWData *pwdata)
1030{
1031 SECStatus rv;
1032 CERTCertificate *cert;
1033 PK11SlotInfo *slot;
1034
1035 slot = PK11_GetInternalKeySlot();
1036 if (PK11_NeedLogin(slot)) {
1037 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
1038 if (rv != SECSuccess) {
1039 SECU_PrintError(progName, "could not authenticate to token %s.",
1040 PK11_GetTokenName(slot));
1041 return SECFailure;
1042 }
1043 }
1044 cert = PK11_FindCertFromNickname(nickname, pwdata);
1045 if (!cert) {
1046 PK11_FreeSlot(slot);
1047 return SECFailure;
1048 }
1049 rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
1050 if (rv != SECSuccess) {
1051 SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
1052 }
1053 CERT_DestroyCertificate(cert);
1054 PK11_FreeSlot(slot);
1055 return rv;
1056}
1057
1058static SECKEYPrivateKey *
1059findPrivateKeyByID(PK11SlotInfo *slot, const char *ckaID, secuPWData *pwarg)
1060{
1061 PORTCheapArenaPool arena;
1062 SECItem ckaIDItem = { 0 };
1063 SECKEYPrivateKey *privkey = NULL((void*)0);
1064 SECStatus rv;
1065
1066 if (PK11_NeedLogin(slot)) {
1067 rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
1068 if (rv != SECSuccess) {
1069 SECU_PrintError(progName, "could not authenticate to token %s.",
1070 PK11_GetTokenName(slot));
1071 return NULL((void*)0);
1072 }
1073 }
1074
1075 if (0 == PL_strncasecmp("0x", ckaID, 2)) {
1076 ckaID += 2; /* skip leading "0x" */
1077 }
1078 PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE(2048));
1079 if (SECU_HexString2SECItem(&arena.arena, &ckaIDItem, ckaID)) {
1080 privkey = PK11_FindKeyByKeyID(slot, &ckaIDItem, pwarg);
1081 }
1082 PORT_DestroyCheapArena(&arena);
1083 return privkey;
1084}
1085
1086static SECStatus
1087DeleteKey(SECKEYPrivateKey *privkey, secuPWData *pwarg)
1088{
1089 SECStatus rv;
1090 PK11SlotInfo *slot;
1091
1092 slot = PK11_GetSlotFromPrivateKey(privkey);
1093 if (PK11_NeedLogin(slot)) {
1094 rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
1095 if (rv != SECSuccess) {
1096 SECU_PrintError(progName, "could not authenticate to token %s.",
1097 PK11_GetTokenName(slot));
1098 return SECFailure;
1099 }
1100 }
1101
1102 rv = PK11_DeleteTokenPrivateKey(privkey, PR_TRUE1);
1103 if (rv != SECSuccess) {
1104 char ckaIDbuf[MAX_CKA_ID_STR_LEN40 + 4];
1105 formatPrivateKeyID(privkey, ckaIDbuf);
1106 SECU_PrintError("problem deleting private key \"%s\"\n", ckaIDbuf);
1107 }
1108
1109 PK11_FreeSlot(slot);
1110 return rv;
1111}
1112
1113/*
1114 * L i s t M o d u l e s
1115 *
1116 * Print a list of the PKCS11 modules that are
1117 * available. This is useful for smartcard people to
1118 * make sure they have the drivers loaded.
1119 *
1120 */
1121static SECStatus
1122ListModules(void)
1123{
1124 PK11SlotList *list;
1125 PK11SlotListElement *le;
1126
1127 /* get them all! */
1128 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, NULL((void*)0));
1129 if (list == NULL((void*)0))
1130 return SECFailure;
1131
1132 /* look at each slot*/
1133 for (le = list->head; le; le = le->next) {
1134 char *token_uri = PK11_GetTokenURI(le->slot);
1135 printf("\n");
1136 printf(" slot: %s\n", PK11_GetSlotName(le->slot));
1137 printf(" token: %s\n", PK11_GetTokenName(le->slot));
1138 printf(" uri: %s\n", token_uri);
1139 PORT_FreePORT_Free_Util(token_uri);
1140 }
1141 PK11_FreeSlotList(list);
1142
1143 return SECSuccess;
1144}
1145
1146static void
1147PrintBuildFlags()
1148{
1149#ifdef NSS_FIPS_DISABLED
1150 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "NSS_FIPS_DISABLED\n");
1151#endif
1152#ifdef NSS_NO_INIT_SUPPORT1
1153 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "NSS_NO_INIT_SUPPORT\n");
1154#endif
1155 exit(0);
1156}
1157
1158static void
1159PrintSyntax()
1160{
1161#define FPS fprintf(stderrstderr,
1162 FPS "Type %s -H for more detailed descriptions\n", progName);
1163 FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName);
1164 FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n"
1165 "\t\t [-f pwfile] [-0 SSO-password]\n", progName);
1166 FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
1167 progName);
1168 FPS "\t%s -B -i batch-file\n", progName);
1169 FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
1170 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
1171 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
1172 "\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n"
1173 "\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n"
1174 "\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n"
1175 "\t\t [-8 dns-names] [-a]\n",
1176 progName);
1177 FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
1178 FPS "\t%s --rename -n cert-name --new-n new-cert-name\n"
1179 "\t\t [-d certdir] [-P dbprefix]\n", progName);
1180 FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
1181 progName);
1182 FPS "\t%s -F -n cert-name [-d certdir] [-P dbprefix]\n",
1183 progName);
1184 FPS "\t%s -F -k key-id [-d certdir] [-P dbprefix]\n",
1185 progName);
1186 FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
1187 "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1188 FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
1189 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1190 FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
1191 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1192 FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n",
1193 progName);
1194 FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
1195 FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
1196 progName);
1197 FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
1198 FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
1199 FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
1200 FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
1201 progName);
1202 FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
1203 FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
1204 FPS "\t%s -L [-n cert-name] [-h token-name] [--email email-address]\n",
1205 progName);
1206 FPS "\t\t [-X] [-r] [-a] [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
1207 FPS "\t%s --build-flags\n", progName);
1208 FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
1209 progName);
1210 FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n"
1211 "\t\t [--simple-self-signed]\n",
1212 progName);
1213 FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
1214 "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n"
1215 "\t\t [-g key-size] [-Z hashAlg]\n",
1216 progName);
1217 FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
1218 "\t\t[-X] [-d certdir] [-P dbprefix]\n",
1219 progName);
1220 FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
1221 progName);
1222 FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
1223 "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
1224 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
1225 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
1226 "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
1227 "\t\t [-8 DNS-names]\n"
1228 "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
1229 "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
1230 "\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
1231 FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
1232 exit(1);
1233}
1234
1235enum usage_level {
1236 usage_all = 0,
1237 usage_selected = 1
1238};
1239
1240static void luCommonDetailsAE();
1241
1242static void
1243luA(enum usage_level ul, const char *command)
1244{
1245 int is_my_command = (command && 0 == strcmp(command, "A"));
1246 if (ul == usage_all || !command || is_my_command)
1247 FPS "%-15s Add a certificate to the database (create if needed)\n",
1248 "-A");
1249 if (ul == usage_selected && !is_my_command)
1250 return;
1251 if (ul == usage_all) {
1252 FPS "%-20s\n", " All options under -E apply");
1253 } else {
1254 luCommonDetailsAE();
1255 }
1256}
1257
1258static void
1259luB(enum usage_level ul, const char *command)
1260{
1261 int is_my_command = (command && 0 == strcmp(command, "B"));
1262 if (ul == usage_all || !command || is_my_command)
1263 FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
1264 if (ul == usage_selected && !is_my_command)
1265 return;
1266 FPS "%-20s Specify the batch file\n", " -i batch-file");
1267}
1268
1269static void
1270luE(enum usage_level ul, const char *command)
1271{
1272 int is_my_command = (command && 0 == strcmp(command, "E"));
1273 if (ul == usage_all || !command || is_my_command)
1274 FPS "%-15s Add an Email certificate to the database (create if needed)\n",
1275 "-E");
1276 if (ul == usage_selected && !is_my_command)
1277 return;
1278 luCommonDetailsAE();
1279}
1280
1281static void
1282luCommonDetailsAE()
1283{
1284 FPS "%-20s Specify the nickname of the certificate to add\n",
1285 " -n cert-name");
1286 FPS "%-20s Set the certificate trust attributes:\n",
1287 " -t trustargs");
1288 FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
1289 FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
1290 FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
1291 FPS "%-25s P \t trusted peer\n", "");
1292 FPS "%-25s c \t valid CA\n", "");
1293 FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
1294 FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
1295 FPS "%-25s u \t user cert\n", "");
1296 FPS "%-25s w \t send warning\n", "");
1297 FPS "%-25s g \t make step-up cert\n", "");
1298 FPS "%-20s Specify the password file\n",
1299 " -f pwfile");
1300 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1301 " -d certdir");
1302 FPS "%-20s Cert & Key database prefix\n",
1303 " -P dbprefix");
1304 FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
1305 " -a");
1306 FPS "%-20s Specify the certificate file (default is stdin)\n",
1307 " -i input");
1308 FPS "\n");
1309}
1310
1311static void
1312luC(enum usage_level ul, const char *command)
1313{
1314 int is_my_command = (command && 0 == strcmp(command, "C"));
1315 if (ul == usage_all || !command || is_my_command)
1316 FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
1317 "-C");
1318 if (ul == usage_selected && !is_my_command)
1319 return;
1320 FPS "%-20s The nickname of the issuer cert\n",
1321 " -c issuer-name");
1322 FPS "%-20s The BINARY certificate request file\n",
1323 " -i cert-request ");
1324 FPS "%-20s Output binary cert to this file (default is stdout)\n",
1325 " -o output-cert");
1326 FPS "%-20s Self sign\n",
1327 " -x");
1328 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1329 " --pss-sign");
1330 FPS "%-20s Cert serial number\n",
1331 " -m serial-number");
1332 FPS "%-20s Time Warp\n",
1333 " -w warp-months");
1334 FPS "%-20s Months valid (default is 3)\n",
1335 " -v months-valid");
1336 FPS "%-20s Specify the password file\n",
1337 " -f pwfile");
1338 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1339 " -d certdir");
1340 FPS "%-20s Cert & Key database prefix\n",
1341 " -P dbprefix");
1342 FPS "%-20s \n"
1343 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1344 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1345 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1346 " -Z hashAlg", "", "", "");
1347 FPS "%-20s \n"
1348 "%-20s Create key usage extension. Possible keywords:\n"
1349 "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
1350 "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
1351 "%-20s \"crlSigning\", \"critical\"\n",
1352 " -1 | --keyUsage keyword,keyword,...", "", "", "", "");
1353 FPS "%-20s Create basic constraint extension\n",
1354 " -2 ");
1355 FPS "%-20s Create authority key ID extension\n",
1356 " -3 ");
1357 FPS "%-20s Create crl distribution point extension\n",
1358 " -4 ");
1359 FPS "%-20s \n"
1360 "%-20s Create netscape cert type extension. Possible keywords:\n"
1361 "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
1362 "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
1363 " -5 | --nsCertType keyword,keyword,... ", "", "", "");
1364 FPS "%-20s \n"
1365 "%-20s Create extended key usage extension. Possible keywords:\n"
1366 "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
1367 "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
1368 "%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
1369 "%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
1370 "%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
1371 "%-20s \"critical\"\n",
1372 " -6 | --extKeyUsage keyword,keyword,...", "", "", "", "", "", "", "");
1373 FPS "%-20s Create an email subject alt name extension\n",
1374 " -7 emailAddrs");
1375 FPS "%-20s Create an dns subject alt name extension\n",
1376 " -8 dnsNames");
1377 FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
1378 " -a");
1379 FPS "\n");
1380}
1381
1382static void
1383luG(enum usage_level ul, const char *command)
1384{
1385 int is_my_command = (command && 0 == strcmp(command, "G"));
1386 if (ul == usage_all || !command || is_my_command)
1387 FPS "%-15s Generate a new key pair\n",
1388 "-G");
1389 if (ul == usage_selected && !is_my_command)
1390 return;
1391 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1392 " -h token-name");
1393 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1394 " -k key-type");
1395 FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
1396 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1397 FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
1398 " -y exp");
1399 FPS "%-20s Specify the password file\n",
1400 " -f password-file");
1401 FPS "%-20s Specify the noise file to be used\n",
1402 " -z noisefile");
1403 FPS "%-20s read PQG value from pqgfile (dsa only)\n",
1404 " -q pqgfile");
1405 FPS "%-20s Elliptic curve name (ec only)\n",
1406 " -q curve-name");
1407 FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", "");
1408 FPS "%-20s If a custom token is present, the following curves are also supported:\n", "");
1409 FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
1410 FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
1411 FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
1412 FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
1413 FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
1414 FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
1415 FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
1416 FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
1417 FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
1418 FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
1419 FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
1420 FPS "%-20s c2tnb191v2, c2tnb191v3, \n", "");
1421 FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
1422 FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
1423 FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
1424 FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
1425 FPS "%-20s sect131r1, sect131r2\n", "");
1426 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1427 " -d keydir");
1428 FPS "%-20s Cert & Key database prefix\n",
1429 " -P dbprefix");
1430 FPS "%-20s\n"
1431 "%-20s PKCS #11 key Attributes.\n",
1432 " --keyAttrFlags attrflags", "");
1433 FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
1434 FPS "%-20s selected from the following list of choices:\n", "");
1435 FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
1436 FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
1437 FPS "%-20s\n",
1438 " --keyOpFlagsOn opflags");
1439 FPS "%-20s\n"
1440 "%-20s PKCS #11 key Operation Flags.\n",
1441 " --keyOpFlagsOff opflags", "");
1442 FPS "%-20s Comma separated list of one or more of the following:\n", "");
1443 FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
1444 FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
1445 FPS "\n");
1446}
1447
1448static void
1449luD(enum usage_level ul, const char *command)
1450{
1451 int is_my_command = (command && 0 == strcmp(command, "D"));
1452 if (ul == usage_all || !command || is_my_command)
1453 FPS "%-15s Delete a certificate from the database\n",
1454 "-D");
1455 if (ul == usage_selected && !is_my_command)
1456 return;
1457 FPS "%-20s The nickname of the cert to delete\n",
1458 " -n cert-name");
1459 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1460 " -d certdir");
1461 FPS "%-20s Cert & Key database prefix\n",
1462 " -P dbprefix");
1463 FPS "\n");
1464}
1465
1466static void
1467luF(enum usage_level ul, const char *command)
1468{
1469 int is_my_command = (command && 0 == strcmp(command, "F"));
1470 if (ul == usage_all || !command || is_my_command)
1471 FPS "%-15s Delete a key and associated certificate from the database\n",
1472 "-F");
1473 if (ul == usage_selected && !is_my_command)
1474 return;
1475 FPS "%-20s The nickname of the key to delete\n",
1476 " -n cert-name");
1477 FPS "%-20s The key id of the key to delete, obtained using -K\n",
1478 " -k key-id");
1479 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1480 " -d certdir");
1481 FPS "%-20s Cert & Key database prefix\n",
1482 " -P dbprefix");
1483 FPS "\n");
1484}
1485
1486static void
1487luU(enum usage_level ul, const char *command)
1488{
1489 int is_my_command = (command && 0 == strcmp(command, "U"));
1490 if (ul == usage_all || !command || is_my_command)
1491 FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
1492 "-U");
1493 if (ul == usage_selected && !is_my_command)
1494 return;
1495 FPS "%-20s Module database directory (default is '~/.netscape')\n",
1496 " -d moddir");
1497 FPS "%-20s Cert & Key database prefix\n",
1498 " -P dbprefix");
1499 FPS "%-20s force the database to open R/W\n",
1500 " -X");
1501 FPS "\n");
1502}
1503
1504static void
1505luK(enum usage_level ul, const char *command)
1506{
1507 int is_my_command = (command && 0 == strcmp(command, "K"));
1508 if (ul == usage_all || !command || is_my_command)
1509 FPS "%-15s List all private keys\n",
1510 "-K");
1511 if (ul == usage_selected && !is_my_command)
1512 return;
1513 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1514 " -h token-name ");
1515
1516 FPS "%-20s Key type (\"all\" (default), \"dsa\","
1517 " \"ec\","
1518 " \"rsa\")\n",
1519 " -k key-type");
1520 FPS "%-20s The nickname of the key or associated certificate\n",
1521 " -n name");
1522 FPS "%-20s Specify the password file\n",
1523 " -f password-file");
1524 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1525 " -d keydir");
1526 FPS "%-20s Cert & Key database prefix\n",
1527 " -P dbprefix");
1528 FPS "%-20s force the database to open R/W\n",
1529 " -X");
1530 FPS "\n");
1531}
1532
1533static void
1534luL(enum usage_level ul, const char *command)
1535{
1536 int is_my_command = (command && 0 == strcmp(command, "L"));
1537 if (ul == usage_all || !command || is_my_command)
1538 FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
1539 "-L");
1540 if (ul == usage_selected && !is_my_command)
1541 return;
1542 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1543 " -h token-name ");
1544 FPS "%-20s Pretty print named cert (list all if unspecified)\n",
1545 " -n cert-name");
1546 FPS "%-20s \n"
1547 "%-20s Pretty print cert with email address (list all if unspecified)\n",
1548 " --email email-address", "");
1549 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1550 " -d certdir");
1551 FPS "%-20s Cert & Key database prefix\n",
1552 " -P dbprefix");
1553 FPS "%-20s force the database to open R/W\n",
1554 " -X");
1555 FPS "%-20s For single cert, print binary DER encoding\n",
1556 " -r");
1557 FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
1558 " -a");
1559 FPS "%-20s \n"
1560 "%-20s For single cert, print binary DER encoding of extension OID\n",
1561 " --dump-ext-val OID", "");
1562 FPS "\n");
1563}
1564
1565static void
1566luM(enum usage_level ul, const char *command)
1567{
1568 int is_my_command = (command && 0 == strcmp(command, "M"));
1569 if (ul == usage_all || !command || is_my_command)
1570 FPS "%-15s Modify trust attributes of certificate\n",
1571 "-M");
1572 if (ul == usage_selected && !is_my_command)
1573 return;
1574 FPS "%-20s The nickname of the cert to modify\n",
1575 " -n cert-name");
1576 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1577 " -t trustargs");
1578 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1579 " -d certdir");
1580 FPS "%-20s Cert & Key database prefix\n",
1581 " -P dbprefix");
1582 FPS "\n");
1583}
1584
1585static void
1586luN(enum usage_level ul, const char *command)
1587{
1588 int is_my_command = (command && 0 == strcmp(command, "N"));
1589 if (ul == usage_all || !command || is_my_command)
1590 FPS "%-15s Create a new certificate database\n",
1591 "-N");
1592 if (ul == usage_selected && !is_my_command)
1593 return;
1594 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1595 " -d certdir");
1596 FPS "%-20s Cert & Key database prefix\n",
1597 " -P dbprefix");
1598 FPS "%-20s Specify the password file\n",
1599 " -f password-file");
1600 FPS "%-20s use empty password when creating a new database\n",
1601 " --empty-password");
1602 FPS "\n");
1603}
1604
1605static void
1606luT(enum usage_level ul, const char *command)
1607{
1608 int is_my_command = (command && 0 == strcmp(command, "T"));
1609 if (ul == usage_all || !command || is_my_command)
1610 FPS "%-15s Reset the Key database or token\n",
1611 "-T");
1612 if (ul == usage_selected && !is_my_command)
1613 return;
1614 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1615 " -d certdir");
1616 FPS "%-20s Cert & Key database prefix\n",
1617 " -P dbprefix");
1618 FPS "%-20s Token to reset (default is internal)\n",
1619 " -h token-name");
1620 FPS "%-20s Set token's Site Security Officer password\n",
1621 " -0 SSO-password");
1622 FPS "\n");
1623}
1624
1625static void
1626luO(enum usage_level ul, const char *command)
1627{
1628 int is_my_command = (command && 0 == strcmp(command, "O"));
1629 if (ul == usage_all || !command || is_my_command)
1630 FPS "%-15s Print the chain of a certificate\n",
1631 "-O");
1632 if (ul == usage_selected && !is_my_command)
1633 return;
1634 FPS "%-20s The nickname of the cert to modify\n",
1635 " -n cert-name");
1636 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1637 " -d certdir");
1638 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1639 " -a");
1640 FPS "%-20s Cert & Key database prefix\n",
1641 " -P dbprefix");
1642 FPS "%-20s force the database to open R/W\n",
1643 " -X");
1644 FPS "%-20s don't search for a chain if issuer name equals subject name\n",
1645 " --simple-self-signed");
1646 FPS "\n");
1647}
1648
1649static void
1650luR(enum usage_level ul, const char *command)
1651{
1652 int is_my_command = (command && 0 == strcmp(command, "R"));
1653 if (ul == usage_all || !command || is_my_command)
1654 FPS "%-15s Generate a certificate request (stdout)\n",
1655 "-R");
1656 if (ul == usage_selected && !is_my_command)
1657 return;
1658 FPS "%-20s Specify the subject name (using RFC1485)\n",
1659 " -s subject");
1660 FPS "%-20s Output the cert request to this file\n",
1661 " -o output-req");
1662 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1663 " -k key-type-or-id");
1664 FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\n",
1665 "");
1666 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1667 " -h token-name");
1668 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1669 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1670 FPS "%-20s Create a certificate request restricted to RSA-PSS (rsa only)\n",
1671 " --pss");
1672 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1673 " -q pqgfile");
1674 FPS "%-20s Elliptic curve name (ec only)\n",
1675 " -q curve-name");
1676 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1677 "");
1678 FPS "%-20s Specify the password file\n",
1679 " -f pwfile");
1680 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1681 " -d keydir");
1682 FPS "%-20s Cert & Key database prefix\n",
1683 " -P dbprefix");
1684 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1685 " -p phone");
1686 FPS "%-20s \n"
1687 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1688 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1689 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1690 " -Z hashAlg", "", "", "");
1691 FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
1692 " -a");
1693 FPS "%-20s \n",
1694 " See -S for available extension options");
1695 FPS "%-20s \n",
1696 " See -G for available key flag options");
1697 FPS "\n");
1698}
1699
1700static void
1701luV(enum usage_level ul, const char *command)
1702{
1703 int is_my_command = (command && 0 == strcmp(command, "V"));
1704 if (ul == usage_all || !command || is_my_command)
1705 FPS "%-15s Validate a certificate\n",
1706 "-V");
1707 if (ul == usage_selected && !is_my_command)
1708 return;
1709 FPS "%-20s The nickname of the cert to Validate\n",
1710 " -n cert-name");
1711 FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
1712 " -b time");
1713 FPS "%-20s Check certificate signature \n",
1714 " -e ");
1715 FPS "%-20s Specify certificate usage:\n", " -u certusage");
1716 FPS "%-25s C \t SSL Client\n", "");
1717 FPS "%-25s V \t SSL Server\n", "");
1718 FPS "%-25s I \t IPsec\n", "");
1719 FPS "%-25s L \t SSL CA\n", "");
1720 FPS "%-25s A \t Any CA\n", "");
1721 FPS "%-25s Y \t Verify CA\n", "");
1722 FPS "%-25s S \t Email signer\n", "");
1723 FPS "%-25s R \t Email Recipient\n", "");
1724 FPS "%-25s O \t OCSP status responder\n", "");
1725 FPS "%-25s J \t Object signer\n", "");
1726 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1727 " -d certdir");
1728 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1729 " -a");
1730 FPS "%-20s Cert & Key database prefix\n",
1731 " -P dbprefix");
1732 FPS "%-20s force the database to open R/W\n",
1733 " -X");
1734 FPS "\n");
1735}
1736
1737static void
1738luW(enum usage_level ul, const char *command)
1739{
1740 int is_my_command = (command && 0 == strcmp(command, "W"));
1741 if (ul == usage_all || !command || is_my_command)
1742 FPS "%-15s Change the key database password\n",
1743 "-W");
1744 if (ul == usage_selected && !is_my_command)
1745 return;
1746 FPS "%-20s cert and key database directory\n",
1747 " -d certdir");
1748 FPS "%-20s Specify a file with the current password\n",
1749 " -f pwfile");
1750 FPS "%-20s Specify a file with the new password in two lines\n",
1751 " -@ newpwfile");
1752 FPS "\n");
1753}
1754
1755static void
1756luRename(enum usage_level ul, const char *command)
1757{
1758 int is_my_command = (command && 0 == strcmp(command, "rename"));
1759 if (ul == usage_all || !command || is_my_command)
1760 FPS "%-15s Change the database nickname of a certificate\n",
1761 "--rename");
1762 if (ul == usage_selected && !is_my_command)
1763 return;
1764 FPS "%-20s The old nickname of the cert to rename\n",
1765 " -n cert-name");
1766 FPS "%-20s The new nickname of the cert to rename\n",
1767 " --new-n new-name");
1768 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1769 " -d certdir");
1770 FPS "%-20s Cert & Key database prefix\n",
1771 " -P dbprefix");
1772 FPS "\n");
1773}
1774
1775static void
1776luUpgradeMerge(enum usage_level ul, const char *command)
1777{
1778 int is_my_command = (command && 0 == strcmp(command, "upgrade-merge"));
1779 if (ul == usage_all || !command || is_my_command)
1780 FPS "%-15s Upgrade an old database and merge it into a new one\n",
1781 "--upgrade-merge");
1782 if (ul == usage_selected && !is_my_command)
1783 return;
1784 FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
1785 " -d certdir");
1786 FPS "%-20s Cert & Key database prefix of the target database\n",
1787 " -P dbprefix");
1788 FPS "%-20s Specify the password file for the target database\n",
1789 " -f pwfile");
1790 FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
1791 " --source-dir certdir", "");
1792 FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
1793 " --source-prefix dbprefix", "");
1794 FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
1795 " --upgrade-id uniqueID", "");
1796 FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
1797 " --upgrade-token-name name", "");
1798 FPS "%-20s Specify the password file for the upgrade database\n",
1799 " -@ pwfile");
1800 FPS "\n");
1801}
1802
1803static void
1804luMerge(enum usage_level ul, const char *command)
1805{
1806 int is_my_command = (command && 0 == strcmp(command, "merge"));
1807 if (ul == usage_all || !command || is_my_command)
1808 FPS "%-15s Merge source database into the target database\n",
1809 "--merge");
1810 if (ul == usage_selected && !is_my_command)
1811 return;
1812 FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
1813 " -d certdir");
1814 FPS "%-20s Cert & Key database prefix of the target database\n",
1815 " -P dbprefix");
1816 FPS "%-20s Specify the password file for the target database\n",
1817 " -f pwfile");
1818 FPS "%-20s \n%-20s Cert database directory of the source database\n",
1819 " --source-dir certdir", "");
1820 FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
1821 " --source-prefix dbprefix", "");
1822 FPS "%-20s Specify the password file for the source database\n",
1823 " -@ pwfile");
1824 FPS "\n");
1825}
1826
1827static void
1828luS(enum usage_level ul, const char *command)
1829{
1830 int is_my_command = (command && 0 == strcmp(command, "S"));
1831 if (ul == usage_all || !command || is_my_command)
1832 FPS "%-15s Make a certificate and add to database\n",
1833 "-S");
1834 if (ul == usage_selected && !is_my_command)
1835 return;
1836 FPS "%-20s Specify the nickname of the cert\n",
1837 " -n key-name");
1838 FPS "%-20s Specify the subject name (using RFC1485)\n",
1839 " -s subject");
1840 FPS "%-20s The nickname of the issuer cert\n",
1841 " -c issuer-name");
1842 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1843 " -t trustargs");
1844 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1845 " -k key-type-or-id");
1846 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1847 " -h token-name");
1848 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1849 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1850 FPS "%-20s Create a certificate restricted to RSA-PSS (rsa only)\n",
1851 " --pss");
1852 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1853 " -q pqgfile");
1854 FPS "%-20s Elliptic curve name (ec only)\n",
1855 " -q curve-name");
1856 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1857 "");
1858 FPS "%-20s Self sign\n",
1859 " -x");
1860 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1861 " --pss-sign");
1862 FPS "%-20s Cert serial number\n",
1863 " -m serial-number");
1864 FPS "%-20s Time Warp\n",
1865 " -w warp-months");
1866 FPS "%-20s Months valid (default is 3)\n",
1867 " -v months-valid");
1868 FPS "%-20s Specify the password file\n",
1869 " -f pwfile");
1870 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1871 " -d certdir");
1872 FPS "%-20s Cert & Key database prefix\n",
1873 " -P dbprefix");
1874 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1875 " -p phone");
1876 FPS "%-20s \n"
1877 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1878 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1879 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1880 " -Z hashAlg", "", "", "");
1881 FPS "%-20s Create key usage extension\n",
1882 " -1 ");
1883 FPS "%-20s Create basic constraint extension\n",
1884 " -2 ");
1885 FPS "%-20s Create authority key ID extension\n",
1886 " -3 ");
1887 FPS "%-20s Create crl distribution point extension\n",
1888 " -4 ");
1889 FPS "%-20s Create netscape cert type extension\n",
1890 " -5 ");
1891 FPS "%-20s Create extended key usage extension\n",
1892 " -6 ");
1893 FPS "%-20s Create an email subject alt name extension\n",
1894 " -7 emailAddrs ");
1895 FPS "%-20s Create a DNS subject alt name extension\n",
1896 " -8 DNS-names");
1897 FPS "%-20s Create an Authority Information Access extension\n",
1898 " --extAIA ");
1899 FPS "%-20s Create a Subject Information Access extension\n",
1900 " --extSIA ");
1901 FPS "%-20s Create a Certificate Policies extension\n",
1902 " --extCP ");
1903 FPS "%-20s Create a Policy Mappings extension\n",
1904 " --extPM ");
1905 FPS "%-20s Create a Policy Constraints extension\n",
1906 " --extPC ");
1907 FPS "%-20s Create an Inhibit Any Policy extension\n",
1908 " --extIA ");
1909 FPS "%-20s Create a subject key ID extension\n",
1910 " --extSKID ");
1911 FPS "%-20s \n",
1912 " See -G for available key flag options");
1913 FPS "%-20s Create a name constraints extension\n",
1914 " --extNC ");
1915 FPS "%-20s \n"
1916 "%-20s Create a Subject Alt Name extension with one or multiple names\n",
1917 " --extSAN type:name[,type:name]...", "");
1918 FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
1919 FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
1920 FPS "%-20s \n"
1921 "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
1922 "%-20s by loading their encodings from external files.\n",
1923 " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
1924 FPS "%-20s - OID (example): 1.2.3.4\n", "");
1925 FPS "%-20s - critical-flag: critical or not-critical\n", "");
1926 FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
1927 FPS "\n");
1928}
1929
1930static void
1931luBuildFlags(enum usage_level ul, const char *command)
1932{
1933 int is_my_command = (command && 0 == strcmp(command, "build-flags"));
1934 if (ul == usage_all || !command || is_my_command)
1935 FPS "%-15s Print enabled build flags relevant for NSS test execution\n",
1936 "--build-flags");
1937 if (ul == usage_selected && !is_my_command)
1938 return;
1939 FPS "\n");
1940}
1941
1942static void
1943LongUsage(enum usage_level ul, const char *command)
1944{
1945 luA(ul, command);
1946 luB(ul, command);
1947 luE(ul, command);
1948 luC(ul, command);
1949 luG(ul, command);
1950 luD(ul, command);
1951 luRename(ul, command);
1952 luF(ul, command);
1953 luU(ul, command);
1954 luK(ul, command);
1955 luL(ul, command);
1956 luBuildFlags(ul, command);
1957 luM(ul, command);
1958 luN(ul, command);
1959 luT(ul, command);
1960 luO(ul, command);
1961 luR(ul, command);
1962 luV(ul, command);
1963 luW(ul, command);
1964 luUpgradeMerge(ul, command);
1965 luMerge(ul, command);
1966 luS(ul, command);
1967#undef FPS
1968}
1969
1970static void
1971Usage()
1972{
1973 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
1974 "%s - Utility to manipulate NSS certificate databases\n\n"
1975 "Usage: %s <command> -d <database-directory> <options>\n\n"
1976 "Valid commands:\n",
1977 progName, progName);
1978 LongUsage(usage_selected, NULL((void*)0));
1979 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n"
1980 "%s -H <command> : Print available options for the given command\n"
1981 "%s -H : Print complete help output of all commands and options\n"
1982 "%s --syntax : Print a short summary of all commands and options\n",
1983 progName, progName, progName);
1984 exit(1);
1985}
1986
1987static CERTCertificate *
1988MakeV1Cert(CERTCertDBHandle *handle,
1989 CERTCertificateRequest *req,
1990 char *issuerNickName,
1991 PRBool selfsign,
1992 unsigned int serialNumber,
1993 int warpmonths,
1994 int validityMonths)
1995{
1996 CERTCertificate *issuerCert = NULL((void*)0);
1997 CERTValidity *validity;
1998 CERTCertificate *cert = NULL((void*)0);
1999 PRExplodedTime printableTime;
2000 PRTime now, after;
2001
2002 if (!selfsign) {
2003 issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
2004 if (!issuerCert) {
2005 SECU_PrintError(progName, "could not find certificate named \"%s\"",
2006 issuerNickName);
2007 return NULL((void*)0);
2008 }
2009 }
2010
2011 now = PR_Now();
2012 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
2013 if (warpmonths) {
2014 printableTime.tm_month += warpmonths;
2015 now = PR_ImplodeTime(&printableTime);
2016 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
2017 }
2018 printableTime.tm_month += validityMonths;
2019 after = PR_ImplodeTime(&printableTime);
2020
2021 /* note that the time is now in micro-second unit */
2022 validity = CERT_CreateValidity(now, after);
2023 if (validity) {
2024 cert = CERT_CreateCertificate(serialNumber,
2025 (selfsign ? &req->subject
2026 : &issuerCert->subject),
2027 validity, req);
2028
2029 CERT_DestroyValidity(validity);
2030 }
2031 if (issuerCert) {
2032 CERT_DestroyCertificate(issuerCert);
2033 }
2034
2035 return (cert);
2036}
2037
2038static SECStatus
2039SetSignatureAlgorithm(PLArenaPool *arena,
2040 SECAlgorithmID *signAlg,
2041 SECAlgorithmID *spkiAlg,
2042 SECOidTag hashAlgTag,
2043 SECKEYPrivateKey *privKey,
2044 PRBool pssSign)
2045{
2046 SECStatus rv;
2047
2048 if (pssSign ||
2049 SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
2050 SECItem *srcParams;
2051 SECItem *params;
2052
2053 if (SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
2054 srcParams = &spkiAlg->parameters;
2055 } else {
2056 /* If the issuer's public key is RSA, the parameter field
2057 * of the SPKI should be NULL, which can't be used as a
2058 * basis of RSA-PSS parameters. */
2059 srcParams = NULL((void*)0);
2060 }
2061 params = SEC_CreateSignatureAlgorithmParameters(arena,
2062 NULL((void*)0),
2063 SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
2064 hashAlgTag,
2065 srcParams,
2066 privKey);
2067 if (!params) {
2068 SECU_PrintError(progName, "Could not create RSA-PSS parameters");
2069 return SECFailure;
2070 }
2071 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, signAlg,
2072 SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
2073 params);
2074 if (rv != SECSuccess) {
2075 SECU_PrintError(progName, "Could not set signature algorithm id.");
2076 return rv;
2077 }
2078 } else {
2079 KeyType keyType = SECKEY_GetPrivateKeyType(privKey);
2080 SECOidTag algID;
2081
2082 algID = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
2083 if (algID == SEC_OID_UNKNOWN) {
2084 SECU_PrintError(progName, "Unknown key or hash type for issuer.");
2085 return SECFailure;
2086 }
2087 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, signAlg, algID, 0);
2088 if (rv != SECSuccess) {
2089 SECU_PrintError(progName, "Could not set signature algorithm id.");
2090 return rv;
2091 }
2092 }
2093 return SECSuccess;
2094}
2095
2096static SECStatus
2097SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
2098 SECOidTag hashAlgTag,
2099 SECKEYPrivateKey *privKey, char *issuerNickName,
2100 int certVersion, PRBool pssSign, void *pwarg)
2101{
2102 SECItem der;
2103 SECKEYPrivateKey *caPrivateKey = NULL((void*)0);
2104 SECStatus rv;
2105 PLArenaPool *arena;
2106 CERTCertificate *issuer;
2107 void *dummy;
2108
2109 arena = cert->arena;
2110
2111 if (selfsign) {
2112 issuer = cert;
2113 } else {
2114 issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
2115 if ((CERTCertificate *)NULL((void*)0) == issuer) {
2116 SECU_PrintError(progName, "unable to find issuer with nickname %s",
2117 issuerNickName);
2118 rv = SECFailure;
2119 goto done;
2120 }
2121 privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
2122 if (caPrivateKey == NULL((void*)0)) {
2123 SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
2124 rv = SECFailure;
2125 CERT_DestroyCertificate(issuer);
2126 goto done;
2127 }
2128 }
2129
2130 if (pssSign &&
2131 (SECKEY_GetPrivateKeyType(privKey) != rsaKey &&
2132 SECKEY_GetPrivateKeyType(privKey) != rsaPssKey)) {
2133 SECU_PrintError(progName, "unable to create RSA-PSS signature with key %s",
2134 issuerNickName);
2135 rv = SECFailure;
2136 if (!selfsign) {
2137 CERT_DestroyCertificate(issuer);
2138 }
2139 goto done;
2140 }
2141
2142 rv = SetSignatureAlgorithm(arena,
2143 &cert->signature,
2144 &issuer->subjectPublicKeyInfo.algorithm,
2145 hashAlgTag,
2146 privKey,
2147 pssSign);
2148 if (!selfsign) {
2149 CERT_DestroyCertificate(issuer);
2150 }
2151 if (rv != SECSuccess) {
2152 goto done;
2153 }
2154
2155 switch (certVersion) {
2156 case (SEC_CERTIFICATE_VERSION_10):
2157 /* The initial version for x509 certificates is version one
2158 * and this default value must be an implicit DER encoding. */
2159 cert->version.data = NULL((void*)0);
2160 cert->version.len = 0;
2161 break;
2162 case (SEC_CERTIFICATE_VERSION_21):
2163 case (SEC_CERTIFICATE_VERSION_32):
2164 case 3: /* unspecified format (would be version 4 certificate). */
2165 *(cert->version.data) = certVersion;
2166 cert->version.len = 1;
2167 break;
2168 default:
2169 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2170 rv = SECFailure;
2171 goto done;
2172 }
2173
2174 der.len = 0;
2175 der.data = NULL((void*)0);
2176 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der, cert,
2177 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate);
2178 if (!dummy) {
2179 fprintf(stderrstderr, "Could not encode certificate.\n");
2180 rv = SECFailure;
2181 goto done;
2182 }
2183
2184 rv = SEC_DerSignDataWithAlgorithmID(arena, &cert->derCert, der.data, der.len,
2185 privKey, &cert->signature);
2186 if (rv != SECSuccess) {
2187 fprintf(stderrstderr, "Could not sign encoded certificate data.\n");
2188 /* result allocated out of the arena, it will be freed
2189 * when the arena is freed */
2190 goto done;
2191 }
2192done:
2193 if (caPrivateKey) {
2194 SECKEY_DestroyPrivateKey(caPrivateKey);
2195 }
2196 return rv;
2197}
2198
2199static SECStatus
2200CreateCert(
2201 CERTCertDBHandle *handle,
2202 PK11SlotInfo *slot,
2203 char *issuerNickName,
2204 const SECItem *certReqDER,
2205 SECKEYPrivateKey **selfsignprivkey,
2206 void *pwarg,
2207 SECOidTag hashAlgTag,
2208 unsigned int serialNumber,
2209 int warpmonths,
2210 int validityMonths,
2211 const char *emailAddrs,
2212 const char *dnsNames,
2213 PRBool ascii,
2214 PRBool selfsign,
2215 certutilExtnList extnList,
2216 const char *extGeneric,
2217 int certVersion,
2218 PRBool pssSign,
2219 SECItem *certDER)
2220{
2221 void *extHandle = NULL((void*)0);
2222 CERTCertificate *subjectCert = NULL((void*)0);
2223 CERTCertificateRequest *certReq = NULL((void*)0);
2224 SECStatus rv = SECSuccess;
2225 CERTCertExtension **CRexts;
2226
2227 do {
2228 /* Create a certrequest object from the input cert request der */
2229 certReq = GetCertRequest(certReqDER, pwarg);
2230 if (certReq == NULL((void*)0)) {
2231 GEN_BREAK(SECFailure)rv = SECFailure; break;
2232 }
2233
2234 subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign,
2235 serialNumber, warpmonths, validityMonths);
2236 if (subjectCert == NULL((void*)0)) {
2237 GEN_BREAK(SECFailure)rv = SECFailure; break;
2238 }
2239
2240 extHandle = CERT_StartCertExtensions(subjectCert);
2241 if (extHandle == NULL((void*)0)) {
2242 GEN_BREAK(SECFailure)rv = SECFailure; break;
2243 }
2244
2245 rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
2246 if (rv != SECSuccess) {
2247 GEN_BREAK(SECFailure)rv = SECFailure; break;
2248 }
2249
2250 if (certReq->attributes != NULL((void*)0) &&
2251 certReq->attributes[0] != NULL((void*)0) &&
2252 certReq->attributes[0]->attrType.data != NULL((void*)0) &&
2253 certReq->attributes[0]->attrType.len > 0 &&
2254 SECOID_FindOIDTagSECOID_FindOIDTag_Util(&certReq->attributes[0]->attrType) ==
2255 SEC_OID_PKCS9_EXTENSION_REQUEST) {
2256 rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
2257 if (rv != SECSuccess)
2258 break;
2259 rv = CERT_MergeExtensions(extHandle, CRexts);
2260 if (rv != SECSuccess)
2261 break;
2262 }
2263
2264 CERT_FinishExtensions(extHandle);
2265 extHandle = NULL((void*)0);
2266
2267 /* self-signing a cert request, find the private key */
2268 if (selfsign && *selfsignprivkey == NULL((void*)0)) {
2269 *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg);
2270 if (!*selfsignprivkey) {
2271 fprintf(stderrstderr, "Failed to locate private key.\n");
2272 rv = SECFailure;
2273 break;
2274 }
2275 }
2276
2277 rv = SignCert(handle, subjectCert, selfsign, hashAlgTag,
2278 *selfsignprivkey, issuerNickName,
2279 certVersion, pssSign, pwarg);
2280 if (rv != SECSuccess)
2281 break;
2282
2283 rv = SECFailure;
2284 if (ascii) {
2285 char *asciiDER = BTOA_DataToAsciiBTOA_DataToAscii_Util(subjectCert->derCert.data,
2286 subjectCert->derCert.len);
2287 if (asciiDER) {
2288 char *wrapped = PR_smprintf("%s\n%s\n%s\n",
2289 NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
2290 asciiDER,
2291 NS_CERT_TRAILER"-----END CERTIFICATE-----");
2292 if (wrapped) {
2293 PRUint32 wrappedLen = PL_strlen(wrapped);
2294 if (SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), certDER, wrappedLen)) {
2295 PORT_Memcpymemcpy(certDER->data, wrapped, wrappedLen);
2296 rv = SECSuccess;
2297 }
2298 PR_smprintf_free(wrapped);
2299 }
2300 PORT_FreePORT_Free_Util(asciiDER);
2301 }
2302 } else {
2303 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), certDER, &subjectCert->derCert);
2304 }
2305 } while (0);
2306 if (extHandle) {
2307 CERT_FinishExtensions(extHandle);
2308 }
2309 CERT_DestroyCertificateRequest(certReq);
2310 CERT_DestroyCertificate(subjectCert);
2311 if (rv != SECSuccess) {
2312 PRErrorCode perr = PR_GetError();
2313 fprintf(stderrstderr, "%s: unable to create cert (%s)\n", progName,
2314 SECU_Strerror(perr)PR_ErrorToString((perr), 0));
2315 }
2316 return (rv);
2317}
2318
2319/*
2320 * map a class to a user presentable string
2321 */
2322static const char *objClassArray[] = {
2323 "Data",
2324 "Certificate",
2325 "Public Key",
2326 "Private Key",
2327 "Secret Key",
2328 "Hardware Feature",
2329 "Domain Parameters",
2330 "Mechanism"
2331};
2332
2333static const char *objNSSClassArray[] = {
2334 "CKO_NSS",
2335 "Crl",
2336 "SMIME Record",
2337 "Trust",
2338 "Builtin Root List"
2339};
2340
2341const char *
2342getObjectClass(CK_ULONG classType)
2343{
2344 static char buf[sizeof(CK_ULONG) * 2 + 3];
2345
2346 if (classType <= CKO_MECHANISM0x00000007UL) {
2347 return objClassArray[classType];
2348 }
2349 if (classType >= CKO_NSS(0x80000000UL | 0x4E534350) && classType <= CKO_NSS_BUILTIN_ROOT_LIST((0x80000000UL | 0x4E534350) + 4)) {
2350 return objNSSClassArray[classType - CKO_NSS(0x80000000UL | 0x4E534350)];
2351 }
2352 snprintf(buf, sizeof(buf), "0x%lx", classType);
2353 return buf;
2354}
2355
2356typedef struct {
2357 char *name;
2358 int nameSize;
2359 CK_ULONG value;
2360} flagArray;
2361
2362#define NAME_SIZE(x)"x", sizeof("x") - 1 #x, sizeof(#x) - 1
2363
2364flagArray opFlagsArray[] = {
2365 { NAME_SIZE(encrypt)"encrypt", sizeof("encrypt") - 1, CKF_ENCRYPT0x00000100UL },
2366 { NAME_SIZE(decrypt)"decrypt", sizeof("decrypt") - 1, CKF_DECRYPT0x00000200UL },
2367 { NAME_SIZE(sign)"sign", sizeof("sign") - 1, CKF_SIGN0x00000800UL },
2368 { NAME_SIZE(sign_recover)"sign_recover", sizeof("sign_recover") - 1, CKF_SIGN_RECOVER0x00001000UL },
2369 { NAME_SIZE(verify)"verify", sizeof("verify") - 1, CKF_VERIFY0x00002000 },
2370 { NAME_SIZE(verify_recover)"verify_recover", sizeof("verify_recover") - 1, CKF_VERIFY_RECOVER0x00004000UL },
2371 { NAME_SIZE(wrap)"wrap", sizeof("wrap") - 1, CKF_WRAP0x00020000UL },
2372 { NAME_SIZE(unwrap)"unwrap", sizeof("unwrap") - 1, CKF_UNWRAP0x00040000UL },
2373 { NAME_SIZE(derive)"derive", sizeof("derive") - 1, CKF_DERIVE0x00080000UL }
2374};
2375
2376int opFlagsCount = PR_ARRAY_SIZE(opFlagsArray)(sizeof(opFlagsArray)/sizeof((opFlagsArray)[0]));
2377
2378flagArray attrFlagsArray[] = {
2379 { NAME_SIZE(token)"token", sizeof("token") - 1, PK11_ATTR_TOKEN0x00000001L },
2380 { NAME_SIZE(session)"session", sizeof("session") - 1, PK11_ATTR_SESSION0x00000002L },
2381 { NAME_SIZE(private)"private", sizeof("private") - 1, PK11_ATTR_PRIVATE0x00000004L },
2382 { NAME_SIZE(public)"public", sizeof("public") - 1, PK11_ATTR_PUBLIC0x00000008L },
2383 { NAME_SIZE(modifiable)"modifiable", sizeof("modifiable") - 1, PK11_ATTR_MODIFIABLE0x00000010L },
2384 { NAME_SIZE(unmodifiable)"unmodifiable", sizeof("unmodifiable") - 1, PK11_ATTR_UNMODIFIABLE0x00000020L },
2385 { NAME_SIZE(sensitive)"sensitive", sizeof("sensitive") - 1, PK11_ATTR_SENSITIVE0x00000040L },
2386 { NAME_SIZE(insensitive)"insensitive", sizeof("insensitive") - 1, PK11_ATTR_INSENSITIVE0x00000080L },
2387 { NAME_SIZE(extractable)"extractable", sizeof("extractable") - 1, PK11_ATTR_EXTRACTABLE0x00000100L },
2388 { NAME_SIZE(unextractable)"unextractable", sizeof("unextractable") - 1, PK11_ATTR_UNEXTRACTABLE0x00000200L }
2389};
2390
2391int attrFlagsCount = PR_ARRAY_SIZE(attrFlagsArray)(sizeof(attrFlagsArray)/sizeof((attrFlagsArray)[0]));
2392
2393#define MAX_STRING30 30
2394CK_ULONG
2395GetFlags(char *flagsString, flagArray *flags, int count)
2396{
2397 CK_ULONG flagsValue = strtol(flagsString, NULL((void*)0), 0);
2398 int i;
2399
2400 if ((flagsValue != 0) || (*flagsString == 0)) {
2401 return flagsValue;
2402 }
2403 while (*flagsString) {
2404 for (i = 0; i < count; i++) {
2405 if (strncmp(flagsString, flags[i].name, flags[i].nameSize) ==
2406 0) {
2407 flagsValue |= flags[i].value;
2408 flagsString += flags[i].nameSize;
2409 if (*flagsString != 0) {
2410 flagsString++;
2411 }
2412 break;
2413 }
2414 }
2415 if (i == count) {
2416 char name[MAX_STRING30];
2417 char *tok;
2418
2419 strncpy(name, flagsString, MAX_STRING30);
2420 name[MAX_STRING30 - 1] = 0;
2421 tok = strchr(name, ',');
2422 if (tok) {
2423 *tok = 0;
2424 }
2425 fprintf(stderrstderr, "Unknown flag (%s)\n", name);
2426 tok = strchr(flagsString, ',');
2427 if (tok == NULL((void*)0)) {
2428 break;
2429 }
2430 flagsString = tok + 1;
2431 }
2432 }
2433 return flagsValue;
2434}
2435
2436CK_FLAGS
2437GetOpFlags(char *flags)
2438{
2439 return GetFlags(flags, opFlagsArray, opFlagsCount);
2440}
2441
2442PK11AttrFlags
2443GetAttrFlags(char *flags)
2444{
2445 return GetFlags(flags, attrFlagsArray, attrFlagsCount);
2446}
2447
2448char *
2449mkNickname(unsigned char *data, int len)
2450{
2451 char *nick = PORT_AllocPORT_Alloc_Util(len + 1);
2452 if (!nick) {
2453 return nick;
2454 }
2455 PORT_Memcpymemcpy(nick, data, len);
2456 nick[len] = 0;
2457 return nick;
2458}
2459
2460/*
2461 * dump a PK11_MergeTokens error log to the console
2462 */
2463void
2464DumpMergeLog(const char *progname, PK11MergeLog *log)
2465{
2466 PK11MergeLogNode *node;
2467
2468 for (node = log->head; node; node = node->next) {
2469 SECItem attrItem;
2470 char *nickname = NULL((void*)0);
2471 const char *objectClass = NULL((void*)0);
2472 SECStatus rv;
2473
2474 attrItem.data = NULL((void*)0);
2475 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2476 CKA_LABEL0x00000003UL, &attrItem);
2477 if (rv == SECSuccess) {
2478 nickname = mkNickname(attrItem.data, attrItem.len);
2479 PORT_FreePORT_Free_Util(attrItem.data);
2480 }
2481 attrItem.data = NULL((void*)0);
2482 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2483 CKA_CLASS0x00000000UL, &attrItem);
2484 if (rv == SECSuccess) {
2485 if (attrItem.len == sizeof(CK_ULONG)) {
2486 objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
2487 }
2488 PORT_FreePORT_Free_Util(attrItem.data);
2489 }
2490
2491 fprintf(stderrstderr, "%s: Could not merge object %s (type %s): %s\n",
2492 progName,
2493 nickname ? nickname : "unnamed",
2494 objectClass ? objectClass : "unknown",
2495 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
2496
2497 if (nickname) {
2498 PORT_FreePORT_Free_Util(nickname);
2499 }
2500 }
2501}
2502
2503/* Certutil commands */
2504enum {
2505 cmd_AddCert = 0,
2506 cmd_CreateNewCert,
2507 cmd_DeleteCert,
2508 cmd_AddEmailCert,
2509 cmd_DeleteKey,
2510 cmd_GenKeyPair,
2511 cmd_PrintHelp,
2512 cmd_PrintSyntax,
2513 cmd_ListKeys,
2514 cmd_ListCerts,
2515 cmd_ModifyCertTrust,
2516 cmd_NewDBs,
2517 cmd_DumpChain,
2518 cmd_CertReq,
2519 cmd_CreateAndAddCert,
2520 cmd_TokenReset,
2521 cmd_ListModules,
2522 cmd_CheckCertValidity,
2523 cmd_ChangePassword,
2524 cmd_Version,
2525 cmd_Batch,
2526 cmd_Merge,
2527 cmd_UpgradeMerge, /* test only */
2528 cmd_Rename,
2529 cmd_BuildFlags,
2530 max_cmd
2531};
2532
2533/* Certutil options */
2534enum certutilOpts {
2535 opt_SSOPass = 0,
2536 opt_AddKeyUsageExt,
2537 opt_AddBasicConstraintExt,
2538 opt_AddAuthorityKeyIDExt,
2539 opt_AddCRLDistPtsExt,
2540 opt_AddNSCertTypeExt,
2541 opt_AddExtKeyUsageExt,
2542 opt_ExtendedEmailAddrs,
2543 opt_ExtendedDNSNames,
2544 opt_ASCIIForIO,
2545 opt_ValidityTime,
2546 opt_IssuerName,
2547 opt_CertDir,
2548 opt_VerifySig,
2549 opt_PasswordFile,
2550 opt_KeySize,
2551 opt_TokenName,
2552 opt_InputFile,
2553 opt_Emailaddress,
2554 opt_KeyIndex,
2555 opt_KeyType,
2556 opt_DetailedInfo,
2557 opt_SerialNumber,
2558 opt_Nickname,
2559 opt_OutputFile,
2560 opt_PhoneNumber,
2561 opt_DBPrefix,
2562 opt_PQGFile,
2563 opt_BinaryDER,
2564 opt_Subject,
2565 opt_Trust,
2566 opt_Usage,
2567 opt_Validity,
2568 opt_OffsetMonths,
2569 opt_SelfSign,
2570 opt_RW,
2571 opt_Exponent,
2572 opt_NoiseFile,
2573 opt_Hash,
2574 opt_NewPasswordFile,
2575 opt_AddAuthInfoAccExt,
2576 opt_AddSubjInfoAccExt,
2577 opt_AddCertPoliciesExt,
2578 opt_AddPolicyMapExt,
2579 opt_AddPolicyConstrExt,
2580 opt_AddInhibAnyExt,
2581 opt_AddNameConstraintsExt,
2582 opt_AddSubjectKeyIDExt,
2583 opt_AddCmdKeyUsageExt,
2584 opt_AddCmdNSCertTypeExt,
2585 opt_AddCmdExtKeyUsageExt,
2586 opt_SourceDir,
2587 opt_SourcePrefix,
2588 opt_UpgradeID,
2589 opt_UpgradeTokenName,
2590 opt_KeyOpFlagsOn,
2591 opt_KeyOpFlagsOff,
2592 opt_KeyAttrFlags,
2593 opt_EmptyPassword,
2594 opt_CertVersion,
2595 opt_AddSubjectAltNameExt,
2596 opt_DumpExtensionValue,
2597 opt_GenericExtensions,
2598 opt_NewNickname,
2599 opt_Pss,
2600 opt_PssSign,
2601 opt_SimpleSelfSigned,
2602 opt_Help
2603};
2604
2605static const secuCommandFlag commands_init[] = {
2606 { /* cmd_AddCert */ 'A', PR_FALSE0, 0, PR_FALSE0 },
2607 { /* cmd_CreateNewCert */ 'C', PR_FALSE0, 0, PR_FALSE0 },
2608 { /* cmd_DeleteCert */ 'D', PR_FALSE0, 0, PR_FALSE0 },
2609 { /* cmd_AddEmailCert */ 'E', PR_FALSE0, 0, PR_FALSE0 },
2610 { /* cmd_DeleteKey */ 'F', PR_FALSE0, 0, PR_FALSE0 },
2611 { /* cmd_GenKeyPair */ 'G', PR_FALSE0, 0, PR_FALSE0 },
2612 { /* cmd_PrintHelp */ 'H', PR_FALSE0, 0, PR_FALSE0, "help" },
2613 { /* cmd_PrintSyntax */ 0, PR_FALSE0, 0, PR_FALSE0,
2614 "syntax" },
2615 { /* cmd_ListKeys */ 'K', PR_FALSE0, 0, PR_FALSE0 },
2616 { /* cmd_ListCerts */ 'L', PR_FALSE0, 0, PR_FALSE0 },
2617 { /* cmd_ModifyCertTrust */ 'M', PR_FALSE0, 0, PR_FALSE0 },
2618 { /* cmd_NewDBs */ 'N', PR_FALSE0, 0, PR_FALSE0 },
2619 { /* cmd_DumpChain */ 'O', PR_FALSE0, 0, PR_FALSE0 },
2620 { /* cmd_CertReq */ 'R', PR_FALSE0, 0, PR_FALSE0 },
2621 { /* cmd_CreateAndAddCert */ 'S', PR_FALSE0, 0, PR_FALSE0 },
2622 { /* cmd_TokenReset */ 'T', PR_FALSE0, 0, PR_FALSE0 },
2623 { /* cmd_ListModules */ 'U', PR_FALSE0, 0, PR_FALSE0 },
2624 { /* cmd_CheckCertValidity */ 'V', PR_FALSE0, 0, PR_FALSE0 },
2625 { /* cmd_ChangePassword */ 'W', PR_FALSE0, 0, PR_FALSE0 },
2626 { /* cmd_Version */ 'Y', PR_FALSE0, 0, PR_FALSE0 },
2627 { /* cmd_Batch */ 'B', PR_FALSE0, 0, PR_FALSE0 },
2628 { /* cmd_Merge */ 0, PR_FALSE0, 0, PR_FALSE0, "merge" },
2629 { /* cmd_UpgradeMerge */ 0, PR_FALSE0, 0, PR_FALSE0,
2630 "upgrade-merge" },
2631 { /* cmd_Rename */ 0, PR_FALSE0, 0, PR_FALSE0,
2632 "rename" },
2633 { /* cmd_BuildFlags */ 0, PR_FALSE0, 0, PR_FALSE0,
2634 "build-flags" }
2635};
2636#define NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])) ((sizeof commands_init) / (sizeof commands_init[0]))
2637
2638static const secuCommandFlag options_init[] = {
2639 { /* opt_SSOPass */ '0', PR_TRUE1, 0, PR_FALSE0 },
2640 { /* opt_AddKeyUsageExt */ '1', PR_FALSE0, 0, PR_FALSE0 },
2641 { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE0, 0, PR_FALSE0 },
2642 { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE0, 0, PR_FALSE0 },
2643 { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE0, 0, PR_FALSE0 },
2644 { /* opt_AddNSCertTypeExt */ '5', PR_FALSE0, 0, PR_FALSE0 },
2645 { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE0, 0, PR_FALSE0 },
2646 { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE1, 0, PR_FALSE0 },
2647 { /* opt_ExtendedDNSNames */ '8', PR_TRUE1, 0, PR_FALSE0 },
2648 { /* opt_ASCIIForIO */ 'a', PR_FALSE0, 0, PR_FALSE0 },
2649 { /* opt_ValidityTime */ 'b', PR_TRUE1, 0, PR_FALSE0 },
2650 { /* opt_IssuerName */ 'c', PR_TRUE1, 0, PR_FALSE0 },
2651 { /* opt_CertDir */ 'd', PR_TRUE1, 0, PR_FALSE0 },
2652 { /* opt_VerifySig */ 'e', PR_FALSE0, 0, PR_FALSE0 },
2653 { /* opt_PasswordFile */ 'f', PR_TRUE1, 0, PR_FALSE0 },
2654 { /* opt_KeySize */ 'g', PR_TRUE1, 0, PR_FALSE0 },
2655 { /* opt_TokenName */ 'h', PR_TRUE1, 0, PR_FALSE0 },
2656 { /* opt_InputFile */ 'i', PR_TRUE1, 0, PR_FALSE0 },
2657 { /* opt_Emailaddress */ 0, PR_TRUE1, 0, PR_FALSE0, "email" },
2658 { /* opt_KeyIndex */ 'j', PR_TRUE1, 0, PR_FALSE0 },
2659 { /* opt_KeyType */ 'k', PR_TRUE1, 0, PR_FALSE0 },
2660 { /* opt_DetailedInfo */ 'l', PR_FALSE0, 0, PR_FALSE0 },
2661 { /* opt_SerialNumber */ 'm', PR_TRUE1, 0, PR_FALSE0 },
2662 { /* opt_Nickname */ 'n', PR_TRUE1, 0, PR_FALSE0 },
2663 { /* opt_OutputFile */ 'o', PR_TRUE1, 0, PR_FALSE0 },
2664 { /* opt_PhoneNumber */ 'p', PR_TRUE1, 0, PR_FALSE0 },
2665 { /* opt_DBPrefix */ 'P', PR_TRUE1, 0, PR_FALSE0 },
2666 { /* opt_PQGFile */ 'q', PR_TRUE1, 0, PR_FALSE0 },
2667 { /* opt_BinaryDER */ 'r', PR_FALSE0, 0, PR_FALSE0 },
2668 { /* opt_Subject */ 's', PR_TRUE1, 0, PR_FALSE0 },
2669 { /* opt_Trust */ 't', PR_TRUE1, 0, PR_FALSE0 },
2670 { /* opt_Usage */ 'u', PR_TRUE1, 0, PR_FALSE0 },
2671 { /* opt_Validity */ 'v', PR_TRUE1, 0, PR_FALSE0 },
2672 { /* opt_OffsetMonths */ 'w', PR_TRUE1, 0, PR_FALSE0 },
2673 { /* opt_SelfSign */ 'x', PR_FALSE0, 0, PR_FALSE0 },
2674 { /* opt_RW */ 'X', PR_FALSE0, 0, PR_FALSE0 },
2675 { /* opt_Exponent */ 'y', PR_TRUE1, 0, PR_FALSE0 },
2676 { /* opt_NoiseFile */ 'z', PR_TRUE1, 0, PR_FALSE0 },
2677 { /* opt_Hash */ 'Z', PR_TRUE1, 0, PR_FALSE0 },
2678 { /* opt_NewPasswordFile */ '@', PR_TRUE1, 0, PR_FALSE0 },
2679 { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extAIA" },
2680 { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extSIA" },
2681 { /* opt_AddCertPoliciesExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extCP" },
2682 { /* opt_AddPolicyMapExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPM" },
2683 { /* opt_AddPolicyConstrExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPC" },
2684 { /* opt_AddInhibAnyExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extIA" },
2685 { /* opt_AddNameConstraintsExt*/ 0, PR_FALSE0, 0, PR_FALSE0, "extNC" },
2686 { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE0, 0, PR_FALSE0,
2687 "extSKID" },
2688 { /* opt_AddCmdKeyUsageExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2689 "keyUsage" },
2690 { /* opt_AddCmdNSCertTypeExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2691 "nsCertType" },
2692 { /* opt_AddCmdExtKeyUsageExt*/ 0, PR_TRUE1, 0, PR_FALSE0,
2693 "extKeyUsage" },
2694
2695 { /* opt_SourceDir */ 0, PR_TRUE1, 0, PR_FALSE0,
2696 "source-dir" },
2697 { /* opt_SourcePrefix */ 0, PR_TRUE1, 0, PR_FALSE0,
2698 "source-prefix" },
2699 { /* opt_UpgradeID */ 0, PR_TRUE1, 0, PR_FALSE0,
2700 "upgrade-id" },
2701 { /* opt_UpgradeTokenName */ 0, PR_TRUE1, 0, PR_FALSE0,
2702 "upgrade-token-name" },
2703 { /* opt_KeyOpFlagsOn */ 0, PR_TRUE1, 0, PR_FALSE0,
2704 "keyOpFlagsOn" },
2705 { /* opt_KeyOpFlagsOff */ 0, PR_TRUE1, 0, PR_FALSE0,
2706 "keyOpFlagsOff" },
2707 { /* opt_KeyAttrFlags */ 0, PR_TRUE1, 0, PR_FALSE0,
2708 "keyAttrFlags" },
2709 { /* opt_EmptyPassword */ 0, PR_FALSE0, 0, PR_FALSE0,
2710 "empty-password" },
2711 { /* opt_CertVersion */ 0, PR_TRUE1, 0, PR_FALSE0,
2712 "certVersion" },
2713 { /* opt_AddSubjectAltExt */ 0, PR_TRUE1, 0, PR_FALSE0, "extSAN" },
2714 { /* opt_DumpExtensionValue */ 0, PR_TRUE1, 0, PR_FALSE0,
2715 "dump-ext-val" },
2716 { /* opt_GenericExtensions */ 0, PR_TRUE1, 0, PR_FALSE0,
2717 "extGeneric" },
2718 { /* opt_NewNickname */ 0, PR_TRUE1, 0, PR_FALSE0,
2719 "new-n" },
2720 { /* opt_Pss */ 0, PR_FALSE0, 0, PR_FALSE0,
2721 "pss" },
2722 { /* opt_PssSign */ 0, PR_FALSE0, 0, PR_FALSE0,
2723 "pss-sign" },
2724 { /* opt_SimpleSelfSigned */ 0, PR_FALSE0, 0, PR_FALSE0,
2725 "simple-self-signed" },
2726};
2727#define NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])) ((sizeof options_init) / (sizeof options_init[0]))
2728
2729static secuCommandFlag certutil_commands[NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0]))];
2730static secuCommandFlag certutil_options[NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0]))];
2731
2732static const secuCommand certutil = {
2733 NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])),
2734 NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])),
2735 certutil_commands,
2736 certutil_options
2737};
2738
2739static certutilExtnList certutil_extns;
2740
2741static int
2742certutil_main(int argc, char **argv, PRBool initialize)
2743{
2744 CERTCertDBHandle *certHandle;
2745 PK11SlotInfo *slot = NULL((void*)0);
2746 CERTName *subject = 0;
2747 PRFileDesc *inFile = PR_STDINPR_GetSpecialFD(PR_StandardInput);
2748 PRFileDesc *outFile = PR_STDOUTPR_GetSpecialFD(PR_StandardOutput);
2749 SECItem certReqDER = { siBuffer, NULL((void*)0), 0 };
2750 SECItem certDER = { siBuffer, NULL((void*)0), 0 };
2751 const char *slotname = "internal";
2752 const char *certPrefix = "";
2753 char *sourceDir = "";
2754 const char *srcCertPrefix = "";
2755 char *upgradeID = "";
2756 char *upgradeTokenName = "";
2757 KeyType keytype = rsaKey;
2758 char *name = NULL((void*)0);
2759 char *newName = NULL((void*)0);
2760 char *email = NULL((void*)0);
2761 char *keysource = NULL((void*)0);
2762 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
2763 int keysize = DEFAULT_KEY_BITS2048;
2764 int publicExponent = 0x010001;
2765 int certVersion = SEC_CERTIFICATE_VERSION_32;
2766 unsigned int serialNumber = 0;
2767 int warpmonths = 0;
2768 int validityMonths = 3;
2769 int commandsEntered = 0;
2770 char commandToRun = '\0';
2771 secuPWData pwdata = { PW_NONE, 0 };
2772 secuPWData pwdata2 = { PW_NONE, 0 };
2773 PRBool readOnly = PR_FALSE0;
2774 PRBool initialized = PR_FALSE0;
2775 CK_FLAGS keyOpFlagsOn = 0;
2776 CK_FLAGS keyOpFlagsOff = 0;
2777 PK11AttrFlags keyAttrFlags =
2778 PK11_ATTR_TOKEN0x00000001L | PK11_ATTR_SENSITIVE0x00000040L | PK11_ATTR_PRIVATE0x00000004L;
2779
2780 SECKEYPrivateKey *privkey = NULL((void*)0);
2781 SECKEYPublicKey *pubkey = NULL((void*)0);
2782
2783 int i;
2784 SECStatus rv;
2785
2786 progName = PORT_Strrchrstrrchr(argv[0], '/');
2787 progName = progName ? progName + 1 : argv[0];
2788 memcpy(certutil_commands, commands_init, sizeof commands_init);
2789 memcpy(certutil_options, options_init, sizeof options_init);
2790
2791 rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
2792
2793 if (rv != SECSuccess)
2794 Usage();
2795
2796 if (certutil.commands[cmd_PrintSyntax].activated) {
2797 PrintSyntax();
2798 }
2799
2800 if (certutil.commands[cmd_PrintHelp].activated) {
2801 char buf[2];
2802 const char *command = NULL((void*)0);
2803 for (i = 0; i < max_cmd; i++) {
2804 if (i == cmd_PrintHelp)
2805 continue;
2806 if (certutil.commands[i].activated) {
2807 if (certutil.commands[i].flag) {
2808 buf[0] = certutil.commands[i].flag;
2809 buf[1] = 0;
2810 command = buf;
2811 } else {
2812 command = certutil.commands[i].longform;
2813 }
2814 break;
2815 }
2816 }
2817 LongUsage((command ? usage_selected : usage_all), command);
2818 exit(1);
2819 }
2820
2821 if (certutil.commands[cmd_BuildFlags].activated) {
2822 PrintBuildFlags();
2823 }
2824
2825 if (certutil.options[opt_PasswordFile].arg) {
2826 pwdata.source = PW_FROMFILE;
2827 pwdata.data = certutil.options[opt_PasswordFile].arg;
2828 }
2829 if (certutil.options[opt_NewPasswordFile].arg) {
2830 pwdata2.source = PW_FROMFILE;
2831 pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
2832 }
2833
2834 if (certutil.options[opt_CertDir].activated)
2835 SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
2836
2837 if (certutil.options[opt_SourceDir].activated)
2838 sourceDir = certutil.options[opt_SourceDir].arg;
2839
2840 if (certutil.options[opt_UpgradeID].activated)
2841 upgradeID = certutil.options[opt_UpgradeID].arg;
2842
2843 if (certutil.options[opt_UpgradeTokenName].activated)
2844 upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
2845
2846 if (certutil.options[opt_KeySize].activated) {
2847 keysize = PORT_Atoi(certutil.options[opt_KeySize].arg)(int)strtol(certutil.options[opt_KeySize].arg, ((void*)0), 10
)
;
2848 if ((keysize < MIN_KEY_BITS512) || (keysize > MAX_KEY_BITS8192)) {
2849 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
2850 "%s -g: Keysize must be between %d and %d.\n",
2851 progName, MIN_KEY_BITS512, MAX_KEY_BITS8192);
2852 return 255;
2853 }
2854 if (keytype == ecKey) {
2855 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -g: Not for ec keys.\n", progName);
2856 return 255;
2857 }
2858 }
2859
2860 /* -h specify token name */
2861 if (certutil.options[opt_TokenName].activated) {
2862 if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
2863 slotname = NULL((void*)0);
2864 else
2865 slotname = certutil.options[opt_TokenName].arg;
2866 }
2867
2868 /* -Z hash type */
2869 if (certutil.options[opt_Hash].activated) {
2870 char *arg = certutil.options[opt_Hash].arg;
2871 hashAlgTag = SECU_StringToSignatureAlgTag(arg);
2872 if (hashAlgTag == SEC_OID_UNKNOWN) {
2873 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -Z: %s is not a recognized type.\n",
2874 progName, arg);
2875 return 255;
2876 }
2877 }
2878
2879 /* -k key type */
2880 if (certutil.options[opt_KeyType].activated) {
2881 char *arg = certutil.options[opt_KeyType].arg;
2882 if (PL_strcmp(arg, "rsa") == 0) {
2883 keytype = rsaKey;
2884 } else if (PL_strcmp(arg, "dsa") == 0) {
2885 keytype = dsaKey;
2886 } else if (PL_strcmp(arg, "ec") == 0) {
2887 keytype = ecKey;
2888 } else if (PL_strcmp(arg, "all") == 0) {
2889 keytype = nullKey;
2890 } else {
2891 /* use an existing private/public key pair */
2892 keysource = arg;
2893 }
2894 } else if (certutil.commands[cmd_ListKeys].activated) {
2895 keytype = nullKey;
2896 }
2897
2898 if (certutil.options[opt_KeyOpFlagsOn].activated) {
2899 keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
2900 }
2901 if (certutil.options[opt_KeyOpFlagsOff].activated) {
2902 keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
2903 keyOpFlagsOn &= ~keyOpFlagsOff; /* make off override on */
2904 }
2905 if (certutil.options[opt_KeyAttrFlags].activated) {
2906 keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
2907 }
2908
2909 /* -m serial number */
2910 if (certutil.options[opt_SerialNumber].activated) {
2911 int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg)(int)strtol(certutil.options[opt_SerialNumber].arg, ((void*)0
), 10)
;
2912 if (sn < 0) {
2913 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -m: %s is not a valid serial number.\n",
2914 progName, certutil.options[opt_SerialNumber].arg);
2915 return 255;
2916 }
2917 serialNumber = sn;
2918 }
2919
2920 /* -P certdb name prefix */
2921 if (certutil.options[opt_DBPrefix].activated) {
2922 if (certutil.options[opt_DBPrefix].arg) {
2923 certPrefix = certutil.options[opt_DBPrefix].arg;
2924 } else {
2925 Usage();
2926 }
2927 }
2928
2929 /* --source-prefix certdb name prefix */
2930 if (certutil.options[opt_SourcePrefix].activated) {
2931 if (certutil.options[opt_SourcePrefix].arg) {
2932 srcCertPrefix = certutil.options[opt_SourcePrefix].arg;
2933 } else {
2934 Usage();
2935 }
2936 }
2937
2938 /* -q PQG file or curve name */
2939 if (certutil.options[opt_PQGFile].activated) {
2940 if ((keytype != dsaKey) && (keytype != ecKey)) {
2941 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -q: specifies a PQG file for DSA keys"
2942 " (-k dsa) or a named curve for EC keys (-k ec)\n)",
2943 progName);
2944 return 255;
2945 }
2946 }
2947
2948 /* -s subject name */
2949 if (certutil.options[opt_Subject].activated) {
2950 subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
2951 if (!subject) {
2952 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -s: improperly formatted name: \"%s\"\n",
2953 progName, certutil.options[opt_Subject].arg);
2954 return 255;
2955 }
2956 }
2957
2958 /* -v validity period */
2959 if (certutil.options[opt_Validity].activated) {
2960 validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg)(int)strtol(certutil.options[opt_Validity].arg, ((void*)0), 10
)
;
2961 if (validityMonths < 0) {
2962 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -v: incorrect validity period: \"%s\"\n",
2963 progName, certutil.options[opt_Validity].arg);
2964 return 255;
2965 }
2966 }
2967
2968 /* -w warp months */
2969 if (certutil.options[opt_OffsetMonths].activated)
2970 warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg)(int)strtol(certutil.options[opt_OffsetMonths].arg, ((void*)0
), 10)
;
2971
2972 /* -y public exponent (for RSA) */
2973 if (certutil.options[opt_Exponent].activated) {
2974 publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg)(int)strtol(certutil.options[opt_Exponent].arg, ((void*)0), 10
)
;
2975 if ((publicExponent != 3) &&
2976 (publicExponent != 17) &&
2977 (publicExponent != 65537)) {
2978 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -y: incorrect public exponent %d.",
2979 progName, publicExponent);
2980 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 3, 17, or 65537.\n");
2981 return 255;
2982 }
2983 }
2984
2985 /* --certVersion */
2986 if (certutil.options[opt_CertVersion].activated) {
2987 certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg)(int)strtol(certutil.options[opt_CertVersion].arg, ((void*)0)
, 10)
;
2988 if (certVersion < 1 || certVersion > 4) {
2989 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -certVersion: incorrect certificate version %d.",
2990 progName, certVersion);
2991 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 1, 2, 3 or 4.\n");
2992 return 255;
2993 }
2994 certVersion = certVersion - 1;
2995 }
2996
2997 /* Check number of commands entered. */
2998 commandsEntered = 0;
2999 for (i = 0; i < certutil.numCommands; i++) {
3000 if (certutil.commands[i].activated) {
3001 commandToRun = certutil.commands[i].flag;
3002 commandsEntered++;
3003 }
3004 if (commandsEntered > 1)
3005 break;
3006 }
3007 if (commandsEntered > 1) {
3008 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: only one command at a time!\n", progName);
3009 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "You entered: ");
3010 for (i = 0; i < certutil.numCommands; i++) {
3011 if (certutil.commands[i].activated)
3012 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " -%c", certutil.commands[i].flag);
3013 }
3014 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n");
3015 return 255;
3016 }
3017 if (commandsEntered == 0) {
3018 Usage();
3019 }
3020
3021 if (certutil.commands[cmd_ListCerts].activated ||
3022 certutil.commands[cmd_PrintHelp].activated ||
3023 certutil.commands[cmd_ListKeys].activated ||
3024 certutil.commands[cmd_ListModules].activated ||
3025 certutil.commands[cmd_CheckCertValidity].activated ||
3026 certutil.commands[cmd_Version].activated) {
3027 readOnly = !certutil.options[opt_RW].activated;
3028 }
3029
3030 /* -A, -D, -M, -S, -V, and all require -n */
3031 if ((certutil.commands[cmd_AddCert].activated ||
3032 certutil.commands[cmd_DeleteCert].activated ||
3033 certutil.commands[cmd_DumpChain].activated ||
3034 certutil.commands[cmd_ModifyCertTrust].activated ||
3035 certutil.commands[cmd_CreateAndAddCert].activated ||
3036 certutil.commands[cmd_CheckCertValidity].activated) &&
3037 !certutil.options[opt_Nickname].activated) {
3038 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3039 "%s -%c: nickname is required for this command (-n).\n",
3040 progName, commandToRun);
3041 return 255;
3042 }
3043
3044 /* -A, -E, -M, -S require trust */
3045 if ((certutil.commands[cmd_AddCert].activated ||
3046 certutil.commands[cmd_AddEmailCert].activated ||
3047 certutil.commands[cmd_ModifyCertTrust].activated ||
3048 certutil.commands[cmd_CreateAndAddCert].activated) &&
3049 !certutil.options[opt_Trust].activated) {
3050 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3051 "%s -%c: trust is required for this command (-t).\n",
3052 progName, commandToRun);
3053 return 255;
3054 }
3055
3056 /* if -L is given raw, ascii or dump mode, it must be for only one cert. */
3057 if (certutil.commands[cmd_ListCerts].activated &&
3058 (certutil.options[opt_ASCIIForIO].activated ||
3059 certutil.options[opt_DumpExtensionValue].activated ||
3060 certutil.options[opt_BinaryDER].activated) &&
3061 !certutil.options[opt_Nickname].activated) {
3062 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3063 "%s: nickname is required to dump cert in raw or ascii mode.\n",
3064 progName);
3065 return 255;
3066 }
3067
3068 /* -L can only be in (raw || ascii). */
3069 if (certutil.commands[cmd_ListCerts].activated &&
3070 certutil.options[opt_ASCIIForIO].activated &&
3071 certutil.options[opt_BinaryDER].activated) {
3072 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3073 "%s: cannot specify both -r and -a when dumping cert.\n",
3074 progName);
3075 return 255;
3076 }
3077
3078 /* If making a cert request, need a subject. */
3079 if ((certutil.commands[cmd_CertReq].activated ||
3080 certutil.commands[cmd_CreateAndAddCert].activated) &&
3081 !(certutil.options[opt_Subject].activated || keysource)) {
3082 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3083 "%s -%c: subject is required to create a cert request.\n",
3084 progName, commandToRun);
3085 return 255;
3086 }
3087
3088 /* If making a cert, need a serial number. */
3089 if ((certutil.commands[cmd_CreateNewCert].activated ||
3090 certutil.commands[cmd_CreateAndAddCert].activated) &&
3091 !certutil.options[opt_SerialNumber].activated) {
3092 /* Make a default serial number from the current time. */
3093 PRTime now = PR_Now();
3094 LL_USHR(now, now, 19)((now) = (PRUint64)(now) >> (19));
3095 LL_L2UI(serialNumber, now)((serialNumber) = (PRUint32)(now));
3096 }
3097
3098 /* Validation needs the usage to validate for. */
3099 if (certutil.commands[cmd_CheckCertValidity].activated &&
3100 !certutil.options[opt_Usage].activated) {
3101 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3102 "%s -V: specify a usage to validate the cert for (-u).\n",
3103 progName);
3104 return 255;
3105 }
3106
3107 /* Rename needs an old and a new nickname */
3108 if (certutil.commands[cmd_Rename].activated &&
3109 !(certutil.options[opt_Nickname].activated &&
3110 certutil.options[opt_NewNickname].activated)) {
3111
3112 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3113 "%s --rename: specify an old nickname (-n) and\n"
3114 " a new nickname (--new-n).\n",
3115 progName);
3116 return 255;
3117 }
3118
3119 /* Delete needs a nickname or a key ID */
3120 if (certutil.commands[cmd_DeleteKey].activated &&
3121 !(certutil.options[opt_Nickname].activated || keysource)) {
3122 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3123 "%s -%c: specify a nickname (-n) or\n"
3124 " a key ID (-k).\n",
3125 progName, commandToRun);
3126 return 255;
3127 }
3128
3129 /* Upgrade/Merge needs a source database and a upgrade id. */
3130 if (certutil.commands[cmd_UpgradeMerge].activated &&
3131 !(certutil.options[opt_SourceDir].activated &&
3132 certutil.options[opt_UpgradeID].activated)) {
3133
3134 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3135 "%s --upgrade-merge: specify an upgrade database directory "
3136 "(--source-dir) and\n"
3137 " an upgrade ID (--upgrade-id).\n",
3138 progName);
3139 return 255;
3140 }
3141
3142 /* Merge needs a source database */
3143 if (certutil.commands[cmd_Merge].activated &&
3144 !certutil.options[opt_SourceDir].activated) {
3145
3146 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3147 "%s --merge: specify an source database directory "
3148 "(--source-dir)\n",
3149 progName);
3150 return 255;
3151 }
3152
3153 /* To make a cert, need either a issuer or to self-sign it. */
3154 if (certutil.commands[cmd_CreateAndAddCert].activated &&
3155 !(certutil.options[opt_IssuerName].activated ||
3156 certutil.options[opt_SelfSign].activated)) {
3157 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3158 "%s -S: must specify issuer (-c) or self-sign (-x).\n",
3159 progName);
3160 return 255;
3161 }
3162
3163 /* Using slotname == NULL for listing keys and certs on all slots,
3164 * but only that. */
3165 if (!(certutil.commands[cmd_ListKeys].activated ||
3166 certutil.commands[cmd_DumpChain].activated ||
3167 certutil.commands[cmd_ListCerts].activated) &&
3168 slotname == NULL((void*)0)) {
3169 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3170 "%s -%c: cannot use \"-h all\" for this command.\n",
3171 progName, commandToRun);
3172 return 255;
3173 }
3174
3175 /* Using keytype == nullKey for list all key types, but only that. */
3176 if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
3177 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3178 "%s -%c: cannot use \"-k all\" for this command.\n",
3179 progName, commandToRun);
3180 return 255;
3181 }
3182
3183 /* Open the input file. */
3184 if (certutil.options[opt_InputFile].activated) {
3185 inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY0x01, 0);
3186 if (!inFile) {
3187 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3188 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3189 progName, certutil.options[opt_InputFile].arg,
3190 PR_GetError(), PR_GetOSError());
3191 return 255;
3192 }
3193 }
3194
3195 /* Open the output file. */
3196 if (certutil.options[opt_OutputFile].activated) {
3197 outFile = PR_Open(certutil.options[opt_OutputFile].arg,
3198 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20, 00660);
3199 if (!outFile) {
3200 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3201 "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
3202 progName, certutil.options[opt_OutputFile].arg,
3203 PR_GetError(), PR_GetOSError());
3204 return 255;
3205 }
3206 }
3207
3208 name = SECU_GetOptionArg(&certutil, opt_Nickname);
3209 newName = SECU_GetOptionArg(&certutil, opt_NewNickname);
3210 email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
3211
3212 PK11_SetPasswordFunc(SECU_GetModulePassword);
3213
3214 if (PR_TRUE1 == initialize) {
3215 /* Initialize NSPR and NSS. */
3216 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
3217 if (!certutil.commands[cmd_UpgradeMerge].activated) {
3218 rv = NSS_Initialize(SECU_ConfigDirectory(NULL((void*)0)),
3219 certPrefix, certPrefix,
3220 "secmod.db", readOnly ? NSS_INIT_READONLY0x1 : 0);
3221 } else {
3222 rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL((void*)0)),
3223 certPrefix, certPrefix, "secmod.db",
3224 sourceDir, srcCertPrefix, srcCertPrefix,
3225 upgradeID, upgradeTokenName,
3226 readOnly ? NSS_INIT_READONLY0x1 : 0);
3227 }
3228 if (rv != SECSuccess) {
3229 SECU_PrintPRandOSError(progName);
3230 rv = SECFailure;
3231 goto shutdown;
3232 }
3233 initialized = PR_TRUE1;
3234 SECU_RegisterDynamicOids();
3235 /* Ensure the SSL error code table has been registered. Bug 1460284. */
3236 SSL_OptionSetDefault(-1, 0);
3237 }
3238 certHandle = CERT_GetDefaultCertDB();
3239
3240 if (certutil.commands[cmd_Version].activated) {
3241 printf("Certificate database content version: command not implemented.\n");
3242 }
3243
3244 if (PL_strcmp(slotname, "internal") == 0)
3245 slot = PK11_GetInternalKeySlot();
3246 else if (slotname != NULL((void*)0))
3247 slot = PK11_FindSlotByName(slotname);
3248
3249 if (!slot && (certutil.commands[cmd_NewDBs].activated ||
3250 certutil.commands[cmd_ModifyCertTrust].activated ||
3251 certutil.commands[cmd_ChangePassword].activated ||
3252 certutil.commands[cmd_TokenReset].activated ||
3253 certutil.commands[cmd_CreateAndAddCert].activated ||
3254 certutil.commands[cmd_AddCert].activated ||
3255 certutil.commands[cmd_Merge].activated ||
3256 certutil.commands[cmd_UpgradeMerge].activated ||
3257 certutil.commands[cmd_AddEmailCert].activated)) {
3258
3259 SECU_PrintError(progName, "could not find the slot %s", slotname);
3260 rv = SECFailure;
3261 goto shutdown;
3262 }
3263
3264 /* If creating new database, initialize the password. */
3265 if (certutil.commands[cmd_NewDBs].activated) {
3266 if (certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) {
3267 rv = PK11_InitPin(slot, (char *)NULL((void*)0), "");
3268 } else {
3269 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3270 certutil.options[opt_NewPasswordFile].arg);
3271 }
3272 if (rv != SECSuccess) {
3273 SECU_PrintError(progName, "Could not set password for the slot");
3274 goto shutdown;
3275 }
3276 }
3277
3278 /* if we are going to modify the cert database,
3279 * make sure it's initialized */
3280 if (certutil.commands[cmd_ModifyCertTrust].activated ||
3281 certutil.commands[cmd_CreateAndAddCert].activated ||
3282 certutil.commands[cmd_AddCert].activated ||
3283 certutil.commands[cmd_AddEmailCert].activated) {
3284 if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
3285 char *password = NULL((void*)0);
3286 /* fetch the password from the command line or the file
3287 * if no password is supplied, initialize the password to NULL */
3288 if (pwdata.source == PW_FROMFILE) {
3289 password = SECU_FilePasswd(slot, PR_FALSE0, pwdata.data);
3290 } else if (pwdata.source == PW_PLAINTEXT) {
3291 password = PL_strdup(pwdata.data);
3292 }
3293 rv = PK11_InitPin(slot, (char *)NULL((void*)0), password ? password : "");
3294 if (password) {
3295 PORT_Memsetmemset(password, 0, PL_strlen(password));
3296 PORT_FreePORT_Free_Util(password);
3297 }
3298 if (rv != SECSuccess) {
3299 SECU_PrintError(progName, "Could not set password for the slot");
3300 goto shutdown;
3301 }
3302 }
3303 }
3304
3305 /* walk through the upgrade merge if necessary.
3306 * This option is more to test what some applications will want to do
3307 * to do an automatic upgrade. The --merge command is more useful for
3308 * the general case where 2 database need to be merged together.
3309 */
3310 if (certutil.commands[cmd_UpgradeMerge].activated) {
3311 if (*upgradeTokenName == 0) {
3312 upgradeTokenName = upgradeID;
3313 }
3314 if (!PK11_IsInternal(slot)) {
3315 fprintf(stderrstderr, "Only internal DB's can be upgraded\n");
3316 rv = SECSuccess;
3317 goto shutdown;
3318 }
3319 if (!PK11_IsRemovable(slot)) {
3320 printf("database already upgraded.\n");
3321 rv = SECSuccess;
3322 goto shutdown;
3323 }
3324 if (!PK11_NeedLogin(slot)) {
3325 printf("upgrade complete!\n");
3326 rv = SECSuccess;
3327 goto shutdown;
3328 }
3329 /* authenticate to the old DB if necessary */
3330 if (PORT_Strcmpstrcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) {
3331 /* if we need a password, supply it. This will be the password
3332 * for the old database */
3333 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata2);
3334 if (rv != SECSuccess) {
3335 SECU_PrintError(progName, "Could not get password for %s",
3336 upgradeTokenName);
3337 goto shutdown;
3338 }
3339 /*
3340 * if we succeeded above, but still aren't logged in, that means
3341 * we just supplied the password for the old database. We may
3342 * need the password for the new database. NSS will automatically
3343 * change the token names at this point
3344 */
3345 if (PK11_IsLoggedIn(slot, &pwdata)) {
3346 printf("upgrade complete!\n");
3347 rv = SECSuccess;
3348 goto shutdown;
3349 }
3350 }
3351
3352 /* call PK11_IsPresent to update our cached token information */
3353 if (!PK11_IsPresent(slot)) {
3354 /* this shouldn't happen. We call isPresent to force a token
3355 * info update */
3356 fprintf(stderrstderr, "upgrade/merge internal error\n");
3357 rv = SECFailure;
3358 goto shutdown;
3359 }
3360
3361 /* the token is now set to the state of the source database,
3362 * if we need a password for it, PK11_Authenticate will
3363 * automatically prompt us */
3364 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3365 if (rv == SECSuccess) {
3366 printf("upgrade complete!\n");
3367 } else {
3368 SECU_PrintError(progName, "Could not get password for %s",
3369 PK11_GetTokenName(slot));
3370 }
3371 goto shutdown;
3372 }
3373
3374 /*
3375 * merge 2 databases.
3376 */
3377 if (certutil.commands[cmd_Merge].activated) {
3378 PK11SlotInfo *sourceSlot = NULL((void*)0);
3379 PK11MergeLog *log;
3380 char *modspec = PR_smprintf(
3381 "configDir='%s' certPrefix='%s' tokenDescription='%s'",
3382 sourceDir, srcCertPrefix,
3383 *upgradeTokenName ? upgradeTokenName : "Source Database");
3384
3385 if (!modspec) {
3386 rv = SECFailure;
3387 goto shutdown;
3388 }
3389
3390 sourceSlot = SECMOD_OpenUserDB(modspec);
3391 PR_smprintf_free(modspec);
3392 if (!sourceSlot) {
3393 SECU_PrintError(progName, "couldn't open source database");
3394 rv = SECFailure;
3395 goto shutdown;
3396 }
3397
3398 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3399 if (rv != SECSuccess) {
3400 SECU_PrintError(progName, "Couldn't get password for %s",
3401 PK11_GetTokenName(slot));
3402 goto merge_fail;
3403 }
3404
3405 rv = PK11_Authenticate(sourceSlot, PR_FALSE0, &pwdata2);
3406 if (rv != SECSuccess) {
3407 SECU_PrintError(progName, "Couldn't get password for %s",
3408 PK11_GetTokenName(sourceSlot));
3409 goto merge_fail;
3410 }
3411
3412 log = PK11_CreateMergeLog();
3413 if (!log) {
3414 rv = SECFailure;
3415 SECU_PrintError(progName, "couldn't create error log");
3416 goto merge_fail;
3417 }
3418
3419 rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
3420 if (rv != SECSuccess) {
3421 DumpMergeLog(progName, log);
3422 }
3423 PK11_DestroyMergeLog(log);
3424
3425 merge_fail:
3426 SECMOD_CloseUserDB(sourceSlot);
3427 PK11_FreeSlot(sourceSlot);
3428 goto shutdown;
3429 }
3430
3431 /* The following 8 options are mutually exclusive with all others. */
3432
3433 /* List certs (-L) */
3434 if (certutil.commands[cmd_ListCerts].activated) {
3435 if (certutil.options[opt_DumpExtensionValue].activated) {
3436 const char *oid_str;
3437 SECItem oid_item;
3438 SECStatus srv;
3439 oid_item.data = NULL((void*)0);
3440 oid_item.len = 0;
3441 oid_str = certutil.options[opt_DumpExtensionValue].arg;
3442 srv = GetOidFromString(NULL((void*)0), &oid_item, oid_str, strlen(oid_str));
3443 if (srv != SECSuccess) {
3444 SECU_PrintError(progName, "malformed extension OID %s",
3445 oid_str);
3446 goto shutdown;
3447 }
3448 rv = ListCerts(certHandle, name, email, slot,
3449 PR_TRUE1 /*binary*/, PR_FALSE0 /*ascii*/,
3450 &oid_item,
3451 outFile, &pwdata);
3452 SECITEM_FreeItemSECITEM_FreeItem_Util(&oid_item, PR_FALSE0);
3453 } else {
3454 rv = ListCerts(certHandle, name, email, slot,
3455 certutil.options[opt_BinaryDER].activated,
3456 certutil.options[opt_ASCIIForIO].activated,
3457 NULL((void*)0), outFile, &pwdata);
3458 }
3459 goto shutdown;
3460 }
3461 if (certutil.commands[cmd_DumpChain].activated) {
3462 rv = DumpChain(certHandle, name,
3463 certutil.options[opt_ASCIIForIO].activated,
3464 certutil.options[opt_SimpleSelfSigned].activated);
3465 goto shutdown;
3466 }
3467 /* XXX needs work */
3468 /* List keys (-K) */
3469 if (certutil.commands[cmd_ListKeys].activated) {
3470 rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE0 /*dopriv*/,
3471 &pwdata);
3472 goto shutdown;
3473 }
3474 /* List modules (-U) */
3475 if (certutil.commands[cmd_ListModules].activated) {
3476 rv = ListModules();
3477 goto shutdown;
3478 }
3479 /* Delete cert (-D) */
3480 if (certutil.commands[cmd_DeleteCert].activated) {
3481 rv = DeleteCert(certHandle, name, &pwdata);
3482 goto shutdown;
3483 }
3484 /* Rename cert (--rename) */
3485 if (certutil.commands[cmd_Rename].activated) {
3486 rv = RenameCert(certHandle, name, newName, &pwdata);
3487 goto shutdown;
3488 }
3489 /* Delete key (-F) */
3490 if (certutil.commands[cmd_DeleteKey].activated) {
3491 if (certutil.options[opt_Nickname].activated) {
3492 rv = DeleteCertAndKey(name, &pwdata);
3493 } else {
3494 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3495 if (!privkey) {
3496 SECU_PrintError(progName, "%s is not a key-id", keysource);
3497 rv = SECFailure;
3498 } else {
3499 rv = DeleteKey(privkey, &pwdata);
3500 /* already destroyed by PK11_DeleteTokenPrivateKey */
3501 privkey = NULL((void*)0);
3502 }
3503 }
3504 goto shutdown;
3505 }
3506 /* Modify trust attribute for cert (-M) */
3507 if (certutil.commands[cmd_ModifyCertTrust].activated) {
3508 rv = ChangeTrustAttributes(certHandle, slot, name,
3509 certutil.options[opt_Trust].arg, &pwdata);
3510 goto shutdown;
3511 }
3512 /* Change key db password (-W) (future - change pw to slot?) */
3513 if (certutil.commands[cmd_ChangePassword].activated) {
3514 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3515 certutil.options[opt_NewPasswordFile].arg);
3516 if (rv != SECSuccess) {
3517 SECU_PrintError(progName, "Could not set password for the slot");
3518 goto shutdown;
3519 }
3520 }
3521 /* Reset the a token */
3522 if (certutil.commands[cmd_TokenReset].activated) {
3523 char *sso_pass = "";
3524
3525 if (certutil.options[opt_SSOPass].activated) {
3526 sso_pass = certutil.options[opt_SSOPass].arg;
3527 }
3528 rv = PK11_ResetToken(slot, sso_pass);
3529
3530 goto shutdown;
3531 }
3532 /* Check cert validity against current time (-V) */
3533 if (certutil.commands[cmd_CheckCertValidity].activated) {
3534 /* XXX temporary hack for fips - must log in to get priv key */
3535 if (certutil.options[opt_VerifySig].activated) {
3536 if (slot && PK11_NeedLogin(slot)) {
3537 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE1, &pwdata);
3538 if (newrv != SECSuccess) {
3539 SECU_PrintError(progName, "could not authenticate to token %s.",
3540 PK11_GetTokenName(slot));
3541 goto shutdown;
3542 }
3543 }
3544 }
3545 rv = ValidateCert(certHandle, name,
3546 certutil.options[opt_ValidityTime].arg,
3547 certutil.options[opt_Usage].arg,
3548 certutil.options[opt_VerifySig].activated,
3549 certutil.options[opt_DetailedInfo].activated,
3550 certutil.options[opt_ASCIIForIO].activated,
3551 &pwdata);
3552 if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS)
3553 SECU_PrintError(progName, "validation failed");
3554 goto shutdown;
3555 }
3556
3557 /*
3558 * Key generation
3559 */
3560
3561 /* These commands may require keygen. */
3562 if (certutil.commands[cmd_CertReq].activated ||
3563 certutil.commands[cmd_CreateAndAddCert].activated ||
3564 certutil.commands[cmd_GenKeyPair].activated) {
3565 if (keysource) {
3566 CERTCertificate *keycert;
3567 keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource);
3568 if (!keycert) {
3569 keycert = PK11_FindCertFromNickname(keysource, NULL((void*)0));
3570 }
3571
3572 if (keycert) {
3573 privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
3574 } else {
3575 /* Interpret keysource as CKA_ID */
3576 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3577 }
3578
3579 if (!privkey) {
3580 SECU_PrintError(
3581 progName,
3582 "%s is neither a key-type nor a nickname nor a key-id", keysource);
3583 return SECFailure;
3584 }
3585
3586 pubkey = SECKEY_ConvertToPublicKey(privkey);
3587 if (!pubkey) {
3588 SECU_PrintError(progName,
3589 "Could not get keys from cert %s", keysource);
3590 if (keycert) {
3591 CERT_DestroyCertificate(keycert);
3592 }
3593 rv = SECFailure;
3594 goto shutdown;
3595 }
3596 keytype = privkey->keyType;
3597
3598 /* On CertReq for renewal if no subject has been
3599 * specified obtain it from the certificate.
3600 */
3601 if (certutil.commands[cmd_CertReq].activated && !subject) {
3602 if (keycert) {
3603 subject = CERT_AsciiToName(keycert->subjectName);
3604 if (!subject) {
3605 SECU_PrintError(
3606 progName,
3607 "Could not get subject from certificate %s",
3608 keysource);
3609 CERT_DestroyCertificate(keycert);
3610 rv = SECFailure;
3611 goto shutdown;
3612 }
3613 } else {
3614 SECU_PrintError(progName, "Subject name not provided");
3615 rv = SECFailure;
3616 goto shutdown;
3617 }
3618 }
3619 if (keycert) {
3620 CERT_DestroyCertificate(keycert);
3621 }
3622 } else {
3623 privkey =
3624 CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
3625 publicExponent,
3626 certutil.options[opt_NoiseFile].arg,
3627 &pubkey,
3628 certutil.options[opt_PQGFile].arg,
3629 keyAttrFlags,
3630 keyOpFlagsOn,
3631 keyOpFlagsOff,
3632 &pwdata);
3633 if (privkey == NULL((void*)0)) {
3634 SECU_PrintError(progName, "unable to generate key(s)\n");
3635 rv = SECFailure;
3636 goto shutdown;
3637 }
3638 }
3639 privkey->wincx = &pwdata;
3640 PORT_Assert(pubkey != NULL)((pubkey != ((void*)0))?((void)0):PR_Assert("pubkey != NULL",
"certutil.c",3640))
;
3641
3642 /* If all that was needed was keygen, exit. */
3643 if (certutil.commands[cmd_GenKeyPair].activated) {
3644 rv = SECSuccess;
3645 goto shutdown;
3646 }
3647 }
3648
3649 if (certutil.options[opt_Pss].activated) {
3650 if (!certutil.commands[cmd_CertReq].activated &&
3651 !certutil.commands[cmd_CreateAndAddCert].activated) {
3652 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3653 "%s -%c: --pss only works with -R or -S.\n",
3654 progName, commandToRun);
3655 return 255;
3656 }
3657 if (keytype != rsaKey) {
3658 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3659 "%s -%c: --pss only works with RSA keys.\n",
3660 progName, commandToRun);
3661 return 255;
3662 }
3663 }
3664
3665 /* --pss-sign is to sign a certificate with RSA-PSS, even if the
3666 * issuer's key is an RSA key. If the key is an RSA-PSS key, the
3667 * generated signature is always RSA-PSS. */
3668 if (certutil.options[opt_PssSign].activated) {
3669 if (!certutil.commands[cmd_CreateNewCert].activated &&
3670 !certutil.commands[cmd_CreateAndAddCert].activated) {
3671 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3672 "%s -%c: --pss-sign only works with -C or -S.\n",
3673 progName, commandToRun);
3674 return 255;
3675 }
3676 if (keytype != rsaKey) {
3677 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3678 "%s -%c: --pss-sign only works with RSA keys.\n",
3679 progName, commandToRun);
3680 return 255;
3681 }
3682 }
3683
3684 if (certutil.options[opt_SimpleSelfSigned].activated &&
3685 !certutil.commands[cmd_DumpChain].activated) {
3686 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3687 "%s -%c: --simple-self-signed only works with -O.\n",
3688 progName, commandToRun);
3689 return 255;
3690 }
3691
3692 /* If we need a list of extensions convert the flags into list format */
3693 if (certutil.commands[cmd_CertReq].activated ||
3694 certutil.commands[cmd_CreateAndAddCert].activated ||
3695 certutil.commands[cmd_CreateNewCert].activated) {
3696 certutil_extns[ext_keyUsage].activated =
3697 certutil.options[opt_AddCmdKeyUsageExt].activated;
3698 if (!certutil_extns[ext_keyUsage].activated) {
3699 certutil_extns[ext_keyUsage].activated =
3700 certutil.options[opt_AddKeyUsageExt].activated;
3701 } else {
3702 certutil_extns[ext_keyUsage].arg =
3703 certutil.options[opt_AddCmdKeyUsageExt].arg;
3704 }
3705 certutil_extns[ext_basicConstraint].activated =
3706 certutil.options[opt_AddBasicConstraintExt].activated;
3707 certutil_extns[ext_nameConstraints].activated =
3708 certutil.options[opt_AddNameConstraintsExt].activated;
3709 certutil_extns[ext_authorityKeyID].activated =
3710 certutil.options[opt_AddAuthorityKeyIDExt].activated;
3711 certutil_extns[ext_subjectKeyID].activated =
3712 certutil.options[opt_AddSubjectKeyIDExt].activated;
3713 certutil_extns[ext_CRLDistPts].activated =
3714 certutil.options[opt_AddCRLDistPtsExt].activated;
3715 certutil_extns[ext_NSCertType].activated =
3716 certutil.options[opt_AddCmdNSCertTypeExt].activated;
3717 if (!certutil_extns[ext_NSCertType].activated) {
3718 certutil_extns[ext_NSCertType].activated =
3719 certutil.options[opt_AddNSCertTypeExt].activated;
3720 } else {
3721 certutil_extns[ext_NSCertType].arg =
3722 certutil.options[opt_AddCmdNSCertTypeExt].arg;
3723 }
3724
3725 certutil_extns[ext_extKeyUsage].activated =
3726 certutil.options[opt_AddCmdExtKeyUsageExt].activated;
3727 if (!certutil_extns[ext_extKeyUsage].activated) {
3728 certutil_extns[ext_extKeyUsage].activated =
3729 certutil.options[opt_AddExtKeyUsageExt].activated;
3730 } else {
3731 certutil_extns[ext_extKeyUsage].arg =
3732 certutil.options[opt_AddCmdExtKeyUsageExt].arg;
3733 }
3734 certutil_extns[ext_subjectAltName].activated =
3735 certutil.options[opt_AddSubjectAltNameExt].activated;
3736 if (certutil_extns[ext_subjectAltName].activated) {
3737 certutil_extns[ext_subjectAltName].arg =
3738 certutil.options[opt_AddSubjectAltNameExt].arg;
3739 }
3740
3741 certutil_extns[ext_authInfoAcc].activated =
3742 certutil.options[opt_AddAuthInfoAccExt].activated;
3743 certutil_extns[ext_subjInfoAcc].activated =
3744 certutil.options[opt_AddSubjInfoAccExt].activated;
3745 certutil_extns[ext_certPolicies].activated =
3746 certutil.options[opt_AddCertPoliciesExt].activated;
3747 certutil_extns[ext_policyMappings].activated =
3748 certutil.options[opt_AddPolicyMapExt].activated;
3749 certutil_extns[ext_policyConstr].activated =
3750 certutil.options[opt_AddPolicyConstrExt].activated;
3751 certutil_extns[ext_inhibitAnyPolicy].activated =
3752 certutil.options[opt_AddInhibAnyExt].activated;
3753 }
3754
3755 /* -A -C or -E Read inFile */
3756 if (certutil.commands[cmd_CreateNewCert].activated ||
3757 certutil.commands[cmd_AddCert].activated ||
3758 certutil.commands[cmd_AddEmailCert].activated) {
3759 PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
3760 rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
3761 certutil.options[opt_ASCIIForIO].activated,
3762 PR_TRUE1);
3763 if (rv)
3764 goto shutdown;
3765 }
3766
3767 /*
3768 * Certificate request
3769 */
3770
3771 /* Make a cert request (-R). */
3772 if (certutil.commands[cmd_CertReq].activated) {
3773 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3774 certutil.options[opt_PhoneNumber].arg,
3775 certutil.options[opt_ASCIIForIO].activated,
3776 certutil.options[opt_ExtendedEmailAddrs].arg,
3777 certutil.options[opt_ExtendedDNSNames].arg,
3778 certutil_extns,
3779 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3780 : NULL((void*)0)),
3781 certutil.options[opt_Pss].activated,
3782 &certReqDER);
3783 if (rv)
3784 goto shutdown;
3785 privkey->wincx = &pwdata;
3786 }
3787
3788 /*
3789 * Certificate creation
3790 */
3791
3792 /* If making and adding a cert, create a cert request file first without
3793 * any extensions, then load it with the command line extensions
3794 * and output the cert to another file.
3795 */
3796 if (certutil.commands[cmd_CreateAndAddCert].activated) {
3797 static certutilExtnList nullextnlist = { { PR_FALSE0, NULL((void*)0) } };
3798 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3799 certutil.options[opt_PhoneNumber].arg,
3800 PR_FALSE0, /* do not BASE64-encode regardless of -a option */
3801 NULL((void*)0),
3802 NULL((void*)0),
3803 nullextnlist,
3804 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3805 : NULL((void*)0)),
3806 certutil.options[opt_Pss].activated,
3807 &certReqDER);
3808 if (rv)
3809 goto shutdown;
3810 privkey->wincx = &pwdata;
3811 }
3812
3813 /* Create a certificate (-C or -S). */
3814 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3815 certutil.commands[cmd_CreateNewCert].activated) {
3816 rv = CreateCert(certHandle, slot,
3817 certutil.options[opt_IssuerName].arg,
3818 &certReqDER, &privkey, &pwdata, hashAlgTag,
3819 serialNumber, warpmonths, validityMonths,
3820 certutil.options[opt_ExtendedEmailAddrs].arg,
3821 certutil.options[opt_ExtendedDNSNames].arg,
3822 certutil.options[opt_ASCIIForIO].activated &&
3823 certutil.commands[cmd_CreateNewCert].activated,
3824 certutil.options[opt_SelfSign].activated,
3825 certutil_extns,
3826 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3827 : NULL((void*)0)),
3828 certVersion,
3829 certutil.options[opt_PssSign].activated,
3830 &certDER);
3831 if (rv)
3832 goto shutdown;
3833 }
3834
3835 /*
3836 * Adding a cert to the database (or slot)
3837 */
3838
3839 /* -A -E or -S Add the cert to the DB */
3840 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3841 certutil.commands[cmd_AddCert].activated ||
3842 certutil.commands[cmd_AddEmailCert].activated) {
3843 if (strstr(certutil.options[opt_Trust].arg, "u")) {
3844 fprintf(stderrstderr, "Notice: Trust flag u is set automatically if the "
3845 "private key is present.\n");
3846 }
3847 rv = AddCert(slot, certHandle, name,
3848 certutil.options[opt_Trust].arg,
3849 &certDER,
3850 certutil.commands[cmd_AddEmailCert].activated, &pwdata);
3851 if (rv)
3852 goto shutdown;
3853 }
3854
3855 if (certutil.commands[cmd_CertReq].activated ||
3856 certutil.commands[cmd_CreateNewCert].activated) {
3857 SECItem *item = certutil.commands[cmd_CertReq].activated ? &certReqDER
3858 : &certDER;
3859 PRInt32 written = PR_Write(outFile, item->data, item->len);
3860 if (written < 0 || (PRUint32)written != item->len) {
3861 rv = SECFailure;
3862 }
3863 }
3864
3865shutdown:
3866 if (slot) {
3867 PK11_FreeSlot(slot);
3868 }
3869 if (privkey) {
3870 SECKEY_DestroyPrivateKey(privkey);
3871 }
3872 if (pubkey) {
3873 SECKEY_DestroyPublicKey(pubkey);
3874 }
3875 if (subject) {
3876 CERT_DestroyName(subject);
3877 }
3878 if (name) {
3879 PL_strfree(name);
3880 }
3881 if (newName) {
3882 PL_strfree(newName);
3883 }
3884 if (inFile && inFile != PR_STDINPR_GetSpecialFD(PR_StandardInput)) {
3885 PR_Close(inFile);
3886 }
3887 if (outFile && outFile != PR_STDOUTPR_GetSpecialFD(PR_StandardOutput)) {
3888 PR_Close(outFile);
3889 }
3890 SECITEM_FreeItemSECITEM_FreeItem_Util(&certReqDER, PR_FALSE0);
3891 SECITEM_FreeItemSECITEM_FreeItem_Util(&certDER, PR_FALSE0);
3892 if (pwdata.data && pwdata.source == PW_PLAINTEXT) {
3893 /* Allocated by a PL_strdup call in SECU_GetModulePassword. */
3894 PL_strfree(pwdata.data);
3895 }
3896 if (email) {
3897 PL_strfree(email);
3898 }
3899
3900 /* Open the batch command file.
3901 *
3902 * - If -B <command line> option is specified, the contents in the
3903 * command file will be interpreted as subsequent certutil
3904 * commands to be executed in the current certutil process
3905 * context after the current certutil command has been executed.
3906 * - Each line in the command file consists of the command
3907 * line arguments for certutil.
3908 * - The -d <configdir> option will be ignored if specified in the
3909 * command file.
3910 * - Quoting with double quote characters ("...") is supported
3911 * to allow white space in a command line argument. The
3912 * double quote character cannot be escaped and quoting cannot
3913 * be nested in this version.
3914 * - each line in the batch file is limited to 512 characters
3915 */
3916
3917 if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) {
3918 FILE *batchFile = NULL((void*)0);
3919 char *nextcommand = NULL((void*)0);
3920 PRInt32 cmd_len = 0, buf_size = 0;
3921 static const int increment = 512;
3922
3923 if (!certutil.options[opt_InputFile].activated ||
3924 !certutil.options[opt_InputFile].arg) {
3925 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3926 "%s: no batch input file specified.\n",
3927 progName);
3928 return 255;
3929 }
3930 batchFile = fopen(certutil.options[opt_InputFile].arg, "r");
3931 if (!batchFile) {
3932 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3933 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3934 progName, certutil.options[opt_InputFile].arg,
3935 PR_GetError(), PR_GetOSError());
3936 return 255;
3937 }
3938 /* read and execute command-lines in a loop */
3939 while (SECSuccess == rv) {
3940 PRBool invalid = PR_FALSE0;
3941 int newargc = 2;
3942 char *space = NULL((void*)0);
3943 char *nextarg = NULL((void*)0);
3944 char **newargv = NULL((void*)0);
3945 char *crlf;
3946
3947 if (cmd_len + increment > buf_size) {
3948 char *new_buf;
3949 buf_size += increment;
3950 new_buf = PORT_ReallocPORT_Realloc_Util(nextcommand, buf_size);
3951 if (!new_buf) {
3952 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: PORT_Realloc(%ld) failed\n",
3953 progName, buf_size);
3954 break;
3955 }
3956 nextcommand = new_buf;
3957 nextcommand[cmd_len] = '\0';
3958 }
3959 if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) {
3960 break;
3961 }
3962 crlf = PORT_Strrchrstrrchr(nextcommand, '\n');
3963 if (crlf) {
3964 *crlf = '\0';
3965 }
3966 cmd_len = strlen(nextcommand);
3967 if (cmd_len && nextcommand[cmd_len - 1] == '\\') {
3968 nextcommand[--cmd_len] = '\0';
3969 continue;
3970 }
3971
3972 /* we now need to split the command into argc / argv format */
3973
3974 newargv = PORT_AllocPORT_Alloc_Util(sizeof(char *) * (newargc + 1));
3975 newargv[0] = progName;
3976 newargv[1] = nextcommand;
3977 nextarg = nextcommand;
3978 while ((space = PORT_Strpbrkstrpbrk(nextarg, " \f\n\r\t\v"))) {
3979 while (isspace(*space)((*__ctype_b_loc ())[(int) ((*space))] & (unsigned short int
) _ISspace)
) {
3980 *space = '\0';
3981 space++;
3982 }
3983 if (*space == '\0') {
3984 break;
3985 } else if (*space != '\"') {
3986 nextarg = space;
3987 } else {
3988 char *closingquote = strchr(space + 1, '\"');
3989 if (closingquote) {
3990 *closingquote = '\0';
3991 space++;
3992 nextarg = closingquote + 1;
3993 } else {
3994 invalid = PR_TRUE1;
3995 nextarg = space;
3996 }
3997 }
3998 newargc++;
3999 newargv = PORT_ReallocPORT_Realloc_Util(newargv, sizeof(char *) * (newargc + 1));
4000 newargv[newargc - 1] = space;
4001 }
4002 newargv[newargc] = NULL((void*)0);
4003
4004 /* invoke next command */
4005 if (PR_TRUE1 == invalid) {
4006 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Missing closing quote in batch command :\n%s\nNot executed.\n",
4007 nextcommand);
4008 rv = SECFailure;
4009 } else {
4010 if (0 != certutil_main(newargc, newargv, PR_FALSE0))
4011 rv = SECFailure;
4012 }
4013 PORT_FreePORT_Free_Util(newargv);
4014 cmd_len = 0;
4015 nextcommand[0] = '\0';
4016 }
4017 PORT_FreePORT_Free_Util(nextcommand);
4018 fclose(batchFile);
4019 }
4020
4021 if ((initialized == PR_TRUE1) && NSS_Shutdown() != SECSuccess) {
4022 exit(1);
4023 }
4024 if (rv == SECSuccess) {
4025 return 0;
4026 } else {
4027 return 255;
4028 }
4029}
4030
4031int
4032main(int argc, char **argv)
4033{
4034 int rv = certutil_main(argc, argv, PR_TRUE1);
4035 PL_ArenaFinish();
4036 PR_Cleanup();
4037 return rv;
4038}