#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <utilLib/common.h>
#include <clAppUtils/clutils.h>
#include <clAppUtils/CertParser.h>
#include <Security/Security.h>
#include "crlNetwork.h"
#include <security_cdsa_utils/cuPrintCert.h>
#define LOOPS_DEF 100
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" -c certFile -- obtain CRL via net from this cert\n");
printf(" -C crlFile -- CRL from this file\n");
printf(" -p -- parse the CRL\n");
printf(" -o outFile -- write the fetched CRL to this file\n");
printf(" -v -- verbose CRL dump\n");
exit(1);
}
static int fetchCrlViaGeneralNames(
const CE_GeneralNames *names,
unsigned char **crl, size_t *crlLen) {
CSSM_DATA crlData = {0, NULL};
CSSM_RETURN crtn;
for(unsigned nameDex=0; nameDex<names->numNames; nameDex++) {
CE_GeneralName *name = &names->generalName[nameDex];
switch(name->nameType) {
case GNT_URI:
if(name->name.Length < 5) {
continue;
}
if(strncmp((char *)name->name.Data, "ldap:", 5) &&
strncmp((char *)name->name.Data, "http:", 5) &&
strncmp((char *)name->name.Data, "https:", 6)) {
continue;
}
crtn = crlNetFetch(&name->name, LT_Crl, &crlData);
if(crtn) {
printf("...net fetch error\n");
return 1;
}
*crl = crlData.Data;
*crlLen = crlData.Length;
return 0;
default:
printf("fetchCrlViaGeneralNames: unknown"
"nameType (%u)", (unsigned)name->nameType);
break;
}
}
printf("...GNT_URI name not found in GeneralNames\n");
return 1;
}
static int fetchCrl(
CertParser &cert,
unsigned char **crl, size_t *crlLen) {
CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)
cert.extensionForOid(CSSMOID_CrlDistributionPoints);
*crl = NULL;
*crlLen = 0;
if(dps == NULL) {
printf("***No CrlDistributionPoints in this cert.\n");
return 0;
}
for(unsigned dex=0; dex<dps->numDistPoints; dex++) {
CE_CRLDistributionPoint *dp = &dps->distPoints[dex];
if(dp->distPointName == NULL) {
continue;
}
switch(dp->distPointName->nameType) {
case CE_CDNT_NameRelativeToCrlIssuer:
printf("...CE_CDNT_NameRelativeToCrlIssuer not implemented\n");
break;
case CE_CDNT_FullName:
{
CE_GeneralNames *names = dp->distPointName->dpn.fullName;
int rtn = fetchCrlViaGeneralNames(names, crl, crlLen);
if(rtn == 0) {
return 0;
}
break;
}
default:
printf("unknown distPointName->nameType (%u)\n",
(unsigned)dp->distPointName->nameType);
break;
}
}
printf("...CrlDistributionPoints found, but nothing we can use.\n");
return 0;
}
int main(int argc, char **argv)
{
char *certFile = NULL;
char *crlFile = NULL;
unsigned char *certData;
unsigned certDataLen;
bool doParse = false;
char *outFile = NULL;
CSSM_BOOL verbose = CSSM_FALSE;
unsigned char *crl = NULL;
size_t crlLen = 0;
int rtn = -1;
if(argc < 2) {
usage(argv);
}
extern char *optarg;
int arg;
while ((arg = getopt(argc, argv, "c:C:po:vh")) != -1) {
switch (arg) {
case 'c':
certFile = optarg;
break;
case 'C':
crlFile = optarg;
break;
case 'p':
doParse = true;
break;
case 'o':
outFile = optarg;
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'h':
usage(argv);
}
}
if(optind != argc) {
usage(argv);
}
if((certFile != NULL) && (crlFile != NULL)) {
printf("***crlFile and certFile are mutually exclusive.\n");
usage(argv);
}
if((certFile == NULL) && (crlFile == NULL)) {
printf("***Must specify either certFile or crlFile\n");
usage(argv);
}
CSSM_RETURN crtn;
CSSM_CL_HANDLE clHand = clStartup();
CertParser parser(clHand);
if(crlFile) {
unsigned len;
if(readFile(crlFile, &crl, &len)) {
printf("***Error reading %s. Aborting.\n", crlFile);
exit(1);
}
crlLen = len;
}
if(certFile) {
if(readFile(certFile, &certData, &certDataLen)) {
printf("***Error reading %s. Aborting.\n", certFile);
exit(1);
}
CSSM_DATA cdata = {certDataLen, certData};
crtn = parser.initWithData(cdata);
if(crtn) {
printf("Error parsing cert %s. Aborting.\n", certFile);
exit(1);
}
rtn = fetchCrl(parser, &crl, &crlLen);
if(rtn) {
printf("***aborting.\n");
exit(1);
}
}
if(doParse) {
if(crl == NULL) {
printf("...parse specified but no CRL found.\n");
}
else {
if(certFile != NULL) {
printf("============== CRL for cert %s ==============\n", certFile);
}
printCrl(crl, crlLen, verbose);
if(certFile != NULL) {
printf("============== end of CRL ==============\n");
}
}
}
if(outFile) {
if(crl == NULL) {
printf("...outFile specified but no CRL found.\n");
}
else {
if(writeFile(outFile, crl, crlLen)) {
printf("***Error writing CRL to %s.\n", outFile);
rtn = 1;
}
else {
printf("...wrote %u bytes to %s\n", (unsigned)crlLen, outFile);
}
}
}
return rtn;
}