1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
41 ** utility for managing certificates and the cert database
73 #define MIN_KEY_BITS 512
74 /* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */
75 #define MAX_KEY_BITS 8192
76 #define DEFAULT_KEY_BITS 1024
78 #define GEN_BREAK(e) rv=e; break;
82 static CERTCertificateRequest
*
83 GetCertRequest(PRFileDesc
*inFile
, PRBool ascii
)
85 CERTCertificateRequest
*certReq
= NULL
;
86 CERTSignedData signedData
;
87 PRArenaPool
*arena
= NULL
;
93 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
95 GEN_BREAK (SECFailure
);
98 rv
= SECU_ReadDERFromFile(&reqDER
, inFile
, ascii
);
102 certReq
= (CERTCertificateRequest
*) PORT_ArenaZAlloc
103 (arena
, sizeof(CERTCertificateRequest
));
105 GEN_BREAK(SECFailure
);
107 certReq
->arena
= arena
;
109 /* Since cert request is a signed data, must decode to get the inner
112 PORT_Memset(&signedData
, 0, sizeof(signedData
));
113 rv
= SEC_ASN1DecodeItem(arena
, &signedData
,
114 SEC_ASN1_GET(CERT_SignedDataTemplate
), &reqDER
);
118 rv
= SEC_ASN1DecodeItem(arena
, certReq
,
119 SEC_ASN1_GET(CERT_CertificateRequestTemplate
), &signedData
.data
);
123 rv
= CERT_VerifySignedDataWithPublicKeyInfo(&signedData
,
124 &certReq
->subjectPublicKeyInfo
, NULL
/* wincx */);
128 SECITEM_FreeItem(&reqDER
, PR_FALSE
);
132 SECU_PrintError(progName
, "bad certificate request\n");
134 PORT_FreeArena(arena
, PR_FALSE
);
143 AddCert(PK11SlotInfo
*slot
, CERTCertDBHandle
*handle
, char *name
, char *trusts
,
144 PRFileDesc
*inFile
, PRBool ascii
, PRBool emailcert
, void *pwdata
)
146 CERTCertTrust
*trust
= NULL
;
147 CERTCertificate
*cert
= NULL
;
153 /* Read in the entire file specified with the -i argument */
154 rv
= SECU_ReadDERFromFile(&certDER
, inFile
, ascii
);
155 if (rv
!= SECSuccess
) {
156 SECU_PrintError(progName
, "unable to read input file");
160 /* Read in an ASCII cert and return a CERTCertificate */
161 cert
= CERT_DecodeCertFromPackage((char *)certDER
.data
, certDER
.len
);
163 SECU_PrintError(progName
, "could not obtain certificate from file");
164 GEN_BREAK(SECFailure
);
167 /* Create a cert trust to pass to SEC_AddPermCertificate */
168 trust
= (CERTCertTrust
*)PORT_ZAlloc(sizeof(CERTCertTrust
));
170 SECU_PrintError(progName
, "unable to allocate cert trust");
171 GEN_BREAK(SECFailure
);
174 rv
= CERT_DecodeTrustString(trust
, trusts
);
176 SECU_PrintError(progName
, "unable to decode trust string");
177 GEN_BREAK(SECFailure
);
180 if (PK11_IsFIPS() || !PK11_IsInternal(slot
)) {
181 rv
= PK11_Authenticate(slot
, PR_TRUE
, pwdata
);
182 if (rv
!= SECSuccess
) {
183 SECU_PrintError(progName
, "could not authenticate to token %s.",
184 PK11_GetTokenName(slot
));
185 GEN_BREAK(SECFailure
);
189 rv
= PK11_ImportCert(slot
, cert
, CK_INVALID_HANDLE
, name
, PR_FALSE
);
190 if (rv
!= SECSuccess
) {
191 SECU_PrintError(progName
, "could not add certificate to token or database");
192 GEN_BREAK(SECFailure
);
195 rv
= CERT_ChangeCertTrust(handle
, cert
, trust
);
196 if (rv
!= SECSuccess
) {
197 if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN
) {
198 rv
= PK11_Authenticate(slot
, PR_TRUE
, pwdata
);
199 if (rv
!= SECSuccess
) {
200 SECU_PrintError(progName
, "could not authenticate to token %s.",
201 PK11_GetTokenName(slot
));
202 GEN_BREAK(SECFailure
);
204 rv
= CERT_ChangeCertTrust(handle
, cert
, trust
);
206 if (rv
!= SECSuccess
) {
207 SECU_PrintError(progName
,
208 "could not change trust on certificate");
209 GEN_BREAK(SECFailure
);
214 CERT_SaveSMimeProfile(cert
, NULL
, pwdata
);
219 CERT_DestroyCertificate (cert
);
221 PORT_Free(certDER
.data
);
227 CertReq(SECKEYPrivateKey
*privk
, SECKEYPublicKey
*pubk
, KeyType keyType
,
228 SECOidTag hashAlgTag
, CERTName
*subject
, char *phone
, int ascii
,
229 const char *emailAddrs
, const char *dnsNames
,
230 certutilExtnList extnList
,
233 CERTSubjectPublicKeyInfo
*spki
;
234 CERTCertificateRequest
*cr
;
236 SECOidTag signAlgTag
;
243 /* Create info about public key */
244 spki
= SECKEY_CreateSubjectPublicKeyInfo(pubk
);
246 SECU_PrintError(progName
, "unable to create subject public key");
250 /* Generate certificate request */
251 cr
= CERT_CreateCertificateRequest(subject
, spki
, NULL
);
253 SECU_PrintError(progName
, "unable to make certificate request");
257 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
259 SECU_PrintError(progName
, "out of memory");
263 extHandle
= CERT_StartCertificateRequestAttributes(cr
);
264 if (extHandle
== NULL
) {
265 PORT_FreeArena (arena
, PR_FALSE
);
268 if (AddExtensions(extHandle
, emailAddrs
, dnsNames
, extnList
)
270 PORT_FreeArena (arena
, PR_FALSE
);
273 CERT_FinishExtensions(extHandle
);
274 CERT_FinishCertificateRequestAttributes(cr
);
276 /* Der encode the request */
277 encoding
= SEC_ASN1EncodeItem(arena
, NULL
, cr
,
278 SEC_ASN1_GET(CERT_CertificateRequestTemplate
));
279 if (encoding
== NULL
) {
280 SECU_PrintError(progName
, "der encoding of request failed");
284 /* Sign the request */
285 signAlgTag
= SEC_GetSignatureAlgorithmOidTag(keyType
, hashAlgTag
);
286 if (signAlgTag
== SEC_OID_UNKNOWN
) {
287 SECU_PrintError(progName
, "unknown Key or Hash type");
290 rv
= SEC_DerSignData(arena
, &result
, encoding
->data
, encoding
->len
,
293 SECU_PrintError(progName
, "signing of data failed");
297 /* Encode request in specified format */
300 char *name
, *email
, *org
, *state
, *country
;
306 obuf
= BTOA_ConvertItemToAscii(it
);
307 total
= PL_strlen(obuf
);
309 name
= CERT_GetCommonName(subject
);
311 name
= strdup("(not specified)");
315 phone
= strdup("(not specified)");
317 email
= CERT_GetCertEmailAddress(subject
);
319 email
= strdup("(not specified)");
321 org
= CERT_GetOrgName(subject
);
323 org
= strdup("(not specified)");
325 state
= CERT_GetStateName(subject
);
327 state
= strdup("(not specified)");
329 country
= CERT_GetCountryName(subject
);
331 country
= strdup("(not specified)");
334 "\nCertificate request generated by Netscape certutil\n");
335 PR_fprintf(outFile
, "Phone: %s\n\n", phone
);
336 PR_fprintf(outFile
, "Common Name: %s\n", name
);
337 PR_fprintf(outFile
, "Email: %s\n", email
);
338 PR_fprintf(outFile
, "Organization: %s\n", org
);
339 PR_fprintf(outFile
, "State: %s\n", state
);
340 PR_fprintf(outFile
, "Country: %s\n\n", country
);
342 PR_fprintf(outFile
, "%s\n", NS_CERTREQ_HEADER
);
343 numBytes
= PR_Write(outFile
, obuf
, total
);
344 if (numBytes
!= total
) {
345 SECU_PrintSystemError(progName
, "write error");
348 PR_fprintf(outFile
, "\n%s\n", NS_CERTREQ_TRAILER
);
350 numBytes
= PR_Write(outFile
, result
.data
, result
.len
);
351 if (numBytes
!= (int)result
.len
) {
352 SECU_PrintSystemError(progName
, "write error");
360 ChangeTrustAttributes(CERTCertDBHandle
*handle
, PK11SlotInfo
*slot
,
361 char *name
, char *trusts
, void *pwdata
)
364 CERTCertificate
*cert
;
365 CERTCertTrust
*trust
;
367 cert
= CERT_FindCertByNicknameOrEmailAddr(handle
, name
);
369 SECU_PrintError(progName
, "could not find certificate named \"%s\"",
374 trust
= (CERTCertTrust
*)PORT_ZAlloc(sizeof(CERTCertTrust
));
376 SECU_PrintError(progName
, "unable to allocate cert trust");
380 /* This function only decodes these characters: pPwcTCu, */
381 rv
= CERT_DecodeTrustString(trust
, trusts
);
383 SECU_PrintError(progName
, "unable to decode trust string");
387 /* CERT_ChangeCertTrust API does not have a way to pass in
388 * a context, so NSS can't prompt for the password if it needs to.
389 * check to see if the failure was token not logged in and
390 * log in if need be. */
391 rv
= CERT_ChangeCertTrust(handle
, cert
, trust
);
392 if (rv
!= SECSuccess
) {
393 if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN
) {
394 rv
= PK11_Authenticate(slot
, PR_TRUE
, pwdata
);
395 if (rv
!= SECSuccess
) {
396 SECU_PrintError(progName
, "could not authenticate to token %s.",
397 PK11_GetTokenName(slot
));
400 rv
= CERT_ChangeCertTrust(handle
, cert
, trust
);
402 if (rv
!= SECSuccess
) {
403 SECU_PrintError(progName
, "unable to modify trust attributes");
407 CERT_DestroyCertificate(cert
);
413 DumpChain(CERTCertDBHandle
*handle
, char *name
)
415 CERTCertificate
*the_cert
;
416 CERTCertificateList
*chain
;
418 the_cert
= PK11_FindCertFromNickname(name
, NULL
);
420 SECU_PrintError(progName
, "Could not find: %s\n", name
);
423 chain
= CERT_CertChainFromCert(the_cert
, 0, PR_TRUE
);
424 CERT_DestroyCertificate(the_cert
);
426 SECU_PrintError(progName
, "Could not obtain chain for: %s\n", name
);
429 for (i
=chain
->len
-1; i
>=0; i
--) {
431 c
= CERT_FindCertByDERCert(handle
, &chain
->certs
[i
]);
432 for (j
=i
; j
<chain
->len
-1; j
++) printf(" ");
433 printf("\"%s\" [%s]\n\n", c
->nickname
, c
->subjectName
);
434 CERT_DestroyCertificate(c
);
436 CERT_DestroyCertificateList(chain
);
441 listCerts(CERTCertDBHandle
*handle
, char *name
, PK11SlotInfo
*slot
,
442 PRBool raw
, PRBool ascii
, PRFileDesc
*outfile
, void *pwarg
)
446 SECStatus rv
= SECFailure
;
448 CERTCertListNode
*node
;
450 /* List certs on a non-internal slot. */
451 if (!PK11_IsFriendly(slot
) && PK11_NeedLogin(slot
)) {
452 SECStatus newrv
= PK11_Authenticate(slot
, PR_TRUE
, pwarg
);
453 if (newrv
!= SECSuccess
) {
454 SECU_PrintError(progName
, "could not authenticate to token %s.",
455 PK11_GetTokenName(slot
));
460 CERTCertificate
*the_cert
;
461 the_cert
= CERT_FindCertByNicknameOrEmailAddr(handle
, name
);
463 the_cert
= PK11_FindCertFromNickname(name
, NULL
);
465 SECU_PrintError(progName
, "Could not find: %s\n", name
);
469 certs
= CERT_CreateSubjectCertList(NULL
, handle
, &the_cert
->derSubject
,
471 CERT_DestroyCertificate(the_cert
);
473 for (node
= CERT_LIST_HEAD(certs
); !CERT_LIST_END(node
,certs
);
474 node
= CERT_LIST_NEXT(node
)) {
475 the_cert
= node
->cert
;
476 /* now get the subjectList that matches this cert */
477 data
.data
= the_cert
->derCert
.data
;
478 data
.len
= the_cert
->derCert
.len
;
480 PR_fprintf(outfile
, "%s\n%s\n%s\n", NS_CERT_HEADER
,
481 BTOA_DataToAscii(data
.data
, data
.len
), NS_CERT_TRAILER
);
484 numBytes
= PR_Write(outfile
, data
.data
, data
.len
);
485 if (numBytes
!= (PRInt32
) data
.len
) {
486 SECU_PrintSystemError(progName
, "error writing raw cert");
491 rv
= SEC_PrintCertificateAndTrust(the_cert
, "Certificate",
493 if (rv
!= SECSuccess
) {
494 SECU_PrintError(progName
, "problem printing certificate");
498 if (rv
!= SECSuccess
) {
504 certs
= PK11_ListCertsInSlot(slot
);
506 for (node
= CERT_LIST_HEAD(certs
); !CERT_LIST_END(node
,certs
);
507 node
= CERT_LIST_NEXT(node
)) {
508 SECU_PrintCertNickname(node
,stdout
);
514 CERT_DestroyCertList(certs
);
517 SECU_PrintError(progName
, "problem printing certificate nicknames");
521 return SECSuccess
; /* not rv ?? */
525 ListCerts(CERTCertDBHandle
*handle
, char *nickname
, PK11SlotInfo
*slot
,
526 PRBool raw
, PRBool ascii
, PRFileDesc
*outfile
, secuPWData
*pwdata
)
530 if (!ascii
&& !raw
) {
531 PR_fprintf(outfile
, "\n%-60s %-5s\n%-60s %-5s\n\n",
532 "Certificate Nickname", "Trust Attributes", "",
533 "SSL,S/MIME,JAR/XPI");
537 CERTCertListNode
*node
;
539 list
= PK11_ListCerts(PK11CertListAll
, pwdata
);
540 for (node
= CERT_LIST_HEAD(list
); !CERT_LIST_END(node
, list
);
541 node
= CERT_LIST_NEXT(node
))
543 SECU_PrintCertNickname(node
, stdout
);
545 CERT_DestroyCertList(list
);
548 rv
= listCerts(handle
,nickname
,slot
,raw
,ascii
,outfile
,pwdata
);
554 DeleteCert(CERTCertDBHandle
*handle
, char *name
)
557 CERTCertificate
*cert
;
559 cert
= CERT_FindCertByNicknameOrEmailAddr(handle
, name
);
561 SECU_PrintError(progName
, "could not find certificate named \"%s\"",
566 rv
= SEC_DeletePermCertificate(cert
);
567 CERT_DestroyCertificate(cert
);
569 SECU_PrintError(progName
, "unable to delete certificate");
577 ValidateCert(CERTCertDBHandle
*handle
, char *name
, char *date
,
578 char *certUsage
, PRBool checkSig
, PRBool logit
, secuPWData
*pwdata
)
581 CERTCertificate
*cert
= NULL
;
583 SECCertificateUsage usage
;
584 CERTVerifyLog reallog
;
585 CERTVerifyLog
*log
= NULL
;
588 PORT_SetError (SEC_ERROR_INVALID_ARGS
);
592 switch (*certUsage
) {
594 usage
= certificateUsageStatusResponder
;
597 usage
= certificateUsageSSLClient
;
600 usage
= certificateUsageSSLServer
;
603 usage
= certificateUsageEmailSigner
;
606 usage
= certificateUsageEmailRecipient
;
609 usage
= certificateUsageObjectSigner
;
612 PORT_SetError (SEC_ERROR_INVALID_ARGS
);
616 cert
= CERT_FindCertByNicknameOrEmailAddr(handle
, name
);
618 SECU_PrintError(progName
, "could not find certificate named \"%s\"",
620 GEN_BREAK (SECFailure
)
624 rv
= DER_AsciiToTime(&timeBoundary
, date
);
626 SECU_PrintError(progName
, "invalid input date");
627 GEN_BREAK (SECFailure
)
630 timeBoundary
= PR_Now();
639 log
->arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
640 if ( log
->arena
== NULL
) {
641 SECU_PrintError(progName
, "out of memory");
642 GEN_BREAK (SECFailure
)
646 rv
= CERT_VerifyCertificate(handle
, cert
, checkSig
, usage
,
647 timeBoundary
, pwdata
, log
, &usage
);
649 if ( log
->head
== NULL
) {
650 fprintf(stdout
, "%s: certificate is valid\n", progName
);
651 GEN_BREAK (SECSuccess
)
654 CERTVerifyLogNode
*node
;
658 if ( node
->cert
->nickname
!= NULL
) {
659 name
= node
->cert
->nickname
;
661 name
= node
->cert
->subjectName
;
663 fprintf(stderr
, "%s : %s\n", name
,
664 SECU_Strerror(node
->error
));
665 CERT_DestroyCertificate(node
->cert
);
670 if (rv
!= SECSuccess
) {
671 PRErrorCode perr
= PORT_GetError();
672 fprintf(stdout
, "%s: certificate is invalid: %s\n",
673 progName
, SECU_Strerror(perr
));
674 GEN_BREAK (SECFailure
)
676 fprintf(stdout
, "%s: certificate is valid\n", progName
);
677 GEN_BREAK (SECSuccess
)
682 CERT_DestroyCertificate(cert
);
689 ItemIsPrintableASCII(const SECItem
* item
)
691 unsigned char *src
= item
->data
;
692 unsigned int len
= item
->len
;
694 unsigned char uc
= *src
++;
695 if (uc
< 0x20 || uc
> 0x7e)
701 /* Caller ensures that dst is at least item->len*2+1 bytes long */
703 SECItemToHex(const SECItem
* item
, char * dst
)
705 if (dst
&& item
&& item
->data
) {
706 unsigned char * src
= item
->data
;
707 unsigned int len
= item
->len
;
708 for (; len
> 0; --len
, dst
+= 2) {
709 sprintf(dst
, "%02x", *src
++);
715 static const char * const keyTypeName
[] = {
716 "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec" };
718 #define MAX_CKA_ID_BIN_LEN 20
719 #define MAX_CKA_ID_STR_LEN 40
721 /* print key number, key ID (in hex or ASCII), key label (nickname) */
723 PrintKey(PRFileDesc
*out
, const char *nickName
, int count
,
724 SECKEYPrivateKey
*key
, void *pwarg
)
727 char ckaIDbuf
[MAX_CKA_ID_STR_LEN
+ 4];
730 ckaID
= PK11_GetLowLevelKeyIDForPrivateKey(key
);
732 strcpy(ckaIDbuf
, "(no CKA_ID)");
733 } else if (ItemIsPrintableASCII(ckaID
)) {
734 int len
= PR_MIN(MAX_CKA_ID_STR_LEN
, ckaID
->len
);
736 memcpy(ckaIDbuf
+ 1, ckaID
->data
, len
);
737 ckaIDbuf
[1 + len
] = '"';
738 ckaIDbuf
[2 + len
] = '\0';
740 /* print ckaid in hex */
741 SECItem idItem
= *ckaID
;
742 if (idItem
.len
> MAX_CKA_ID_BIN_LEN
)
743 idItem
.len
= MAX_CKA_ID_BIN_LEN
;
744 SECItemToHex(&idItem
, ckaIDbuf
);
747 PR_fprintf(out
, "<%2d> %-8.8s %-42.42s %s\n", count
,
748 keyTypeName
[key
->keyType
], ckaIDbuf
, nickName
);
749 SECITEM_ZfreeItem(ckaID
, PR_TRUE
);
754 /* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
756 ListKeysInSlot(PK11SlotInfo
*slot
, const char *nickName
, KeyType keyType
,
759 SECKEYPrivateKeyList
*list
;
760 SECKEYPrivateKeyListNode
*node
;
763 if (PK11_NeedLogin(slot
)) {
764 SECStatus rv
= PK11_Authenticate(slot
, PR_TRUE
, pwarg
);
765 if (rv
!= SECSuccess
) {
766 SECU_PrintError(progName
, "could not authenticate to token %s.",
767 PK11_GetTokenName(slot
));
772 if (nickName
&& nickName
[0])
773 list
= PK11_ListPrivKeysInSlot(slot
, (char *)nickName
, pwarg
);
775 list
= PK11_ListPrivateKeysInSlot(slot
);
777 SECU_PrintError(progName
, "problem listing keys");
780 for (node
=PRIVKEY_LIST_HEAD(list
);
781 !PRIVKEY_LIST_END(node
,list
);
782 node
=PRIVKEY_LIST_NEXT(node
)) {
784 static const char orphan
[] = { "(orphan)" };
786 if (keyType
!= nullKey
&& keyType
!= node
->key
->keyType
)
788 keyName
= PK11_GetPrivateKeyNickname(node
->key
);
789 if (!keyName
|| !keyName
[0]) {
790 /* Try extra hard to find nicknames for keys that lack them. */
791 CERTCertificate
* cert
;
792 PORT_Free((void *)keyName
);
794 cert
= PK11_GetCertFromPrivateKey(node
->key
);
796 if (cert
->nickname
&& !cert
->nickname
[0]) {
797 keyName
= PORT_Strdup(cert
->nickname
);
798 } else if (cert
->emailAddr
&& cert
->emailAddr
[0]) {
799 keyName
= PORT_Strdup(cert
->emailAddr
);
801 CERT_DestroyCertificate(cert
);
805 if (!keyName
|| PL_strcmp(keyName
,nickName
)) {
806 /* PKCS#11 module returned unwanted keys */
807 PORT_Free((void *)keyName
);
812 keyName
= (char *)orphan
;
814 PrintKey(PR_STDOUT
, keyName
, count
, node
->key
, pwarg
);
816 if (keyName
!= (char *)orphan
)
817 PORT_Free((void *)keyName
);
820 SECKEY_DestroyPrivateKeyList(list
);
823 PR_fprintf(PR_STDOUT
, "%s: no keys found\n", progName
);
829 /* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
831 ListKeys(PK11SlotInfo
*slot
, const char *nickName
, int index
,
832 KeyType keyType
, PRBool dopriv
, secuPWData
*pwdata
)
834 SECStatus rv
= SECFailure
;
838 PK11SlotListElement
*le
;
840 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_FALSE
,pwdata
);
842 for (le
= list
->head
; le
; le
= le
->next
) {
843 rv
&= ListKeysInSlot(le
->slot
,nickName
,keyType
,pwdata
);
845 PK11_FreeSlotList(list
);
848 rv
= ListKeysInSlot(slot
,nickName
,keyType
,pwdata
);
854 DeleteKey(char *nickname
, secuPWData
*pwdata
)
857 CERTCertificate
*cert
;
860 slot
= PK11_GetInternalKeySlot();
861 if (PK11_NeedLogin(slot
)) {
862 SECStatus rv
= PK11_Authenticate(slot
, PR_TRUE
, pwdata
);
863 if (rv
!= SECSuccess
) {
864 SECU_PrintError(progName
, "could not authenticate to token %s.",
865 PK11_GetTokenName(slot
));
869 cert
= PK11_FindCertFromNickname(nickname
, pwdata
);
874 rv
= PK11_DeleteTokenCertAndKey(cert
, pwdata
);
875 if (rv
!= SECSuccess
) {
876 SECU_PrintError("problem deleting private key \"%s\"\n", nickname
);
878 CERT_DestroyCertificate(cert
);
885 * L i s t M o d u l e s
887 * Print a list of the PKCS11 modules that are
888 * available. This is useful for smartcard people to
889 * make sure they have the drivers loaded.
896 PK11SlotListElement
*le
;
899 list
= PK11_GetAllTokens(CKM_INVALID_MECHANISM
,PR_FALSE
,PR_FALSE
,NULL
);
900 if (list
== NULL
) return SECFailure
;
902 /* look at each slot*/
903 for (le
= list
->head
; le
; le
= le
->next
) {
905 printf (" slot: %s\n", PK11_GetSlotName(le
->slot
));
906 printf (" token: %s\n", PK11_GetTokenName(le
->slot
));
908 PK11_FreeSlotList(list
);
914 Usage(char *progName
)
916 #define FPS fprintf(stderr,
917 FPS
"Type %s -H for more detailed descriptions\n", progName
);
918 FPS
"Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile]\n", progName
);
919 FPS
"Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name] [-f pwfile]\n", progName
);
920 FPS
"\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
922 FPS
"\t%s -B -i batch-file\n", progName
);
923 FPS
"\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
924 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
925 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-1] [-2] [-3] [-4] [-5]\n"
926 "\t\t [-6] [-7 emailAddrs] [-8 dns-names] [-a]\n",
928 FPS
"\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName
);
929 FPS
"\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
931 FPS
"\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
932 "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName
);
933 FPS
"\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
934 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName
);
935 #ifdef NSS_ENABLE_ECC
936 FPS
"\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
937 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName
);
938 FPS
"\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n",
941 FPS
"\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n",
943 #endif /* NSS_ENABLE_ECC */
944 FPS
"\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
945 FPS
"\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
947 FPS
"\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
948 FPS
"\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
949 FPS
"\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
950 FPS
"\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
952 FPS
"\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
953 FPS
"\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
954 FPS
"\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\n", progName
);
955 FPS
"\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
957 FPS
"\t%s -O -n cert-name [-X] [-d certdir] [-P dbprefix]\n", progName
);
958 FPS
"\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
959 "\t\t [-y emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile] [-g key-size]\n",
961 FPS
"\t%s -V -n cert-name -u usage [-b time] [-e] \n"
962 "\t\t[-X] [-d certdir] [-P dbprefix]\n",
964 FPS
"\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
965 "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
966 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
967 "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n"
968 "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
969 "\t\t [-8 DNS-names]\n"
970 "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
971 "\t\t [--extSKID]\n", progName
);
972 FPS
"\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName
);
976 static void LongUsage(char *progName
)
979 FPS
"%-15s Add a certificate to the database (create if needed)\n",
981 FPS
"%-20s\n", " All options under -E apply");
982 FPS
"%-15s Run a series of certutil commands from a batch file\n", "-B");
983 FPS
"%-20s Specify the batch file\n", " -i batch-file");
984 FPS
"%-15s Add an Email certificate to the database (create if needed)\n",
986 FPS
"%-20s Specify the nickname of the certificate to add\n",
988 FPS
"%-20s Set the certificate trust attributes:\n",
990 FPS
"%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
991 FPS
"%-25s and z is for code signing\n", "");
992 FPS
"%-25s p \t valid peer\n", "");
993 FPS
"%-25s P \t trusted peer (implies p)\n", "");
994 FPS
"%-25s c \t valid CA\n", "");
995 FPS
"%-25s T \t trusted CA to issue client certs (implies c)\n", "");
996 FPS
"%-25s C \t trusted CA to issue server certs (implies c)\n", "");
997 FPS
"%-25s u \t user cert\n", "");
998 FPS
"%-25s w \t send warning\n", "");
999 FPS
"%-25s g \t make step-up cert\n", "");
1000 FPS
"%-20s Specify the password file\n",
1002 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1004 FPS
"%-20s Cert & Key database prefix\n",
1006 FPS
"%-20s The input certificate is encoded in ASCII (RFC1113)\n",
1008 FPS
"%-20s Specify the certificate file (default is stdin)\n",
1012 FPS
"%-15s Create a new binary certificate from a BINARY cert request\n",
1014 FPS
"%-20s The nickname of the issuer cert\n",
1016 FPS
"%-20s The BINARY certificate request file\n",
1017 " -i cert-request ");
1018 FPS
"%-20s Output binary cert to this file (default is stdout)\n",
1020 FPS
"%-20s Self sign\n",
1022 FPS
"%-20s Cert serial number\n",
1023 " -m serial-number");
1024 FPS
"%-20s Time Warp\n",
1026 FPS
"%-20s Months valid (default is 3)\n",
1027 " -v months-valid");
1028 FPS
"%-20s Specify the password file\n",
1030 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1032 FPS
"%-20s Cert & Key database prefix\n",
1034 FPS
"%-20s Create key usage extension\n",
1036 FPS
"%-20s Create basic constraint extension\n",
1038 FPS
"%-20s Create authority key ID extension\n",
1040 FPS
"%-20s Create crl distribution point extension\n",
1042 FPS
"%-20s Create netscape cert type extension\n",
1044 FPS
"%-20s Create extended key usage extension\n",
1046 FPS
"%-20s Create an email subject alt name extension\n",
1048 FPS
"%-20s Create an dns subject alt name extension\n",
1050 FPS
"%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
1054 FPS
"%-15s Generate a new key pair\n",
1056 FPS
"%-20s Name of token in which to generate key (default is internal)\n",
1058 #ifdef NSS_ENABLE_ECC
1059 FPS
"%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1061 FPS
"%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
1062 " -g key-size", MIN_KEY_BITS
, MAX_KEY_BITS
, DEFAULT_KEY_BITS
);
1064 FPS
"%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
1066 FPS
"%-20s Key size in bits, (min %d, max %d, default %d)\n",
1067 " -g key-size", MIN_KEY_BITS
, MAX_KEY_BITS
, DEFAULT_KEY_BITS
);
1068 #endif /* NSS_ENABLE_ECC */
1069 FPS
"%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
1071 FPS
"%-20s Specify the password file\n",
1072 " -f password-file");
1073 FPS
"%-20s Specify the noise file to be used\n",
1075 FPS
"%-20s read PQG value from pqgfile (dsa only)\n",
1077 #ifdef NSS_ENABLE_ECC
1078 FPS
"%-20s Elliptic curve name (ec only)\n",
1080 FPS
"%-20s One of nistp256, nistp384, nistp521\n", "");
1081 #ifdef NSS_ECC_MORE_THAN_SUITE_B
1082 FPS
"%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
1083 FPS
"%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
1084 FPS
"%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
1085 FPS
"%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
1086 FPS
"%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
1087 FPS
"%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
1088 FPS
"%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
1089 FPS
"%-20s secp256r1, secp384r1, secp521r1,\n", "");
1090 FPS
"%-20s prime192v1, prime192v2, prime192v3, \n", "");
1091 FPS
"%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
1092 FPS
"%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
1093 FPS
"%-20s c2tnb191v2, c2tnb191v3, \n", "");
1094 FPS
"%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
1095 FPS
"%-20s c2pnb272w1, c2pnb304w1, \n", "");
1096 FPS
"%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
1097 FPS
"%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
1098 FPS
"%-20s sect131r1, sect131r2\n", "");
1099 #endif /* NSS_ECC_MORE_THAN_SUITE_B */
1101 FPS
"%-20s Key database directory (default is ~/.netscape)\n",
1103 FPS
"%-20s Cert & Key database prefix\n",
1107 FPS
"%-15s Delete a certificate from the database\n",
1109 FPS
"%-20s The nickname of the cert to delete\n",
1111 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1113 FPS
"%-20s Cert & Key database prefix\n",
1117 FPS
"%-15s List all modules\n", /*, or print out a single named module\n",*/
1119 FPS
"%-20s Module database directory (default is '~/.netscape')\n",
1121 FPS
"%-20s Cert & Key database prefix\n",
1123 FPS
"%-20s force the database to open R/W\n",
1127 FPS
"%-15s List all private keys\n",
1129 FPS
"%-20s Name of token to search (\"all\" for all tokens)\n",
1132 FPS
"%-20s Key type (\"all\" (default), \"dsa\","
1133 #ifdef NSS_ENABLE_ECC
1138 FPS
"%-20s The nickname of the key or associated certificate\n",
1140 FPS
"%-20s Specify the password file\n",
1141 " -f password-file");
1142 FPS
"%-20s Key database directory (default is ~/.netscape)\n",
1144 FPS
"%-20s Cert & Key database prefix\n",
1146 FPS
"%-20s force the database to open R/W\n",
1150 FPS
"%-15s List all certs, or print out a single named cert\n",
1152 FPS
"%-20s Pretty print named cert (list all if unspecified)\n",
1154 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1156 FPS
"%-20s Cert & Key database prefix\n",
1158 FPS
"%-20s force the database to open R/W\n",
1160 FPS
"%-20s For single cert, print binary DER encoding\n",
1162 FPS
"%-20s For single cert, print ASCII encoding (RFC1113)\n",
1166 FPS
"%-15s Modify trust attributes of certificate\n",
1168 FPS
"%-20s The nickname of the cert to modify\n",
1170 FPS
"%-20s Set the certificate trust attributes (see -A above)\n",
1172 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1174 FPS
"%-20s Cert & Key database prefix\n",
1178 FPS
"%-15s Create a new certificate database\n",
1180 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1182 FPS
"%-20s Cert & Key database prefix\n",
1185 FPS
"%-15s Reset the Key database or token\n",
1187 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1189 FPS
"%-20s Cert & Key database prefix\n",
1191 FPS
"%-20s Token to reset (default is internal)\n",
1196 FPS
"%-15s Print the chain of a certificate\n",
1198 FPS
"%-20s The nickname of the cert to modify\n",
1200 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1202 FPS
"%-20s Cert & Key database prefix\n",
1204 FPS
"%-20s force the database to open R/W\n",
1208 FPS
"%-15s Generate a certificate request (stdout)\n",
1210 FPS
"%-20s Specify the subject name (using RFC1485)\n",
1212 FPS
"%-20s Output the cert request to this file\n",
1214 #ifdef NSS_ENABLE_ECC
1215 FPS
"%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1217 FPS
"%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
1218 #endif /* NSS_ENABLE_ECC */
1219 " -k key-type-or-id");
1220 FPS
"%-20s or nickname of the cert key to use \n",
1222 FPS
"%-20s Name of token in which to generate key (default is internal)\n",
1224 FPS
"%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1225 " -g key-size", MIN_KEY_BITS
, MAX_KEY_BITS
, DEFAULT_KEY_BITS
);
1226 FPS
"%-20s Name of file containing PQG parameters (dsa only)\n",
1228 #ifdef NSS_ENABLE_ECC
1229 FPS
"%-20s Elliptic curve name (ec only)\n",
1231 FPS
"%-20s See the \"-G\" option for a full list of supported names.\n",
1233 #endif /* NSS_ENABLE_ECC */
1234 FPS
"%-20s Specify the password file\n",
1236 FPS
"%-20s Key database directory (default is ~/.netscape)\n",
1238 FPS
"%-20s Cert & Key database prefix\n",
1240 FPS
"%-20s Specify the contact phone number (\"123-456-7890\")\n",
1242 FPS
"%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
1245 " See -S for available extension options");
1248 FPS
"%-15s Validate a certificate\n",
1250 FPS
"%-20s The nickname of the cert to Validate\n",
1252 FPS
"%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
1254 FPS
"%-20s Check certificate signature \n",
1256 FPS
"%-20s Specify certificate usage:\n", " -u certusage");
1257 FPS
"%-25s C \t SSL Client\n", "");
1258 FPS
"%-25s V \t SSL Server\n", "");
1259 FPS
"%-25s S \t Email signer\n", "");
1260 FPS
"%-25s R \t Email Recipient\n", "");
1261 FPS
"%-25s O \t OCSP status responder\n", "");
1262 FPS
"%-25s J \t Object signer\n", "");
1263 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1265 FPS
"%-20s Cert & Key database prefix\n",
1267 FPS
"%-20s force the database to open R/W\n",
1271 FPS
"%-15s Upgrade an old database and merge it into a new one\n",
1273 FPS
"%-20s Cert database directory to merge into (default is ~/.netscape)\n",
1275 FPS
"%-20s Cert & Key database prefix of the target database\n",
1277 FPS
"%-20s Specify the password file for the target database\n",
1279 FPS
"%-20s \n%-20s Cert database directory to upgrade from\n",
1280 " --source-dir certdir", "");
1281 FPS
"%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
1282 " --soruce-prefix dbprefix", "");
1283 FPS
"%-20s \n%-20s Unique identifier for the upgrade database\n",
1284 " --upgrade-id uniqueID", "");
1285 FPS
"%-20s \n%-20s Name of the token while it is in upgrade state\n",
1286 " --upgrade-token-name name", "");
1287 FPS
"%-20s Specify the password file for the upgrade database\n",
1291 FPS
"%-15s Merge source database into the target database\n",
1293 FPS
"%-20s Cert database directory of target (default is ~/.netscape)\n",
1295 FPS
"%-20s Cert & Key database prefix of the target database\n",
1297 FPS
"%-20s Specify the password file for the target database\n",
1299 FPS
"%-20s \n%-20s Cert database directory of the source database\n",
1300 " --source-dir certdir", "");
1301 FPS
"%-20s \n%-20s Cert & Key database prefix of the source database\n",
1302 " --source-prefix dbprefix", "");
1303 FPS
"%-20s Specify the password file for the source database\n",
1307 FPS
"%-15s Make a certificate and add to database\n",
1309 FPS
"%-20s Specify the nickname of the cert\n",
1311 FPS
"%-20s Specify the subject name (using RFC1485)\n",
1313 FPS
"%-20s The nickname of the issuer cert\n",
1315 FPS
"%-20s Set the certificate trust attributes (see -A above)\n",
1317 #ifdef NSS_ENABLE_ECC
1318 FPS
"%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1320 FPS
"%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
1321 #endif /* NSS_ENABLE_ECC */
1322 " -k key-type-or-id");
1323 FPS
"%-20s Name of token in which to generate key (default is internal)\n",
1325 FPS
"%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1326 " -g key-size", MIN_KEY_BITS
, MAX_KEY_BITS
, DEFAULT_KEY_BITS
);
1327 FPS
"%-20s Name of file containing PQG parameters (dsa only)\n",
1329 #ifdef NSS_ENABLE_ECC
1330 FPS
"%-20s Elliptic curve name (ec only)\n",
1332 FPS
"%-20s See the \"-G\" option for a full list of supported names.\n",
1334 #endif /* NSS_ENABLE_ECC */
1335 FPS
"%-20s Self sign\n",
1337 FPS
"%-20s Cert serial number\n",
1338 " -m serial-number");
1339 FPS
"%-20s Time Warp\n",
1341 FPS
"%-20s Months valid (default is 3)\n",
1342 " -v months-valid");
1343 FPS
"%-20s Specify the password file\n",
1345 FPS
"%-20s Cert database directory (default is ~/.netscape)\n",
1347 FPS
"%-20s Cert & Key database prefix\n",
1349 FPS
"%-20s Specify the contact phone number (\"123-456-7890\")\n",
1351 FPS
"%-20s Create key usage extension\n",
1353 FPS
"%-20s Create basic constraint extension\n",
1355 FPS
"%-20s Create authority key ID extension\n",
1357 FPS
"%-20s Create crl distribution point extension\n",
1359 FPS
"%-20s Create netscape cert type extension\n",
1361 FPS
"%-20s Create extended key usage extension\n",
1363 FPS
"%-20s Create an email subject alt name extension\n",
1365 FPS
"%-20s Create a DNS subject alt name extension\n",
1367 FPS
"%-20s Create an Authority Information Access extension\n",
1369 FPS
"%-20s Create a Subject Information Access extension\n",
1371 FPS
"%-20s Create a Certificate Policies extension\n",
1373 FPS
"%-20s Create a Policy Mappings extension\n",
1375 FPS
"%-20s Create a Policy Constraints extension\n",
1377 FPS
"%-20s Create an Inhibit Any Policy extension\n",
1379 FPS
"%-20s Create a subject key ID extension\n",
1388 static CERTCertificate
*
1389 MakeV1Cert( CERTCertDBHandle
* handle
,
1390 CERTCertificateRequest
*req
,
1391 char * issuerNickName
,
1393 unsigned int serialNumber
,
1397 CERTCertificate
*issuerCert
= NULL
;
1398 CERTValidity
*validity
;
1399 CERTCertificate
*cert
= NULL
;
1400 PRExplodedTime printableTime
;
1404 issuerCert
= CERT_FindCertByNicknameOrEmailAddr(handle
, issuerNickName
);
1406 SECU_PrintError(progName
, "could not find certificate named \"%s\"",
1413 PR_ExplodeTime (now
, PR_GMTParameters
, &printableTime
);
1415 printableTime
.tm_month
+= warpmonths
;
1416 now
= PR_ImplodeTime (&printableTime
);
1417 PR_ExplodeTime (now
, PR_GMTParameters
, &printableTime
);
1419 printableTime
.tm_month
+= validityMonths
;
1420 after
= PR_ImplodeTime (&printableTime
);
1422 /* note that the time is now in micro-second unit */
1423 validity
= CERT_CreateValidity (now
, after
);
1425 cert
= CERT_CreateCertificate(serialNumber
,
1426 (selfsign
? &req
->subject
1427 : &issuerCert
->subject
),
1430 CERT_DestroyValidity(validity
);
1433 CERT_DestroyCertificate (issuerCert
);
1440 SignCert(CERTCertDBHandle
*handle
, CERTCertificate
*cert
, PRBool selfsign
,
1441 SECOidTag hashAlgTag
,
1442 SECKEYPrivateKey
*privKey
, char *issuerNickName
, void *pwarg
)
1445 SECItem
*result
= NULL
;
1446 SECKEYPrivateKey
*caPrivateKey
= NULL
;
1453 CERTCertificate
*issuer
= PK11_FindCertFromNickname(issuerNickName
, pwarg
);
1454 if( (CERTCertificate
*)NULL
== issuer
) {
1455 SECU_PrintError(progName
, "unable to find issuer with nickname %s",
1457 return (SECItem
*)NULL
;
1460 privKey
= caPrivateKey
= PK11_FindKeyByAnyCert(issuer
, pwarg
);
1461 CERT_DestroyCertificate(issuer
);
1462 if (caPrivateKey
== NULL
) {
1463 SECU_PrintError(progName
, "unable to retrieve key %s", issuerNickName
);
1468 arena
= cert
->arena
;
1470 algID
= SEC_GetSignatureAlgorithmOidTag(privKey
->keyType
, hashAlgTag
);
1471 if (algID
== SEC_OID_UNKNOWN
) {
1472 fprintf(stderr
, "Unknown key or hash type for issuer.");
1476 rv
= SECOID_SetAlgorithmID(arena
, &cert
->signature
, algID
, 0);
1477 if (rv
!= SECSuccess
) {
1478 fprintf(stderr
, "Could not set signature algorithm id.");
1482 /* we only deal with cert v3 here */
1483 *(cert
->version
.data
) = 2;
1484 cert
->version
.len
= 1;
1488 dummy
= SEC_ASN1EncodeItem (arena
, &der
, cert
,
1489 SEC_ASN1_GET(CERT_CertificateTemplate
));
1491 fprintf (stderr
, "Could not encode certificate.\n");
1495 result
= (SECItem
*) PORT_ArenaZAlloc (arena
, sizeof (SECItem
));
1496 if (result
== NULL
) {
1497 fprintf (stderr
, "Could not allocate item for certificate data.\n");
1501 rv
= SEC_DerSignData(arena
, result
, der
.data
, der
.len
, privKey
, algID
);
1502 if (rv
!= SECSuccess
) {
1503 fprintf (stderr
, "Could not sign encoded certificate data.\n");
1504 /* result allocated out of the arena, it will be freed
1505 * when the arena is freed */
1509 cert
->derCert
= *result
;
1512 SECKEY_DestroyPrivateKey(caPrivateKey
);
1519 CERTCertDBHandle
*handle
,
1520 char * issuerNickName
,
1522 PRFileDesc
*outFile
,
1523 SECKEYPrivateKey
*selfsignprivkey
,
1525 SECOidTag hashAlgTag
,
1526 unsigned int serialNumber
,
1529 const char *emailAddrs
,
1530 const char *dnsNames
,
1533 certutilExtnList extnList
)
1537 PRArenaPool
*arena
= NULL
;
1538 CERTCertificate
*subjectCert
= NULL
;
1539 CERTCertificateRequest
*certReq
= NULL
;
1540 SECStatus rv
= SECSuccess
;
1542 CERTCertExtension
**CRexts
;
1546 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1548 GEN_BREAK (SECFailure
);
1551 /* Create a certrequest object from the input cert request der */
1552 certReq
= GetCertRequest(inFile
, ascii
);
1553 if (certReq
== NULL
) {
1554 GEN_BREAK (SECFailure
)
1557 subjectCert
= MakeV1Cert (handle
, certReq
, issuerNickName
, selfsign
,
1558 serialNumber
, warpmonths
, validityMonths
);
1559 if (subjectCert
== NULL
) {
1560 GEN_BREAK (SECFailure
)
1564 extHandle
= CERT_StartCertExtensions (subjectCert
);
1565 if (extHandle
== NULL
) {
1566 GEN_BREAK (SECFailure
)
1569 rv
= AddExtensions(extHandle
, emailAddrs
, dnsNames
, extnList
);
1570 if (rv
!= SECSuccess
) {
1571 GEN_BREAK (SECFailure
)
1574 if (certReq
->attributes
!= NULL
&&
1575 certReq
->attributes
[0] != NULL
&&
1576 certReq
->attributes
[0]->attrType
.data
!= NULL
&&
1577 certReq
->attributes
[0]->attrType
.len
> 0 &&
1578 SECOID_FindOIDTag(&certReq
->attributes
[0]->attrType
)
1579 == SEC_OID_PKCS9_EXTENSION_REQUEST
) {
1580 rv
= CERT_GetCertificateRequestExtensions(certReq
, &CRexts
);
1581 if (rv
!= SECSuccess
)
1583 rv
= CERT_MergeExtensions(extHandle
, CRexts
);
1584 if (rv
!= SECSuccess
)
1588 CERT_FinishExtensions(extHandle
);
1590 certDER
= SignCert(handle
, subjectCert
, selfsign
, hashAlgTag
,
1591 selfsignprivkey
, issuerNickName
,pwarg
);
1595 PR_fprintf(outFile
, "%s\n%s\n%s\n", NS_CERT_HEADER
,
1596 BTOA_DataToAscii(certDER
->data
, certDER
->len
),
1599 PR_Write(outFile
, certDER
->data
, certDER
->len
);
1604 CERT_DestroyCertificateRequest (certReq
);
1605 CERT_DestroyCertificate (subjectCert
);
1606 PORT_FreeArena (arena
, PR_FALSE
);
1607 if (rv
!= SECSuccess
) {
1608 PRErrorCode perr
= PR_GetError();
1609 fprintf(stderr
, "%s: unable to create cert (%s)\n", progName
,
1610 SECU_Strerror(perr
));
1617 * map a class to a user presentable string
1619 static const char *objClassArray
[] = {
1626 "Domain Parameters",
1630 static const char *objNSSClassArray
[] = {
1640 getObjectClass(CK_ULONG classType
)
1642 static char buf
[sizeof(CK_ULONG
)*2+3];
1644 if (classType
<= CKO_MECHANISM
) {
1645 return objClassArray
[classType
];
1647 if (classType
>= CKO_NSS
&& classType
<= CKO_NSS_BUILTIN_ROOT_LIST
) {
1648 return objNSSClassArray
[classType
- CKO_NSS
];
1650 sprintf(buf
, "0x%lx", classType
);
1654 char *mkNickname(unsigned char *data
, int len
)
1656 char *nick
= PORT_Alloc(len
+1);
1660 PORT_Memcpy(nick
, data
, len
);
1666 * dump a PK11_MergeTokens error log to the console
1669 DumpMergeLog(const char *progname
, PK11MergeLog
*log
)
1671 PK11MergeLogNode
*node
;
1673 for (node
= log
->head
; node
; node
= node
->next
) {
1675 char *nickname
= NULL
;
1676 const char *objectClass
= NULL
;
1679 attrItem
.data
= NULL
;
1680 rv
= PK11_ReadRawAttribute(PK11_TypeGeneric
, node
->object
,
1681 CKA_LABEL
, &attrItem
);
1682 if (rv
== SECSuccess
) {
1683 nickname
= mkNickname(attrItem
.data
, attrItem
.len
);
1684 PORT_Free(attrItem
.data
);
1686 attrItem
.data
= NULL
;
1687 rv
= PK11_ReadRawAttribute(PK11_TypeGeneric
, node
->object
,
1688 CKA_CLASS
, &attrItem
);
1689 if (rv
== SECSuccess
) {
1690 if (attrItem
.len
== sizeof(CK_ULONG
)) {
1691 objectClass
= getObjectClass(*(CK_ULONG
*)attrItem
.data
);
1693 PORT_Free(attrItem
.data
);
1696 fprintf(stderr
, "%s: Could not merge object %s (type %s): %s\n",
1698 nickname
? nickname
: "unnamed",
1699 objectClass
? objectClass
: "unknown",
1700 SECU_Strerror(node
->error
));
1703 PORT_Free(nickname
);
1708 /* Certutil commands */
1719 cmd_ModifyCertTrust
,
1723 cmd_CreateAndAddCert
,
1726 cmd_CheckCertValidity
,
1731 cmd_UpgradeMerge
, /* test only */
1734 /* Certutil options */
1738 opt_AddBasicConstraintExt
,
1739 opt_AddAuthorityKeyIDExt
,
1740 opt_AddCRLDistPtsExt
,
1741 opt_AddNSCertTypeExt
,
1742 opt_AddExtKeyUsageExt
,
1743 opt_ExtendedEmailAddrs
,
1744 opt_ExtendedDNSNames
,
1774 opt_NewPasswordFile
,
1775 opt_AddAuthInfoAccExt
,
1776 opt_AddSubjInfoAccExt
,
1777 opt_AddCertPoliciesExt
,
1778 opt_AddPolicyMapExt
,
1779 opt_AddPolicyConstrExt
,
1781 opt_AddSubjectKeyIDExt
,
1785 opt_UpgradeTokenName
1789 secuCommandFlag commands_init
[] =
1791 { /* cmd_AddCert */ 'A', PR_FALSE
, 0, PR_FALSE
},
1792 { /* cmd_CreateNewCert */ 'C', PR_FALSE
, 0, PR_FALSE
},
1793 { /* cmd_DeleteCert */ 'D', PR_FALSE
, 0, PR_FALSE
},
1794 { /* cmd_AddEmailCert */ 'E', PR_FALSE
, 0, PR_FALSE
},
1795 { /* cmd_DeleteKey */ 'F', PR_FALSE
, 0, PR_FALSE
},
1796 { /* cmd_GenKeyPair */ 'G', PR_FALSE
, 0, PR_FALSE
},
1797 { /* cmd_PrintHelp */ 'H', PR_FALSE
, 0, PR_FALSE
},
1798 { /* cmd_ListKeys */ 'K', PR_FALSE
, 0, PR_FALSE
},
1799 { /* cmd_ListCerts */ 'L', PR_FALSE
, 0, PR_FALSE
},
1800 { /* cmd_ModifyCertTrust */ 'M', PR_FALSE
, 0, PR_FALSE
},
1801 { /* cmd_NewDBs */ 'N', PR_FALSE
, 0, PR_FALSE
},
1802 { /* cmd_DumpChain */ 'O', PR_FALSE
, 0, PR_FALSE
},
1803 { /* cmd_CertReq */ 'R', PR_FALSE
, 0, PR_FALSE
},
1804 { /* cmd_CreateAndAddCert */ 'S', PR_FALSE
, 0, PR_FALSE
},
1805 { /* cmd_TokenReset */ 'T', PR_FALSE
, 0, PR_FALSE
},
1806 { /* cmd_ListModules */ 'U', PR_FALSE
, 0, PR_FALSE
},
1807 { /* cmd_CheckCertValidity */ 'V', PR_FALSE
, 0, PR_FALSE
},
1808 { /* cmd_ChangePassword */ 'W', PR_FALSE
, 0, PR_FALSE
},
1809 { /* cmd_Version */ 'Y', PR_FALSE
, 0, PR_FALSE
},
1810 { /* cmd_Batch */ 'B', PR_FALSE
, 0, PR_FALSE
},
1811 { /* cmd_Merge */ 0, PR_FALSE
, 0, PR_FALSE
, "merge" },
1812 { /* cmd_UpgradeMerge */ 0, PR_FALSE
, 0, PR_FALSE
,
1815 #define NUM_COMMANDS ((sizeof commands_init) / (sizeof commands_init[0]))
1818 secuCommandFlag options_init
[] =
1820 { /* opt_SSOPass */ '0', PR_TRUE
, 0, PR_FALSE
},
1821 { /* opt_AddKeyUsageExt */ '1', PR_FALSE
, 0, PR_FALSE
},
1822 { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE
, 0, PR_FALSE
},
1823 { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE
, 0, PR_FALSE
},
1824 { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE
, 0, PR_FALSE
},
1825 { /* opt_AddNSCertTypeExt */ '5', PR_FALSE
, 0, PR_FALSE
},
1826 { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE
, 0, PR_FALSE
},
1827 { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE
, 0, PR_FALSE
},
1828 { /* opt_ExtendedDNSNames */ '8', PR_TRUE
, 0, PR_FALSE
},
1829 { /* opt_ASCIIForIO */ 'a', PR_FALSE
, 0, PR_FALSE
},
1830 { /* opt_ValidityTime */ 'b', PR_TRUE
, 0, PR_FALSE
},
1831 { /* opt_IssuerName */ 'c', PR_TRUE
, 0, PR_FALSE
},
1832 { /* opt_CertDir */ 'd', PR_TRUE
, 0, PR_FALSE
},
1833 { /* opt_VerifySig */ 'e', PR_FALSE
, 0, PR_FALSE
},
1834 { /* opt_PasswordFile */ 'f', PR_TRUE
, 0, PR_FALSE
},
1835 { /* opt_KeySize */ 'g', PR_TRUE
, 0, PR_FALSE
},
1836 { /* opt_TokenName */ 'h', PR_TRUE
, 0, PR_FALSE
},
1837 { /* opt_InputFile */ 'i', PR_TRUE
, 0, PR_FALSE
},
1838 { /* opt_KeyIndex */ 'j', PR_TRUE
, 0, PR_FALSE
},
1839 { /* opt_KeyType */ 'k', PR_TRUE
, 0, PR_FALSE
},
1840 { /* opt_DetailedInfo */ 'l', PR_FALSE
, 0, PR_FALSE
},
1841 { /* opt_SerialNumber */ 'm', PR_TRUE
, 0, PR_FALSE
},
1842 { /* opt_Nickname */ 'n', PR_TRUE
, 0, PR_FALSE
},
1843 { /* opt_OutputFile */ 'o', PR_TRUE
, 0, PR_FALSE
},
1844 { /* opt_PhoneNumber */ 'p', PR_TRUE
, 0, PR_FALSE
},
1845 { /* opt_DBPrefix */ 'P', PR_TRUE
, 0, PR_FALSE
},
1846 { /* opt_PQGFile */ 'q', PR_TRUE
, 0, PR_FALSE
},
1847 { /* opt_BinaryDER */ 'r', PR_FALSE
, 0, PR_FALSE
},
1848 { /* opt_Subject */ 's', PR_TRUE
, 0, PR_FALSE
},
1849 { /* opt_Trust */ 't', PR_TRUE
, 0, PR_FALSE
},
1850 { /* opt_Usage */ 'u', PR_TRUE
, 0, PR_FALSE
},
1851 { /* opt_Validity */ 'v', PR_TRUE
, 0, PR_FALSE
},
1852 { /* opt_OffsetMonths */ 'w', PR_TRUE
, 0, PR_FALSE
},
1853 { /* opt_SelfSign */ 'x', PR_FALSE
, 0, PR_FALSE
},
1854 { /* opt_RW */ 'X', PR_FALSE
, 0, PR_FALSE
},
1855 { /* opt_Exponent */ 'y', PR_TRUE
, 0, PR_FALSE
},
1856 { /* opt_NoiseFile */ 'z', PR_TRUE
, 0, PR_FALSE
},
1857 { /* opt_Hash */ 'Z', PR_TRUE
, 0, PR_FALSE
},
1858 { /* opt_NewPasswordFile */ '@', PR_TRUE
, 0, PR_FALSE
},
1859 { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extAIA" },
1860 { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extSIA" },
1861 { /* opt_AddCertPoliciesExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extCP" },
1862 { /* opt_AddPolicyMapExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extPM" },
1863 { /* opt_AddPolicyConstrExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extPC" },
1864 { /* opt_AddInhibAnyExt */ 0, PR_FALSE
, 0, PR_FALSE
, "extIA" },
1865 { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE
, 0, PR_FALSE
,
1867 { /* opt_SourceDir */ 0, PR_TRUE
, 0, PR_FALSE
,
1869 { /* opt_SourcePrefix */ 0, PR_TRUE
, 0, PR_FALSE
,
1871 { /* opt_UpgradeID */ 0, PR_TRUE
, 0, PR_FALSE
,
1873 { /* opt_UpgradeTokenName */ 0, PR_TRUE
, 0, PR_FALSE
,
1874 "upgrade-token-name"},
1876 #define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0]))
1878 static secuCommandFlag certutil_commands
[NUM_COMMANDS
];
1879 static secuCommandFlag certutil_options
[NUM_OPTIONS
];
1881 static const secuCommand certutil
= {
1888 static certutilExtnList certutil_extns
;
1891 certutil_main(int argc
, char **argv
, PRBool initialize
)
1893 CERTCertDBHandle
*certHandle
;
1894 PK11SlotInfo
*slot
= NULL
;
1895 CERTName
* subject
= 0;
1896 PRFileDesc
*inFile
= PR_STDIN
;
1897 PRFileDesc
*outFile
= NULL
;
1898 char * certfile
= "tempcert";
1899 char * certreqfile
= "tempcertreq";
1900 char * slotname
= "internal";
1901 char * certPrefix
= "";
1902 char * sourceDir
= "";
1903 char * srcCertPrefix
= "";
1904 char * upgradeID
= "";
1905 char * upgradeTokenName
= "";
1906 KeyType keytype
= rsaKey
;
1908 char * keysource
= NULL
;
1909 SECOidTag hashAlgTag
= SEC_OID_UNKNOWN
;
1910 int keysize
= DEFAULT_KEY_BITS
;
1911 int publicExponent
= 0x010001;
1912 unsigned int serialNumber
= 0;
1914 int validityMonths
= 3;
1915 int commandsEntered
= 0;
1916 char commandToRun
= '\0';
1917 secuPWData pwdata
= { PW_NONE
, 0 };
1918 secuPWData pwdata2
= { PW_NONE
, 0 };
1919 PRBool readOnly
= PR_FALSE
;
1920 PRBool initialized
= PR_FALSE
;
1922 SECKEYPrivateKey
*privkey
= NULL
;
1923 SECKEYPublicKey
*pubkey
= NULL
;
1928 progName
= PORT_Strrchr(argv
[0], '/');
1929 progName
= progName
? progName
+1 : argv
[0];
1930 memcpy(certutil_commands
, commands_init
, sizeof commands_init
);
1931 memcpy(certutil_options
, options_init
, sizeof options_init
);
1933 rv
= SECU_ParseCommandLine(argc
, argv
, progName
, &certutil
);
1935 if (rv
!= SECSuccess
)
1938 if (certutil
.commands
[cmd_PrintHelp
].activated
)
1939 LongUsage(progName
);
1941 if (certutil
.options
[opt_PasswordFile
].arg
) {
1942 pwdata
.source
= PW_FROMFILE
;
1943 pwdata
.data
= certutil
.options
[opt_PasswordFile
].arg
;
1945 if (certutil
.options
[opt_NewPasswordFile
].arg
) {
1946 pwdata2
.source
= PW_FROMFILE
;
1947 pwdata2
.data
= certutil
.options
[opt_NewPasswordFile
].arg
;
1950 if (certutil
.options
[opt_CertDir
].activated
)
1951 SECU_ConfigDirectory(certutil
.options
[opt_CertDir
].arg
);
1953 if (certutil
.options
[opt_SourceDir
].activated
)
1954 sourceDir
= certutil
.options
[opt_SourceDir
].arg
;
1956 if (certutil
.options
[opt_UpgradeID
].activated
)
1957 upgradeID
= certutil
.options
[opt_UpgradeID
].arg
;
1959 if (certutil
.options
[opt_UpgradeTokenName
].activated
)
1960 upgradeTokenName
= certutil
.options
[opt_UpgradeTokenName
].arg
;
1962 if (certutil
.options
[opt_KeySize
].activated
) {
1963 keysize
= PORT_Atoi(certutil
.options
[opt_KeySize
].arg
);
1964 if ((keysize
< MIN_KEY_BITS
) || (keysize
> MAX_KEY_BITS
)) {
1965 PR_fprintf(PR_STDERR
,
1966 "%s -g: Keysize must be between %d and %d.\n",
1967 progName
, MIN_KEY_BITS
, MAX_KEY_BITS
);
1970 #ifdef NSS_ENABLE_ECC
1971 if (keytype
== ecKey
) {
1972 PR_fprintf(PR_STDERR
, "%s -g: Not for ec keys.\n", progName
);
1975 #endif /* NSS_ENABLE_ECC */
1979 /* -h specify token name */
1980 if (certutil
.options
[opt_TokenName
].activated
) {
1981 if (PL_strcmp(certutil
.options
[opt_TokenName
].arg
, "all") == 0)
1984 slotname
= PL_strdup(certutil
.options
[opt_TokenName
].arg
);
1988 if (certutil
.options
[opt_Hash
].activated
) {
1989 char * arg
= certutil
.options
[opt_Hash
].arg
;
1990 hashAlgTag
= SECU_StringToSignatureAlgTag(arg
);
1991 if (hashAlgTag
== SEC_OID_UNKNOWN
) {
1992 PR_fprintf(PR_STDERR
, "%s -Z: %s is not a recognized type.\n",
1999 if (certutil
.options
[opt_KeyType
].activated
) {
2000 char * arg
= certutil
.options
[opt_KeyType
].arg
;
2001 if (PL_strcmp(arg
, "rsa") == 0) {
2003 } else if (PL_strcmp(arg
, "dsa") == 0) {
2005 #ifdef NSS_ENABLE_ECC
2006 } else if (PL_strcmp(arg
, "ec") == 0) {
2008 #endif /* NSS_ENABLE_ECC */
2009 } else if (PL_strcmp(arg
, "all") == 0) {
2012 /* use an existing private/public key pair */
2015 } else if (certutil
.commands
[cmd_ListKeys
].activated
) {
2019 /* -m serial number */
2020 if (certutil
.options
[opt_SerialNumber
].activated
) {
2021 int sn
= PORT_Atoi(certutil
.options
[opt_SerialNumber
].arg
);
2023 PR_fprintf(PR_STDERR
, "%s -m: %s is not a valid serial number.\n",
2024 progName
, certutil
.options
[opt_SerialNumber
].arg
);
2030 /* -P certdb name prefix */
2031 if (certutil
.options
[opt_DBPrefix
].activated
) {
2032 if (certutil
.options
[opt_DBPrefix
].arg
) {
2033 certPrefix
= strdup(certutil
.options
[opt_DBPrefix
].arg
);
2039 /* --source-prefix certdb name prefix */
2040 if (certutil
.options
[opt_SourcePrefix
].activated
) {
2041 if (certutil
.options
[opt_SourcePrefix
].arg
) {
2042 srcCertPrefix
= strdup(certutil
.options
[opt_SourcePrefix
].arg
);
2048 /* -q PQG file or curve name */
2049 if (certutil
.options
[opt_PQGFile
].activated
) {
2050 #ifdef NSS_ENABLE_ECC
2051 if ((keytype
!= dsaKey
) && (keytype
!= ecKey
)) {
2052 PR_fprintf(PR_STDERR
, "%s -q: specifies a PQG file for DSA keys" \
2053 " (-k dsa) or a named curve for EC keys (-k ec)\n)",
2056 if (keytype
!= dsaKey
) {
2057 PR_fprintf(PR_STDERR
, "%s -q: PQG file is for DSA key (-k dsa).\n)",
2059 #endif /* NSS_ENABLE_ECC */
2064 /* -s subject name */
2065 if (certutil
.options
[opt_Subject
].activated
) {
2066 subject
= CERT_AsciiToName(certutil
.options
[opt_Subject
].arg
);
2068 PR_fprintf(PR_STDERR
, "%s -s: improperly formatted name: \"%s\"\n",
2069 progName
, certutil
.options
[opt_Subject
].arg
);
2074 /* -v validity period */
2075 if (certutil
.options
[opt_Validity
].activated
) {
2076 validityMonths
= PORT_Atoi(certutil
.options
[opt_Validity
].arg
);
2077 if (validityMonths
< 0) {
2078 PR_fprintf(PR_STDERR
, "%s -v: incorrect validity period: \"%s\"\n",
2079 progName
, certutil
.options
[opt_Validity
].arg
);
2084 /* -w warp months */
2085 if (certutil
.options
[opt_OffsetMonths
].activated
)
2086 warpmonths
= PORT_Atoi(certutil
.options
[opt_OffsetMonths
].arg
);
2088 /* -y public exponent (for RSA) */
2089 if (certutil
.options
[opt_Exponent
].activated
) {
2090 publicExponent
= PORT_Atoi(certutil
.options
[opt_Exponent
].arg
);
2091 if ((publicExponent
!= 3) &&
2092 (publicExponent
!= 17) &&
2093 (publicExponent
!= 65537)) {
2094 PR_fprintf(PR_STDERR
, "%s -y: incorrect public exponent %d.",
2095 progName
, publicExponent
);
2096 PR_fprintf(PR_STDERR
, "Must be 3, 17, or 65537.\n");
2101 /* Check number of commands entered. */
2102 commandsEntered
= 0;
2103 for (i
=0; i
< certutil
.numCommands
; i
++) {
2104 if (certutil
.commands
[i
].activated
) {
2105 commandToRun
= certutil
.commands
[i
].flag
;
2108 if (commandsEntered
> 1)
2111 if (commandsEntered
> 1) {
2112 PR_fprintf(PR_STDERR
, "%s: only one command at a time!\n", progName
);
2113 PR_fprintf(PR_STDERR
, "You entered: ");
2114 for (i
=0; i
< certutil
.numCommands
; i
++) {
2115 if (certutil
.commands
[i
].activated
)
2116 PR_fprintf(PR_STDERR
, " -%c", certutil
.commands
[i
].flag
);
2118 PR_fprintf(PR_STDERR
, "\n");
2121 if (commandsEntered
== 0) {
2122 PR_fprintf(PR_STDERR
, "%s: you must enter a command!\n", progName
);
2126 if (certutil
.commands
[cmd_ListCerts
].activated
||
2127 certutil
.commands
[cmd_PrintHelp
].activated
||
2128 certutil
.commands
[cmd_ListKeys
].activated
||
2129 certutil
.commands
[cmd_ListModules
].activated
||
2130 certutil
.commands
[cmd_CheckCertValidity
].activated
||
2131 certutil
.commands
[cmd_Version
].activated
) {
2132 readOnly
= !certutil
.options
[opt_RW
].activated
;
2135 /* -A, -D, -F, -M, -S, -V, and all require -n */
2136 if ((certutil
.commands
[cmd_AddCert
].activated
||
2137 certutil
.commands
[cmd_DeleteCert
].activated
||
2138 certutil
.commands
[cmd_DeleteKey
].activated
||
2139 certutil
.commands
[cmd_DumpChain
].activated
||
2140 certutil
.commands
[cmd_ModifyCertTrust
].activated
||
2141 certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2142 certutil
.commands
[cmd_CheckCertValidity
].activated
) &&
2143 !certutil
.options
[opt_Nickname
].activated
) {
2144 PR_fprintf(PR_STDERR
,
2145 "%s -%c: nickname is required for this command (-n).\n",
2146 progName
, commandToRun
);
2150 /* -A, -E, -M, -S require trust */
2151 if ((certutil
.commands
[cmd_AddCert
].activated
||
2152 certutil
.commands
[cmd_AddEmailCert
].activated
||
2153 certutil
.commands
[cmd_ModifyCertTrust
].activated
||
2154 certutil
.commands
[cmd_CreateAndAddCert
].activated
) &&
2155 !certutil
.options
[opt_Trust
].activated
) {
2156 PR_fprintf(PR_STDERR
,
2157 "%s -%c: trust is required for this command (-t).\n",
2158 progName
, commandToRun
);
2162 /* if -L is given raw or ascii mode, it must be for only one cert. */
2163 if (certutil
.commands
[cmd_ListCerts
].activated
&&
2164 (certutil
.options
[opt_ASCIIForIO
].activated
||
2165 certutil
.options
[opt_BinaryDER
].activated
) &&
2166 !certutil
.options
[opt_Nickname
].activated
) {
2167 PR_fprintf(PR_STDERR
,
2168 "%s: nickname is required to dump cert in raw or ascii mode.\n",
2173 /* -L can only be in (raw || ascii). */
2174 if (certutil
.commands
[cmd_ListCerts
].activated
&&
2175 certutil
.options
[opt_ASCIIForIO
].activated
&&
2176 certutil
.options
[opt_BinaryDER
].activated
) {
2177 PR_fprintf(PR_STDERR
,
2178 "%s: cannot specify both -r and -a when dumping cert.\n",
2183 /* For now, deny -C -x combination */
2184 if (certutil
.commands
[cmd_CreateNewCert
].activated
&&
2185 certutil
.options
[opt_SelfSign
].activated
) {
2186 PR_fprintf(PR_STDERR
,
2187 "%s: self-signing a cert request is not supported.\n",
2192 /* If making a cert request, need a subject. */
2193 if ((certutil
.commands
[cmd_CertReq
].activated
||
2194 certutil
.commands
[cmd_CreateAndAddCert
].activated
) &&
2195 !certutil
.options
[opt_Subject
].activated
) {
2196 PR_fprintf(PR_STDERR
,
2197 "%s -%c: subject is required to create a cert request.\n",
2198 progName
, commandToRun
);
2202 /* If making a cert, need a serial number. */
2203 if ((certutil
.commands
[cmd_CreateNewCert
].activated
||
2204 certutil
.commands
[cmd_CreateAndAddCert
].activated
) &&
2205 !certutil
.options
[opt_SerialNumber
].activated
) {
2206 /* Make a default serial number from the current time. */
2207 PRTime now
= PR_Now();
2208 LL_USHR(now
, now
, 19);
2209 LL_L2UI(serialNumber
, now
);
2212 /* Validation needs the usage to validate for. */
2213 if (certutil
.commands
[cmd_CheckCertValidity
].activated
&&
2214 !certutil
.options
[opt_Usage
].activated
) {
2215 PR_fprintf(PR_STDERR
,
2216 "%s -V: specify a usage to validate the cert for (-u).\n",
2221 /* Upgrade/Merge needs a source database and a upgrade id. */
2222 if (certutil
.commands
[cmd_UpgradeMerge
].activated
&&
2223 !(certutil
.options
[opt_SourceDir
].activated
&&
2224 certutil
.options
[opt_UpgradeID
].activated
)) {
2226 PR_fprintf(PR_STDERR
,
2227 "%s --upgrade-merge: specify an upgrade database directory "
2228 "(--source-dir) and\n"
2229 " an upgrade ID (--upgrade-id).\n",
2234 /* Merge needs a source database */
2235 if (certutil
.commands
[cmd_Merge
].activated
&&
2236 !certutil
.options
[opt_SourceDir
].activated
) {
2239 PR_fprintf(PR_STDERR
,
2240 "%s --merge: specify an source database directory "
2247 /* To make a cert, need either a issuer or to self-sign it. */
2248 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
&&
2249 !(certutil
.options
[opt_IssuerName
].activated
||
2250 certutil
.options
[opt_SelfSign
].activated
)) {
2251 PR_fprintf(PR_STDERR
,
2252 "%s -S: must specify issuer (-c) or self-sign (-x).\n",
2257 /* Using slotname == NULL for listing keys and certs on all slots,
2259 if (!(certutil
.commands
[cmd_ListKeys
].activated
||
2260 certutil
.commands
[cmd_DumpChain
].activated
||
2261 certutil
.commands
[cmd_ListCerts
].activated
) && slotname
== NULL
) {
2262 PR_fprintf(PR_STDERR
,
2263 "%s -%c: cannot use \"-h all\" for this command.\n",
2264 progName
, commandToRun
);
2268 /* Using keytype == nullKey for list all key types, but only that. */
2269 if (!certutil
.commands
[cmd_ListKeys
].activated
&& keytype
== nullKey
) {
2270 PR_fprintf(PR_STDERR
,
2271 "%s -%c: cannot use \"-k all\" for this command.\n",
2272 progName
, commandToRun
);
2276 /* -S open outFile, temporary file for cert request. */
2277 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
) {
2278 outFile
= PR_Open(certreqfile
,
2279 PR_RDWR
| PR_CREATE_FILE
| PR_TRUNCATE
, 00660);
2281 PR_fprintf(PR_STDERR
,
2282 "%s -o: unable to open \"%s\" for writing (%ld, %ld)\n",
2283 progName
, certreqfile
,
2284 PR_GetError(), PR_GetOSError());
2289 /* Open the input file. */
2290 if (certutil
.options
[opt_InputFile
].activated
) {
2291 inFile
= PR_Open(certutil
.options
[opt_InputFile
].arg
, PR_RDONLY
, 0);
2293 PR_fprintf(PR_STDERR
,
2294 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
2295 progName
, certutil
.options
[opt_InputFile
].arg
,
2296 PR_GetError(), PR_GetOSError());
2301 /* Open the output file. */
2302 if (certutil
.options
[opt_OutputFile
].activated
&& !outFile
) {
2303 outFile
= PR_Open(certutil
.options
[opt_OutputFile
].arg
,
2304 PR_CREATE_FILE
| PR_RDWR
| PR_TRUNCATE
, 00660);
2306 PR_fprintf(PR_STDERR
,
2307 "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
2308 progName
, certutil
.options
[opt_OutputFile
].arg
,
2309 PR_GetError(), PR_GetOSError());
2314 name
= SECU_GetOptionArg(&certutil
, opt_Nickname
);
2316 PK11_SetPasswordFunc(SECU_GetModulePassword
);
2318 if (PR_TRUE
== initialize
) {
2319 /* Initialize NSPR and NSS. */
2320 PR_Init(PR_SYSTEM_THREAD
, PR_PRIORITY_NORMAL
, 1);
2321 if (!certutil
.commands
[cmd_UpgradeMerge
].activated
) {
2322 rv
= NSS_Initialize(SECU_ConfigDirectory(NULL
),
2323 certPrefix
, certPrefix
,
2324 "secmod.db", readOnly
? NSS_INIT_READONLY
: 0);
2326 rv
= NSS_InitWithMerge(SECU_ConfigDirectory(NULL
),
2327 certPrefix
, certPrefix
, "secmod.db",
2328 sourceDir
, srcCertPrefix
, srcCertPrefix
,
2329 upgradeID
, upgradeTokenName
,
2330 readOnly
? NSS_INIT_READONLY
: 0);
2332 if (rv
!= SECSuccess
) {
2333 SECU_PrintPRandOSError(progName
);
2337 initialized
= PR_TRUE
;
2338 SECU_RegisterDynamicOids();
2340 certHandle
= CERT_GetDefaultCertDB();
2342 if (certutil
.commands
[cmd_Version
].activated
) {
2343 printf("Certificate database content version: command not implemented.\n");
2346 if (PL_strcmp(slotname
, "internal") == 0)
2347 slot
= PK11_GetInternalKeySlot();
2348 else if (slotname
!= NULL
)
2349 slot
= PK11_FindSlotByName(slotname
);
2354 if ( !slot
&& (certutil
.commands
[cmd_NewDBs
].activated
||
2355 certutil
.commands
[cmd_ModifyCertTrust
].activated
||
2356 certutil
.commands
[cmd_ChangePassword
].activated
||
2357 certutil
.commands
[cmd_TokenReset
].activated
||
2358 certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2359 certutil
.commands
[cmd_AddCert
].activated
||
2360 certutil
.commands
[cmd_Merge
].activated
||
2361 certutil
.commands
[cmd_UpgradeMerge
].activated
||
2362 certutil
.commands
[cmd_AddEmailCert
].activated
)) {
2364 SECU_PrintError(progName
, "could not find the slot %s",slotname
);
2369 /* If creating new database, initialize the password. */
2370 if (certutil
.commands
[cmd_NewDBs
].activated
) {
2371 SECU_ChangePW2(slot
, 0, 0, certutil
.options
[opt_PasswordFile
].arg
,
2372 certutil
.options
[opt_NewPasswordFile
].arg
);
2375 /* walk through the upgrade merge if necessary.
2376 * This option is more to test what some applications will want to do
2377 * to do an automatic upgrade. The --merge command is more useful for
2378 * the general case where 2 database need to be merged together.
2380 if (certutil
.commands
[cmd_UpgradeMerge
].activated
) {
2381 if (*upgradeTokenName
== 0) {
2382 upgradeTokenName
= upgradeID
;
2384 if (!PK11_IsInternal(slot
)) {
2385 fprintf(stderr
, "Only internal DB's can be upgraded\n");
2389 if (!PK11_IsRemovable(slot
)) {
2390 printf("database already upgraded.\n");
2394 if (!PK11_NeedLogin(slot
)) {
2395 printf("upgrade complete!\n");
2399 /* authenticate to the old DB if necessary */
2400 if (PORT_Strcmp(PK11_GetTokenName(slot
), upgradeTokenName
) == 0) {
2401 /* if we need a password, supply it. This will be the password
2402 * for the old database */
2403 rv
= PK11_Authenticate(slot
, PR_FALSE
, &pwdata2
);
2404 if (rv
!= SECSuccess
) {
2405 SECU_PrintError(progName
, "Could not get password for %s",
2410 * if we succeeded above, but still aren't logged in, that means
2411 * we just supplied the password for the old database. We may
2412 * need the password for the new database. NSS will automatically
2413 * change the token names at this point
2415 if (PK11_IsLoggedIn(slot
, &pwdata
)) {
2416 printf("upgrade complete!\n");
2422 /* call PK11_IsPresent to update our cached token information */
2423 if (!PK11_IsPresent(slot
)) {
2424 /* this shouldn't happen. We call isPresent to force a token
2426 fprintf(stderr
, "upgrade/merge internal error\n");
2431 /* the token is now set to the state of the source database,
2432 * if we need a password for it, PK11_Authenticate will
2433 * automatically prompt us */
2434 rv
= PK11_Authenticate(slot
, PR_FALSE
, &pwdata
);
2435 if (rv
== SECSuccess
) {
2436 printf("upgrade complete!\n");
2438 SECU_PrintError(progName
, "Could not get password for %s",
2439 PK11_GetTokenName(slot
));
2445 * merge 2 databases.
2447 if (certutil
.commands
[cmd_Merge
].activated
) {
2448 PK11SlotInfo
*sourceSlot
= NULL
;
2450 char *modspec
= PR_smprintf(
2451 "configDir='%s' certPrefix='%s' tokenDescription='%s'",
2452 sourceDir
, srcCertPrefix
,
2453 *upgradeTokenName
? upgradeTokenName
: "Source Database");
2460 sourceSlot
= SECMOD_OpenUserDB(modspec
);
2461 PR_smprintf_free(modspec
);
2463 SECU_PrintError(progName
, "couldn't open source database");
2468 rv
= PK11_Authenticate(slot
, PR_FALSE
, &pwdata
);
2469 if (rv
!= SECSuccess
) {
2470 SECU_PrintError(progName
, "Couldn't get password for %s",
2471 PK11_GetTokenName(slot
));
2475 rv
= PK11_Authenticate(sourceSlot
, PR_FALSE
, &pwdata2
);
2476 if (rv
!= SECSuccess
) {
2477 SECU_PrintError(progName
, "Couldn't get password for %s",
2478 PK11_GetTokenName(sourceSlot
));
2482 log
= PK11_CreateMergeLog();
2485 SECU_PrintError(progName
, "couldn't create error log");
2489 rv
= PK11_MergeTokens(slot
, sourceSlot
, log
, &pwdata
, &pwdata2
);
2490 if (rv
!= SECSuccess
) {
2491 DumpMergeLog(progName
, log
);
2493 PK11_DestroyMergeLog(log
);
2496 SECMOD_CloseUserDB(sourceSlot
);
2497 PK11_FreeSlot(sourceSlot
);
2501 /* The following 8 options are mutually exclusive with all others. */
2503 /* List certs (-L) */
2504 if (certutil
.commands
[cmd_ListCerts
].activated
) {
2505 rv
= ListCerts(certHandle
, name
, slot
,
2506 certutil
.options
[opt_BinaryDER
].activated
,
2507 certutil
.options
[opt_ASCIIForIO
].activated
,
2508 (outFile
) ? outFile
: PR_STDOUT
, &pwdata
);
2511 if (certutil
.commands
[cmd_DumpChain
].activated
) {
2512 rv
= DumpChain(certHandle
, name
);
2515 /* XXX needs work */
2516 /* List keys (-K) */
2517 if (certutil
.commands
[cmd_ListKeys
].activated
) {
2518 rv
= ListKeys(slot
, name
, 0 /*keyindex*/, keytype
, PR_FALSE
/*dopriv*/,
2522 /* List modules (-U) */
2523 if (certutil
.commands
[cmd_ListModules
].activated
) {
2527 /* Delete cert (-D) */
2528 if (certutil
.commands
[cmd_DeleteCert
].activated
) {
2529 rv
= DeleteCert(certHandle
, name
);
2532 /* Delete key (-F) */
2533 if (certutil
.commands
[cmd_DeleteKey
].activated
) {
2534 rv
= DeleteKey(name
, &pwdata
);
2537 /* Modify trust attribute for cert (-M) */
2538 if (certutil
.commands
[cmd_ModifyCertTrust
].activated
) {
2539 if (PK11_IsFIPS() || !PK11_IsFriendly(slot
)) {
2540 rv
= PK11_Authenticate(slot
, PR_TRUE
, &pwdata
);
2541 if (rv
!= SECSuccess
) {
2542 SECU_PrintError(progName
, "could not authenticate to token %s.",
2543 PK11_GetTokenName(slot
));
2547 rv
= ChangeTrustAttributes(certHandle
, slot
, name
,
2548 certutil
.options
[opt_Trust
].arg
, &pwdata
);
2551 /* Change key db password (-W) (future - change pw to slot?) */
2552 if (certutil
.commands
[cmd_ChangePassword
].activated
) {
2553 rv
= SECU_ChangePW2(slot
, 0, 0, certutil
.options
[opt_PasswordFile
].arg
,
2554 certutil
.options
[opt_NewPasswordFile
].arg
);
2557 /* Reset the a token */
2558 if (certutil
.commands
[cmd_TokenReset
].activated
) {
2559 char *sso_pass
= "";
2561 if (certutil
.options
[opt_SSOPass
].activated
) {
2562 sso_pass
= certutil
.options
[opt_SSOPass
].arg
;
2564 rv
= PK11_ResetToken(slot
,sso_pass
);
2568 /* Check cert validity against current time (-V) */
2569 if (certutil
.commands
[cmd_CheckCertValidity
].activated
) {
2570 /* XXX temporary hack for fips - must log in to get priv key */
2571 if (certutil
.options
[opt_VerifySig
].activated
) {
2572 if (slot
&& PK11_NeedLogin(slot
)) {
2573 SECStatus newrv
= PK11_Authenticate(slot
, PR_TRUE
, &pwdata
);
2574 if (newrv
!= SECSuccess
) {
2575 SECU_PrintError(progName
, "could not authenticate to token %s.",
2576 PK11_GetTokenName(slot
));
2581 rv
= ValidateCert(certHandle
, name
,
2582 certutil
.options
[opt_ValidityTime
].arg
,
2583 certutil
.options
[opt_Usage
].arg
,
2584 certutil
.options
[opt_VerifySig
].activated
,
2585 certutil
.options
[opt_DetailedInfo
].activated
,
2587 if (rv
!= SECSuccess
&& PR_GetError() == SEC_ERROR_INVALID_ARGS
)
2588 SECU_PrintError(progName
, "validation failed");
2596 /* These commands may require keygen. */
2597 if (certutil
.commands
[cmd_CertReq
].activated
||
2598 certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2599 certutil
.commands
[cmd_GenKeyPair
].activated
) {
2601 CERTCertificate
*keycert
;
2602 keycert
= CERT_FindCertByNicknameOrEmailAddr(certHandle
, keysource
);
2604 keycert
= PK11_FindCertFromNickname(keysource
, NULL
);
2606 SECU_PrintError(progName
,
2607 "%s is neither a key-type nor a nickname", keysource
);
2611 privkey
= PK11_FindKeyByDERCert(slot
, keycert
, &pwdata
);
2613 pubkey
= CERT_ExtractPublicKey(keycert
);
2614 CERT_DestroyCertificate(keycert
);
2616 SECU_PrintError(progName
,
2617 "Could not get keys from cert %s", keysource
);
2621 keytype
= privkey
->keyType
;
2624 CERTUTIL_GeneratePrivateKey(keytype
, slot
, keysize
,
2626 certutil
.options
[opt_NoiseFile
].arg
,
2628 certutil
.options
[opt_PQGFile
].arg
,
2630 if (privkey
== NULL
) {
2631 SECU_PrintError(progName
, "unable to generate key(s)\n");
2636 privkey
->wincx
= &pwdata
;
2637 PORT_Assert(pubkey
!= NULL
);
2639 /* If all that was needed was keygen, exit. */
2640 if (certutil
.commands
[cmd_GenKeyPair
].activated
) {
2646 /* If we need a list of extensions convert the flags into list format */
2647 if (certutil
.commands
[cmd_CertReq
].activated
||
2648 certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2649 certutil
.commands
[cmd_CreateNewCert
].activated
) {
2650 certutil_extns
[ext_keyUsage
] =
2651 certutil
.options
[opt_AddKeyUsageExt
].activated
;
2652 certutil_extns
[ext_basicConstraint
] =
2653 certutil
.options
[opt_AddBasicConstraintExt
].activated
;
2654 certutil_extns
[ext_authorityKeyID
] =
2655 certutil
.options
[opt_AddAuthorityKeyIDExt
].activated
;
2656 certutil_extns
[ext_subjectKeyID
] =
2657 certutil
.options
[opt_AddSubjectKeyIDExt
].activated
;
2658 certutil_extns
[ext_CRLDistPts
] =
2659 certutil
.options
[opt_AddCRLDistPtsExt
].activated
;
2660 certutil_extns
[ext_NSCertType
] =
2661 certutil
.options
[opt_AddNSCertTypeExt
].activated
;
2662 certutil_extns
[ext_extKeyUsage
] =
2663 certutil
.options
[opt_AddExtKeyUsageExt
].activated
;
2664 certutil_extns
[ext_authInfoAcc
] =
2665 certutil
.options
[opt_AddAuthInfoAccExt
].activated
;
2666 certutil_extns
[ext_subjInfoAcc
] =
2667 certutil
.options
[opt_AddSubjInfoAccExt
].activated
;
2668 certutil_extns
[ext_certPolicies
] =
2669 certutil
.options
[opt_AddCertPoliciesExt
].activated
;
2670 certutil_extns
[ext_policyMappings
] =
2671 certutil
.options
[opt_AddPolicyMapExt
].activated
;
2672 certutil_extns
[ext_policyConstr
] =
2673 certutil
.options
[opt_AddPolicyConstrExt
].activated
;
2674 certutil_extns
[ext_inhibitAnyPolicy
] =
2675 certutil
.options
[opt_AddInhibAnyExt
].activated
;
2678 * Certificate request
2681 /* Make a cert request (-R). */
2682 if (certutil
.commands
[cmd_CertReq
].activated
) {
2683 rv
= CertReq(privkey
, pubkey
, keytype
, hashAlgTag
, subject
,
2684 certutil
.options
[opt_PhoneNumber
].arg
,
2685 certutil
.options
[opt_ASCIIForIO
].activated
,
2686 certutil
.options
[opt_ExtendedEmailAddrs
].arg
,
2687 certutil
.options
[opt_ExtendedDNSNames
].arg
,
2689 outFile
? outFile
: PR_STDOUT
);
2692 privkey
->wincx
= &pwdata
;
2696 * Certificate creation
2699 /* If making and adding a cert, create a cert request file first without
2700 * any extensions, then load it with the command line extensions
2701 * and output the cert to another file.
2703 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
) {
2704 static certutilExtnList nullextnlist
= {PR_FALSE
};
2705 rv
= CertReq(privkey
, pubkey
, keytype
, hashAlgTag
, subject
,
2706 certutil
.options
[opt_PhoneNumber
].arg
,
2707 certutil
.options
[opt_ASCIIForIO
].activated
,
2711 outFile
? outFile
: PR_STDOUT
);
2714 privkey
->wincx
= &pwdata
;
2716 inFile
= PR_Open(certreqfile
, PR_RDONLY
, 0);
2718 PR_fprintf(PR_STDERR
, "Failed to open file \"%s\" (%ld, %ld).\n",
2719 certreqfile
, PR_GetError(), PR_GetOSError());
2723 outFile
= PR_Open(certfile
,
2724 PR_RDWR
| PR_CREATE_FILE
| PR_TRUNCATE
, 00660);
2726 PR_fprintf(PR_STDERR
, "Failed to open file \"%s\" (%ld, %ld).\n",
2727 certfile
, PR_GetError(), PR_GetOSError());
2733 /* Create a certificate (-C or -S). */
2734 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2735 certutil
.commands
[cmd_CreateNewCert
].activated
) {
2736 rv
= CreateCert(certHandle
,
2737 certutil
.options
[opt_IssuerName
].arg
,
2738 inFile
, outFile
, privkey
, &pwdata
, hashAlgTag
,
2739 serialNumber
, warpmonths
, validityMonths
,
2740 certutil
.options
[opt_ExtendedEmailAddrs
].arg
,
2741 certutil
.options
[opt_ExtendedDNSNames
].arg
,
2742 certutil
.options
[opt_ASCIIForIO
].activated
,
2743 certutil
.options
[opt_SelfSign
].activated
,
2750 * Adding a cert to the database (or slot)
2753 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
) {
2754 PORT_Assert(inFile
!= PR_STDIN
);
2757 inFile
= PR_Open(certfile
, PR_RDONLY
, 0);
2759 PR_fprintf(PR_STDERR
, "Failed to open file \"%s\" (%ld, %ld).\n",
2760 certfile
, PR_GetError(), PR_GetOSError());
2766 /* -A -E or -S Add the cert to the DB */
2767 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
||
2768 certutil
.commands
[cmd_AddCert
].activated
||
2769 certutil
.commands
[cmd_AddEmailCert
].activated
) {
2770 rv
= AddCert(slot
, certHandle
, name
,
2771 certutil
.options
[opt_Trust
].arg
,
2773 certutil
.options
[opt_ASCIIForIO
].activated
,
2774 certutil
.commands
[cmd_AddEmailCert
].activated
,&pwdata
);
2779 if (certutil
.commands
[cmd_CreateAndAddCert
].activated
) {
2780 PORT_Assert(inFile
!= PR_STDIN
);
2782 PR_Delete(certfile
);
2783 PR_Delete(certreqfile
);
2788 PK11_FreeSlot(slot
);
2791 SECKEY_DestroyPrivateKey(privkey
);
2794 SECKEY_DestroyPublicKey(pubkey
);
2797 /* Open the batch command file.
2799 * - If -B <command line> option is specified, the contents in the
2800 * command file will be interpreted as subsequent certutil
2801 * commands to be executed in the current certutil process
2802 * context after the current certutil command has been executed.
2803 * - Each line in the command file consists of the command
2804 * line arguments for certutil.
2805 * - The -d <configdir> option will be ignored if specified in the
2807 * - Quoting with double quote characters ("...") is supported
2808 * to allow white space in a command line argument. The
2809 * double quote character cannot be escaped and quoting cannot
2810 * be nested in this version.
2811 * - each line in the batch file is limited to 512 characters
2814 if ((SECSuccess
== rv
) && certutil
.commands
[cmd_Batch
].activated
) {
2815 FILE* batchFile
= NULL
;
2816 char nextcommand
[512];
2817 if (!certutil
.options
[opt_InputFile
].activated
||
2818 !certutil
.options
[opt_InputFile
].arg
) {
2819 PR_fprintf(PR_STDERR
,
2820 "%s: no batch input file specified.\n",
2824 batchFile
= fopen(certutil
.options
[opt_InputFile
].arg
, "r");
2826 PR_fprintf(PR_STDERR
,
2827 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
2828 progName
, certutil
.options
[opt_InputFile
].arg
,
2829 PR_GetError(), PR_GetOSError());
2832 /* read and execute command-lines in a loop */
2833 while ( (SECSuccess
== rv
) &&
2834 fgets(nextcommand
, sizeof(nextcommand
), batchFile
)) {
2835 /* we now need to split the command into argc / argv format */
2836 char* commandline
= PORT_Strdup(nextcommand
);
2837 PRBool invalid
= PR_FALSE
;
2840 char* nextarg
= NULL
;
2841 char** newargv
= NULL
;
2842 char* crlf
= PORT_Strrchr(commandline
, '\n');
2847 newargv
= PORT_Alloc(sizeof(char*)*(newargc
+1));
2848 newargv
[0] = progName
;
2849 newargv
[1] = commandline
;
2850 nextarg
= commandline
;
2851 while ((space
= PORT_Strpbrk(nextarg
, " \f\n\r\t\v")) ) {
2852 while (isspace(*space
) ) {
2856 if (*space
== '\0') {
2858 } else if (*space
!= '\"') {
2861 char* closingquote
= strchr(space
+1, '\"');
2863 *closingquote
= '\0';
2865 nextarg
= closingquote
+1;
2872 newargv
= PORT_Realloc(newargv
, sizeof(char*)*(newargc
+1));
2873 newargv
[newargc
-1] = space
;
2875 newargv
[newargc
] = NULL
;
2877 /* invoke next command */
2878 if (PR_TRUE
== invalid
) {
2879 PR_fprintf(PR_STDERR
, "Missing closing quote in batch command :\n%s\nNot executed.\n",
2883 if (0 != certutil_main(newargc
, newargv
, PR_FALSE
) )
2887 PORT_Free(commandline
);
2892 if ((initialized
== PR_TRUE
) && NSS_Shutdown() != SECSuccess
) {
2897 if (rv
== SECSuccess
) {
2905 main(int argc
, char **argv
)
2907 return certutil_main(argc
, argv
, PR_TRUE
);