1/* MDS per-thread basher */
2#include <time.h>
3#include <stdio.h>
4#include "testParams.h"
5#include <security_cdsa_client/mdsclient.h>
6
7/* for malloc debug */
8#define DO_PAUSE			0
9
10using namespace Security;
11
12/* most of this is cribbed from cspxutils/mdsLookup/ */
13
14/* free attribute(s) allocated by MDS */
15static void freeAttrs(
16	CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR	recordAttrs)
17{
18	unsigned i;
19
20	for(i=0; i<recordAttrs->NumberOfAttributes; i++) {
21		CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i];
22		if(attrData == NULL) {
23			/* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */
24			printf("***freeAttrs screwup: NULL attrData\n");
25			return;
26		}
27		unsigned j;
28		for(j=0; j<attrData->NumberOfValues; j++) {
29			CSSM_DATA_PTR data = &attrData->Value[j];
30			if(data == NULL) {
31				/* fault of MDS, who said there was a value here */
32				printf("***freeAttrs screwup: NULL data\n");
33				return;
34			}
35			/* we're using cdsa_client, what's the appFree equivalent? */
36			free(data->Data);
37			data->Data = NULL;
38			data->Length = 0;
39		}
40		free(attrData->Value);
41		attrData->Value = NULL;
42	}
43}
44
45static int doLookup(
46	MDSClient::Directory		&mds,
47
48	/* Record type, a.k.a. Relation, e.g. MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE */
49	CSSM_DB_RECORDTYPE			recordType,
50
51	/* key, value, valForm, and valOp are the thing we search on */
52	/* Note CSSM_DB_ATTRIBUTE_NAME_FORMAT - the format of the attribute name -
53	 *    is always CSSM_DB_ATTRIBUTE_NAME_AS_STRING for MDS. */
54	const char					*key,		// e.g. "AlgType"
55	const void					*valPtr,
56	unsigned					valLen,
57	CSSM_DB_ATTRIBUTE_FORMAT	valForm,	// CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc.
58	CSSM_DB_OPERATOR			valOp)		// normally CSSM_DB_EQUAL
59{
60	CSSM_QUERY						query;
61	CSSM_DB_UNIQUE_RECORD_PTR		record = NULL;
62	CSSM_HANDLE						resultHand;
63	CSSM_DB_RECORD_ATTRIBUTE_DATA	recordAttrs;
64	CSSM_SELECTION_PREDICATE		predicate;
65	CSSM_DATA						predData;
66	CSSM_DB_ATTRIBUTE_DATA			outAttr;
67	CSSM_DB_ATTRIBUTE_INFO_PTR		attrInfo;
68	const char 						*attrName = "ModuleID";
69
70	/* We want one attribute back, name and format specified by caller */
71	recordAttrs.DataRecordType = recordType;
72	recordAttrs.SemanticInformation = 0;
73	recordAttrs.NumberOfAttributes = 1;
74	recordAttrs.AttributeData = &outAttr;
75
76	memset(&outAttr, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA));
77	attrInfo = &outAttr.Info;
78	attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
79	attrInfo->Label.AttributeName = (char *)attrName;
80	attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
81
82	/* one predicate - the caller's key and CSSM_DB_OPERATOR */
83	predicate.DbOperator = valOp;
84	predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
85	predicate.Attribute.Info.Label.AttributeName = (char *)key;
86	predicate.Attribute.Info.AttributeFormat = valForm;
87	predData.Data = (uint8 *)valPtr;
88	predData.Length = valLen;
89	predicate.Attribute.Value = &predData;
90	predicate.Attribute.NumberOfValues = 1;
91
92	query.RecordType = recordType;
93	query.Conjunctive = CSSM_DB_NONE;
94	query.NumSelectionPredicates = 1;
95	query.SelectionPredicate = &predicate;
96	query.QueryLimits.TimeLimit = 0;			// FIXME - meaningful?
97	query.QueryLimits.SizeLimit = 1;			// FIXME - meaningful?
98	query.QueryFlags = 0;		// CSSM_QUERY_RETURN_DATA...FIXME - used?
99
100	/* until this API settles down bag this test */
101	#if 0
102		printf("doLookup: mds.dlGetFirst unstable' skipping!\n");
103		return -1;
104	#else
105	try {
106		/* 8A268 has this */
107		#if 0
108		resultHand = mds.dlGetFirst(query, recordAttrs, record);
109		#else
110		/* TOT */
111		resultHand = mds.dlGetFirst(query, recordAttrs, NULL, record);
112		#endif
113	}
114	catch(...) {
115		printf("doLookup: dlGetFirst threw exception!\n");
116		return -1;
117	}
118	#endif
119	if(resultHand == 0) {
120		printf("doLookup: no record found\n");
121		return -1;
122	}
123
124	/* we could examine the record here of we wanted to */
125	mds.dlFreeUniqueId(record);
126	freeAttrs(&recordAttrs);
127	mds.dlAbortQuery(resultHand);
128	return 0;
129}
130
131/* nothing here for now */
132int mdsLookupInit(TestParams *tp)
133{
134	return 0;
135}
136
137int mdsLookup(TestParams *testParams)
138{
139	for(unsigned loopNum=0; loopNum<testParams->numLoops; loopNum++) {
140		if(testParams->verbose) {
141			printf("mdsLookup loop %d\n", loopNum);
142		}
143		else if(!testParams->quiet) {
144			printChar(testParams->progressChar);
145		}
146		try {
147			MDSClient::Directory &mds = MDSClient::mds();
148			uint32 val = CSSM_ALGID_SHA1;
149			if(doLookup(mds, MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE,
150					"AlgType", &val, sizeof(uint32),
151					CSSM_DB_ATTRIBUTE_FORMAT_UINT32, CSSM_DB_EQUAL)) {
152				printf("***thread %u aborting\n", testParams->threadNum);
153				return -1;
154			}
155		}
156		catch(CssmError &err) {
157			cssmPerror("MDS init", err.error);
158			printf("mdsLookup: MDSClient::mds() threw CssmError!\n");
159			return -1;
160		}
161		catch(...) {
162			printf("mdsLookup: MDSClient::mds() threw exception!\n");
163			return -1;
164		}
165		#if	DO_PAUSE
166		fpurge(stdin);
167		printf("Hit CR to continue: ");
168		getchar();
169		#endif
170	}
171	return 0;
172}
173
174