nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / cmd / crlutil / crlutil.c
blobb5220b497a34f51ce6aff972b6512fa3fc1d63c7
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
12 * License.
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.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 ** certutil.c
40 ** utility for managing certificates and the cert database
43 /* test only */
45 #include "nspr.h"
46 #include "plgetopt.h"
47 #include "secutil.h"
48 #include "cert.h"
49 #include "certi.h"
50 #include "certdb.h"
51 #include "nss.h"
52 #include "pk11func.h"
53 #include "crlgen.h"
55 #define SEC_CERT_DB_EXISTS 0
56 #define SEC_CREATE_CERT_DB 1
58 static char *progName;
60 static CERTSignedCrl *FindCRL
61 (CERTCertDBHandle *certHandle, char *name, int type)
63 CERTSignedCrl *crl = NULL;
64 CERTCertificate *cert = NULL;
65 SECItem derName;
67 derName.data = NULL;
68 derName.len = 0;
70 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name);
71 if (!cert) {
72 CERTName *certName = NULL;
73 PRArenaPool *arena = NULL;
75 certName = CERT_AsciiToName(name);
76 if (certName) {
77 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
78 if (arena) {
79 SECItem *nameItem =
80 SEC_ASN1EncodeItem (arena, NULL, (void *)certName,
81 SEC_ASN1_GET(CERT_NameTemplate));
82 if (nameItem) {
83 SECITEM_CopyItem(NULL, &derName, nameItem);
85 PORT_FreeArena(arena, PR_FALSE);
87 CERT_DestroyName(certName);
90 if (!derName.len || !derName.data) {
91 SECU_PrintError(progName, "could not find certificate named '%s'", name);
92 return ((CERTSignedCrl *)NULL);
94 } else {
95 SECITEM_CopyItem(NULL, &derName, &cert->derSubject);
96 CERT_DestroyCertificate (cert);
99 crl = SEC_FindCrlByName(certHandle, &derName, type);
100 if (crl ==NULL)
101 SECU_PrintError
102 (progName, "could not find %s's CRL", name);
103 if (derName.data) {
104 SECITEM_FreeItem(&derName, PR_FALSE);
106 return (crl);
109 static SECStatus DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
111 CERTSignedCrl *crl = NULL;
113 crl = FindCRL (certHandle, nickName, crlType);
115 if (crl) {
116 SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0);
117 SEC_DestroyCrl (crl);
118 return SECSuccess;
120 return SECFailure;
123 static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
125 CERTCrlHeadNode *crlList = NULL;
126 CERTCrlNode *crlNode = NULL;
127 CERTName *name = NULL;
128 PRArenaPool *arena = NULL;
129 SECStatus rv;
131 do {
132 arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
133 if (arena == NULL) {
134 fprintf(stderr, "%s: fail to allocate memory\n", progName);
135 break;
138 name = PORT_ArenaZAlloc (arena, sizeof(*name));
139 if (name == NULL) {
140 fprintf(stderr, "%s: fail to allocate memory\n", progName);
141 break;
143 name->arena = arena;
145 rv = SEC_LookupCrls (certHandle, &crlList, crlType);
146 if (rv != SECSuccess) {
147 fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName,
148 SECU_Strerror(PORT_GetError()));
149 break;
152 /* just in case */
153 if (!crlList)
154 break;
156 crlNode = crlList->first;
158 fprintf (stdout, "\n");
159 fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
160 while (crlNode) {
161 char* asciiname = NULL;
162 CERTCertificate *cert = NULL;
163 if (crlNode->crl && &crlNode->crl->crl.derName) {
164 cert = CERT_FindCertByName(certHandle,
165 &crlNode->crl->crl.derName);
166 if (!cert) {
167 SECU_PrintError(progName, "could not find signing "
168 "certificate in database");
171 if (cert) {
172 char* certName = NULL;
173 if (cert->nickname && PORT_Strlen(cert->nickname) > 0) {
174 certName = cert->nickname;
175 } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) {
176 certName = cert->emailAddr;
178 if (certName) {
179 asciiname = PORT_Strdup(certName);
181 CERT_DestroyCertificate(cert);
184 if (!asciiname) {
185 name = &crlNode->crl->crl.name;
186 if (!name){
187 SECU_PrintError(progName, "fail to get the CRL "
188 "issuer name");
189 continue;
191 asciiname = CERT_NameToAscii(name);
193 fprintf (stdout, "%-40s %-5s\n", asciiname, "CRL");
194 if (asciiname) {
195 PORT_Free(asciiname);
197 if ( PR_TRUE == deletecrls) {
198 CERTSignedCrl* acrl = NULL;
199 SECItem* issuer = &crlNode->crl->crl.derName;
200 acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
201 if (acrl)
203 SEC_DeletePermCRL(acrl);
204 SEC_DestroyCrl(acrl);
207 crlNode = crlNode->next;
210 } while (0);
211 if (crlList)
212 PORT_FreeArena (crlList->arena, PR_FALSE);
213 PORT_FreeArena (arena, PR_FALSE);
216 static SECStatus ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
218 if (nickName == NULL) {
219 ListCRLNames (certHandle, crlType, PR_FALSE);
220 return SECSuccess;
223 return DisplayCRL (certHandle, nickName, crlType);
228 static SECStatus DeleteCRL (CERTCertDBHandle *certHandle, char *name, int type)
230 CERTSignedCrl *crl = NULL;
231 SECStatus rv = SECFailure;
233 crl = FindCRL (certHandle, name, type);
234 if (!crl) {
235 SECU_PrintError
236 (progName, "could not find the issuer %s's CRL", name);
237 return SECFailure;
239 rv = SEC_DeletePermCRL (crl);
240 SEC_DestroyCrl(crl);
241 if (rv != SECSuccess) {
242 SECU_PrintError(progName, "fail to delete the issuer %s's CRL "
243 "from the perm database (reason: %s)",
244 name, SECU_Strerror(PORT_GetError()));
245 return SECFailure;
247 return (rv);
250 SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type,
251 PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions)
253 CERTSignedCrl *crl = NULL;
254 SECItem crlDER;
255 PK11SlotInfo* slot = NULL;
256 int rv;
257 #if defined(DEBUG_jpierre)
258 PRIntervalTime starttime, endtime, elapsed;
259 PRUint32 mins, secs, msecs;
260 #endif
262 crlDER.data = NULL;
265 /* Read in the entire file specified with the -f argument */
266 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE);
267 if (rv != SECSuccess) {
268 SECU_PrintError(progName, "unable to read input file");
269 return (SECFailure);
272 decodeOptions |= CRL_DECODE_DONT_COPY_DER;
274 slot = PK11_GetInternalKeySlot();
276 #if defined(DEBUG_jpierre)
277 starttime = PR_IntervalNow();
278 #endif
279 crl = PK11_ImportCRL(slot, &crlDER, url, type,
280 NULL, importOptions, NULL, decodeOptions);
281 #if defined(DEBUG_jpierre)
282 endtime = PR_IntervalNow();
283 elapsed = endtime - starttime;
284 mins = PR_IntervalToSeconds(elapsed) / 60;
285 secs = PR_IntervalToSeconds(elapsed) % 60;
286 msecs = PR_IntervalToMilliseconds(elapsed) % 1000;
287 printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs);
288 #endif
289 if (!crl) {
290 const char *errString;
292 rv = SECFailure;
293 errString = SECU_Strerror(PORT_GetError());
294 if ( errString && PORT_Strlen (errString) == 0)
295 SECU_PrintError (progName,
296 "CRL is not imported (error: input CRL is not up to date.)");
297 else
298 SECU_PrintError (progName, "unable to import CRL");
299 } else {
300 SEC_DestroyCrl (crl);
302 if (slot) {
303 PK11_FreeSlot(slot);
305 return (rv);
309 static CERTCertificate*
310 FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl,
311 char *certNickName)
313 CERTCertificate *cert = NULL, *certTemp = NULL;
314 SECStatus rv = SECFailure;
315 CERTAuthKeyID* authorityKeyID = NULL;
316 SECItem* subject = NULL;
318 PORT_Assert(certHandle != NULL);
319 if (!certHandle || (!signCrl && !certNickName)) {
320 SECU_PrintError(progName, "invalid args for function "
321 "FindSigningCert \n");
322 return NULL;
325 if (signCrl) {
326 #if 0
327 authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl);
328 #endif
329 subject = &signCrl->crl.derName;
330 } else {
331 certTemp = CERT_FindCertByNickname(certHandle, certNickName);
332 if (!certTemp) {
333 SECU_PrintError(progName, "could not find certificate \"%s\" "
334 "in database", certNickName);
335 goto loser;
337 subject = &certTemp->derSubject;
340 cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now());
341 if (!cert) {
342 SECU_PrintError(progName, "could not find signing certificate "
343 "in database");
344 goto loser;
345 } else {
346 rv = SECSuccess;
349 loser:
350 if (certTemp)
351 CERT_DestroyCertificate(certTemp);
352 if (cert && rv != SECSuccess)
353 CERT_DestroyCertificate(cert);
354 return cert;
357 static CERTSignedCrl*
358 CreateModifiedCRLCopy(PRArenaPool *arena, CERTCertDBHandle *certHandle,
359 CERTCertificate **cert, char *certNickName,
360 PRFileDesc *inFile, PRInt32 decodeOptions,
361 PRInt32 importOptions)
363 SECItem crlDER;
364 CERTSignedCrl *signCrl = NULL;
365 CERTSignedCrl *modCrl = NULL;
366 PRArenaPool *modArena = NULL;
367 SECStatus rv = SECSuccess;
369 PORT_Assert(arena != NULL && certHandle != NULL &&
370 certNickName != NULL);
371 if (!arena || !certHandle || !certNickName) {
372 SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n");
373 return NULL;
376 modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
377 if (!modArena) {
378 SECU_PrintError(progName, "fail to allocate memory\n");
379 return NULL;
382 if (inFile != NULL) {
383 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE);
384 if (rv != SECSuccess) {
385 SECU_PrintError(progName, "unable to read input file");
386 PORT_FreeArena(modArena, PR_FALSE);
387 goto loser;
390 decodeOptions |= CRL_DECODE_DONT_COPY_DER;
392 modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE,
393 decodeOptions);
394 if (!modCrl) {
395 SECU_PrintError(progName, "fail to decode CRL");
396 goto loser;
399 if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){
400 /* If caCert is a v2 certificate, make sure that it
401 * can be used for crl signing purpose */
402 *cert = FindSigningCert(certHandle, modCrl, NULL);
403 if (!*cert) {
404 goto loser;
407 rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
408 PR_Now(), NULL);
409 if (rv != SECSuccess) {
410 SECU_PrintError(progName, "fail to verify signed data\n");
411 goto loser;
414 } else {
415 modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE);
416 if (!modCrl) {
417 SECU_PrintError(progName, "fail to find crl %s in database\n",
418 certNickName);
419 goto loser;
423 signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
424 if (signCrl == NULL) {
425 SECU_PrintError(progName, "fail to allocate memory\n");
426 goto loser;
429 rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl);
430 if (rv != SECSuccess) {
431 SECU_PrintError(progName, "unable to dublicate crl for "
432 "modification.");
433 goto loser;
436 /* Make sure the update time is current. It can be modified later
437 * by "update <time>" command from crl generation script */
438 rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
439 if (rv != SECSuccess) {
440 SECU_PrintError(progName, "fail to encode current time\n");
441 goto loser;
444 signCrl->arena = arena;
446 loser:
447 SECITEM_FreeItem(&crlDER, PR_FALSE);
448 if (modCrl)
449 SEC_DestroyCrl(modCrl);
450 if (rv != SECSuccess && signCrl) {
451 SEC_DestroyCrl(signCrl);
452 signCrl = NULL;
454 return signCrl;
458 static CERTSignedCrl*
459 CreateNewCrl(PRArenaPool *arena, CERTCertDBHandle *certHandle,
460 CERTCertificate *cert)
462 CERTSignedCrl *signCrl = NULL;
463 void *dummy = NULL;
464 SECStatus rv;
465 void* mark = NULL;
467 /* if the CERTSignedCrl structure changes, this function will need to be
468 updated as well */
469 PORT_Assert(cert != NULL);
470 if (!cert || !arena) {
471 SECU_PrintError(progName, "invalid args for function "
472 "CreateNewCrl\n");
473 return NULL;
476 mark = PORT_ArenaMark(arena);
478 signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
479 if (signCrl == NULL) {
480 SECU_PrintError(progName, "fail to allocate memory\n");
481 return NULL;
484 dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version,
485 SEC_CRL_VERSION_2);
486 /* set crl->version */
487 if (!dummy) {
488 SECU_PrintError(progName, "fail to create crl version data "
489 "container\n");
490 goto loser;
493 /* copy SECItem name from cert */
494 rv = SECITEM_CopyItem(arena, &signCrl->crl.derName, &cert->derSubject);
495 if (rv != SECSuccess) {
496 SECU_PrintError(progName, "fail to duplicate der name from "
497 "certificate.\n");
498 goto loser;
501 /* copy CERTName name structure from cert issuer */
502 rv = CERT_CopyName (arena, &signCrl->crl.name, &cert->subject);
503 if (rv != SECSuccess) {
504 SECU_PrintError(progName, "fail to duplicate RD name from "
505 "certificate.\n");
506 goto loser;
509 rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
510 if (rv != SECSuccess) {
511 SECU_PrintError(progName, "fail to encode current time\n");
512 goto loser;
515 /* set fields */
516 signCrl->arena = arena;
517 signCrl->dbhandle = certHandle;
518 signCrl->crl.arena = arena;
520 return signCrl;
522 loser:
523 PORT_ArenaRelease(arena, mark);
524 return NULL;
528 static SECStatus
529 UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile)
531 CRLGENGeneratorData *crlGenData = NULL;
532 SECStatus rv;
534 PORT_Assert(signCrl != NULL && inCrlInitFile != NULL);
535 if (!signCrl || !inCrlInitFile) {
536 SECU_PrintError(progName, "invalid args for function "
537 "CreateNewCrl\n");
538 return SECFailure;
541 crlGenData = CRLGEN_InitCrlGeneration(signCrl, inCrlInitFile);
542 if (!crlGenData) {
543 SECU_PrintError(progName, "can not initialize parser structure.\n");
544 return SECFailure;
547 rv = CRLGEN_ExtHandleInit(crlGenData);
548 if (rv == SECFailure) {
549 SECU_PrintError(progName, "can not initialize entries handle.\n");
550 goto loser;
553 rv = CRLGEN_StartCrlGen(crlGenData);
554 if (rv != SECSuccess) {
555 SECU_PrintError(progName, "crl generation failed");
556 goto loser;
559 loser:
560 /* CommitExtensionsAndEntries is partially responsible for freeing
561 * up memory that was used for CRL generation. Should be called regardless
562 * of previouse call status, but only after initialization of
563 * crlGenData was done. It will commit all changes that was done before
564 * an error has occured.
566 if (SECSuccess != CRLGEN_CommitExtensionsAndEntries(crlGenData)) {
567 SECU_PrintError(progName, "crl generation failed");
568 rv = SECFailure;
570 CRLGEN_FinalizeCrlGeneration(crlGenData);
571 return rv;
574 static SECStatus
575 SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert,
576 char *outFileName, SECOidTag hashAlgTag, int ascii,
577 char *slotName, char *url, secuPWData *pwdata)
579 PK11SlotInfo *slot = NULL;
580 PRFileDesc *outFile = NULL;
581 SECStatus rv;
582 SignAndEncodeFuncExitStat errCode;
584 PORT_Assert(signCrl && (!ascii || outFileName));
585 if (!signCrl || (ascii && !outFileName)) {
586 SECU_PrintError(progName, "invalid args for function "
587 "SignAndStoreCrl\n");
588 return SECFailure;
591 if (!slotName || !PL_strcmp(slotName, "internal"))
592 slot = PK11_GetInternalKeySlot();
593 else
594 slot = PK11_FindSlotByName(slotName);
595 if (!slot) {
596 SECU_PrintError(progName, "can not find requested slot");
597 return SECFailure;
600 if (PK11_NeedLogin(slot)) {
601 rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
602 if (rv != SECSuccess)
603 goto loser;
606 rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode);
607 if (rv != SECSuccess) {
608 char* errMsg = NULL;
609 switch (errCode)
611 case noKeyFound:
612 errMsg = "No private key found of signing cert";
613 break;
615 case noSignatureMatch:
616 errMsg = "Key and Algorithm OId are do not match";
617 break;
619 default:
620 case failToEncode:
621 errMsg = "Failed to encode crl structure";
622 break;
624 case failToSign:
625 errMsg = "Failed to sign crl structure";
626 break;
628 case noMem:
629 errMsg = "Can not allocate memory";
630 break;
632 SECU_PrintError(progName, "%s\n", errMsg);
633 goto loser;
636 if (outFileName) {
637 outFile = PR_Open(outFileName, PR_WRONLY|PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
638 if (!outFile) {
639 SECU_PrintError(progName, "unable to open \"%s\" for writing\n",
640 outFileName);
641 goto loser;
645 rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url);
646 if (rv != SECSuccess) {
647 SECU_PrintError(progName, "fail to save CRL\n");
650 loser:
651 if (outFile)
652 PR_Close(outFile);
653 if (slot)
654 PK11_FreeSlot(slot);
655 return rv;
658 static SECStatus
659 GenerateCRL (CERTCertDBHandle *certHandle, char *certNickName,
660 PRFileDesc *inCrlInitFile, PRFileDesc *inFile,
661 char *outFileName, int ascii, char *slotName,
662 PRInt32 importOptions, char *alg, PRBool quiet,
663 PRInt32 decodeOptions, char *url, secuPWData *pwdata,
664 int modifyFlag)
666 CERTCertificate *cert = NULL;
667 CERTSignedCrl *signCrl = NULL;
668 PRArenaPool *arena = NULL;
669 SECStatus rv;
670 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
672 if (alg) {
673 hashAlgTag = SECU_StringToSignatureAlgTag(alg);
674 if (hashAlgTag == SEC_OID_UNKNOWN) {
675 SECU_PrintError(progName, "%s -Z: %s is not a recognized type.\n",
676 progName, alg);
677 return SECFailure;
679 } else {
680 hashAlgTag = SEC_OID_UNKNOWN;
683 arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
684 if (!arena) {
685 SECU_PrintError(progName, "fail to allocate memory\n");
686 return SECFailure;
689 if (modifyFlag == PR_TRUE) {
690 signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName,
691 inFile, decodeOptions, importOptions);
692 if (signCrl == NULL) {
693 goto loser;
697 if (!cert) {
698 cert = FindSigningCert(certHandle, signCrl, certNickName);
699 if (cert == NULL) {
700 goto loser;
704 if (!signCrl) {
705 if (modifyFlag == PR_TRUE) {
706 if (!outFileName) {
707 int len = strlen(certNickName) + 5;
708 outFileName = PORT_ArenaAlloc(arena, len);
709 PR_snprintf(outFileName, len, "%s.crl", certNickName);
711 SECU_PrintError(progName, "Will try to generate crl. "
712 "It will be saved in file: %s",
713 outFileName);
715 signCrl = CreateNewCrl(arena, certHandle, cert);
716 if (!signCrl)
717 goto loser;
720 rv = UpdateCrl(signCrl, inCrlInitFile);
721 if (rv != SECSuccess) {
722 goto loser;
725 rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii,
726 slotName, url, pwdata);
727 if (rv != SECSuccess) {
728 goto loser;
731 if (signCrl && !quiet) {
732 SECU_PrintCRLInfo (stdout, &signCrl->crl, "CRL Info:\n", 0);
735 loser:
736 if (arena && (!signCrl || !signCrl->arena))
737 PORT_FreeArena (arena, PR_FALSE);
738 if (signCrl)
739 SEC_DestroyCrl (signCrl);
740 if (cert)
741 CERT_DestroyCertificate (cert);
742 return (rv);
745 static void Usage(char *progName)
747 fprintf(stderr,
748 "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n"
749 " %s -D -n nickname [-d keydir] [-P dbprefix]\n"
750 " %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B] "
751 "[-p pwd-file] -w [pwd-string]\n"
752 " %s -E -t crlType [-d keydir] [-P dbprefix]\n"
753 " %s -T\n"
754 " %s -G|-M -c crl-init-file -n nickname [-i crl] [-u url] "
755 "[-d keydir] [-P dbprefix] [-Z alg] ] [-p pwd-file] -w [pwd-string] "
756 "[-a] [-B]\n",
757 progName, progName, progName, progName, progName, progName);
759 fprintf (stderr, "%-15s List CRL\n", "-L");
760 fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
761 "-n nickname");
762 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
763 "-d keydir");
764 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
765 "-P dbprefix");
767 fprintf (stderr, "%-15s Delete a CRL from the cert database\n", "-D");
768 fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n",
769 "-n nickname");
770 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
771 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
772 "-d keydir");
773 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
774 "-P dbprefix");
776 fprintf (stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E");
777 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
778 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
779 "-d keydir");
780 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
781 "-P dbprefix");
783 fprintf (stderr, "%-15s Import a CRL to the cert database\n", "-I");
784 fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
785 "-i crl");
786 fprintf(stderr, "%-20s Specify the url.\n", "-u url");
787 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
788 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
789 "-d keydir");
790 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
791 "-P dbprefix");
792 #ifdef DEBUG
793 fprintf (stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T");
794 #endif
795 fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " ");
796 fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " ");
797 fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " ");
798 fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
799 fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p");
800 fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>");
801 fprintf(stderr, "\n%-15s Create CRL\n", "-G");
802 fprintf(stderr, "%-15s Modify CRL\n", "-M");
803 fprintf(stderr, "%-20s Specify crl initialization file\n",
804 "-c crl-conf-file");
805 fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
806 "-n nickname");
807 fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
808 "-i crl");
809 fprintf(stderr, "%-20s Specify a CRL output file\n",
810 "-o crl-output-file");
811 fprintf(stderr, "%-20s Specify to use base64 encoded CRL output format\n",
812 "-a");
813 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
814 "-d keydir");
815 fprintf(stderr, "%-20s Provide path to a default pwd file\n",
816 "-f pwd-file");
817 fprintf(stderr, "%-20s Provide db password in command line\n",
818 "-w pwd-string");
819 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
820 "-P dbprefix");
821 fprintf(stderr, "%-20s Specify the url.\n", "-u url");
822 fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
824 exit(-1);
827 int main(int argc, char **argv)
829 SECItem privKeyDER;
830 CERTCertDBHandle *certHandle;
831 FILE *certFile;
832 PRFileDesc *inFile;
833 PRFileDesc *inCrlInitFile = NULL;
834 int generateCRL;
835 int modifyCRL;
836 int listCRL;
837 int importCRL;
838 int deleteCRL;
839 int rv;
840 char *nickName;
841 char *url;
842 char *dbPrefix = "";
843 char *alg = NULL;
844 char *outFile = NULL;
845 char *slotName = NULL;
846 int ascii = 0;
847 int crlType;
848 PLOptState *optstate;
849 PLOptStatus status;
850 SECStatus secstatus;
851 PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS;
852 PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
853 PRBool quiet = PR_FALSE;
854 PRBool test = PR_FALSE;
855 PRBool erase = PR_FALSE;
856 PRInt32 i = 0;
857 PRInt32 iterations = 1;
858 PRBool readonly = PR_FALSE;
860 secuPWData pwdata = { PW_NONE, 0 };
862 progName = strrchr(argv[0], '/');
863 progName = progName ? progName+1 : argv[0];
865 rv = 0;
866 deleteCRL = importCRL = listCRL = generateCRL = modifyCRL = 0;
867 certFile = NULL;
868 inFile = NULL;
869 nickName = url = NULL;
870 privKeyDER.data = NULL;
871 certHandle = NULL;
872 crlType = SEC_CRL_TYPE;
874 * Parse command line arguments
876 optstate = PL_CreateOptState(argc, argv, "sqBCDGILMTEP:f:d:i:h:n:p:t:u:r:aZ:o:c:");
877 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
878 switch (optstate->option) {
879 case '?':
880 Usage(progName);
881 break;
883 case 'T':
884 test = PR_TRUE;
885 break;
887 case 'E':
888 erase = PR_TRUE;
889 break;
891 case 'B':
892 importOptions |= CRL_IMPORT_BYPASS_CHECKS;
893 break;
895 case 'G':
896 generateCRL = 1;
897 break;
899 case 'M':
900 modifyCRL = 1;
901 break;
903 case 'D':
904 deleteCRL = 1;
905 break;
907 case 'I':
908 importCRL = 1;
909 break;
911 case 'C':
912 case 'L':
913 listCRL = 1;
914 break;
916 case 'P':
917 dbPrefix = strdup(optstate->value);
918 break;
920 case 'Z':
921 alg = strdup(optstate->value);
922 break;
924 case 'a':
925 ascii = 1;
926 break;
928 case 'c':
929 inCrlInitFile = PR_Open(optstate->value, PR_RDONLY, 0);
930 if (!inCrlInitFile) {
931 PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
932 progName, optstate->value);
933 PL_DestroyOptState(optstate);
934 return -1;
936 break;
938 case 'd':
939 SECU_ConfigDirectory(optstate->value);
940 break;
942 case 'f':
943 pwdata.source = PW_FROMFILE;
944 pwdata.data = strdup(optstate->value);
945 break;
947 case 'h':
948 slotName = strdup(optstate->value);
949 break;
951 case 'i':
952 inFile = PR_Open(optstate->value, PR_RDONLY, 0);
953 if (!inFile) {
954 PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
955 progName, optstate->value);
956 PL_DestroyOptState(optstate);
957 return -1;
959 break;
961 case 'n':
962 nickName = strdup(optstate->value);
963 break;
965 case 'o':
966 outFile = strdup(optstate->value);
967 break;
969 case 'p':
970 decodeOptions |= CRL_DECODE_SKIP_ENTRIES;
971 break;
973 case 'r': {
974 const char* str = optstate->value;
975 if (str && atoi(str)>0)
976 iterations = atoi(str);
978 break;
980 case 't': {
981 char *type;
983 type = strdup(optstate->value);
984 crlType = atoi (type);
985 if (crlType != SEC_CRL_TYPE && crlType != SEC_KRL_TYPE) {
986 PR_fprintf(PR_STDERR, "%s: invalid crl type\n", progName);
987 PL_DestroyOptState(optstate);
988 return -1;
990 break;
992 case 'q':
993 quiet = PR_TRUE;
994 break;
996 case 'w':
997 pwdata.source = PW_PLAINTEXT;
998 pwdata.data = strdup(optstate->value);
999 break;
1001 case 'u':
1002 url = strdup(optstate->value);
1003 break;
1008 PL_DestroyOptState(optstate);
1010 if (deleteCRL && !nickName) Usage (progName);
1011 if (importCRL && !inFile) Usage (progName);
1012 if ((generateCRL && !nickName) ||
1013 (modifyCRL && !inFile && !nickName)) Usage (progName);
1014 if (!(listCRL || deleteCRL || importCRL || generateCRL ||
1015 modifyCRL || test || erase)) Usage (progName);
1017 if (listCRL) {
1018 readonly = PR_TRUE;
1021 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
1023 PK11_SetPasswordFunc(SECU_GetModulePassword);
1025 secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix,
1026 "secmod.db", readonly ? NSS_INIT_READONLY : 0);
1027 if (secstatus != SECSuccess) {
1028 SECU_PrintPRandOSError(progName);
1029 return -1;
1031 SECU_RegisterDynamicOids();
1033 certHandle = CERT_GetDefaultCertDB();
1034 if (certHandle == NULL) {
1035 SECU_PrintError(progName, "unable to open the cert db");
1036 /*ignoring return value of NSS_Shutdown() as code returns -1*/
1037 (void) NSS_Shutdown();
1038 return (-1);
1041 CRLGEN_InitCrlGenParserLock();
1043 for (i=0; i<iterations; i++) {
1044 /* Read in the private key info */
1045 if (deleteCRL)
1046 DeleteCRL (certHandle, nickName, crlType);
1047 else if (listCRL) {
1048 rv = ListCRL (certHandle, nickName, crlType);
1050 else if (importCRL) {
1051 rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
1052 decodeOptions);
1053 } else if (generateCRL || modifyCRL) {
1054 if (!inCrlInitFile)
1055 inCrlInitFile = PR_STDIN;
1056 rv = GenerateCRL (certHandle, nickName, inCrlInitFile,
1057 inFile, outFile, ascii, slotName,
1058 importOptions, alg, quiet,
1059 decodeOptions, url, &pwdata,
1060 modifyCRL);
1062 else if (erase) {
1063 /* list and delete all CRLs */
1064 ListCRLNames (certHandle, crlType, PR_TRUE);
1066 #ifdef DEBUG
1067 else if (test) {
1068 /* list and delete all CRLs */
1069 ListCRLNames (certHandle, crlType, PR_TRUE);
1070 /* list CRLs */
1071 ListCRLNames (certHandle, crlType, PR_FALSE);
1072 /* import CRL as a blob */
1073 rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
1074 decodeOptions);
1075 /* list CRLs */
1076 ListCRLNames (certHandle, crlType, PR_FALSE);
1078 #endif
1081 CRLGEN_DestroyCrlGenParserLock();
1083 if (NSS_Shutdown() != SECSuccess) {
1084 rv = SECFailure;
1087 return (rv != SECSuccess);