1/* 2 * crlTool.cpp 3 */ 4 5#include <stdlib.h> 6#include <strings.h> 7#include <stdio.h> 8#include <unistd.h> 9#include <security_cdsa_utils/cuFileIo.h> 10#include <utilLib/common.h> 11#include <clAppUtils/clutils.h> 12#include <clAppUtils/CertParser.h> 13#include <Security/Security.h> 14#include "crlNetwork.h" 15#include <security_cdsa_utils/cuPrintCert.h> 16#define LOOPS_DEF 100 17 18static void usage(char **argv) 19{ 20 printf("usage: %s [options]\n", argv[0]); 21 printf("Options:\n"); 22 printf(" -c certFile -- obtain CRL via net from this cert\n"); 23 printf(" -C crlFile -- CRL from this file\n"); 24 printf(" -p -- parse the CRL\n"); 25 printf(" -o outFile -- write the fetched CRL to this file\n"); 26 printf(" -v -- verbose CRL dump\n"); 27 /* etc. */ 28 exit(1); 29} 30 31static int fetchCrlViaGeneralNames( 32 const CE_GeneralNames *names, 33 unsigned char **crl, // mallocd and RETURNED 34 size_t *crlLen) // RETURNED 35{ 36 CSSM_DATA crlData = {0, NULL}; 37 CSSM_RETURN crtn; 38 39 for(unsigned nameDex=0; nameDex<names->numNames; nameDex++) { 40 CE_GeneralName *name = &names->generalName[nameDex]; 41 switch(name->nameType) { 42 case GNT_URI: 43 if(name->name.Length < 5) { 44 continue; 45 } 46 if(strncmp((char *)name->name.Data, "ldap:", 5) && 47 strncmp((char *)name->name.Data, "http:", 5) && 48 strncmp((char *)name->name.Data, "https:", 6)) { 49 /* eventually handle other schemes here */ 50 continue; 51 } 52 53 /* OK, we can do this */ 54 crtn = crlNetFetch(&name->name, LT_Crl, &crlData); 55 if(crtn) { 56 printf("...net fetch error\n"); 57 return 1; 58 } 59 *crl = crlData.Data; 60 *crlLen = crlData.Length; 61 return 0; 62 63 default: 64 printf("fetchCrlViaGeneralNames: unknown" 65 "nameType (%u)", (unsigned)name->nameType); 66 break; 67 } 68 } 69 printf("...GNT_URI name not found in GeneralNames\n"); 70 return 1; 71} 72 73static int fetchCrl( 74 CertParser &cert, 75 unsigned char **crl, // mallocd and RETURNED 76 size_t *crlLen) // RETURNED 77{ 78 CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *) 79 cert.extensionForOid(CSSMOID_CrlDistributionPoints); 80 81 *crl = NULL; 82 *crlLen = 0; 83 if(dps == NULL) { 84 /* not an error, just indicate NULL return */ 85 printf("***No CrlDistributionPoints in this cert.\n"); 86 return 0; 87 } 88 for(unsigned dex=0; dex<dps->numDistPoints; dex++) { 89 90 CE_CRLDistributionPoint *dp = &dps->distPoints[dex]; 91 if(dp->distPointName == NULL) { 92 continue; 93 } 94 switch(dp->distPointName->nameType) { 95 case CE_CDNT_NameRelativeToCrlIssuer: 96 printf("...CE_CDNT_NameRelativeToCrlIssuer not implemented\n"); 97 break; 98 99 case CE_CDNT_FullName: 100 { 101 CE_GeneralNames *names = dp->distPointName->dpn.fullName; 102 int rtn = fetchCrlViaGeneralNames(names, crl, crlLen); 103 if(rtn == 0) { 104 return 0; 105 } 106 /* else try again if there's another name */ 107 break; 108 } /* CE_CDNT_FullName */ 109 110 default: 111 /* not yet */ 112 printf("unknown distPointName->nameType (%u)\n", 113 (unsigned)dp->distPointName->nameType); 114 break; 115 } /* switch distPointName->nameType */ 116 } /* for each distPoints */ 117 printf("...CrlDistributionPoints found, but nothing we can use.\n"); 118 return 0; 119} 120 121int main(int argc, char **argv) 122{ 123 char *certFile = NULL; 124 char *crlFile = NULL; 125 unsigned char *certData; 126 unsigned certDataLen; 127 bool doParse = false; 128 char *outFile = NULL; 129 CSSM_BOOL verbose = CSSM_FALSE; 130 unsigned char *crl = NULL; 131 size_t crlLen = 0; 132 int rtn = -1; 133 134 if(argc < 2) { 135 usage(argv); 136 } 137 138 extern char *optarg; 139 int arg; 140 while ((arg = getopt(argc, argv, "c:C:po:vh")) != -1) { 141 switch (arg) { 142 case 'c': 143 certFile = optarg; 144 break; 145 case 'C': 146 crlFile = optarg; 147 break; 148 case 'p': 149 doParse = true; 150 break; 151 case 'o': 152 outFile = optarg; 153 break; 154 case 'v': 155 verbose = CSSM_TRUE; 156 break; 157 case 'h': 158 usage(argv); 159 } 160 } 161 if(optind != argc) { 162 usage(argv); 163 } 164 if((certFile != NULL) && (crlFile != NULL)) { 165 printf("***crlFile and certFile are mutually exclusive.\n"); 166 usage(argv); 167 } 168 if((certFile == NULL) && (crlFile == NULL)) { 169 printf("***Must specify either certFile or crlFile\n"); 170 usage(argv); 171 } 172 173 CSSM_RETURN crtn; 174 CSSM_CL_HANDLE clHand = clStartup(); 175 CertParser parser(clHand); 176 177 if(crlFile) { 178 unsigned len; 179 if(readFile(crlFile, &crl, &len)) { 180 printf("***Error reading %s. Aborting.\n", crlFile); 181 exit(1); 182 } 183 crlLen = len; 184 } 185 if(certFile) { 186 if(readFile(certFile, &certData, &certDataLen)) { 187 printf("***Error reading %s. Aborting.\n", certFile); 188 exit(1); 189 } 190 CSSM_DATA cdata = {certDataLen, certData}; 191 crtn = parser.initWithData(cdata); 192 if(crtn) { 193 printf("Error parsing cert %s. Aborting.\n", certFile); 194 exit(1); 195 } 196 rtn = fetchCrl(parser, &crl, &crlLen); 197 if(rtn) { 198 printf("***aborting.\n"); 199 exit(1); 200 } 201 } 202 203 if(doParse) { 204 if(crl == NULL) { 205 printf("...parse specified but no CRL found.\n"); 206 } 207 else { 208 if(certFile != NULL) { 209 printf("============== CRL for cert %s ==============\n", certFile); 210 } 211 printCrl(crl, crlLen, verbose); 212 if(certFile != NULL) { 213 printf("============== end of CRL ==============\n"); 214 } 215 } 216 } 217 if(outFile) { 218 if(crl == NULL) { 219 printf("...outFile specified but no CRL found.\n"); 220 } 221 else { 222 if(writeFile(outFile, crl, crlLen)) { 223 printf("***Error writing CRL to %s.\n", outFile); 224 rtn = 1; 225 } 226 else { 227 printf("...wrote %u bytes to %s\n", (unsigned)crlLen, outFile); 228 } 229 } 230 } 231 return rtn; 232} 233