X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/mdsdump/mdsdump.cpp diff --git a/SecurityTests/cspxutils/mdsdump/mdsdump.cpp b/SecurityTests/cspxutils/mdsdump/mdsdump.cpp new file mode 100644 index 00000000..15d50cc4 --- /dev/null +++ b/SecurityTests/cspxutils/mdsdump/mdsdump.cpp @@ -0,0 +1,558 @@ +/* + * mdsdump.cpp - dump contents of system MDS databases + */ + + /**** FIXME this uses a private API not currently exported in any way from + **** Security project + ****/ + +#include +#include +#include +#include +#include +#include +#include "MDSSchema.h" +#include + +#define MAX_MDS_ATTRS 32 + +static CSSM_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +static void showInfoTypes() +{ + printf(" o Object records\n"); + printf(" C CSSM records\n"); + printf(" p Plugin Common records\n"); + printf(" c CSP records\n"); + printf(" l CL records\n"); + printf(" t TP records\n"); + printf(" d DL records\n"); + printf(" a All records from Object DB\n"); + printf(" A All records from CDSA directory DB\n"); +} + +static void usage(char **argv) +{ + printf("Usage: %s info_type [options...]\n", argv[0]); + printf("info_type values:\n"); + showInfoTypes(); + printf(" h help\n"); + printf("Options:\n"); + printf(" i perform MDS_Install()\n"); + printf(" v verbose\n"); + printf(" k keep connected and go again\n"); + exit(1); +} + +#define NORM_KEY_LEN 20 + +/* print a key name, padding out to NORM_KEY_LEN columns */ +static void printName( + const char *attrName) +{ + printf(" %s", attrName); + int len = strlen(attrName); + if(len > NORM_KEY_LEN) { + return; + } + int numSpaces = NORM_KEY_LEN - len; + for(int i=0; iname != NULL) { + if(nameValues->value == val) { + printf("%s", nameValues->name); + return; + } + nameValues++; + } + } + /* Oh well */ + printf("0x%x", val); +} +#endif + +/* print value string, surrounded by single quotes, then a newline */ +static void printValue( + const CSSM_DATA *attrValue) +{ + printf("'"); + for(uint32 dex=0; dexLength; dex++) { + printf("%c", attrValue->Data[dex]); + } + printf("'\n"); +} + +/* Print one attribute value */ +static void dumpAttr( + CSSM_DB_ATTRIBUTE_FORMAT attrForm, + const CSSM_DATA *attrData) +{ + if((attrData == NULL) || (attrData->Data == NULL)) { + printf("\n"); + return; + } + void *data = attrData->Data; + switch(attrForm) { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + printValue(attrData); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: // not really supported in MDS + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + unsigned val = *(unsigned *)data; + printf("0x%x\n", val); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + { + printf("BLOB length %u : ", (unsigned)attrData->Length); + for(unsigned i=0; iLength; i++) { + unsigned dat = attrData->Data[i]; + printf("%02X ", dat); + } + printf("\n"); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + printf("multi_int["); + uint32 numInts = attrData->Length / sizeof(uint32); + uint32 *uip = (uint32 *)data; + for(unsigned i=0; i 0) { + printf(", "); + } + printf("0x%x", (unsigned)(*uip++)); + } + printf("]\n"); + break; + } + default: + printf("***UNKNOWN FORMAT (%u), Length %u\n", + (unsigned)attrForm, (unsigned)attrData->Length); + break; + } +} + +/* + * Vanilla "dump one record" routine. Assumes format of all attribute labels + * as string. Uses a MDSNameValuePair ptr array in parallel to the attributes + * themselves to facilitate displaying numeric values as strings (e.g. + * "CSSM_ALGID_SHA1") where possible. + */ +static void dumpRecord( + const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs) +{ + unsigned dex; + for(dex=0; dexNumberOfAttributes; dex++) { + const CSSM_DB_ATTRIBUTE_DATA *attrData = &recordAttrs->AttributeData[dex]; + if(attrData->Info.AttributeNameFormat != CSSM_DB_ATTRIBUTE_NAME_AS_STRING) { + printf("***BAD ATTR_NAME FORMAT (%u)\n", + (unsigned)attrData->Info.AttributeNameFormat); + continue; + } + const char *attrName = attrData->Info.Label.AttributeName; + printName(attrName); + printf(": "); + /* note currently in MDS NumberOfValues is always one or zero */ + for(unsigned attrNum=0; attrNumNumberOfValues; attrNum++) { + dumpAttr(attrData->Info.AttributeFormat, + &attrData->Value[attrNum]); + } + if(attrData->NumberOfValues == 0) { + printf("<>\n"); + } + } +} + +/* free attribute(s) allocated by MDS */ +static void freeAttrs( + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs) +{ + unsigned i; + + for(i=0; iNumberOfAttributes; i++) { + CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i]; + if(attrData == NULL) { + /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */ + printf("***freeAttrs screwup: NULL attrData\n"); + return; + } + unsigned j; + for(j=0; jNumberOfValues; j++) { + CSSM_DATA_PTR data = &attrData->Value[j]; + if(data == NULL) { + /* fault of MDS, who said there was a value here */ + printf("***freeAttrs screwup: NULL data\n"); + return; + } + appFree(data->Data, NULL); + data->Data = NULL; + data->Length = 0; + } + appFree(attrData->Value, NULL); + attrData->Value = NULL; + } +} + +/* + * Fetch and display all records of specified CSSM_DB_RECORDTYPE. + */ +static void fetchAllAttrs( + MDS_FUNCS *mdsFuncs, + MDS_DB_HANDLE dlDb, + CSSM_DB_RECORDTYPE recordType) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_ATTRIBUTE_DATA attrs[MAX_MDS_ATTRS]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + const RelationInfo *relInfo; + + relInfo = MDSRecordTypeToRelation(recordType); + if(relInfo == NULL) { + printf("***UNKNOWN recordType %d\n", (int)recordType); + return; + } + + /* build an attr array from schema so we get all known attrs */ + memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * MAX_MDS_ATTRS); + unsigned attrDex; + for(attrDex=0; attrDexNumberOfAttributes; attrDex++) { + attrs[attrDex].Info = relInfo->AttributeInfo[attrDex]; + } + recordAttrs.DataRecordType = recordType; + recordAttrs.NumberOfAttributes = relInfo->NumberOfAttributes; + recordAttrs.AttributeData = attrs; + + /* just search by recordType, no predicates */ + query.RecordType = recordType; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = mdsFuncs->DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("%s: no record found\n", relInfo->relationName); + return; + default: + printError("DataGetFirst", crtn); + return; + } + unsigned recNum = 0; + printf("%s:\n", relInfo->relationName); + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = mdsFuncs->DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +/* + * This is different - it's schema-independent. Fetch all records from specified + * DlDb which contain a ModuleID attribute. + */ +static void fetchAllRecords( + MDS_FUNCS *mdsFuncs, + MDS_DB_HANDLE dlDb) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA theAttr; + CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo = &theAttr.Info; + CSSM_DATA attrValue = {0, NULL}; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_ANY; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = 1; + recordAttrs.AttributeData = &theAttr; + + attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attrInfo->Label.AttributeName = (char *)"ModuleID"; + attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING; + + theAttr.NumberOfValues = 1; + theAttr.Value = &attrValue; + + /* just search by recordType, no predicates */ + query.RecordType = CSSM_DL_DB_RECORD_ANY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = mdsFuncs->DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("no record found\n"); + return; + default: + printError("DataGetFirst", crtn); + return; + } + unsigned recNum = 0; + printf("Records containing a ModuleID attribute:\n"); + printf(" record %d:\n", recNum++); + + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = mdsFuncs->DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + printf(" record %d:\n", recNum++); + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +static void doInstall( + MDS_HANDLE mdsHand) +{ + CFAbsoluteTime start, end; + + start = CFAbsoluteTimeGetCurrent(); + CSSM_RETURN crtn = MDS_Install(mdsHand); + end = CFAbsoluteTimeGetCurrent(); + if(crtn) { + printError("MDS_Install", crtn); + } + else { + printf("MDS_Install took %gs\n", end - start); + } +} + +int main(int argc, char **argv) +{ + MDS_FUNCS mdsFuncs; + MDS_HANDLE mdsHand; + CSSM_RETURN crtn; + int arg; + char op; + char *dbName; + CSSM_DB_HANDLE dbHand = 0; + MDS_DB_HANDLE dlDb; + bool verbose = 0; + bool keepConnected = false; + bool install = false; + + if(argc < 2) { + usage(argv); + } + op = argv[1][0]; + if(op == 'h') { + usage(argv); + } + for(arg=2; arg