1/* 2 * certsFromDb.cpp - extract all certs from a DB, write to files or parse to stdout. 3 */ 4#include <security_cdsa_utils/cuFileIo.h> 5#include <utilLib/common.h> 6#include <utilLib/cspwrap.h> 7#include <security_cdsa_utils/cuPrintCert.h> 8#include <stdlib.h> 9#include <stdio.h> 10#include <string.h> 11#include <Security/cssm.h> 12#include <string.h> 13 14static void usage(char **argv) 15{ 16 printf("Usage: \n"); 17 printf(" %s keychainFile f certFileBase [option...]\n", argv[0]); 18 printf(" %s keychainFile p(arse) [option...]\n", argv[0]); 19 printf("Options:\n"); 20 printf(" R fetch CRLs, not certs\n"); 21 printf(" P pause for MallocDebug one each item\n"); 22 printf(" q Quiet\n"); 23 exit(1); 24} 25 26int main(int argc, char **argv) 27{ 28 int rtn; 29 CSSM_DL_DB_HANDLE dlDbHand; 30 CSSM_RETURN crtn; 31 char filePath[300]; 32 unsigned certNum=0; 33 CSSM_QUERY query; 34 CSSM_DB_UNIQUE_RECORD_PTR record = NULL; 35 CSSM_HANDLE resultHand; 36 CSSM_DATA theData = {0, NULL}; 37 char *fileBase = NULL; 38 CSSM_BOOL doPause = CSSM_FALSE; 39 CSSM_BOOL isCrl = CSSM_FALSE; 40 CSSM_BOOL quiet = CSSM_FALSE; 41 int optarg = 3; 42 43 if(argc < 3) { 44 usage(argv); 45 } 46 switch(argv[2][0]) { 47 case 'f': 48 if(argc < 4) { 49 usage(argv); 50 } 51 fileBase = argv[3]; 52 optarg = 4; 53 break; 54 case 'p': 55 /* default, parse mode */ 56 break; 57 default: 58 usage(argv); 59 } 60 for(int arg=optarg; arg<argc; arg++) { 61 switch(argv[arg][0]) { 62 case 'q': 63 quiet = CSSM_TRUE; 64 break; 65 case 'P': 66 doPause = CSSM_TRUE; 67 break; 68 case 'R': 69 isCrl = CSSM_TRUE; 70 break; 71 default: 72 usage(argv); 73 } 74 } 75 76 /* attach to specified keychain as a DL/DB */ 77 dlDbHand.DLHandle = dlStartup(); 78 if(dlDbHand.DLHandle == 0) { 79 exit(1); 80 } 81 crtn = dbCreateOpen(dlDbHand.DLHandle, argv[1], 82 CSSM_FALSE, // doCreate 83 CSSM_FALSE, // deleteExist 84 NULL, // pwd 85 &dlDbHand.DBHandle); 86 if(crtn) { 87 exit(1); 88 } 89 90loopTop: 91 /* search by record type, no predicates, no returned attributes. We just want 92 * the data. */ 93 query.RecordType = isCrl ? CSSM_DL_DB_RECORD_X509_CRL : 94 CSSM_DL_DB_RECORD_X509_CERTIFICATE; 95 query.Conjunctive = CSSM_DB_NONE; 96 query.NumSelectionPredicates = 0; 97 query.SelectionPredicate = NULL; 98 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? 99 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? 100 query.QueryFlags = CSSM_QUERY_RETURN_DATA; // FIXME - used? 101 102 crtn = CSSM_DL_DataGetFirst(dlDbHand, 103 &query, 104 &resultHand, 105 NULL, 106 &theData, 107 &record); 108 if(crtn) { 109 printError("CSSM_DL_DataGetFirst", crtn); 110 printf("Error fetching certs from %s. Aborting.\n", argv[1]); 111 exit(1); 112 } 113 CSSM_DL_FreeUniqueRecord(dlDbHand, record); 114 115 if(doPause) { 116 fpurge(stdin); 117 printf("set up MallocDebug, then any key to continue: "); 118 getchar(); 119 } 120 if(fileBase) { 121 /* write the data */ 122 sprintf(filePath, "%s_%d", fileBase, certNum); 123 rtn = writeFile(filePath, theData.Data, theData.Length); 124 if(rtn == 0) { 125 if(!quiet) { 126 printf("...wrote %u bytes to %s\n", (unsigned)theData.Length, 127 filePath); 128 } 129 } 130 else { 131 printf("***Error writing %s: %s\n", filePath, strerror(rtn)); 132 exit(1); 133 } 134 } 135 else { 136 if(isCrl) { 137 printf("CRL 0:\n"); 138 printCrl(theData.Data, theData.Length, CSSM_FALSE); 139 } 140 else { 141 printf("Cert 0:\n"); 142 printCert(theData.Data, theData.Length, CSSM_FALSE); 143 } 144 } 145 CSSM_FREE(theData.Data); 146 certNum++; 147 148 /* again */ 149 for(;;) { 150 crtn = CSSM_DL_DataGetNext(dlDbHand, 151 resultHand, 152 NULL, 153 &theData, 154 &record); 155 switch(crtn) { 156 case CSSM_OK: 157 if(fileBase) { 158 sprintf(filePath, "%s_%d", fileBase, certNum); 159 rtn = writeFile(filePath, theData.Data, theData.Length); 160 if(rtn == 0) { 161 if(!quiet) { 162 printf("...wrote %u bytes to %s\n", (unsigned)theData.Length, 163 filePath); 164 } 165 } 166 else { 167 printf("***Error writing %s: %s\n", filePath, strerror(rtn)); 168 exit(1); 169 } 170 } 171 else { 172 if(isCrl) { 173 printf("CRL 0:\n"); 174 printCrl(theData.Data, theData.Length, CSSM_FALSE); 175 } 176 else { 177 printf("Cert %u:\n", certNum); 178 printCert(theData.Data, theData.Length, CSSM_FALSE); 179 } 180 } 181 certNum++; 182 CSSM_FREE(theData.Data); 183 CSSM_DL_FreeUniqueRecord(dlDbHand, record); 184 break; // and go again 185 case CSSMERR_DL_ENDOFDATA: 186 /* normal termination */ 187 break; 188 default: 189 printError("DataGetNext", crtn); 190 break; 191 } 192 if(crtn != CSSM_OK) { 193 break; 194 } 195 } 196 CSSM_DL_DataAbortQuery(dlDbHand, resultHand); 197 if(doPause) { 198 fpurge(stdin); 199 printf("End of loop, l to loop, enything else to end: "); 200 char c = getchar(); 201 if(c == 'l') { 202 goto loopTop; 203 } 204 } 205 if(!quiet) { 206 printf("...%d %s extracted.\n", certNum, isCrl ? "CRLs" : "certs"); 207 } 208 return 0; 209} 210 211