--- /dev/null
+/*
+ * crlTool.cpp
+ */
+
+#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");
+ /* etc. */
+ exit(1);
+}
+
+static int fetchCrlViaGeneralNames(
+ const CE_GeneralNames *names,
+ unsigned char **crl, // mallocd and RETURNED
+ size_t *crlLen) // RETURNED
+{
+ 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)) {
+ /* eventually handle other schemes here */
+ continue;
+ }
+
+ /* OK, we can do this */
+ 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, // mallocd and RETURNED
+ size_t *crlLen) // RETURNED
+{
+ CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)
+ cert.extensionForOid(CSSMOID_CrlDistributionPoints);
+
+ *crl = NULL;
+ *crlLen = 0;
+ if(dps == NULL) {
+ /* not an error, just indicate NULL return */
+ 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;
+ }
+ /* else try again if there's another name */
+ break;
+ } /* CE_CDNT_FullName */
+
+ default:
+ /* not yet */
+ printf("unknown distPointName->nameType (%u)\n",
+ (unsigned)dp->distPointName->nameType);
+ break;
+ } /* switch distPointName->nameType */
+ } /* for each distPoints */
+ 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;
+}