#include <CoreFoundation/CoreFoundation.h>
#include <stdlib.h>
#include <stdio.h>
#include <Security/mds.h>
#include <common.h>
#include <Security/mds_schema.h>
#include "MDSSchema.h"
#include <strings.h>
#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
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; i<numSpaces; i++) {
putchar(' ');
}
}
#if 0
static void printValueAsString(
unsigned val,
const Security::MDSNameValuePair *nameValues) {
if(nameValues != NULL) {
while(nameValues->name != NULL) {
if(nameValues->value == val) {
printf("%s", nameValues->name);
return;
}
nameValues++;
}
}
printf("0x%x", val);
}
#endif
static void printValue(
const CSSM_DATA *attrValue)
{
printf("'");
for(uint32 dex=0; dex<attrValue->Length; dex++) {
printf("%c", attrValue->Data[dex]);
}
printf("'\n");
}
static void dumpAttr(
CSSM_DB_ATTRIBUTE_FORMAT attrForm,
const CSSM_DATA *attrData)
{
if((attrData == NULL) || (attrData->Data == NULL)) {
printf("<NULL DATA>\n");
return;
}
void *data = attrData->Data;
switch(attrForm) {
case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
printValue(attrData);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: 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; i<attrData->Length; 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<numInts; i++) {
if(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;
}
}
static void dumpRecord(
const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs)
{
unsigned dex;
for(dex=0; dex<recordAttrs->NumberOfAttributes; 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(": ");
for(unsigned attrNum=0; attrNum<attrData->NumberOfValues; attrNum++) {
dumpAttr(attrData->Info.AttributeFormat,
&attrData->Value[attrNum]);
}
if(attrData->NumberOfValues == 0) {
printf("<<no values present>>\n");
}
}
}
static void freeAttrs(
CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs)
{
unsigned i;
for(i=0; i<recordAttrs->NumberOfAttributes; i++) {
CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i];
if(attrData == NULL) {
printf("***freeAttrs screwup: NULL attrData\n");
return;
}
unsigned j;
for(j=0; j<attrData->NumberOfValues; j++) {
CSSM_DATA_PTR data = &attrData->Value[j];
if(data == NULL) {
printf("***freeAttrs screwup: NULL data\n");
return;
}
appFree(data->Data, NULL);
data->Data = NULL;
data->Length = 0;
}
appFree(attrData->Value, NULL);
attrData->Value = NULL;
}
}
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;
}
memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * MAX_MDS_ATTRS);
unsigned attrDex;
for(attrDex=0; attrDex<relInfo->NumberOfAttributes; attrDex++) {
attrs[attrDex].Info = relInfo->AttributeInfo[attrDex];
}
recordAttrs.DataRecordType = recordType;
recordAttrs.NumberOfAttributes = relInfo->NumberOfAttributes;
recordAttrs.AttributeData = attrs;
query.RecordType = recordType;
query.Conjunctive = CSSM_DB_NONE;
query.NumSelectionPredicates = 0;
query.SelectionPredicate = NULL;
query.QueryLimits.TimeLimit = 0; query.QueryLimits.SizeLimit = 1; query.QueryFlags = 0;
crtn = mdsFuncs->DataGetFirst(dlDb,
&query,
&resultHand,
&recordAttrs,
NULL, &record);
switch(crtn) {
case CSSM_OK:
break; 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);
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; case CSSMERR_DL_ENDOFDATA:
break;
default:
printError("DataGetNext", crtn);
break;
}
if(crtn != CSSM_OK) {
break;
}
}
}
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;
query.RecordType = CSSM_DL_DB_RECORD_ANY;
query.Conjunctive = CSSM_DB_NONE;
query.NumSelectionPredicates = 0;
query.SelectionPredicate = NULL;
query.QueryLimits.TimeLimit = 0; query.QueryLimits.SizeLimit = 1; query.QueryFlags = 0;
crtn = mdsFuncs->DataGetFirst(dlDb,
&query,
&resultHand,
&recordAttrs,
NULL, &record);
switch(crtn) {
case CSSM_OK:
break; 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);
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; case CSSMERR_DL_ENDOFDATA:
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<argc; arg++) {
switch(argv[arg][0]) {
case 'v':
verbose = true;
break;
case 'i':
install = true;
break;
case 'k':
keepConnected = true;
break;
default:
usage(argv);
}
}
if(verbose) {
printf("..calling MDS_Initialize\n");
}
crtn = MDS_Initialize(NULL, &memFuncs,
&mdsFuncs,
&mdsHand);
if(crtn) {
printError("MDS_Initialize", crtn);
exit(1);
}
if(install) {
doInstall(mdsHand);
}
do {
switch(op) {
case 'o':
case 'a':
dbName = (char *)MDS_OBJECT_DIRECTORY_NAME;
break;
default:
dbName = (char *)MDS_CDSA_DIRECTORY_NAME;
break;
}
crtn = mdsFuncs.DbOpen(mdsHand,
dbName,
NULL, CSSM_DB_ACCESS_READ,
NULL, NULL, &dbHand);
if(crtn) {
printError("DbOpen", crtn);
exit(1);
}
dlDb.DLHandle = mdsHand;
dlDb.DBHandle = dbHand;
switch(op) {
case 'o':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_OBJECT_RECORDTYPE);
break;
case 'C':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSSM_RECORDTYPE);
break;
case 'p':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_COMMON_RECORDTYPE);
break;
case 'c':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE);
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE);
if(verbose) {
fetchAllAttrs(&mdsFuncs, dlDb,
MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE);
fetchAllAttrs(&mdsFuncs, dlDb,
MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE);
}
break;
case 'l':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_CL_PRIMARY_RECORDTYPE);
break;
case 't':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_TP_PRIMARY_RECORDTYPE);
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_TP_OIDS_RECORDTYPE);
if(verbose) {
fetchAllAttrs(&mdsFuncs, dlDb,
MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE);
}
break;
case 'd':
fetchAllAttrs(&mdsFuncs, dlDb, MDS_CDSADIR_DL_PRIMARY_RECORDTYPE);
break;
case 'a':
case 'A':
fetchAllRecords(&mdsFuncs, dlDb);
break;
default:
usage(argv);
}
crtn = mdsFuncs.DbClose(dlDb);
if(crtn) {
printError("DbClose", crtn);
}
if(keepConnected) {
printf("\n");
showInfoTypes();
fpurge(stdin);
printf("Enter new info type: ");
op = getchar();
}
} while(keepConnected);
crtn = MDS_Terminate(mdsHand);
if(crtn) {
printError("MDS_Terminate", crtn);
}
return 0;
}