2 * mdsLookup.cpp - demonstrate some MDS lookups
7 #include <Security/mds.h>
8 #include <Security/mds_schema.h>
9 #include <Security/oidsalg.h> // for TP OIDs
13 /* the memory functions themselves are in utilLib/common.c. */
14 static CSSM_MEMORY_FUNCS memFuncs
= {
22 static void usage(char **argv
)
24 printf("Usage: %s [options]\n", argv
[0]);
26 printf(" k keep connected and go again\n");
30 #define NORM_KEY_LEN 10
32 /* print a key name, padding out to NORM_KEY_LEN columns */
33 static void printName(
36 printf(" %s", attrName
);
37 int len
= strlen(attrName
);
38 if(len
> NORM_KEY_LEN
) {
41 int numSpaces
= NORM_KEY_LEN
- len
;
42 for(int i
=0; i
<numSpaces
; i
++) {
48 /* print value string, surrounded by single quotes, then a newline */
49 static void printValue(
50 const CSSM_DATA
*attrValue
)
53 for(uint32 dex
=0; dex
<attrValue
->Length
; dex
++) {
54 printf("%c", attrValue
->Data
[dex
]);
59 /* Print one attribute value */
61 CSSM_DB_ATTRIBUTE_FORMAT attrForm
,
62 const CSSM_DATA
*attrData
)
64 if((attrData
== NULL
) || (attrData
->Data
== NULL
)) {
65 printf("<NULL DATA>\n");
68 void *data
= attrData
->Data
;
70 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
:
73 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32
: // not really supported in MDS
74 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32
:
76 unsigned val
= *(unsigned *)data
;
77 printf("0x%x\n", val
);
80 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
:
82 printf("BLOB length %u : ", (unsigned)attrData
->Length
);
83 for(unsigned i
=0; i
<attrData
->Length
; i
++) {
84 unsigned dat
= attrData
->Data
[i
];
90 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
:
93 uint32 numInts
= attrData
->Length
/ sizeof(uint32
);
94 uint32
*uip
= (uint32
*)data
;
95 for(unsigned i
=0; i
<numInts
; i
++) {
99 printf("0x%x", (unsigned)*uip
++);
105 printf("***UNKNOWN FORMAT (%u), Length %u\n",
106 (unsigned)attrForm
, (unsigned)attrData
->Length
);
112 * Vanilla "dump one record" routine. Assumes format of all attribute labels
115 static void dumpRecord(
116 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*recordAttrs
)
119 for(dex
=0; dex
<recordAttrs
->NumberOfAttributes
; dex
++) {
120 const CSSM_DB_ATTRIBUTE_DATA
*attrData
= &recordAttrs
->AttributeData
[dex
];
121 if(attrData
->Info
.AttributeNameFormat
!=
122 CSSM_DB_ATTRIBUTE_NAME_AS_STRING
) {
123 printf("***BAD ATTR_NAME FORMAT (%u)\n",
124 (unsigned)attrData
->Info
.AttributeNameFormat
);
127 const char *attrName
= attrData
->Info
.Label
.AttributeName
;
130 for(unsigned attrNum
=0; attrNum
<attrData
->NumberOfValues
; attrNum
++) {
131 dumpAttr(attrData
->Info
.AttributeFormat
,
132 &attrData
->Value
[attrNum
]);
134 if(attrData
->NumberOfValues
== 0) {
135 printf("<<no values present>>\n");
140 /* free attribute(s) allocated by MDS */
141 static void freeAttrs(
142 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs
)
146 for(i
=0; i
<recordAttrs
->NumberOfAttributes
; i
++) {
147 CSSM_DB_ATTRIBUTE_DATA_PTR attrData
= &recordAttrs
->AttributeData
[i
];
148 if(attrData
== NULL
) {
149 /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */
150 printf("***freeAttrs screwup: NULL attrData\n");
154 for(j
=0; j
<attrData
->NumberOfValues
; j
++) {
155 CSSM_DATA_PTR data
= &attrData
->Value
[j
];
157 /* fault of MDS, who said there was a value here */
158 printf("***freeAttrs screwup: NULL data\n");
161 appFree(data
->Data
, NULL
);
165 appFree(attrData
->Value
, NULL
);
166 attrData
->Value
= NULL
;
171 * Core MDS lookup routine. Used in two situations. It's called by main() to perform
172 * a lookup in the CDSA Directory Database based one one key/value pair; this
173 * call fetches one attribute from the associated record - the GUID ("ModuleID"
174 * in MDS lingo). Then the function calls itself to do a lookup in the Object DB,
175 * based on that GUID, in order to fetch the path of the module associated with
176 * that GUID. The first call (from main()) corresponds to an application's
177 * typical use of MDS. The recursive call, which does a lookup in the Object
178 * DB, corresponds to CSSM's typical use of MDS, which is to map a GUID to a
181 * The ModuleID and Path of all modules satisfying the initial search criteria
182 * are displayed on stdout.
184 * Caller specifies one search attribute, by name, value,Êand value format.
185 * Whether this is the first or second (recursive) call is indicated by the
186 * cdsaLookup argument. That determines both the DB to search and the attribute
187 * to fetch (ModuleID or Path).
189 static void doLookup(
192 /* Two DBs and a flag indicating which one to use */
193 MDS_DB_HANDLE objDlDb
,
194 MDS_DB_HANDLE cdsaDlDb
,
195 bool cdsaLookup
, // true - use cdsaDlDb; false - objDlDb
197 /* Record type, a.k.a. Relation, e.g. MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE */
198 CSSM_DB_RECORDTYPE recordType
,
200 /* key, value, valForm, and valOp are the thing we search on */
201 /* Note CSSM_DB_ATTRIBUTE_NAME_FORMAT - the format of the attribute name -
202 * is always CSSM_DB_ATTRIBUTE_NAME_AS_STRING for MDS. */
203 const char *key
, // e.g. "AlgType"
206 CSSM_DB_ATTRIBUTE_FORMAT valForm
, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc.
207 CSSM_DB_OPERATOR valOp
, // normally CSSM_DB_EQUAL
209 /* for display only */
213 CSSM_DB_UNIQUE_RECORD_PTR record
= NULL
;
214 CSSM_HANDLE resultHand
;
215 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs
;
216 CSSM_SELECTION_PREDICATE predicate
;
218 CSSM_DB_ATTRIBUTE_DATA outAttr
;
219 CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo
;
222 const char *attrName
;
225 /* first call, fetching guid from the CDSA Directory DB */
227 attrName
= "ModuleID";
230 /* recursive call, fetching path from Object DB */
235 /* We want one attributes back, name and format specified by caller */
236 recordAttrs
.DataRecordType
= recordType
;
237 recordAttrs
.SemanticInformation
= 0;
238 recordAttrs
.NumberOfAttributes
= 1;
239 recordAttrs
.AttributeData
= &outAttr
;
241 memset(&outAttr
, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA
));
242 attrInfo
= &outAttr
.Info
;
243 attrInfo
->AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
244 attrInfo
->Label
.AttributeName
= (char *)attrName
;
245 attrInfo
->AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_STRING
;
247 /* one predicate - the caller's key and CSSM_DB_OPERATOR */
248 predicate
.DbOperator
= valOp
;
249 predicate
.Attribute
.Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
250 predicate
.Attribute
.Info
.Label
.AttributeName
= (char *)key
;
251 predicate
.Attribute
.Info
.AttributeFormat
= valForm
;
252 predData
.Data
= (uint8
*)valPtr
;
253 predData
.Length
= valLen
;
254 predicate
.Attribute
.Value
= &predData
;
255 predicate
.Attribute
.NumberOfValues
= 1;
257 query
.RecordType
= recordType
;
258 query
.Conjunctive
= CSSM_DB_NONE
;
259 query
.NumSelectionPredicates
= 1;
260 query
.SelectionPredicate
= &predicate
;
261 query
.QueryLimits
.TimeLimit
= 0; // FIXME - meaningful?
262 query
.QueryLimits
.SizeLimit
= 1; // FIXME - meaningful?
263 query
.QueryFlags
= 0; // CSSM_QUERY_RETURN_DATA...FIXME - used?
265 crtn
= mdsFuncs
->DataGetFirst(dlDb
,
274 case CSSMERR_DL_ENDOFDATA
:
275 printf("%s: no record found\n", srchStr
);
278 printError("DataGetFirst", crtn
);
281 /* dump this record, one attribute */
283 /* not done on recursive call */
284 printf("%s found:\n", srchStr
);
286 dumpRecord(&recordAttrs
);
287 mdsFuncs
->FreeUniqueRecord(dlDb
, record
);
289 if(srchStr
!= NULL
) {
291 * Now do a lookup in Object DB of this guid, looking for path.
292 * Apps normally don't do this; this is what CSSM does when given
293 * the GUID of a module.
295 if(outAttr
.Value
== NULL
) {
296 printf("***Screwup: DataGetFirst worked, but no outAttr\n");
302 false, // use objDlDb
303 MDS_OBJECT_RECORDTYPE
,
305 outAttr
.Value
->Data
, // valPtr, ModuleID, as string
306 outAttr
.Value
->Length
, // valLen
307 CSSM_DB_ATTRIBUTE_FORMAT_STRING
,
311 freeAttrs(&recordAttrs
);
313 /* now the rest of them */
315 crtn
= mdsFuncs
->DataGetNext(dlDb
,
322 dumpRecord(&recordAttrs
);
323 mdsFuncs
->FreeUniqueRecord(cdsaDlDb
, record
);
324 if(srchStr
!= NULL
) {
325 if(outAttr
.Value
== NULL
) {
326 printf("***Screwup: DataGetNext worked, but no outAttr\n");
332 false, // use objDlDb
333 MDS_OBJECT_RECORDTYPE
,
335 outAttr
.Value
->Data
, // valPtr, ModuleID, as string
336 outAttr
.Value
->Length
, // valLen
337 CSSM_DB_ATTRIBUTE_FORMAT_STRING
,
341 freeAttrs(&recordAttrs
);
342 break; // and go again
343 case CSSMERR_DL_ENDOFDATA
:
344 /* normal termination */
347 printError("DataGetNext", crtn
);
350 if(crtn
!= CSSM_OK
) {
356 int main(int argc
, char **argv
)
362 CSSM_DB_HANDLE dbHand
= 0;
363 MDS_DB_HANDLE objDlDb
;
364 MDS_DB_HANDLE cdsaDlDb
;
365 bool keepConnected
= false;
368 for(arg
=2; arg
<argc
; arg
++) {
369 switch(argv
[arg
][0]) {
371 keepConnected
= true;
377 crtn
= MDS_Initialize(NULL
, // callerGuid
382 printError("MDS_Initialize", crtn
);
388 * Open both MDS DBs - apps normally only have to open
389 * MDS_CDSA_DIRECTORY_NAME.
391 crtn
= mdsFuncs
.DbOpen(mdsHand
,
392 MDS_OBJECT_DIRECTORY_NAME
,
395 NULL
, // AccessCred - hopefully optional
396 NULL
, // OpenParameters
399 printError("DbOpen(MDS_OBJECT_DIRECTORY_NAME)", crtn
);
402 objDlDb
.DLHandle
= mdsHand
;
403 objDlDb
.DBHandle
= dbHand
;
405 crtn
= mdsFuncs
.DbOpen(mdsHand
,
406 MDS_CDSA_DIRECTORY_NAME
,
409 NULL
, // AccessCred - hopefully optional
410 NULL
, // OpenParameters
413 printError("DbOpen(MDS_CDSA_DIRECTORY_NAME)", crtn
);
416 cdsaDlDb
.DLHandle
= mdsHand
;
417 cdsaDlDb
.DBHandle
= dbHand
;
420 * Do some typical lookups.
423 /* a CSP which can do SHA1 digest */
424 val
= CSSM_ALGID_SHA1
;
429 MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE
,
433 CSSM_DB_ATTRIBUTE_FORMAT_UINT32
,
435 "CSP for SHA1 digest");
437 /* a TP which can do iSign verification */
442 MDS_CDSADIR_TP_OIDS_RECORDTYPE
,
444 CSSMOID_APPLE_ISIGN
.Data
,
445 CSSMOID_APPLE_ISIGN
.Length
,
446 CSSM_DB_ATTRIBUTE_FORMAT_BLOB
,
448 "TP for CSSMOID_APPLE_ISIGN policy");
450 /* an X509-savvy CL */
451 /* Very weird data form - two fields in one 32-bit word */
452 val
= (CSSM_CERT_X_509v3
<< 16) | CSSM_CERT_ENCODING_DER
;
457 MDS_CDSADIR_CL_PRIMARY_RECORDTYPE
,
461 CSSM_DB_ATTRIBUTE_FORMAT_UINT32
,
465 /* A DL which can do CSSM_DB_AND */
471 MDS_CDSADIR_DL_PRIMARY_RECORDTYPE
,
475 CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
,
476 /* This is a multi-uint32, meaning we want to search for a
477 * ConjunctiveOps which contains the specified value */
479 "DL with ConjunctiveOp CSSM_DB_AND");
481 /* a CSP which can do CSSM_ALGID_IDEA, should fail */
482 val
= CSSM_ALGID_IDEA
;
487 MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE
,
491 CSSM_DB_ATTRIBUTE_FORMAT_UINT32
,
493 "CSP for CSSM_ALGID_BLOWFISH, expect failure");
495 /* a TP which can obtain a .mac signing certificate */
500 MDS_CDSADIR_TP_OIDS_RECORDTYPE
,
502 CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN
.Data
,
503 CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN
.Length
,
504 CSSM_DB_ATTRIBUTE_FORMAT_BLOB
,
506 "TP for .mac signing certificate policy");
508 crtn
= mdsFuncs
.DbClose(objDlDb
);
510 printError("DbClose(objDlDb)", crtn
);
512 crtn
= mdsFuncs
.DbClose(cdsaDlDb
);
514 printError("DbClose(cdsaDlDb)", crtn
);
519 printf("Enter CR to go again: ");
522 } while(keepConnected
);
523 crtn
= MDS_Terminate(mdsHand
);
525 printError("MDS_Terminate", crtn
);