2 * mdsdump.cpp - dump contents of system MDS databases
5 /**** FIXME this uses a private API not currently exported in any way from
9 #include <CoreFoundation/CoreFoundation.h>
12 #include <Security/mds.h>
14 #include <Security/mds_schema.h>
15 #include "MDSSchema.h"
18 #define MAX_MDS_ATTRS 32
20 static CSSM_MEMORY_FUNCS memFuncs
= {
28 static void showInfoTypes()
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");
41 static void usage(char **argv
)
43 printf("Usage: %s info_type [options...]\n", argv
[0]);
44 printf("info_type values:\n");
48 printf(" i perform MDS_Install()\n");
49 printf(" v verbose\n");
50 printf(" k keep connected and go again\n");
54 #define NORM_KEY_LEN 20
56 /* print a key name, padding out to NORM_KEY_LEN columns */
57 static void printName(
60 printf(" %s", attrName
);
61 int len
= strlen(attrName
);
62 if(len
> NORM_KEY_LEN
) {
65 int numSpaces
= NORM_KEY_LEN
- len
;
66 for(int i
=0; i
<numSpaces
; i
++) {
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.
80 static void printValueAsString(
82 const Security::MDSNameValuePair
*nameValues
) // optional
84 if(nameValues
!= NULL
) {
85 while(nameValues
->name
!= NULL
) {
86 if(nameValues
->value
== val
) {
87 printf("%s", nameValues
->name
);
98 /* print value string, surrounded by single quotes, then a newline */
99 static void printValue(
100 const CSSM_DATA
*attrValue
)
103 for(uint32 dex
=0; dex
<attrValue
->Length
; dex
++) {
104 printf("%c", attrValue
->Data
[dex
]);
109 /* Print one attribute value */
110 static void dumpAttr(
111 CSSM_DB_ATTRIBUTE_FORMAT attrForm
,
112 const CSSM_DATA
*attrData
)
114 if((attrData
== NULL
) || (attrData
->Data
== NULL
)) {
115 printf("<NULL DATA>\n");
118 void *data
= attrData
->Data
;
120 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
:
121 printValue(attrData
);
123 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32
: // not really supported in MDS
124 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32
:
126 unsigned val
= *(unsigned *)data
;
127 printf("0x%x\n", val
);
130 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
:
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
);
140 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
:
142 printf("multi_int[");
143 uint32 numInts
= attrData
->Length
/ sizeof(uint32
);
144 uint32
*uip
= (uint32
*)data
;
145 for(unsigned i
=0; i
<numInts
; i
++) {
149 printf("0x%x", (unsigned)(*uip
++));
155 printf("***UNKNOWN FORMAT (%u), Length %u\n",
156 (unsigned)attrForm
, (unsigned)attrData
->Length
);
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.
167 static void dumpRecord(
168 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*recordAttrs
)
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
);
178 const char *attrName
= attrData
->Info
.Label
.AttributeName
;
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
]);
186 if(attrData
->NumberOfValues
== 0) {
187 printf("<<no values present>>\n");
192 /* free attribute(s) allocated by MDS */
193 static void freeAttrs(
194 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs
)
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");
206 for(j
=0; j
<attrData
->NumberOfValues
; j
++) {
207 CSSM_DATA_PTR data
= &attrData
->Value
[j
];
209 /* fault of MDS, who said there was a value here */
210 printf("***freeAttrs screwup: NULL data\n");
213 appFree(data
->Data
, NULL
);
217 appFree(attrData
->Value
, NULL
);
218 attrData
->Value
= NULL
;
223 * Fetch and display all records of specified CSSM_DB_RECORDTYPE.
225 static void fetchAllAttrs(
228 CSSM_DB_RECORDTYPE recordType
)
231 CSSM_DB_UNIQUE_RECORD_PTR record
= NULL
;
233 CSSM_HANDLE resultHand
;
234 CSSM_DB_ATTRIBUTE_DATA attrs
[MAX_MDS_ATTRS
];
235 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs
;
236 const RelationInfo
*relInfo
;
238 relInfo
= MDSRecordTypeToRelation(recordType
);
239 if(relInfo
== NULL
) {
240 printf("***\10UNKNOWN recordType %d\n", (int)recordType
);
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
);
247 for(attrDex
=0; attrDex
<relInfo
->NumberOfAttributes
; attrDex
++) {
248 attrs
[attrDex
].Info
= relInfo
->AttributeInfo
[attrDex
];
250 recordAttrs
.DataRecordType
= recordType
;
251 recordAttrs
.NumberOfAttributes
= relInfo
->NumberOfAttributes
;
252 recordAttrs
.AttributeData
= attrs
;
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?
263 crtn
= mdsFuncs
->DataGetFirst(dlDb
,
272 case CSSMERR_DL_ENDOFDATA
:
273 printf("%s: no record found\n", relInfo
->relationName
);
276 printError("DataGetFirst", crtn
);
280 printf("%s:\n", relInfo
->relationName
);
281 printf(" record %d; numAttrs %d:\n",
282 recNum
++, (int)recordAttrs
.NumberOfAttributes
);
284 dumpRecord(&recordAttrs
);
285 mdsFuncs
->FreeUniqueRecord(dlDb
, record
);
286 freeAttrs(&recordAttrs
);
288 /* now the rest of them */
289 /* hopefully we don't have to re-init the recordAttr array */
291 crtn
= mdsFuncs
->DataGetNext(dlDb
,
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 */
308 printError("DataGetNext", crtn
);
311 if(crtn
!= CSSM_OK
) {
318 * This is different - it's schema-independent. Fetch all records from specified
319 * DlDb which contain a ModuleID attribute.
321 static void fetchAllRecords(
326 CSSM_DB_UNIQUE_RECORD_PTR record
= NULL
;
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
};
334 recordAttrs
.DataRecordType
= CSSM_DL_DB_RECORD_ANY
;
335 recordAttrs
.SemanticInformation
= 0;
336 recordAttrs
.NumberOfAttributes
= 1;
337 recordAttrs
.AttributeData
= &theAttr
;
339 attrInfo
->AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
340 attrInfo
->Label
.AttributeName
= (char *)"ModuleID";
341 attrInfo
->AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_STRING
;
343 theAttr
.NumberOfValues
= 1;
344 theAttr
.Value
= &attrValue
;
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?
355 crtn
= mdsFuncs
->DataGetFirst(dlDb
,
364 case CSSMERR_DL_ENDOFDATA
:
365 printf("no record found\n");
368 printError("DataGetFirst", crtn
);
372 printf("Records containing a ModuleID attribute:\n");
373 printf(" record %d:\n", recNum
++);
375 dumpRecord(&recordAttrs
);
376 mdsFuncs
->FreeUniqueRecord(dlDb
, record
);
377 freeAttrs(&recordAttrs
);
379 /* now the rest of them */
380 /* hopefully we don't have to re-init the recordAttr array */
382 crtn
= mdsFuncs
->DataGetNext(dlDb
,
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 */
398 printError("DataGetNext", crtn
);
401 if(crtn
!= CSSM_OK
) {
407 static void doInstall(
410 CFAbsoluteTime start
, end
;
412 start
= CFAbsoluteTimeGetCurrent();
413 CSSM_RETURN crtn
= MDS_Install(mdsHand
);
414 end
= CFAbsoluteTimeGetCurrent();
416 printError("MDS_Install", crtn
);
419 printf("MDS_Install took %gs\n", end
- start
);
423 int main(int argc
, char **argv
)
431 CSSM_DB_HANDLE dbHand
= 0;
434 bool keepConnected
= false;
435 bool install
= false;
444 for(arg
=2; arg
<argc
; arg
++) {
445 switch(argv
[arg
][0]) {
453 keepConnected
= true;
460 printf("..calling MDS_Initialize\n");
462 crtn
= MDS_Initialize(NULL
, // callerGuid
467 printError("MDS_Initialize", crtn
);
474 /* open one or the other DB */
478 dbName
= (char *)MDS_OBJECT_DIRECTORY_NAME
;
481 dbName
= (char *)MDS_CDSA_DIRECTORY_NAME
;
484 crtn
= mdsFuncs
.DbOpen(mdsHand
,
488 NULL
, // AccessCred - hopefully optional
489 NULL
, // OpenParameters
492 printError("DbOpen", crtn
);
495 dlDb
.DLHandle
= mdsHand
;
496 dlDb
.DBHandle
= dbHand
;
501 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_OBJECT_RECORDTYPE
);
504 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_CSSM_RECORDTYPE
);
507 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_COMMON_RECORDTYPE
);
510 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE
);
511 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE
);
513 fetchAllAttrs(&mdsFuncs
, dlDb
,
514 MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE
);
515 fetchAllAttrs(&mdsFuncs
, dlDb
,
516 MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE
);
520 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_CL_PRIMARY_RECORDTYPE
);
523 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_TP_PRIMARY_RECORDTYPE
);
524 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_TP_OIDS_RECORDTYPE
);
526 fetchAllAttrs(&mdsFuncs
, dlDb
,
527 MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE
);
531 fetchAllAttrs(&mdsFuncs
, dlDb
, MDS_CDSADIR_DL_PRIMARY_RECORDTYPE
);
535 fetchAllRecords(&mdsFuncs
, dlDb
);
541 crtn
= mdsFuncs
.DbClose(dlDb
);
543 printError("DbClose", crtn
);
549 printf("Enter new info type: ");
552 } while(keepConnected
);
553 crtn
= MDS_Terminate(mdsHand
);
555 printError("MDS_Terminate", crtn
);