X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/crlTool/crlTool.cpp diff --git a/SecurityTests/clxutils/crlTool/crlTool.cpp b/SecurityTests/clxutils/crlTool/crlTool.cpp new file mode 100644 index 00000000..54050bb3 --- /dev/null +++ b/SecurityTests/clxutils/crlTool/crlTool.cpp @@ -0,0 +1,232 @@ +/* + * crlTool.cpp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crlNetwork.h" +#include +#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; nameDexnumNames; 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; dexnumDistPoints; 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; +}