security/nss/cmd/crlutil/crlutil.c

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6 ** certutil.c
     7 **
     8 ** utility for managing certificates and the cert database
     9 **
    10 */
    11 /* test only */
    13 #include "nspr.h"
    14 #include "plgetopt.h"
    15 #include "secutil.h"
    16 #include "cert.h"
    17 #include "certi.h"
    18 #include "certdb.h"
    19 #include "nss.h"
    20 #include "pk11func.h"
    21 #include "crlgen.h"
    23 #define SEC_CERT_DB_EXISTS 0
    24 #define SEC_CREATE_CERT_DB 1
    26 static char *progName;
    28 static CERTSignedCrl *FindCRL
    29    (CERTCertDBHandle *certHandle, char *name, int type)
    30 {
    31     CERTSignedCrl *crl = NULL;    
    32     CERTCertificate *cert = NULL;
    33     SECItem derName;
    35     derName.data = NULL;
    36     derName.len = 0;
    38     cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name);
    39     if (!cert) {
    40         CERTName *certName = NULL;
    41         PLArenaPool *arena = NULL;
    43         certName = CERT_AsciiToName(name);
    44         if (certName) {
    45             arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    46             if (arena) {
    47                 SECItem *nameItem = 
    48                     SEC_ASN1EncodeItem (arena, NULL, (void *)certName,
    49                                         SEC_ASN1_GET(CERT_NameTemplate));
    50                 if (nameItem) {
    51                     SECITEM_CopyItem(NULL, &derName, nameItem);
    52                 }
    53                 PORT_FreeArena(arena, PR_FALSE);
    54             }
    55             CERT_DestroyName(certName);
    56         }
    58         if (!derName.len || !derName.data) {
    59             SECU_PrintError(progName, "could not find certificate named '%s'", name);
    60             return ((CERTSignedCrl *)NULL);
    61         }
    62     } else {
    63         SECITEM_CopyItem(NULL, &derName, &cert->derSubject);
    64         CERT_DestroyCertificate (cert);
    65     }
    67     crl = SEC_FindCrlByName(certHandle, &derName, type);
    68     if (crl ==NULL) 
    69 	SECU_PrintError
    70 		(progName, "could not find %s's CRL", name);
    71     if (derName.data) {
    72         SECITEM_FreeItem(&derName, PR_FALSE);
    73     }
    74     return (crl);
    75 }
    77 static SECStatus DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
    78 {
    79     CERTSignedCrl *crl = NULL;
    81     crl = FindCRL (certHandle, nickName, crlType);
    83     if (crl) {
    84 	SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0);
    85 	SEC_DestroyCrl (crl);
    86 	return SECSuccess;
    87     }
    88     return SECFailure;
    89 }
    91 static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
    92 {
    93     CERTCrlHeadNode *crlList = NULL;
    94     CERTCrlNode *crlNode = NULL;
    95     CERTName *name = NULL;
    96     PLArenaPool *arena = NULL;
    97     SECStatus rv;
    99     do {
   100 	arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
   101 	if (arena == NULL) {
   102 	    fprintf(stderr, "%s: fail to allocate memory\n", progName);
   103 	    break;
   104 	}
   106 	name = PORT_ArenaZAlloc (arena, sizeof(*name));
   107 	if (name == NULL) {
   108 	    fprintf(stderr, "%s: fail to allocate memory\n", progName);
   109 	    break;
   110 	}
   111 	name->arena = arena;
   113 	rv = SEC_LookupCrls (certHandle, &crlList, crlType);
   114 	if (rv != SECSuccess) {
   115 	    fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName,
   116 	    SECU_Strerror(PORT_GetError()));
   117 	    break;
   118 	}
   120 	/* just in case */
   121 	if (!crlList)
   122 	    break;
   124 	crlNode  = crlList->first;
   126         fprintf (stdout, "\n");
   127 	fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
   128 	while (crlNode) {
   129 	    char* asciiname = NULL;
   130 	    CERTCertificate *cert = NULL;
   131 	    if (crlNode->crl && &crlNode->crl->crl.derName) {
   132 	        cert = CERT_FindCertByName(certHandle,
   133 	                                   &crlNode->crl->crl.derName);
   134 	        if (!cert) {
   135 	            SECU_PrintError(progName, "could not find signing "
   136 	                         "certificate in database");
   137 	        }
   138 	    }
   139 	    if (cert) {
   140 	        char* certName = NULL;
   141                  if (cert->nickname && PORT_Strlen(cert->nickname) > 0) {
   142 	            certName = cert->nickname;
   143 	        } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) {
   144 	            certName = cert->emailAddr;
   145 	        }
   146 	        if (certName) {
   147 	            asciiname = PORT_Strdup(certName);
   148 	        }
   149 	        CERT_DestroyCertificate(cert);
   150 	    }
   152 	    if (!asciiname) {
   153 	        name = &crlNode->crl->crl.name;
   154 	        if (!name){
   155 	            SECU_PrintError(progName, "fail to get the CRL "
   156 	                           "issuer name");
   157 	            continue;
   158 	        }
   159 	        asciiname = CERT_NameToAscii(name);
   160 	    }
   161 	    fprintf (stdout, "%-40s %-5s\n", asciiname, "CRL");
   162 	    if (asciiname) {
   163 		PORT_Free(asciiname);
   164 	    }
   165             if ( PR_TRUE == deletecrls) {
   166                 CERTSignedCrl* acrl = NULL;
   167                 SECItem* issuer = &crlNode->crl->crl.derName;
   168                 acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
   169                 if (acrl)
   170                 {
   171                     SEC_DeletePermCRL(acrl);
   172                     SEC_DestroyCrl(acrl);
   173                 }
   174             }
   175             crlNode = crlNode->next;
   176 	} 
   178     } while (0);
   179     if (crlList)
   180 	PORT_FreeArena (crlList->arena, PR_FALSE);
   181     PORT_FreeArena (arena, PR_FALSE);
   182 }
   184 static SECStatus ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
   185 {
   186     if (nickName == NULL) {
   187 	ListCRLNames (certHandle, crlType, PR_FALSE);
   188 	return SECSuccess;
   189     } 
   191     return DisplayCRL (certHandle, nickName, crlType);
   192 }
   196 static SECStatus DeleteCRL (CERTCertDBHandle *certHandle, char *name, int type)
   197 {
   198     CERTSignedCrl *crl = NULL;    
   199     SECStatus rv = SECFailure;
   201     crl = FindCRL (certHandle, name, type);
   202     if (!crl) {
   203 	SECU_PrintError
   204 		(progName, "could not find the issuer %s's CRL", name);
   205 	return SECFailure;
   206     }
   207     rv = SEC_DeletePermCRL (crl);
   208     SEC_DestroyCrl(crl);
   209     if (rv != SECSuccess) {
   210 	SECU_PrintError(progName, "fail to delete the issuer %s's CRL "
   211 	                "from the perm database (reason: %s)",
   212 	                name, SECU_Strerror(PORT_GetError()));
   213 	return SECFailure;
   214     }
   215     return (rv);
   216 }
   218 SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, 
   219                      PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions,
   220                      secuPWData *pwdata)
   221 {
   222     CERTSignedCrl *crl = NULL;
   223     SECItem crlDER;
   224     PK11SlotInfo* slot = NULL;
   225     int rv;
   226 #if defined(DEBUG_jp96085)
   227     PRIntervalTime starttime, endtime, elapsed;
   228     PRUint32 mins, secs, msecs;
   229 #endif
   231     crlDER.data = NULL;
   234     /* Read in the entire file specified with the -f argument */
   235     rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
   236     if (rv != SECSuccess) {
   237 	SECU_PrintError(progName, "unable to read input file");
   238 	return (SECFailure);
   239     }
   241     decodeOptions |= CRL_DECODE_DONT_COPY_DER;
   243     slot = PK11_GetInternalKeySlot();
   245     if (PK11_NeedLogin(slot)) {
   246 	rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   247     if (rv != SECSuccess)
   248 	goto loser;
   249     }
   251 #if defined(DEBUG_jp96085)
   252     starttime = PR_IntervalNow();
   253 #endif
   254     crl = PK11_ImportCRL(slot, &crlDER, url, type,
   255           NULL, importOptions, NULL, decodeOptions);
   256 #if defined(DEBUG_jp96085)
   257     endtime = PR_IntervalNow();
   258     elapsed = endtime - starttime;
   259     mins = PR_IntervalToSeconds(elapsed) / 60;
   260     secs = PR_IntervalToSeconds(elapsed) % 60;
   261     msecs = PR_IntervalToMilliseconds(elapsed) % 1000;
   262     printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs);
   263 #endif
   264     if (!crl) {
   265 	const char *errString;
   267 	rv = SECFailure;
   268 	errString = SECU_Strerror(PORT_GetError());
   269 	if ( errString && PORT_Strlen (errString) == 0)
   270 	    SECU_PrintError (progName, 
   271 	        "CRL is not imported (error: input CRL is not up to date.)");
   272 	else    
   273 	    SECU_PrintError (progName, "unable to import CRL");
   274     } else {
   275 	SEC_DestroyCrl (crl);
   276     }
   277   loser:
   278     if (slot) {
   279         PK11_FreeSlot(slot);
   280     }
   281     return (rv);
   282 }
   284 SECStatus DumpCRL(PRFileDesc *inFile)
   285 {
   286     int rv;
   287     PLArenaPool *arena = NULL;
   288     CERTSignedCrl *newCrl = NULL;
   290     SECItem crlDER;
   291     crlDER.data = NULL;
   293     /* Read in the entire file specified with the -f argument */
   294     rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
   295     if (rv != SECSuccess) {
   296 	SECU_PrintError(progName, "unable to read input file");
   297 	return (SECFailure);
   298     }
   300     rv = SEC_ERROR_NO_MEMORY;
   301     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   302     if (!arena)
   303     	return rv;
   305     newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE,
   306 					CRL_DECODE_DEFAULT_OPTIONS);
   307     if (!newCrl)
   308     	return SECFailure;
   310     SECU_PrintCRLInfo (stdout, &newCrl->crl, "CRL file contents", 0);
   312     PORT_FreeArena (arena, PR_FALSE);
   313     return rv;
   314 }
   316 static CERTCertificate*
   317 FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl,
   318                 char *certNickName)
   319 {                   
   320     CERTCertificate *cert = NULL, *certTemp = NULL;
   321     SECStatus rv = SECFailure;
   322     CERTAuthKeyID* authorityKeyID = NULL;
   323     SECItem* subject = NULL;
   325     PORT_Assert(certHandle != NULL);
   326     if (!certHandle || (!signCrl && !certNickName)) {
   327         SECU_PrintError(progName, "invalid args for function "
   328                         "FindSigningCert \n");
   329         return NULL;
   330     }
   332     if (signCrl) {
   333 #if 0
   334         authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl);
   335 #endif
   336         subject = &signCrl->crl.derName;
   337     } else {
   338         certTemp = CERT_FindCertByNickname(certHandle, certNickName);
   339         if (!certTemp) {
   340             SECU_PrintError(progName, "could not find certificate \"%s\" "
   341                             "in database", certNickName);
   342             goto loser;
   343         }
   344         subject = &certTemp->derSubject;
   345     }
   347     cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now());
   348     if (!cert) {
   349         SECU_PrintError(progName, "could not find signing certificate "
   350                         "in database");
   351         goto loser;
   352     } else {
   353         rv = SECSuccess;
   354     }
   356   loser:
   357     if (certTemp)
   358         CERT_DestroyCertificate(certTemp);
   359     if (cert && rv != SECSuccess)
   360         CERT_DestroyCertificate(cert);
   361     return cert;
   362 }
   364 static CERTSignedCrl*
   365 CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle,
   366                 CERTCertificate **cert, char *certNickName,
   367                 PRFileDesc *inFile, PRInt32 decodeOptions,
   368                 PRInt32 importOptions)
   369 {
   370     SECItem crlDER = {0, NULL, 0};
   371     CERTSignedCrl *signCrl = NULL;
   372     CERTSignedCrl *modCrl = NULL;
   373     PLArenaPool *modArena = NULL;
   374     SECStatus rv = SECSuccess;
   376     if (!arena || !certHandle || !certNickName) {
   377         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   378         SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n");
   379         return NULL;
   380     }
   382     modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   383     if (!modArena) {
   384         SECU_PrintError(progName, "fail to allocate memory\n");
   385         return NULL;
   386     }
   388     if (inFile != NULL) {
   389         rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
   390         if (rv != SECSuccess) {
   391             SECU_PrintError(progName, "unable to read input file");
   392             PORT_FreeArena(modArena, PR_FALSE);
   393             goto loser;
   394         }
   396         decodeOptions |= CRL_DECODE_DONT_COPY_DER;
   398         modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE,
   399                                             decodeOptions);
   400         if (!modCrl) {
   401             SECU_PrintError(progName, "fail to decode CRL");
   402             goto loser;
   403         }
   405         if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){
   406             /* If caCert is a v2 certificate, make sure that it
   407              * can be used for crl signing purpose */
   408             *cert = FindSigningCert(certHandle, modCrl, NULL);
   409             if (!*cert) {
   410                 goto loser;
   411             }
   413             rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
   414                                        PR_Now(), NULL);
   415             if (rv != SECSuccess) {
   416                 SECU_PrintError(progName, "fail to verify signed data\n");
   417                 goto loser;
   418             }
   419         }
   420     } else {
   421         modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE);
   422         if (!modCrl) {
   423             SECU_PrintError(progName, "fail to find crl %s in database\n",
   424                             certNickName);
   425             goto loser;
   426         }
   427     }
   429     signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
   430     if (signCrl == NULL) {
   431         SECU_PrintError(progName, "fail to allocate memory\n");
   432         goto loser;
   433     }
   435     rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl);
   436     if (rv != SECSuccess) {
   437         SECU_PrintError(progName, "unable to dublicate crl for "
   438                         "modification.");
   439         goto loser;
   440     }  
   442     /* Make sure the update time is current. It can be modified later
   443      * by "update <time>" command from crl generation script */
   444     rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
   445     if (rv != SECSuccess) {
   446         SECU_PrintError(progName, "fail to encode current time\n");
   447         goto loser;
   448     }
   450     signCrl->arena = arena;
   452   loser:
   453     if (crlDER.data) {
   454         SECITEM_FreeItem(&crlDER, PR_FALSE);
   455     }
   456     if (modCrl)
   457         SEC_DestroyCrl(modCrl);
   458     if (rv != SECSuccess && signCrl) {
   459         SEC_DestroyCrl(signCrl);
   460         signCrl = NULL;
   461     }
   462     return signCrl;
   463 }
   466 static CERTSignedCrl*
   467 CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle,
   468              CERTCertificate *cert)
   469 { 
   470     CERTSignedCrl *signCrl = NULL;
   471     void *dummy = NULL;
   472     SECStatus rv;
   473     void* mark = NULL;
   475     /* if the CERTSignedCrl structure changes, this function will need to be
   476        updated as well */
   477     if (!cert || !arena) {
   478         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   479         SECU_PrintError(progName, "invalid args for function "
   480                         "CreateNewCrl\n");
   481         return NULL;
   482     }
   484     mark = PORT_ArenaMark(arena);
   486     signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
   487     if (signCrl == NULL) {
   488         SECU_PrintError(progName, "fail to allocate memory\n");
   489         return NULL;
   490     }
   492     dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version,
   493                                   SEC_CRL_VERSION_2);
   494     /* set crl->version */
   495     if (!dummy) {
   496         SECU_PrintError(progName, "fail to create crl version data "
   497                         "container\n");
   498         goto loser;
   499     }
   501     /* copy SECItem name from cert */
   502     rv = SECITEM_CopyItem(arena, &signCrl->crl.derName, &cert->derSubject);
   503     if (rv != SECSuccess) {
   504         SECU_PrintError(progName, "fail to duplicate der name from "
   505                         "certificate.\n");
   506         goto loser;
   507     }
   509     /* copy CERTName name structure from cert issuer */
   510     rv = CERT_CopyName (arena, &signCrl->crl.name, &cert->subject);
   511     if (rv != SECSuccess) {
   512         SECU_PrintError(progName, "fail to duplicate RD name from "
   513                         "certificate.\n");
   514         goto loser;
   515     }
   517     rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
   518     if (rv != SECSuccess) {
   519         SECU_PrintError(progName, "fail to encode current time\n");
   520         goto loser;
   521     }
   523     /* set fields */
   524     signCrl->arena = arena;
   525     signCrl->dbhandle = certHandle;
   526     signCrl->crl.arena = arena;
   528     return signCrl;
   530   loser:
   531     PORT_ArenaRelease(arena, mark);
   532     return NULL;
   533 }
   536 static SECStatus
   537 UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile)
   538 {
   539     CRLGENGeneratorData *crlGenData = NULL;
   540     SECStatus rv;
   542     if (!signCrl || !inCrlInitFile) {
   543         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   544         SECU_PrintError(progName, "invalid args for function "
   545                         "CreateNewCrl\n");
   546         return SECFailure;
   547     }
   549     crlGenData = CRLGEN_InitCrlGeneration(signCrl, inCrlInitFile);
   550     if (!crlGenData) {
   551 	SECU_PrintError(progName, "can not initialize parser structure.\n");
   552 	return SECFailure;
   553     }
   555     rv = CRLGEN_ExtHandleInit(crlGenData);
   556     if (rv == SECFailure) {
   557 	SECU_PrintError(progName, "can not initialize entries handle.\n");
   558 	goto loser;
   559     }
   561     rv = CRLGEN_StartCrlGen(crlGenData);
   562     if (rv != SECSuccess) {
   563 	SECU_PrintError(progName, "crl generation failed");
   564 	goto loser;
   565     }
   567   loser:
   568     /* CommitExtensionsAndEntries is partially responsible for freeing
   569      * up memory that was used for CRL generation. Should be called regardless
   570      * of previouse call status, but only after initialization of
   571      * crlGenData was done. It will commit all changes that was done before
   572      * an error has occurred.
   573      */
   574     if (SECSuccess != CRLGEN_CommitExtensionsAndEntries(crlGenData)) {
   575         SECU_PrintError(progName, "crl generation failed");
   576         rv = SECFailure;
   577     }
   578     CRLGEN_FinalizeCrlGeneration(crlGenData);    
   579     return rv;
   580 }
   582 static SECStatus
   583 SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert,
   584                 char *outFileName, SECOidTag hashAlgTag, int ascii,
   585                 char *slotName, char *url, secuPWData *pwdata)
   586 {
   587     PK11SlotInfo *slot = NULL;
   588     PRFileDesc   *outFile = NULL;
   589     SECStatus rv;
   590     SignAndEncodeFuncExitStat errCode;
   592     PORT_Assert(signCrl && (!ascii || outFileName));
   593     if (!signCrl || (ascii && !outFileName)) {
   594         SECU_PrintError(progName, "invalid args for function "
   595                         "SignAndStoreCrl\n");
   596         return SECFailure;
   597     }
   599     if (!slotName || !PL_strcmp(slotName, "internal"))
   600 	slot = PK11_GetInternalKeySlot();
   601     else
   602 	slot = PK11_FindSlotByName(slotName);
   603     if (!slot) {
   604 	SECU_PrintError(progName, "can not find requested slot");
   605 	return SECFailure;
   606     }
   608     if (PK11_NeedLogin(slot)) {
   609         rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
   610 	if (rv != SECSuccess)
   611 	    goto loser;
   612     }
   614     rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode);
   615     if (rv != SECSuccess) {
   616         char* errMsg = NULL;
   617         switch (errCode)
   618         {
   619             case noKeyFound:
   620                 errMsg = "No private key found of signing cert";
   621                 break;
   623             case noSignatureMatch:
   624                 errMsg = "Key and Algorithm OId are do not match";
   625                 break;
   627             default:
   628             case failToEncode:
   629                 errMsg = "Failed to encode crl structure";
   630                 break;
   632             case failToSign:
   633                 errMsg = "Failed to sign crl structure";
   634                 break;
   636             case noMem:
   637                 errMsg = "Can not allocate memory";
   638                 break;
   639         }
   640 	SECU_PrintError(progName, "%s\n", errMsg);
   641 	goto loser;
   642     }
   644     if (outFileName) {
   645 	outFile = PR_Open(outFileName, PR_WRONLY|PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
   646 	if (!outFile) {
   647 	    SECU_PrintError(progName, "unable to open \"%s\" for writing\n",
   648 			    outFileName);
   649 	    goto loser;
   650 	}
   651     }
   653     rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url);
   654     if (rv != SECSuccess) {
   655         SECU_PrintError(progName, "fail to save CRL\n");
   656     }
   658   loser:
   659     if (outFile)
   660 	PR_Close(outFile);
   661     if (slot)
   662 	PK11_FreeSlot(slot);
   663     return rv;
   664 }
   666 static SECStatus
   667 GenerateCRL (CERTCertDBHandle *certHandle, char *certNickName, 
   668 	     PRFileDesc *inCrlInitFile,  PRFileDesc *inFile,
   669 	     char *outFileName, int ascii, char *slotName,
   670 	     PRInt32 importOptions, char *alg, PRBool quiet,
   671              PRInt32 decodeOptions, char *url, secuPWData *pwdata,
   672              int modifyFlag)
   673 {
   674     CERTCertificate *cert = NULL;
   675     CERTSignedCrl *signCrl = NULL;
   676     PLArenaPool *arena = NULL;
   677     SECStatus rv;
   678     SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
   680     if (alg) {
   681         hashAlgTag = SECU_StringToSignatureAlgTag(alg);
   682         if (hashAlgTag == SEC_OID_UNKNOWN) {
   683             SECU_PrintError(progName, "%s -Z:  %s is not a recognized type.\n",
   684                             progName, alg);
   685             return SECFailure;
   686         }
   687     } else {
   688         hashAlgTag = SEC_OID_UNKNOWN;
   689     }
   691     arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
   692     if (!arena) {
   693         SECU_PrintError(progName, "fail to allocate memory\n");
   694         return SECFailure;
   695     }
   697     if (modifyFlag == PR_TRUE) {
   698         signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName,
   699                                          inFile, decodeOptions, importOptions);
   700         if (signCrl == NULL) {
   701             goto loser;
   702         }
   703     }
   705     if (!cert) {
   706         cert = FindSigningCert(certHandle, signCrl, certNickName);
   707         if (cert == NULL) {
   708             goto loser;
   709         }
   710     }
   712     if (!signCrl) {
   713         if (modifyFlag == PR_TRUE) {
   714             if (!outFileName) {
   715                 int len = strlen(certNickName) + 5;
   716                 outFileName = PORT_ArenaAlloc(arena, len);
   717                 PR_snprintf(outFileName, len, "%s.crl", certNickName);
   718             }
   719             SECU_PrintError(progName, "Will try to generate crl. "
   720                             "It will be saved in file: %s",
   721                             outFileName);
   722         }
   723         signCrl = CreateNewCrl(arena, certHandle, cert);
   724         if (!signCrl)
   725             goto loser;
   726     }
   728     rv = UpdateCrl(signCrl, inCrlInitFile);
   729     if (rv != SECSuccess) {
   730         goto loser;
   731     }
   733     rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii,
   734                          slotName, url, pwdata);
   735     if (rv != SECSuccess) {
   736         goto loser;
   737     }
   739     if (signCrl && !quiet) {
   740 	SECU_PrintCRLInfo (stdout, &signCrl->crl, "CRL Info:\n", 0);
   741     }
   743   loser:
   744     if (arena && (!signCrl || !signCrl->arena))
   745         PORT_FreeArena (arena, PR_FALSE);
   746     if (signCrl)
   747 	SEC_DestroyCrl (signCrl);
   748     if (cert)
   749 	CERT_DestroyCertificate (cert);
   750     return (rv);
   751 }
   753 static void Usage(char *progName)
   754 {
   755     fprintf(stderr,
   756 	    "Usage:  %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n"
   757 	    "        %s -D -n nickname [-d keydir] [-P dbprefix]\n"
   758 	    "        %s -S -i crl\n"
   759 	    "        %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B] "
   760             "[-p pwd-file] -w [pwd-string]\n"
   761 	    "        %s -E -t crlType [-d keydir] [-P dbprefix]\n"
   762 	    "        %s -T\n"
   763 	    "        %s -G|-M -c crl-init-file -n nickname [-i crl] [-u url] "
   764             "[-d keydir] [-P dbprefix] [-Z alg] ] [-p pwd-file] -w [pwd-string] "
   765             "[-a] [-B]\n",
   766 	    progName, progName, progName, progName, progName, progName, progName);
   768     fprintf (stderr, "%-15s List CRL\n", "-L");
   769     fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
   770 	    "-n nickname");
   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 Delete a CRL from the cert database\n", "-D");    
   777     fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n",
   778 	    "-n nickname");
   779     fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
   780     fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
   781 	    "-d keydir");
   782     fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
   783 	    "-P dbprefix");
   785     fprintf (stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E");
   786     fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
   787     fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
   788 	    "-d keydir");
   789     fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
   790 	    "-P dbprefix");
   792     fprintf (stderr, "%-15s Show contents of a CRL file (without database)\n", "-S");
   793     fprintf(stderr, "%-20s Specify the file which contains the CRL to show\n",
   794 	    "-i crl");
   796     fprintf (stderr, "%-15s Import a CRL to the cert database\n", "-I");    
   797     fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
   798 	    "-i crl");
   799     fprintf(stderr, "%-20s Specify the url.\n", "-u url");
   800     fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
   801     fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
   802 	    "-d keydir");
   803     fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
   804 	    "-P dbprefix");
   805 #ifdef DEBUG
   806     fprintf (stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T");
   807 #endif
   808     fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " ");
   809     fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " ");
   810     fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " ");        
   811     fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
   812     fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p");
   813     fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>");
   814     fprintf(stderr, "\n%-15s Create CRL\n", "-G");
   815     fprintf(stderr, "%-15s Modify CRL\n", "-M");
   816     fprintf(stderr, "%-20s Specify crl initialization file\n",
   817 	    "-c crl-conf-file");
   818     fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
   819 	    "-n nickname");
   820     fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
   821 	    "-i crl");
   822     fprintf(stderr, "%-20s Specify a CRL output file\n",
   823 	    "-o crl-output-file");
   824     fprintf(stderr, "%-20s Specify to use base64 encoded CRL output format\n",
   825 	    "-a");
   826     fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
   827 	    "-d keydir");
   828     fprintf(stderr, "%-20s Provide path to a default pwd file\n",
   829 	    "-f pwd-file");
   830     fprintf(stderr, "%-20s Provide db password in command line\n",
   831 	    "-w pwd-string");
   832     fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
   833 	    "-P dbprefix");
   834     fprintf(stderr, "%-20s Specify the url.\n", "-u url");
   835     fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
   837     exit(-1);
   838 }
   840 int main(int argc, char **argv)
   841 {
   842     CERTCertDBHandle *certHandle;
   843     PRFileDesc *inFile;
   844     PRFileDesc *inCrlInitFile = NULL;
   845     int generateCRL;
   846     int modifyCRL;
   847     int listCRL;
   848     int importCRL;
   849     int showFileCRL;
   850     int deleteCRL;
   851     int rv;
   852     char *nickName;
   853     char *url;
   854     char *dbPrefix = "";
   855     char *alg = NULL;
   856     char *outFile = NULL;
   857     char *slotName = NULL;
   858     int ascii = 0;
   859     int crlType;
   860     PLOptState *optstate;
   861     PLOptStatus status;
   862     SECStatus secstatus;
   863     PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS;
   864     PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
   865     PRBool quiet = PR_FALSE;
   866     PRBool test = PR_FALSE;
   867     PRBool erase = PR_FALSE;
   868     PRInt32 i = 0;
   869     PRInt32 iterations = 1;
   870     PRBool readonly = PR_FALSE;
   872     secuPWData  pwdata          = { PW_NONE, 0 };
   874     progName = strrchr(argv[0], '/');
   875     progName = progName ? progName+1 : argv[0];
   877     rv = 0;
   878     deleteCRL = importCRL = listCRL = generateCRL = modifyCRL = showFileCRL = 0;
   879     inFile = NULL;
   880     nickName = url = NULL;
   881     certHandle = NULL;
   882     crlType = SEC_CRL_TYPE;
   883     /*
   884      * Parse command line arguments
   885      */
   886     optstate = PL_CreateOptState(argc, argv, "sqBCDGILMSTEP:f:d:i:h:n:p:t:u:r:aZ:o:c:");
   887     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   888 	switch (optstate->option) {
   889 	  case '?':
   890 	    Usage(progName);
   891 	    break;
   893           case 'T':
   894             test = PR_TRUE;
   895             break;
   897           case 'E':
   898             erase = PR_TRUE;
   899             break;
   901 	  case 'B':
   902             importOptions |= CRL_IMPORT_BYPASS_CHECKS;
   903             break;
   905 	  case 'G':
   906 	    generateCRL = 1;
   907 	    break;
   909           case 'M':
   910             modifyCRL = 1;
   911             break;
   913 	  case 'D':
   914 	      deleteCRL = 1;
   915 	      break;
   917 	  case 'I':
   918 	      importCRL = 1;
   919 	      break;
   921 	  case 'S':
   922 	      showFileCRL = 1;
   923 	      break;
   925 	  case 'C':
   926 	  case 'L':
   927 	      listCRL = 1;
   928 	      break;
   930 	  case 'P':
   931  	    dbPrefix = strdup(optstate->value);
   932  	    break;
   934 	  case 'Z':
   935               alg = strdup(optstate->value);
   936               break;
   938 	  case 'a':
   939 	      ascii = 1;
   940 	      break;
   942 	  case 'c':
   943               inCrlInitFile = PR_Open(optstate->value, PR_RDONLY, 0);
   944               if (!inCrlInitFile) {
   945                   PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
   946                              progName, optstate->value);
   947                   PL_DestroyOptState(optstate);
   948                   return -1;
   949               }
   950               break;
   952 	  case 'd':
   953               SECU_ConfigDirectory(optstate->value);
   954               break;
   956 	  case 'f':
   957 	      pwdata.source = PW_FROMFILE;
   958 	      pwdata.data = strdup(optstate->value);
   959 	      break;
   961 	  case 'h':
   962               slotName = strdup(optstate->value);
   963               break;
   965 	  case 'i':
   966 	    inFile = PR_Open(optstate->value, PR_RDONLY, 0);
   967 	    if (!inFile) {
   968 		PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n",
   969 			progName, optstate->value);
   970 		PL_DestroyOptState(optstate);
   971 		return -1;
   972 	    }
   973 	    break;
   975 	  case 'n':
   976 	    nickName = strdup(optstate->value);
   977 	    break;
   979 	  case 'o':
   980 	    outFile = strdup(optstate->value);
   981 	    break;
   983 	  case 'p':
   984 	    decodeOptions |= CRL_DECODE_SKIP_ENTRIES;
   985 	    break;
   987 	  case 'r': {
   988 	    const char* str = optstate->value;
   989 	    if (str && atoi(str)>0)
   990 		iterations = atoi(str);
   991 	    }
   992 	    break;
   994 	  case 't': {
   995 	    crlType = atoi(optstate->value);
   996 	    if (crlType != SEC_CRL_TYPE && crlType != SEC_KRL_TYPE) {
   997 		PR_fprintf(PR_STDERR, "%s: invalid crl type\n", progName);
   998 		PL_DestroyOptState(optstate);
   999 		return -1;
  1001 	    break;
  1003 	  case 'q':
  1004             quiet = PR_TRUE;
  1005 	    break;
  1007 	  case 'w':
  1008 	      pwdata.source = PW_PLAINTEXT;
  1009 	      pwdata.data = strdup(optstate->value);
  1010 	      break;
  1012 	  case 'u':
  1013 	    url = strdup(optstate->value);
  1014 	    break;
  1019     PL_DestroyOptState(optstate);
  1021     if (deleteCRL && !nickName) Usage (progName);
  1022     if (importCRL && !inFile) Usage (progName);
  1023     if (showFileCRL && !inFile) Usage (progName);
  1024     if ((generateCRL && !nickName) ||
  1025         (modifyCRL && !inFile && !nickName)) Usage (progName);
  1026     if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL ||
  1027 	  modifyCRL || test || erase)) Usage (progName);
  1029     if (listCRL || showFileCRL) {
  1030         readonly = PR_TRUE;
  1033     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  1035     PK11_SetPasswordFunc(SECU_GetModulePassword);
  1037     if (showFileCRL) {
  1038 	NSS_NoDB_Init(NULL);
  1040     else {
  1041 	secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix,
  1042 				"secmod.db", readonly ? NSS_INIT_READONLY : 0);
  1043 	if (secstatus != SECSuccess) {
  1044 	    SECU_PrintPRandOSError(progName);
  1045 	    return -1;
  1049     SECU_RegisterDynamicOids();
  1051     certHandle = CERT_GetDefaultCertDB();
  1052     if (certHandle == NULL) {
  1053 	SECU_PrintError(progName, "unable to open the cert db");	    	
  1054 	/*ignoring return value of NSS_Shutdown() as code returns -1*/
  1055 	(void) NSS_Shutdown();
  1056 	return (-1);
  1059     CRLGEN_InitCrlGenParserLock();
  1061     for (i=0; i<iterations; i++) {
  1062 	/* Read in the private key info */
  1063 	if (deleteCRL) 
  1064 	    DeleteCRL (certHandle, nickName, crlType);
  1065 	else if (listCRL) {
  1066 	    rv = ListCRL (certHandle, nickName, crlType);
  1068 	else if (importCRL) {
  1069 	    rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
  1070 			    decodeOptions, &pwdata);
  1072 	else if (showFileCRL) {
  1073 	    rv = DumpCRL (inFile);
  1074 	} else if (generateCRL || modifyCRL) {
  1075 	    if (!inCrlInitFile)
  1076 		inCrlInitFile = PR_STDIN;
  1077 	    rv = GenerateCRL (certHandle, nickName, inCrlInitFile,
  1078 			      inFile, outFile, ascii,  slotName,
  1079 			      importOptions, alg, quiet,
  1080 			      decodeOptions, url, &pwdata,
  1081 			      modifyCRL);
  1083 	else if (erase) {
  1084 	    /* list and delete all CRLs */
  1085 	    ListCRLNames (certHandle, crlType, PR_TRUE);
  1087 #ifdef DEBUG
  1088 	else if (test) {
  1089 	    /* list and delete all CRLs */
  1090 	    ListCRLNames (certHandle, crlType, PR_TRUE);
  1091 	    /* list CRLs */
  1092 	    ListCRLNames (certHandle, crlType, PR_FALSE);
  1093 	    /* import CRL as a blob */
  1094 	    rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
  1095 			    decodeOptions, &pwdata);
  1096 	    /* list CRLs */
  1097 	    ListCRLNames (certHandle, crlType, PR_FALSE);
  1099 #endif    
  1102     CRLGEN_DestroyCrlGenParserLock();
  1104     if (NSS_Shutdown() != SECSuccess) {
  1105         rv = SECFailure;
  1108     return (rv != SECSuccess);

mercurial