]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/mdsdump/mdsdump.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / mdsdump / mdsdump.cpp
1 /*
2 * mdsdump.cpp - dump contents of system MDS databases
3 */
4
5 /**** FIXME this uses a private API not currently exported in any way from
6 **** Security project
7 ****/
8
9 #include <CoreFoundation/CoreFoundation.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <Security/mds.h>
13 #include <common.h>
14 #include <Security/mds_schema.h>
15 #include "MDSSchema.h"
16 #include <strings.h>
17
18 #define MAX_MDS_ATTRS 32
19
20 static CSSM_MEMORY_FUNCS memFuncs = {
21 appMalloc,
22 appFree,
23 appRealloc,
24 appCalloc,
25 NULL
26 };
27
28 static void showInfoTypes()
29 {
30 printf(" o Object records\n");
31 printf(" C CSSM records\n");
32 printf(" p Plugin Common records\n");
33 printf(" c CSP records\n");
34 printf(" l CL records\n");
35 printf(" t TP records\n");
36 printf(" d DL records\n");
37 printf(" a All records from Object DB\n");
38 printf(" A All records from CDSA directory DB\n");
39 }
40
41 static void usage(char **argv)
42 {
43 printf("Usage: %s info_type [options...]\n", argv[0]);
44 printf("info_type values:\n");
45 showInfoTypes();
46 printf(" h help\n");
47 printf("Options:\n");
48 printf(" i perform MDS_Install()\n");
49 printf(" v verbose\n");
50 printf(" k keep connected and go again\n");
51 exit(1);
52 }
53
54 #define NORM_KEY_LEN 20
55
56 /* print a key name, padding out to NORM_KEY_LEN columns */
57 static void printName(
58 const char *attrName)
59 {
60 printf(" %s", attrName);
61 int len = strlen(attrName);
62 if(len > NORM_KEY_LEN) {
63 return;
64 }
65 int numSpaces = NORM_KEY_LEN - len;
66 for(int i=0; i<numSpaces; i++) {
67 putchar(' ');
68 }
69
70 }
71
72 #if 0
73 /*
74 * Attempt to print a numeric value as a string, per a MDSNameValuePair table.
75 * Of course this can not deal with OR'd together values; the MDSNameValuePair
76 * mechanism does not indicate on a per-field basis which fields are OR-able.
77 * If the value is in fact a collection of legal values (per the nameValues
78 * array), the value will just be printed in hex.
79 */
80 static void printValueAsString(
81 unsigned val,
82 const Security::MDSNameValuePair *nameValues) // optional
83 {
84 if(nameValues != NULL) {
85 while(nameValues->name != NULL) {
86 if(nameValues->value == val) {
87 printf("%s", nameValues->name);
88 return;
89 }
90 nameValues++;
91 }
92 }
93 /* Oh well */
94 printf("0x%x", val);
95 }
96 #endif
97
98 /* print value string, surrounded by single quotes, then a newline */
99 static void printValue(
100 const CSSM_DATA *attrValue)
101 {
102 printf("'");
103 for(uint32 dex=0; dex<attrValue->Length; dex++) {
104 printf("%c", attrValue->Data[dex]);
105 }
106 printf("'\n");
107 }
108
109 /* Print one attribute value */
110 static void dumpAttr(
111 CSSM_DB_ATTRIBUTE_FORMAT attrForm,
112 const CSSM_DATA *attrData)
113 {
114 if((attrData == NULL) || (attrData->Data == NULL)) {
115 printf("<NULL DATA>\n");
116 return;
117 }
118 void *data = attrData->Data;
119 switch(attrForm) {
120 case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
121 printValue(attrData);
122 break;
123 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: // not really supported in MDS
124 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
125 {
126 unsigned val = *(unsigned *)data;
127 printf("0x%x\n", val);
128 break;
129 }
130 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
131 {
132 printf("BLOB length %u : ", (unsigned)attrData->Length);
133 for(unsigned i=0; i<attrData->Length; i++) {
134 unsigned dat = attrData->Data[i];
135 printf("%02X ", dat);
136 }
137 printf("\n");
138 break;
139 }
140 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
141 {
142 printf("multi_int[");
143 uint32 numInts = attrData->Length / sizeof(uint32);
144 uint32 *uip = (uint32 *)data;
145 for(unsigned i=0; i<numInts; i++) {
146 if(i > 0) {
147 printf(", ");
148 }
149 printf("0x%x", (unsigned)(*uip++));
150 }
151 printf("]\n");
152 break;
153 }
154 default:
155 printf("***UNKNOWN FORMAT (%u), Length %u\n",
156 (unsigned)attrForm, (unsigned)attrData->Length);
157 break;
158 }
159 }
160
161 /*
162 * Vanilla "dump one record" routine. Assumes format of all attribute labels
163 * as string. Uses a MDSNameValuePair ptr array in parallel to the attributes
164 * themselves to facilitate displaying numeric values as strings (e.g.
165 * "CSSM_ALGID_SHA1") where possible.
166 */
167 static void dumpRecord(
168 const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs)
169 {
170 unsigned dex;
171 for(dex=0; dex<recordAttrs->NumberOfAttributes; dex++) {
172 const CSSM_DB_ATTRIBUTE_DATA *attrData = &recordAttrs->AttributeData[dex];
173 if(attrData->Info.AttributeNameFormat != CSSM_DB_ATTRIBUTE_NAME_AS_STRING) {
174 printf("***BAD ATTR_NAME FORMAT (%u)\n",
175 (unsigned)attrData->Info.AttributeNameFormat);
176 continue;
177 }
178 const char *attrName = attrData->Info.Label.AttributeName;
179 printName(attrName);
180 printf(": ");
181 /* note currently in MDS NumberOfValues is always one or zero */
182 for(unsigned attrNum=0; attrNum<attrData->NumberOfValues; attrNum++) {
183 dumpAttr(attrData->Info.AttributeFormat,
184 &attrData->Value[attrNum]);
185 }
186 if(attrData->NumberOfValues == 0) {
187 printf("<<no values present>>\n");
188 }
189 }
190 }
191
192 /* free attribute(s) allocated by MDS */
193 static void freeAttrs(
194 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs)
195 {
196 unsigned i;
197
198 for(i=0; i<recordAttrs->NumberOfAttributes; i++) {
199 CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i];
200 if(attrData == NULL) {
201 /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */
202 printf("***freeAttrs screwup: NULL attrData\n");
203 return;
204 }
205 unsigned j;
206 for(j=0; j<attrData->NumberOfValues; j++) {
207 CSSM_DATA_PTR data = &attrData->Value[j];
208 if(data == NULL) {
209 /* fault of MDS, who said there was a value here */
210 printf("***freeAttrs screwup: NULL data\n");
211 return;
212 }
213 appFree(data->Data, NULL);
214 data->Data = NULL;
215 data->Length = 0;
216 }
217 appFree(attrData->Value, NULL);
218 attrData->Value = NULL;
219 }
220 }
221
222 /*
223 * Fetch and display all records of specified CSSM_DB_RECORDTYPE.
224 */
225 static void fetchAllAttrs(
226 MDS_FUNCS *mdsFuncs,
227 MDS_DB_HANDLE dlDb,
228 CSSM_DB_RECORDTYPE recordType)
229 {
230 CSSM_QUERY query;
231 CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
232 CSSM_RETURN crtn;
233 CSSM_HANDLE resultHand;
234 CSSM_DB_ATTRIBUTE_DATA attrs[MAX_MDS_ATTRS];
235 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
236 const RelationInfo *relInfo;
237
238 relInfo = MDSRecordTypeToRelation(recordType);
239 if(relInfo == NULL) {
240 printf("***\10UNKNOWN recordType %d\n", (int)recordType);
241 return;
242 }
243
244 /* build an attr array from schema so we get all known attrs */
245 memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * MAX_MDS_ATTRS);
246 unsigned attrDex;
247 for(attrDex=0; attrDex<relInfo->NumberOfAttributes; attrDex++) {
248 attrs[attrDex].Info = relInfo->AttributeInfo[attrDex];
249 }
250 recordAttrs.DataRecordType = recordType;
251 recordAttrs.NumberOfAttributes = relInfo->NumberOfAttributes;
252 recordAttrs.AttributeData = attrs;
253
254 /* just search by recordType, no predicates */
255 query.RecordType = recordType;
256 query.Conjunctive = CSSM_DB_NONE;
257 query.NumSelectionPredicates = 0;
258 query.SelectionPredicate = NULL;
259 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
260 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
261 query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used?
262
263 crtn = mdsFuncs->DataGetFirst(dlDb,
264 &query,
265 &resultHand,
266 &recordAttrs,
267 NULL, // No data
268 &record);
269 switch(crtn) {
270 case CSSM_OK:
271 break; // proceed
272 case CSSMERR_DL_ENDOFDATA:
273 printf("%s: no record found\n", relInfo->relationName);
274 return;
275 default:
276 printError("DataGetFirst", crtn);
277 return;
278 }
279 unsigned recNum = 0;
280 printf("%s:\n", relInfo->relationName);
281 printf(" record %d; numAttrs %d:\n",
282 recNum++, (int)recordAttrs.NumberOfAttributes);
283
284 dumpRecord(&recordAttrs);
285 mdsFuncs->FreeUniqueRecord(dlDb, record);
286 freeAttrs(&recordAttrs);
287
288 /* now the rest of them */
289 /* hopefully we don't have to re-init the recordAttr array */
290 for(;;) {
291 crtn = mdsFuncs->DataGetNext(dlDb,
292 resultHand,
293 &recordAttrs,
294 NULL,
295 &record);
296 switch(crtn) {
297 case CSSM_OK:
298 printf(" record %d; numAttrs %d:\n",
299 recNum++, (int)recordAttrs.NumberOfAttributes);
300 dumpRecord(&recordAttrs);
301 mdsFuncs->FreeUniqueRecord(dlDb, record);
302 freeAttrs(&recordAttrs);
303 break; // and go again
304 case CSSMERR_DL_ENDOFDATA:
305 /* normal termination */
306 break;
307 default:
308 printError("DataGetNext", crtn);
309 break;
310 }
311 if(crtn != CSSM_OK) {
312 break;
313 }
314 }
315 }
316
317 /*
318 * This is different - it's schema-independent. Fetch all records from specified
319 * DlDb which contain a ModuleID attribute.
320 */
321 static void fetchAllRecords(
322 MDS_FUNCS *mdsFuncs,
323 MDS_DB_HANDLE dlDb)
324 {
325 CSSM_QUERY query;
326 CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
327 CSSM_RETURN crtn;
328 CSSM_HANDLE resultHand;
329 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
330 CSSM_DB_ATTRIBUTE_DATA theAttr;
331 CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo = &theAttr.Info;
332 CSSM_DATA attrValue = {0, NULL};
333
334 recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_ANY;
335 recordAttrs.SemanticInformation = 0;
336 recordAttrs.NumberOfAttributes = 1;
337 recordAttrs.AttributeData = &theAttr;
338
339 attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
340 attrInfo->Label.AttributeName = (char *)"ModuleID";
341 attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
342
343 theAttr.NumberOfValues = 1;
344 theAttr.Value = &attrValue;
345
346 /* just search by recordType, no predicates */
347 query.RecordType = CSSM_DL_DB_RECORD_ANY;
348 query.Conjunctive = CSSM_DB_NONE;
349 query.NumSelectionPredicates = 0;
350 query.SelectionPredicate = NULL;
351 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
352 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
353 query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used?
354
355 crtn = mdsFuncs->DataGetFirst(dlDb,
356 &query,
357 &resultHand,
358 &recordAttrs,
359 NULL, // No data
360 &record);
361 switch(crtn) {
362 case CSSM_OK:
363 break; // proceed
364 case CSSMERR_DL_ENDOFDATA:
365 printf("no record found\n");
366 return;
367 default:
368 printError("DataGetFirst", crtn);
369 return;
370 }
371 unsigned recNum = 0;
372 printf("Records containing a ModuleID attribute:\n");
373 printf(" record %d:\n", recNum++);
374
375 dumpRecord(&recordAttrs);
376 mdsFuncs->FreeUniqueRecord(dlDb, record);
377 freeAttrs(&recordAttrs);
378
379 /* now the rest of them */
380 /* hopefully we don't have to re-init the recordAttr array */
381 for(;;) {
382 crtn = mdsFuncs->DataGetNext(dlDb,
383 resultHand,
384 &recordAttrs,
385 NULL,
386 &record);
387 switch(crtn) {
388 case CSSM_OK:
389 printf(" record %d:\n", recNum++);
390 dumpRecord(&recordAttrs);
391 mdsFuncs->FreeUniqueRecord(dlDb, record);
392 freeAttrs(&recordAttrs);
393 break; // and go again
394 case CSSMERR_DL_ENDOFDATA:
395 /* normal termination */
396 break;
397 default:
398 printError("DataGetNext", crtn);
399 break;
400 }
401 if(crtn != CSSM_OK) {
402 break;
403 }
404 }
405 }
406
407 static void doInstall(
408 MDS_HANDLE mdsHand)
409 {
410 CFAbsoluteTime start, end;
411
412 start = CFAbsoluteTimeGetCurrent();
413 CSSM_RETURN crtn = MDS_Install(mdsHand);
414 end = CFAbsoluteTimeGetCurrent();
415 if(crtn) {
416 printError("MDS_Install", crtn);
417 }
418 else {
419 printf("MDS_Install took %gs\n", end - start);
420 }
421 }
422
423 int main(int argc, char **argv)
424 {
425 MDS_FUNCS mdsFuncs;
426 MDS_HANDLE mdsHand;
427 CSSM_RETURN crtn;
428 int arg;
429 char op;
430 char *dbName;
431 CSSM_DB_HANDLE dbHand = 0;
432 MDS_DB_HANDLE dlDb;
433 bool verbose = 0;
434 bool keepConnected = false;
435 bool install = false;
436
437 if(argc < 2) {
438 usage(argv);
439 }
440 op = argv[1][0];
441 if(op == 'h') {
442 usage(argv);
443 }
444 for(arg=2; arg<argc; arg++) {
445 switch(argv[arg][0]) {
446 case 'v':
447 verbose = true;
448 break;
449 case 'i':
450 install = true;
451 break;
452 case 'k':
453 keepConnected = true;
454 break;
455 default:
456 usage(argv);
457 }
458 }
459 if(verbose) {
460 printf("..calling MDS_Initialize\n");
461 }
462 crtn = MDS_Initialize(NULL, // callerGuid
463 &memFuncs,
464 &mdsFuncs,
465 &mdsHand);
466 if(crtn) {
467 printError("MDS_Initialize", crtn);
468 exit(1);
469 }
470 if(install) {
471 doInstall(mdsHand);
472 }
473 do {
474 /* open one or the other DB */
475 switch(op) {
476 case 'o':
477 case 'a':
478 dbName = (char *)MDS_OBJECT_DIRECTORY_NAME;
479 break;
480 default:
481 dbName = (char *)MDS_CDSA_DIRECTORY_NAME;
482 break;
483 }
484 crtn = mdsFuncs.DbOpen(mdsHand,
485 dbName,
486 NULL, // DbLocation
487 CSSM_DB_ACCESS_READ,
488 NULL, // AccessCred - hopefully optional
489 NULL, // OpenParameters
490 &dbHand);
491 if(crtn) {
492 printError("DbOpen", crtn);
493 exit(1);
494 }
495 dlDb.DLHandle = mdsHand;
496 dlDb.DBHandle = dbHand;
497
498 /* go for it */
499 switch(op) {
500 case 'o':
501 fetchAllAttrs(&mdsFuncs, dlDb, MDS_OBJECT_RECORDTYPE);
502 break;
503 case 'C':
504 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSSM_RECORDTYPE);
505 break;
506 case 'p':
507 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_COMMON_RECORDTYPE);
508 break;
509 case 'c':
510 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE);
511 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE);
512 if(verbose) {
513 fetchAllAttrs(&mdsFuncs, dlDb,
514 MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE);
515 fetchAllAttrs(&mdsFuncs, dlDb,
516 MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE);
517 }
518 break;
519 case 'l':
520 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CL_PRIMARY_RECORDTYPE);
521 break;
522 case 't':
523 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_TP_PRIMARY_RECORDTYPE);
524 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_TP_OIDS_RECORDTYPE);
525 if(verbose) {
526 fetchAllAttrs(&mdsFuncs, dlDb,
527 MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE);
528 }
529 break;
530 case 'd':
531 fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_DL_PRIMARY_RECORDTYPE);
532 break;
533 case 'a':
534 case 'A':
535 fetchAllRecords(&mdsFuncs, dlDb);
536 break;
537 default:
538 usage(argv);
539 }
540
541 crtn = mdsFuncs.DbClose(dlDb);
542 if(crtn) {
543 printError("DbClose", crtn);
544 }
545 if(keepConnected) {
546 printf("\n");
547 showInfoTypes();
548 fpurge(stdin);
549 printf("Enter new info type: ");
550 op = getchar();
551 }
552 } while(keepConnected);
553 crtn = MDS_Terminate(mdsHand);
554 if(crtn) {
555 printError("MDS_Terminate", crtn);
556 }
557 return 0;
558 }