#include <stdlib.h>
#include <stdio.h>
#include <Security/mds.h>
#include <Security/mds_schema.h>
#include <Security/oidsalg.h> // for TP OIDs
#include "common.h"
#include <strings.h>
static CSSM_MEMORY_FUNCS memFuncs = {
appMalloc,
appFree,
appRealloc,
appCalloc,
NULL
};
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" k keep connected and go again\n");
exit(1);
}
#define NORM_KEY_LEN 10
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(' ');
}
}
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 doLookup(
MDS_FUNCS *mdsFuncs,
MDS_DB_HANDLE objDlDb,
MDS_DB_HANDLE cdsaDlDb,
bool cdsaLookup,
CSSM_DB_RECORDTYPE recordType,
const char *key, const void *valPtr,
unsigned valLen,
CSSM_DB_ATTRIBUTE_FORMAT valForm, CSSM_DB_OPERATOR valOp,
const char *srchStr)
{
CSSM_QUERY query;
CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
CSSM_HANDLE resultHand;
CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
CSSM_SELECTION_PREDICATE predicate;
CSSM_DATA predData;
CSSM_DB_ATTRIBUTE_DATA outAttr;
CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo;
CSSM_RETURN crtn;
MDS_DB_HANDLE dlDb;
const char *attrName;
if(cdsaLookup) {
dlDb = cdsaDlDb;
attrName = "ModuleID";
}
else {
dlDb = objDlDb;
attrName = "Path";
}
recordAttrs.DataRecordType = recordType;
recordAttrs.SemanticInformation = 0;
recordAttrs.NumberOfAttributes = 1;
recordAttrs.AttributeData = &outAttr;
memset(&outAttr, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA));
attrInfo = &outAttr.Info;
attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attrInfo->Label.AttributeName = (char *)attrName;
attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
predicate.DbOperator = valOp;
predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
predicate.Attribute.Info.Label.AttributeName = (char *)key;
predicate.Attribute.Info.AttributeFormat = valForm;
predData.Data = (uint8 *)valPtr;
predData.Length = valLen;
predicate.Attribute.Value = &predData;
predicate.Attribute.NumberOfValues = 1;
query.RecordType = recordType;
query.Conjunctive = CSSM_DB_NONE;
query.NumSelectionPredicates = 1;
query.SelectionPredicate = &predicate;
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", srchStr);
return;
default:
printError("DataGetFirst", crtn);
return;
}
if(srchStr) {
printf("%s found:\n", srchStr);
}
dumpRecord(&recordAttrs);
mdsFuncs->FreeUniqueRecord(dlDb, record);
if(srchStr != NULL) {
if(outAttr.Value == NULL) {
printf("***Screwup: DataGetFirst worked, but no outAttr\n");
return;
}
doLookup(mdsFuncs,
objDlDb,
cdsaDlDb,
false, MDS_OBJECT_RECORDTYPE,
"ModuleID", outAttr.Value->Data, outAttr.Value->Length, CSSM_DB_ATTRIBUTE_FORMAT_STRING,
CSSM_DB_EQUAL,
NULL); }
freeAttrs(&recordAttrs);
for(;;) {
crtn = mdsFuncs->DataGetNext(dlDb,
resultHand,
&recordAttrs,
NULL,
&record);
switch(crtn) {
case CSSM_OK:
dumpRecord(&recordAttrs);
mdsFuncs->FreeUniqueRecord(cdsaDlDb, record);
if(srchStr != NULL) {
if(outAttr.Value == NULL) {
printf("***Screwup: DataGetNext worked, but no outAttr\n");
return;
}
doLookup(mdsFuncs,
objDlDb,
cdsaDlDb,
false, MDS_OBJECT_RECORDTYPE,
"ModuleID", outAttr.Value->Data, outAttr.Value->Length, CSSM_DB_ATTRIBUTE_FORMAT_STRING,
CSSM_DB_EQUAL,
NULL); }
freeAttrs(&recordAttrs);
break; case CSSMERR_DL_ENDOFDATA:
break;
default:
printError("DataGetNext", crtn);
break;
}
if(crtn != CSSM_OK) {
break;
}
}
}
int main(int argc, char **argv)
{
MDS_FUNCS mdsFuncs;
MDS_HANDLE mdsHand;
CSSM_RETURN crtn;
int arg;
CSSM_DB_HANDLE dbHand = 0;
MDS_DB_HANDLE objDlDb;
MDS_DB_HANDLE cdsaDlDb;
bool keepConnected = false;
uint32 val;
for(arg=2; arg<argc; arg++) {
switch(argv[arg][0]) {
case 'k':
keepConnected = true;
break;
default:
usage(argv);
}
}
crtn = MDS_Initialize(NULL, &memFuncs,
&mdsFuncs,
&mdsHand);
if(crtn) {
printError("MDS_Initialize", crtn);
exit(1);
}
do {
crtn = mdsFuncs.DbOpen(mdsHand,
MDS_OBJECT_DIRECTORY_NAME,
NULL, CSSM_DB_ACCESS_READ,
NULL, NULL, &dbHand);
if(crtn) {
printError("DbOpen(MDS_OBJECT_DIRECTORY_NAME)", crtn);
exit(1);
}
objDlDb.DLHandle = mdsHand;
objDlDb.DBHandle = dbHand;
crtn = mdsFuncs.DbOpen(mdsHand,
MDS_CDSA_DIRECTORY_NAME,
NULL, CSSM_DB_ACCESS_READ,
NULL, NULL, &dbHand);
if(crtn) {
printError("DbOpen(MDS_CDSA_DIRECTORY_NAME)", crtn);
exit(1);
}
cdsaDlDb.DLHandle = mdsHand;
cdsaDlDb.DBHandle = dbHand;
val = CSSM_ALGID_SHA1;
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE,
"AlgType",
&val,
sizeof(uint32),
CSSM_DB_ATTRIBUTE_FORMAT_UINT32,
CSSM_DB_EQUAL,
"CSP for SHA1 digest");
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_TP_OIDS_RECORDTYPE,
"OID",
CSSMOID_APPLE_ISIGN.Data,
CSSMOID_APPLE_ISIGN.Length,
CSSM_DB_ATTRIBUTE_FORMAT_BLOB,
CSSM_DB_EQUAL,
"TP for CSSMOID_APPLE_ISIGN policy");
val = (CSSM_CERT_X_509v3 << 16) | CSSM_CERT_ENCODING_DER;
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_CL_PRIMARY_RECORDTYPE,
"CertTypeFormat",
&val,
sizeof(uint32),
CSSM_DB_ATTRIBUTE_FORMAT_UINT32,
CSSM_DB_EQUAL,
"X509 CL");
val = CSSM_DB_AND;
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_DL_PRIMARY_RECORDTYPE,
"ConjunctiveOps",
&val,
sizeof(uint32),
CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32,
CSSM_DB_CONTAINS,
"DL with ConjunctiveOp CSSM_DB_AND");
val = CSSM_ALGID_IDEA;
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE,
"AlgType",
&val,
sizeof(uint32),
CSSM_DB_ATTRIBUTE_FORMAT_UINT32,
CSSM_DB_EQUAL,
"CSP for CSSM_ALGID_BLOWFISH, expect failure");
doLookup(&mdsFuncs,
objDlDb,
cdsaDlDb,
true,
MDS_CDSADIR_TP_OIDS_RECORDTYPE,
"OID",
CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN.Data,
CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN.Length,
CSSM_DB_ATTRIBUTE_FORMAT_BLOB,
CSSM_DB_EQUAL,
"TP for .mac signing certificate policy");
crtn = mdsFuncs.DbClose(objDlDb);
if(crtn) {
printError("DbClose(objDlDb)", crtn);
}
crtn = mdsFuncs.DbClose(cdsaDlDb);
if(crtn) {
printError("DbClose(cdsaDlDb)", crtn);
}
if(keepConnected) {
printf("\n");
fpurge(stdin);
printf("Enter CR to go again: ");
getchar();
}
} while(keepConnected);
crtn = MDS_Terminate(mdsHand);
if(crtn) {
printError("MDS_Terminate", crtn);
}
return 0;
}