1/*
2 * g++ -F/usr/local/SecurityPieces/Frameworks -g -Wall path/to/xdr_test.cpp
3 * -framework [securityd_client, security_cdsa_utilities, security_utilities]
4 *
5 * -W triggers a lot of warnings in Security code....
6 */
7#include <stdio.h>
8#include <rpc/types.h>	/* bool_t */
9#include <stdlib.h>		/* exit(3), malloc(3) */
10#include <string.h>		/* memcmp(3), memset(3), strdup(3) */
11#include <fcntl.h>		/* open(2) */
12#include <errno.h>		/* errno */
13#include <sys/types.h>	/* read() */
14#include <sys/uio.h>	/* read() */
15#include <unistd.h>		/* read(), getopt(3) */
16#include <Security/cssmtype.h>
17#include <security_cdsa_utilities/walkers.h>
18#include <security_cdsa_utilities/context.h>
19#include <security_cdsa_utilities/cssmaclpod.h>
20#include <securityd_client/xdr_cssm.h>
21#include "securityd_data_saver.h"
22
23using Security::DataWalkers::Copier;
24
25const char *testString = "FOOBAR";
26
27/*
28 * securityd is extremely sloppy about zeroing out data fields it doesn't
29 * use.  It's unlikely that sloppiness will be cleaned up in one fell
30 * swoop, so we'll never be able to set this to 0; instead, search on the
31 * symbol name and selectively unbracket code as securityd is fixed.
32 */
33#define SECURITYD_SENDS_GARBAGE	1
34
35
36/*
37 * The securityd RPC protocol can't handle 64-bit quantities until both
38 * securityd itself and our XDR implementation do.  Ergo, don't be tempted
39 * to make ALIGNMENT depend on __LP64__.
40 *
41 * ALIGNMENT and ALIGNUP borrowed from libsecurityd, sec_xdr.c.  They
42 * really should be defined once in a more central location, like
43 * libsecurity_utilities.
44 */
45#define LP64_FULLY_SUPPORTED	0
46
47#if LP64_FULLY_SUPPORTED
48#define ALIGNMENT 8
49#else
50#define ALIGNMENT 4
51#endif	// LP64_FULLY_SUPPORTED
52
53#define ALIGNUP(LEN)		(((LEN - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT)
54#define ALIGNSIZE(TYPE)		ALIGNUP(sizeof(TYPE))
55
56#define NULLCHECK(a, b, func) \
57	if (!(a) && !(b))\
58		return OK;\
59	else if (!(a) && (b) || (a) && !(b))\
60	{\
61		fprintf(stderr, "%s (NULL and non-NULL parameter)\n", (func));\
62		return MISMATCH;\
63	}
64
65#define N_ITERS			3		/* # of encode/decode cycles */
66
67#define OK				  0
68#define XDR_ENCODE_ERROR -1
69#define XDR_DECODE_ERROR -2
70#define MISMATCH		 -3
71#define UNKNOWN_TYPE	 -4		/* invalid union discriminator */
72#define MEM_ERROR		-10
73#define BAD_PARAM		-11
74#define BAD_FILE		-12
75#define BAD_READ		-13
76#define READ_EOF		-14		/* not an error per se */
77#define INCOMPATIBLE	-98		/* input data format not recognized */
78#define NOT_IMPLEMENTED	-99
79
80/* This isn't publicly exposed */
81#ifdef __cplusplus
82extern "C" {
83extern unsigned long xdr_sizeof(xdrproc_t, void *);
84}
85#endif
86
87/*
88 * CSSM data structures of interest.  Chosen either for their complexity
89 * (e.g., CSSM_CONTEXT) or their ubiquity (CSSM_DATA).
90 *
91 * CSSM_DATA
92 * CSSM_GUID
93 * CSSM_CRYPTO_DATA (possible callback)
94 * CSSM_LIST_ELEMENT (union)
95 * CSSM_LIST (pointers)
96 * CSSM_SAMPLEGROUP (array of CSSM_SAMPLEs)
97 * CSSM_DATE (fixed-size arrays handled via xdr_vector())
98 * CSSM_KEY (heavily used)
99 * CSSM_DB_RECORD_ATTRIBUTE_DATA (exercises a lot of the above)
100 * CSSM_CONTEXT (exercises a lot of the above)
101 * AccessCredentials
102 * CSSM_AUTHORIZATIONGROUP
103 * CSSM_ACL_VALIDITY_PERIOD
104 * CSSM_ACL_ENTRY_PROTOTYPE
105 * CSSM_ACL_OWNER_PROTOTYPE
106 * CSSM_ACL_ENTRY_INPUT
107 * CSSM_ACL_ENTRY_INFO
108 * CSSM_QUERY
109 */
110
111/* utility routines */
112bool_t xdr_stdio(void *data, xdrproc_t proc, enum xdr_op op);	/* XXX/gh  needed? */
113bool_t xdr_mem_encode(void *input, void **output, u_int *outlen,
114					  xdrproc_t proc);
115bool_t xdr_mem_decode(void *input, void *output, u_int bytesNeeded,
116					  xdrproc_t proc);
117void flip(uint8_t *addr, size_t size);
118int readPreamble(int fd, uint32_t *doflip, uint32_t *vers, uint32_t *type);
119int fill_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr,
120								CSSM_ATTRIBUTE_TYPE type,
121								uint32_t attrlen,
122								void *attrval);
123
124/* byte reordering routines */
125void hostorder_CSSM_DATA(CSSM_DATA *data, off_t offset);
126void hostorder_CSSM_GUID(CSSM_GUID *guid);
127void hostorder_CSSM_VERSION(CSSM_VERSION *version);
128void hostorder_CSSM_SUBSERVICE_UID(CSSM_SUBSERVICE_UID *ssuid);
129void hostorder_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *crypto, off_t offset);
130void hostorder_CSSM_LIST(CSSM_LIST *list, off_t offset);
131void hostorder_CSSM_LIST_ELEMENT(CSSM_LIST_ELEMENT *element, off_t offset);
132void hostorder_CSSM_SAMPLE(CSSM_SAMPLE *sample, off_t offset);
133void hostorder_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp, off_t offset);
134void hostorder_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert, off_t offset);
135void hostorder_CSSM_CERTGROUP(CSSM_CERTGROUP *grp, off_t offset);
136void hostorder_CSSM_BASE_CERTS(CSSM_BASE_CERTS *certs, off_t offset);
137void hostorder_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds,
138									   off_t offset);
139void hostorder_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp,
140									   off_t offset);
141void hostorder_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period,
142										off_t offset);
143void hostorder_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto,
144										off_t offset);
145void hostorder_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto,
146										off_t offset);
147void hostorder_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input, off_t offset);
148void hostorder_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info, off_t offset);
149void hostorder_CSSM_KEYHEADER(CSSM_KEYHEADER *key);
150void hostorder_CSSM_KEY(CSSM_KEY *key, off_t offset);
151void hostorder_CSSM_DL_DB_HANDLE(CSSM_DL_DB_HANDLE *handle);
152void hostorder_CSSM_RANGE(CSSM_RANGE *range);
153void hostorder_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr,
154									  off_t offset);
155void hostorder_CSSM_CONTEXT(CSSM_CONTEXT *ctx, CSSM_CONTEXT_ATTRIBUTE *attrs);
156void hostorder_CSSM_OID(CSSM_OID *oid, off_t offset);
157void hostorder_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo,
158									  off_t offset);
159void hostorder_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata,
160									  off_t offset);
161void hostorder_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred,
162										off_t offset);
163void hostorder_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits);
164void hostorder_CSSM_QUERY(CSSM_QUERY *range, off_t offset);
165
166/* comparators */
167int compare_CSSM_DATA(CSSM_DATA *data1, CSSM_DATA *data2);
168int compare_CSSM_SUBSERVICE_UID(const CSSM_SUBSERVICE_UID *ssuid1,
169								const CSSM_SUBSERVICE_UID *ssuid2);
170int compare_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *data1, CSSM_CRYPTO_DATA *data2);
171int compare_CSSM_LIST(const CSSM_LIST *list1, const CSSM_LIST *list2);
172int compare_CSSM_SAMPLE(const CSSM_SAMPLE *sample1, const CSSM_SAMPLE *sample2);
173int compare_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp1, CSSM_SAMPLEGROUP *sgrp2);
174int compare_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert1,
175							  CSSM_ENCODED_CERT *cert2);
176int compare_CSSM_CERTGROUP(CSSM_CERTGROUP *grp1, CSSM_CERTGROUP *grp2);
177int compare_CSSM_BASE_CERTS(CSSM_BASE_CERTS *bases1, CSSM_BASE_CERTS *bases2);
178int compare_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds1,
179									CSSM_ACCESS_CREDENTIALS *creds2);
180int compare_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp1,
181									CSSM_AUTHORIZATIONGROUP *grp2);
182int compare_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period1,
183									 CSSM_ACL_VALIDITY_PERIOD *period2);
184int compare_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto1,
185									 CSSM_ACL_ENTRY_PROTOTYPE *proto2,
186									 int skipGarbage);
187int compare_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto1,
188									 CSSM_ACL_OWNER_PROTOTYPE *proto2);
189int compare_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input1,
190								 CSSM_ACL_ENTRY_INPUT *input2);
191int compare_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info1,
192								CSSM_ACL_ENTRY_INFO *info2);
193int compare_CSSM_DATE(CSSM_DATE *date1, CSSM_DATE *date2);
194int compare_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr1, CSSM_KEYHEADER *hdr2);
195int compare_CSSM_KEY(CSSM_KEY *key1, CSSM_KEY *key2);
196int compare_CSSM_RANGE(CSSM_RANGE *range1, CSSM_RANGE *range2);
197int compare_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr1,
198								   CSSM_CONTEXT_ATTRIBUTE *attr2);
199int compare_CSSM_OID(CSSM_OID *oid1, CSSM_OID *oid2);
200int compare_CSSM_CONTEXT(CSSM_CONTEXT *ctx1, CSSM_CONTEXT *ctx2);
201int compare_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo1,
202								   CSSM_DB_ATTRIBUTE_INFO *attrinfo2);
203int compare_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata1,
204								   CSSM_DB_ATTRIBUTE_DATA *attrdata2);
205int compare_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred1,
206									 CSSM_SELECTION_PREDICATE *pred2);
207int compare_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits1,
208							  CSSM_QUERY_LIMITS *limits2);
209int compare_CSSM_QUERY(CSSM_QUERY *query1, CSSM_QUERY *query2);
210
211CSSM_RETURN dummyCSSMCallback(CSSM_DATA *data, void *context);
212CSSM_RETURN dummyACLSubjectCallback(const CSSM_LIST *subjectRequest,
213									void *callerContext,
214									const CSSM_MEMORY_FUNCS *MemFuncs);
215
216/* the actual test functions */
217int test_CSSM_DB_RECORD_ATTRIBUTE_DATA(const char *srcfile);	/* TODO/gh */
218int test_xdrwalk_CSSM_CONTEXT(CSSM_CONTEXT *ctx, int dbglvl);
219int test_CSSM_CONTEXT(int fd, int doflip, int dbglvl);
220int test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype, int dbglvl);
221int test_CSSM_ACL_OWNER_PROTOTYPE(int fd, int doflip, int dbglvl);
222int test_xdrwalk_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *aclEntryInput,
223									  int dbglvl);
224int test_CSSM_ACL_ENTRY_INPUT(int fd, int doflip, int dbglvl);
225int test_xdrwalk_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *aclEntryInfo,
226									 int dbglvl);
227int test_CSSM_ACL_ENTRY_INFO(int fd, int doflip, int dbglvl);
228int test_xdrwalk_CSSM_QUERY(CSSM_QUERY *query, int dbglvl);
229int test_CSSM_QUERY(int fd, int doflip, int dbglvl);
230
231
232/**************************************************************************
233 * misc utility functions
234 **************************************************************************/
235
236/* XXX/gh  needed? */
237/* XXX/gh  should "data" be a uint8_t *? */
238bool_t xdr_stdio(void *data, xdrproc_t proc, enum xdr_op op)
239{
240	XDR xdr;
241	/* should we call xdrstdio_create(...,..., XDR_FREE) when done? */
242	xdrstdio_create(&xdr, stdout, op);
243	if (proc(&xdr, data))
244		return (FALSE);
245	return (TRUE);
246}
247
248/* note no error-checking of parameters */
249bool_t xdr_mem_encode(void *input, void **output, u_int *outlen,
250					  xdrproc_t proc)
251{
252	XDR xdr;
253	char *data;
254	u_int length;
255
256	length = xdr_sizeof(proc, input);
257	if ((data = (char *)malloc(length)) == NULL)
258	{
259		fprintf(stderr, "xdr_mem_encode(): malloc() error\n");
260		return (FALSE);
261	}
262	xdrmem_create(&xdr, data, length, XDR_ENCODE);
263	if (!proc(&xdr, input))
264	{
265		fprintf(stderr, "xdr_mem_encode(): XDR error\n");
266		free(data);
267		return (FALSE);
268	}
269	*output = data;
270	if (outlen)
271		*outlen = length;
272	return (TRUE);
273}
274
275/* note no error-checking of parameters */
276bool_t xdr_mem_decode(void *input, void *output, u_int bytesNeeded,
277					  xdrproc_t proc)
278{
279	XDR xdr;
280
281	xdrmem_create(&xdr, (char *)input, bytesNeeded, XDR_DECODE);
282	if (!proc(&xdr, output))
283		return (FALSE);
284	return (TRUE);
285}
286
287/*
288 * Because sometimes ntoh*() isn't enough.  Stolen from securityd and
289 * slightly modified to avoid type dependencies.
290 */
291void flip(void *inaddr, size_t size)
292{
293	uint8 *addr = reinterpret_cast<uint8 *>(inaddr);
294	size_t n;
295
296	assert(size > 1 && (size % 2 == 0));
297	uint8_t *word = addr;
298	for (n = 0; n < size/2; n++)
299	{
300		uint8_t b = word[n];
301		word[n] = word[size-1-n];
302		word[size-1-n] = b;
303	}
304}
305
306/*
307 * note that if this returns prematurely, you can make no assumption about
308 * the value of "doflip," "vers," or "type"
309 */
310int readPreamble(int fd, uint32_t *doflip, uint32_t *vers, uint32_t *type)
311{
312	const char *func = "readPreamble()";
313	uint32_t value;
314	ssize_t bytesRead;
315
316	/* byte order sentry value */
317	if ((bytesRead = read(fd, &value, sizeof(value))) != sizeof(value))
318	{
319		if (bytesRead == 0)
320			return READ_EOF;
321		fprintf(stderr, "%s: error reading byte order sentry\n", func);
322		return BAD_READ;
323	}
324	if (value == SecuritydDataSave::sentry)
325		*doflip = 0;
326	else if (value == 0x34120000)
327		*doflip = 1;
328	else
329	{
330		fprintf(stderr, "%s: unrecognized sentry value %d\n", func, value);
331		return INCOMPATIBLE;
332	}
333
334	/* version info (for this disk-saving protocol) */
335	if (read(fd, &value, sizeof(value)) != sizeof(value))
336	{
337		fprintf(stderr, "%s: error reading data format version\n", func);
338		return BAD_READ;
339	}
340	if (*doflip)
341		flip(&value, sizeof(value));
342	*vers = value;
343
344	switch(*vers)
345	{
346		case 1:
347			/* type of record */
348			if (read(fd, &value, sizeof(value)) != sizeof(value))
349			{
350				fprintf(stderr, "%s: error reading data type\n", func);
351				return BAD_READ;
352			}
353			if (*doflip)
354				flip(&value, sizeof(value));
355			*type = value;
356			break;
357		default:
358			fprintf(stderr, "%s: incompatible version (expected <= %d, got %d)\n",
359					func, SecuritydDataSave::version, *vers);
360			return INCOMPATIBLE;
361			break;
362	}
363	return OK;
364}
365
366int fill_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr,
367								CSSM_ATTRIBUTE_TYPE type,
368								uint32_t attrlen,
369								void *attrval)
370{
371	if (!attr || !attrval)
372		return BAD_PARAM;
373	attr->AttributeType = type;
374	attr->AttributeLength = attrlen;
375	/* XXX  copy instead of assigning */
376	switch (type & CSSM_ATTRIBUTE_TYPE_MASK)
377	{
378		case CSSM_ATTRIBUTE_DATA_UINT32:
379			attr->Attribute.Uint32 = *(reinterpret_cast<uint32_t *>(attrval));
380			break;
381		case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
382			attr->Attribute.Data = (CSSM_DATA_PTR)attrval;
383			break;
384		case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
385			attr->Attribute.CryptoData = (CSSM_CRYPTO_DATA_PTR)attrval;
386			break;
387		case CSSM_ATTRIBUTE_DATA_KEY:
388			attr->Attribute.Key = (CSSM_KEY_PTR)attrval;
389			break;
390		case CSSM_ATTRIBUTE_DATA_STRING:
391			attr->Attribute.String = (char *)attrval;
392			break;
393		case CSSM_ATTRIBUTE_DATA_DATE:
394			attr->Attribute.Date = (CSSM_DATE_PTR)attrval;
395			break;
396		case CSSM_ATTRIBUTE_DATA_RANGE:
397			attr->Attribute.Range = (CSSM_RANGE_PTR)attrval;
398			break;
399		case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
400			attr->Attribute.AccessCredentials = (CSSM_ACCESS_CREDENTIALS_PTR)attrval;
401			break;
402		case CSSM_ATTRIBUTE_DATA_VERSION:
403			attr->Attribute.Version = (CSSM_VERSION_PTR)attrval;
404			break;
405		case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
406			attr->Attribute.DLDBHandle = (CSSM_DL_DB_HANDLE_PTR)attrval;
407			break;
408		/* _KR_PROFILE not supported? */
409		default:
410			return BAD_PARAM;
411	}
412	return OK;
413}
414
415
416/**************************************************************************
417 * These do their best to handle byte-ordering issues.
418 *
419 * Note that pointers are generally (maybe always) byte-order swapped in
420 * these routines, since you generally need to do some kind of arithmetic
421 * with them (relocation).
422 **************************************************************************/
423
424void hostorder_CSSM_DATA(CSSM_DATA *data, off_t offset)
425{
426	intptr_t newaddr;		/* for readability */
427
428	if (!data) return;
429	flip(&data->Length, sizeof(data->Length));
430	if (data->Data)
431	{
432		flip(&data->Data, sizeof(data->Data));
433		newaddr = reinterpret_cast<intptr_t>(data->Data) + offset;
434		data->Data = reinterpret_cast<uint8 *>(newaddr);
435	}
436}
437
438void hostorder_CSSM_GUID(CSSM_GUID *guid)
439{
440	if (!guid) return;
441	flip(&guid->Data1, sizeof(guid->Data1));
442	flip(&guid->Data2, sizeof(guid->Data2));
443	flip(&guid->Data3, sizeof(guid->Data3));
444}
445
446void hostorder_CSSM_VERSION(CSSM_VERSION *version)
447{
448	if (!version) return;
449	flip(&version->Major, sizeof(version->Major));
450	flip(&version->Minor, sizeof(version->Minor));
451}
452
453void hostorder_CSSM_SUBSERVICE_UID(CSSM_SUBSERVICE_UID *ssuid)
454{
455	if (!ssuid) return;
456	hostorder_CSSM_GUID(&ssuid->Guid);
457	hostorder_CSSM_VERSION(&ssuid->Version);
458	flip(&ssuid->SubserviceId, sizeof(ssuid->SubserviceId));
459	flip(&ssuid->SubserviceType, sizeof(ssuid->SubserviceType));
460}
461
462void hostorder_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *crypto, off_t offset)
463{
464	if (!crypto) return;
465	hostorder_CSSM_DATA(&crypto->Param, offset);
466	flip(&crypto->Callback, sizeof(crypto->Callback));
467	flip(&crypto->CallerCtx, sizeof(crypto->CallerCtx));
468}
469
470void hostorder_CSSM_LIST(CSSM_LIST *list, off_t offset)
471{
472	CSSM_LIST_ELEMENT_PTR ptr;
473	intptr_t newaddr;			/* for readability */
474
475	if (!list) return;
476
477	flip(&list->ListType, sizeof(list->ListType));
478
479	if (list->Head)
480	{
481		flip(&list->Head, sizeof(list->Head));
482		newaddr = reinterpret_cast<intptr_t>(list->Head) + offset;
483		list->Head = reinterpret_cast<CSSM_LIST_ELEMENT *>(newaddr);
484	}
485
486	if (list->Tail)
487	{
488		flip(&list->Tail, sizeof(list->Tail));
489		newaddr = reinterpret_cast<intptr_t>(list->Tail) + offset;
490		list->Tail = reinterpret_cast<CSSM_LIST_ELEMENT *>(newaddr);
491	}
492
493	for (ptr = list->Head; ptr != NULL; ptr = ptr->NextElement)
494	{
495		hostorder_CSSM_LIST_ELEMENT(ptr, offset);
496	}
497}
498
499void hostorder_CSSM_LIST_ELEMENT(CSSM_LIST_ELEMENT *element, off_t offset)
500{
501	intptr_t newaddr;			/* for readability */
502
503	if (!element) return;
504
505	if (element->NextElement)
506	{
507		flip(&element->NextElement, sizeof(element->NextElement));
508		newaddr = reinterpret_cast<intptr_t>(element->NextElement) + offset;
509		element->NextElement = reinterpret_cast<CSSM_LIST_ELEMENT_PTR>(newaddr);
510	}
511
512	flip(&element->WordID, sizeof(element->WordID));
513	flip(&element->ElementType, sizeof(element->ElementType));
514	switch (element->ElementType)
515	{
516		case CSSM_LIST_ELEMENT_DATUM:
517			hostorder_CSSM_DATA(&element->Element.Word, offset);
518			break;
519		case CSSM_LIST_ELEMENT_SUBLIST:
520			hostorder_CSSM_LIST(&element->Element.Sublist, offset);
521			break;
522		case CSSM_LIST_ELEMENT_WORDID:
523			break;
524		default:
525			fprintf(stderr, "hostorder_CSSM_LIST_ELEMENT() (unknown ListElement type)\n");
526	}
527}
528
529void hostorder_CSSM_SAMPLE(CSSM_SAMPLE *sample, off_t offset)
530{
531	CSSM_SUBSERVICE_UID *ptr;
532
533	if (!sample) return;
534	hostorder_CSSM_LIST(&sample->TypedSample, offset);
535	if (sample->Verifier)
536	{
537		ptr = const_cast<CSSM_SUBSERVICE_UID *>(sample->Verifier);
538		flip(&ptr, sizeof(CSSM_SUBSERVICE_UID *));
539		sample->Verifier = reinterpret_cast<CSSM_SUBSERVICE_UID *>(reinterpret_cast<intptr_t>(ptr) + offset);
540		/* Verifier had better not be really and truly immutable... */
541		hostorder_CSSM_SUBSERVICE_UID(const_cast<CSSM_SUBSERVICE_UID *>(sample->Verifier));
542	}
543}
544
545void hostorder_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp, off_t offset)
546{
547	u_int i;
548	CSSM_SAMPLE *ptr;
549
550	if (!sgrp) return;
551	flip(&sgrp->NumberOfSamples, sizeof(sgrp->NumberOfSamples));
552	if (sgrp->Samples)
553	{
554		ptr = const_cast<CSSM_SAMPLE *>(sgrp->Samples);
555		flip(&ptr, sizeof(ptr));
556		sgrp->Samples = reinterpret_cast<CSSM_SAMPLE *>(reinterpret_cast<intptr_t>(ptr) + offset);
557		for (i = 0; i < sgrp->NumberOfSamples; ++i)
558		{
559			hostorder_CSSM_SAMPLE(const_cast<CSSM_SAMPLE *>(&sgrp->Samples[i]), offset);
560		}
561	}
562}
563
564void hostorder_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert, off_t offset)
565{
566	if (!cert) return;
567	flip(&cert->CertType, sizeof(cert->CertType));
568	flip(&cert->CertEncoding, sizeof(cert->CertEncoding));
569	hostorder_CSSM_DATA(&cert->CertBlob, offset);
570}
571
572void hostorder_CSSM_CERTGROUP(CSSM_CERTGROUP *grp, off_t offset)
573{
574	const char *func = "hostorder_CSSM_CERTGROUP()";
575	intptr_t newaddr;			/* for readability */
576	u_int i;
577
578	if (!grp) return;
579	flip(&grp->CertType, sizeof(grp->CertType));
580	flip(&grp->CertEncoding, sizeof(grp->CertEncoding));
581	flip(&grp->NumCerts, sizeof(grp->NumCerts));
582	/* Any field in the union will do; CertList is the shortest to type */
583	if (grp->GroupList.CertList)
584	{
585		flip(&grp->GroupList.CertList, sizeof(CSSM_DATA *));
586		newaddr = reinterpret_cast<intptr_t>(grp->GroupList.CertList) + offset;
587		grp->GroupList.CertList = reinterpret_cast<CSSM_DATA_PTR>(newaddr);
588	}
589	/* handled out of order of definition since for() loop depends on it */
590	flip(&grp->CertGroupType, sizeof(grp->CertGroupType));
591
592	/* Note: we will crash if GroupList contains NULL and NumCerts > 0 */
593	for (i = 0; i < grp->NumCerts; ++i)
594	{
595		char *err = NULL;
596
597		switch (grp->CertGroupType)
598		{
599			case CSSM_CERTGROUP_DATA:
600				hostorder_CSSM_DATA(&grp->GroupList.CertList[i], offset);
601				break;
602			/* damned if I can find an example of the others */
603			case CSSM_CERTGROUP_ENCODED_CERT:
604				/* See the cautionary note in compare_CSSM_CERTGROUP() */
605				hostorder_CSSM_ENCODED_CERT(&grp->GroupList.EncodedCertList[i],
606											offset);
607				break;
608			case CSSM_CERTGROUP_PARSED_CERT:
609				err = "CSSM_CERTGROUP_PARSED_CERT unimplemented";
610				break;
611			case CSSM_CERTGROUP_CERT_PAIR:
612				err = "CSSM_CERTGROUP_CERT_PAIR unimplemented";
613				break;
614			default:
615				err = "unknown type";
616				break;
617		}
618		if (err)
619		{
620			fprintf(stderr, "%s (%s)\n", func, err);
621			return;
622		}
623	}
624	flip(&grp->Reserved, sizeof(grp->Reserved));
625	/* Depending on how Reserved is used, this code might be required
626	newaddr = reinterpret_cast<intptr_t>(grp->Reserved) + offset;
627	grp->Reserved = reinterpret_cast<void *>(newaddr);
628	*/
629}
630
631void hostorder_CSSM_BASE_CERTS(CSSM_BASE_CERTS *certs, off_t offset)
632{
633	if (!certs) return;
634	flip(&certs->TPHandle, sizeof(certs->TPHandle));
635	flip(&certs->CLHandle, sizeof(certs->CLHandle));
636	hostorder_CSSM_CERTGROUP(&certs->Certs, offset);
637}
638
639void hostorder_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp,
640									   off_t offset)
641{
642	intptr_t newaddr;		/* for readability */
643	uint32_t i;
644
645	flip(&grp->NumberOfAuthTags, sizeof(grp->NumberOfAuthTags));
646	if (grp->AuthTags)
647	{
648		flip(&grp->AuthTags, sizeof(grp->AuthTags));
649		newaddr = reinterpret_cast<intptr_t>(grp->AuthTags) + offset;
650		grp->AuthTags = reinterpret_cast<CSSM_ACL_AUTHORIZATION_TAG *>(newaddr);
651	}
652	for (i = 0; i < grp->NumberOfAuthTags; ++i)
653	{
654		flip(&grp->AuthTags[i], sizeof(CSSM_ACL_AUTHORIZATION_TAG));
655	}
656}
657
658void hostorder_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period,
659										off_t offset)
660{
661	hostorder_CSSM_DATA(&period->StartDate, offset);
662	hostorder_CSSM_DATA(&period->EndDate, offset);
663}
664
665void hostorder_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto,
666										off_t offset)
667{
668	hostorder_CSSM_LIST(&proto->TypedSubject, offset);
669	flip(&proto->Delegate, sizeof(proto->Delegate));
670}
671
672void hostorder_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto,
673										off_t offset)
674{
675	hostorder_CSSM_LIST(&proto->TypedSubject, offset);
676	flip(&proto->Delegate, sizeof(proto->Delegate));
677	hostorder_CSSM_AUTHORIZATIONGROUP(&proto->Authorization, offset);
678	hostorder_CSSM_ACL_VALIDITY_PERIOD(&proto->TimeRange, offset);
679}
680
681void hostorder_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input, off_t offset)
682{
683	hostorder_CSSM_ACL_ENTRY_PROTOTYPE(&input->Prototype, offset);
684	flip(&input->Callback, sizeof(input->Callback));
685	flip(&input->CallerContext, sizeof(input->CallerContext));
686}
687
688void hostorder_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info, off_t offset)
689{
690	hostorder_CSSM_ACL_ENTRY_PROTOTYPE(&info->EntryPublicInfo, offset);
691	flip(&info->EntryHandle, sizeof(info->EntryHandle));
692}
693
694void hostorder_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds,
695									   off_t offset)
696{
697	if (!creds) return;
698	hostorder_CSSM_BASE_CERTS(&creds->BaseCerts, offset);
699	hostorder_CSSM_SAMPLEGROUP(&creds->Samples, offset);
700	flip(&creds->Callback, sizeof(creds->Callback));
701	flip(&creds->CallerCtx, sizeof(creds->CallerCtx));
702}
703
704void hostorder_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr)
705{
706	if (!hdr) return;
707	flip(&hdr->HeaderVersion, sizeof(hdr->HeaderVersion));
708	flip(&hdr->BlobType, sizeof(hdr->BlobType));
709	flip(&hdr->Format, sizeof(hdr->Format));
710	flip(&hdr->AlgorithmId, sizeof(hdr->AlgorithmId));
711	flip(&hdr->KeyClass, sizeof(hdr->KeyClass));
712	flip(&hdr->LogicalKeySizeInBits, sizeof(hdr->LogicalKeySizeInBits));
713	flip(&hdr->KeyAttr, sizeof(hdr->KeyAttr));
714	flip(&hdr->KeyUsage, sizeof(hdr->KeyUsage));
715	flip(&hdr->WrapAlgorithmId, sizeof(hdr->WrapAlgorithmId));
716	flip(&hdr->WrapMode, sizeof(hdr->WrapMode));
717	flip(&hdr->Reserved, sizeof(hdr->Reserved));
718}
719
720void hostorder_CSSM_KEY(CSSM_KEY *key, off_t offset)
721{
722	if (!key) return;
723	hostorder_CSSM_KEYHEADER(&key->KeyHeader);
724	hostorder_CSSM_DATA(&key->KeyData, offset);
725}
726
727void hostorder_CSSM_DL_DB_HANDLE(CSSM_DL_DB_HANDLE *handle)
728{
729	if (!handle) return;
730	/*
731	 * XXX/gh  offset is needed if these values are being treated as
732	 * as pointers!
733	 */
734	flip(&handle->DLHandle, sizeof(handle->DLHandle));
735	flip(&handle->DBHandle, sizeof(handle->DBHandle));
736}
737
738void hostorder_CSSM_RANGE(CSSM_RANGE *range)
739{
740	if (!range) return;
741	flip(&range->Min, sizeof(range->Min));
742	flip(&range->Max, sizeof(range->Max));
743}
744
745void hostorder_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr,
746									  off_t offset)
747{
748	if (!attr) return;
749	flip(&attr->AttributeType, sizeof(attr->AttributeType));
750	flip(&attr->AttributeLength, sizeof(attr->AttributeLength));
751	if ((attr->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) == CSSM_ATTRIBUTE_DATA_UINT32)
752	{
753		flip(&attr->Attribute.Uint32, sizeof(attr->Attribute.Uint32));
754	}
755	else
756	{
757		intptr_t newaddr;			/* for readability */
758
759		/* any pointer accessor of the union will do */
760		if (attr->Attribute.String)
761		{
762			flip(&attr->Attribute.String, sizeof(attr->Attribute.String));
763			newaddr = reinterpret_cast<intptr_t>(attr->Attribute.String) + offset;
764			attr->Attribute.String = reinterpret_cast<char *>(newaddr);
765		}
766		switch (attr->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK)
767		{
768			case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
769				hostorder_CSSM_DATA(attr->Attribute.Data, offset);
770				break;
771			case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
772				hostorder_CSSM_CRYPTO_DATA(attr->Attribute.CryptoData, offset);
773				break;
774			case CSSM_ATTRIBUTE_DATA_KEY:
775				hostorder_CSSM_KEY(attr->Attribute.Key, offset);
776				break;
777			case CSSM_ATTRIBUTE_DATA_STRING:
778			case CSSM_ATTRIBUTE_DATA_DATE:
779				break;
780			case CSSM_ATTRIBUTE_DATA_RANGE:
781				hostorder_CSSM_RANGE(attr->Attribute.Range);
782				break;
783			case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
784				hostorder_CSSM_ACCESS_CREDENTIALS(attr->Attribute.AccessCredentials, offset);
785				break;
786			case CSSM_ATTRIBUTE_DATA_VERSION:
787				hostorder_CSSM_VERSION(attr->Attribute.Version);
788				break;
789			case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
790				hostorder_CSSM_DL_DB_HANDLE(attr->Attribute.DLDBHandle);
791				break;
792			/* _KR_PROFILE not supported? */
793			default:
794				fprintf(stderr, "hostorder_CSSM_CONTEXT_ATTRIBUTE(): unrecognized attribute type\n");
795		}
796	}	/* end if (CSSM_ATTRIBUTE_DATA_UINT32 */
797}
798
799void hostorder_CSSM_CONTEXT(CSSM_CONTEXT *ctx, CSSM_CONTEXT_ATTRIBUTE *attrs)
800{
801	off_t offset;
802	uint32_t i;
803
804	if (!ctx) return;
805	flip(&ctx->ContextType, sizeof(ctx->ContextType));
806	flip(&ctx->AlgorithmType, sizeof(ctx->AlgorithmType));
807	flip(&ctx->NumberOfAttributes, sizeof(ctx->NumberOfAttributes));
808	if (ctx->ContextAttributes)
809	{
810		flip(&ctx->ContextAttributes, sizeof(ctx->ContextAttributes));
811		offset = reinterpret_cast<intptr_t>(attrs) - reinterpret_cast<intptr_t>(ctx->ContextAttributes);
812		ctx->ContextAttributes = reinterpret_cast<CSSM_CONTEXT_ATTRIBUTE *>(attrs);
813	}
814	for (i = 0; i < ctx->NumberOfAttributes; ++i)
815	{
816		hostorder_CSSM_CONTEXT_ATTRIBUTE(&ctx->ContextAttributes[i], offset);
817	}
818	flip(&ctx->CSPHandle, sizeof(ctx->CSPHandle));
819	flip(&ctx->Privileged, sizeof(ctx->Privileged));
820	flip(&ctx->EncryptionProhibited, sizeof(ctx->EncryptionProhibited));
821	flip(&ctx->WorkFactor, sizeof(ctx->WorkFactor));
822	flip(&ctx->Reserved, sizeof(ctx->Reserved));
823}
824
825void hostorder_CSSM_OID(CSSM_OID *oid, off_t offset)
826{
827	hostorder_CSSM_DATA(reinterpret_cast<CSSM_DATA *>(oid), offset);
828}
829
830void hostorder_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo,
831									  off_t offset)
832{
833	if (!attrinfo) return;
834	flip(&attrinfo->AttributeNameFormat, sizeof(attrinfo->AttributeNameFormat));
835	switch(attrinfo->AttributeNameFormat)
836	{
837		case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
838		{
839			intptr_t newaddr;			/* for readability */
840			flip(&attrinfo->Label.AttributeName, sizeof(attrinfo->Label.AttributeName));
841			newaddr = reinterpret_cast<intptr_t>(attrinfo->Label.AttributeName) + offset;
842			attrinfo->Label.AttributeName = reinterpret_cast<char *>(newaddr);
843			break;
844		}
845		case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
846			hostorder_CSSM_OID(&attrinfo->Label.AttributeOID, offset);
847			break;
848		case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
849			flip(&attrinfo->Label.AttributeID, sizeof(attrinfo->Label.AttributeID));
850			break;
851		default:
852			break;		/* error, but no way to tell caller */
853	}
854	flip(&attrinfo->AttributeFormat, sizeof(attrinfo->AttributeFormat));
855}
856
857void hostorder_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata,
858									  off_t offset)
859{
860	uint32_t i;
861
862	if (!attrdata) return;
863	hostorder_CSSM_DB_ATTRIBUTE_INFO(&attrdata->Info, offset);
864	flip(&attrdata->NumberOfValues, sizeof(attrdata->NumberOfValues));
865	for (i = 0; i < attrdata->NumberOfValues; ++i)
866	{
867		hostorder_CSSM_DATA(&attrdata->Value[i], offset);
868	}
869}
870
871void hostorder_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred,
872										off_t offset)
873{
874	if (!pred) return;
875	flip(&pred->DbOperator, sizeof(pred->DbOperator));
876	hostorder_CSSM_DB_ATTRIBUTE_DATA(&pred->Attribute, offset);
877}
878
879void hostorder_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits)
880{
881	if (!limits) return;
882	flip(&limits->TimeLimit, sizeof(limits->TimeLimit));
883	flip(&limits->SizeLimit, sizeof(limits->SizeLimit));
884}
885
886void hostorder_CSSM_QUERY(CSSM_QUERY *query, off_t offset)
887{
888	uint32_t i;
889
890	if (!query) return;
891	flip(&query->RecordType, sizeof(query->RecordType));
892	flip(&query->Conjunctive, sizeof(query->Conjunctive));
893	flip(&query->NumSelectionPredicates, sizeof(query->NumSelectionPredicates));
894	if (query->SelectionPredicate)
895	{
896		intptr_t newaddr;		/* for readability */
897
898		flip(&query->SelectionPredicate, sizeof(query->SelectionPredicate));
899		newaddr = reinterpret_cast<intptr_t>(query->SelectionPredicate) + offset;
900		query->SelectionPredicate = reinterpret_cast<CSSM_SELECTION_PREDICATE *>(newaddr);
901	}
902	for (i = 0; i < query->NumSelectionPredicates; ++i)
903	{
904		hostorder_CSSM_SELECTION_PREDICATE(&query->SelectionPredicate[i], offset);
905	}
906	hostorder_CSSM_QUERY_LIMITS(&query->QueryLimits);
907	flip(&query->QueryFlags, sizeof(query->QueryFlags));
908}
909
910
911/**************************************************************************
912 * Comparators--data integrity checking routines.
913 *
914 * Each comparator compares two of the same high-level data structure, one
915 * of which is presumed to have been through at least one
916 * encoding/decoding cycle; these comparators check for errors introduced
917 * during that cycle.
918 *
919 * TODO/gh  A hand-crafted function per type seems sloppy, not well thought
920 * out.  I bet I could leverage part of the walker machinery to create a
921 * more elegant solution (a "comparison walker," anyone?).  Whether the
922 * result would be maintainable is, of course, a different question....
923 **************************************************************************/
924
925int compare_CSSM_DATA(CSSM_DATA *data1, CSSM_DATA *data2)
926{
927	const char *func = "compare_CSSM_DATA()";
928
929	NULLCHECK(data1, data2, func);
930	if (data1->Length != data2->Length ||
931		memcmp(data1->Data, data2->Data, data1->Length))
932	{
933		fprintf(stderr, "%s (mismatch)\n", func);
934		return MISMATCH;
935	}
936	return OK;
937}
938
939int compare_CSSM_SUBSERVICE_UID(const CSSM_SUBSERVICE_UID *ssuid1,
940								const CSSM_SUBSERVICE_UID *ssuid2)
941{
942	const char *func = "compare_CSSM_SUBSERVICE_UID()";
943
944	NULLCHECK(ssuid1, ssuid2, func);
945	if (memcmp(&ssuid1->Guid, &ssuid2->Guid, sizeof(CSSM_GUID))          ||
946		memcmp(&ssuid1->Version, &ssuid2->Version, sizeof(CSSM_VERSION)) ||
947		ssuid1->SubserviceId   != ssuid2->SubserviceId                   ||
948		ssuid1->SubserviceType != ssuid2->SubserviceType)
949	{
950		fprintf(stderr, "%s (mismatch)\n", func);
951		return MISMATCH;
952	}
953	return OK;
954}
955
956int compare_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *data1, CSSM_CRYPTO_DATA *data2)
957{
958	const char *func = "compare_CSSM_CRYPTO_DATA()";
959	int ret;
960
961	NULLCHECK(data1, data2, func);
962	if ((ret = compare_CSSM_DATA(&data1->Param, &data2->Param)) != OK)
963	{
964		fprintf(stderr, "%s\n", func);
965		return ret;
966	}
967	if (data1->Callback  != data2->Callback  ||
968		data1->CallerCtx != data2->CallerCtx)
969	{
970		fprintf(stderr, "%s (mismatch)\n", func);
971		return MISMATCH;
972	}
973	return OK;
974}
975
976int compare_CSSM_LIST(const CSSM_LIST *list1, const CSSM_LIST *list2)
977{
978	const char *func = "compare_CSSM_LIST()";
979	CSSM_LIST_ELEMENT_PTR p1, p2;
980	int ret;
981
982	NULLCHECK(list1, list2, func);
983	if (list1->ListType != list2->ListType)
984	{
985		fprintf(stderr, "%s (ListType)\n", func);
986		return MISMATCH;
987	}
988	for (p1 = list1->Head, p2 = list2->Head;
989		 p1 != NULL && p2 != NULL;
990		 p1 = p1->NextElement, p2 = p2->NextElement)
991	{
992		if (p1->ElementType != p2->ElementType)
993		{
994			fprintf(stderr, "%s (ListElements' ElementType)\n", func);
995			return MISMATCH;
996		}
997		switch (p1->ElementType)
998		{
999			case CSSM_LIST_ELEMENT_DATUM:
1000				ret = compare_CSSM_DATA(&p1->Element.Word, &p2->Element.Word);
1001				if (ret != OK)
1002				{
1003					fprintf(stderr, "%s\n", func);
1004					return ret;
1005				}
1006				break;
1007			case CSSM_LIST_ELEMENT_SUBLIST:
1008				ret = compare_CSSM_LIST(&p1->Element.Sublist, &p2->Element.Sublist);
1009				if (ret != OK)
1010				{
1011					fprintf(stderr, "%s\n", func);
1012					return ret;
1013				}
1014				break;
1015			case CSSM_LIST_ELEMENT_WORDID:
1016				if (p1->WordID != p2->WordID)
1017				{
1018					fprintf(stderr, "%s (ListElements' WordID)\n", func);
1019					return MISMATCH;
1020				}
1021				break;
1022			default:
1023				fprintf(stderr, "%s (unknown ListElement type)\n", func);
1024				return UNKNOWN_TYPE;
1025		}
1026		if ((p1->NextElement == NULL && p1 != list1->Tail) ||
1027			(p2->NextElement == NULL && p2 != list2->Tail))
1028		{
1029			fprintf(stderr, "%s (tail mismatch)\n", func);
1030			return MISMATCH;
1031		}
1032	}
1033	if (p1 != NULL || p2 != NULL)	/* lists didn't both terminate */
1034	{
1035		fprintf(stderr, "%s (unequal lists)\n", func);
1036		return MISMATCH;
1037	}
1038	return OK;
1039}
1040
1041int compare_CSSM_SAMPLE(const CSSM_SAMPLE *sample1, const CSSM_SAMPLE *sample2)
1042{
1043	const char *func = "compare_CSSM_SAMPLE()";
1044	int ret;
1045
1046	NULLCHECK(sample1, sample2, func);
1047	ret = compare_CSSM_LIST(&sample1->TypedSample, &sample2->TypedSample);
1048	if (ret != OK)
1049	{
1050		fprintf(stderr, "%s\n", func);
1051		return ret;
1052	}
1053	if (sample1->Verifier && sample2->Verifier)
1054	{
1055		ret = compare_CSSM_SUBSERVICE_UID(sample1->Verifier, sample2->Verifier);
1056		if (ret != OK)
1057		{
1058			fprintf(stderr, "%s\n", func);
1059			return ret;
1060		}
1061	}
1062	else if (sample1->Verifier && !sample2->Verifier ||
1063			 !sample1->Verifier && sample2->Verifier)
1064	{
1065		fprintf(stderr, "%s (Verifier mismatch)\n", func);
1066		return MISMATCH;
1067	}
1068	return OK;
1069}
1070
1071int compare_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp1, CSSM_SAMPLEGROUP *sgrp2)
1072{
1073	const char *func = "compare_CSSM_SAMPLEGROUP()";
1074	int ret;
1075	u_int i;
1076
1077	NULLCHECK(sgrp1, sgrp2, func);
1078	if (sgrp1->NumberOfSamples != sgrp2->NumberOfSamples)
1079	{
1080		fprintf(stderr, "%s (NumberOfSamples mismatch)\n", func);
1081		return MISMATCH;
1082	}
1083	for (i = 0; i < sgrp1->NumberOfSamples; ++i)
1084	{
1085		ret = compare_CSSM_SAMPLE(&sgrp1->Samples[i], &sgrp2->Samples[i]);
1086		if (ret != OK)
1087		{
1088			fprintf(stderr, "%s\n", func);
1089			return ret;
1090		}
1091	}
1092	return OK;
1093}
1094
1095int compare_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert1,
1096							  CSSM_ENCODED_CERT *cert2)
1097{
1098	const char *func = "compare_CSSM_ENCODED_CERT()";
1099	int ret;
1100
1101	NULLCHECK(cert1, cert2, func);
1102	if (cert1->CertType     != cert2->CertType     ||
1103		cert1->CertEncoding != cert2->CertEncoding)
1104	{
1105		fprintf(stderr, "%s (mismatch)\n", func);
1106		return MISMATCH;
1107	}
1108	if ((ret = compare_CSSM_DATA(&cert1->CertBlob, &cert2->CertBlob)) != OK)
1109		fprintf(stderr, "%s\n", func);
1110	return ret;
1111}
1112
1113int compare_CSSM_CERTGROUP(CSSM_CERTGROUP *grp1, CSSM_CERTGROUP *grp2)
1114{
1115	const char *func = "compare_CSSM_CERTGROUP()";
1116	int ret;
1117	u_int i;
1118
1119	NULLCHECK(grp1, grp2, func);
1120	if (grp1->CertType      != grp2->CertType      ||
1121		grp1->CertEncoding  != grp2->CertEncoding  ||
1122		grp1->NumCerts      != grp2->NumCerts      ||
1123		grp1->CertGroupType != grp2->CertGroupType ||
1124		grp1->Reserved      != grp2->Reserved)
1125	{
1126		fprintf(stderr, "%s (mismatch)\n", func);
1127		return MISMATCH;
1128	}
1129	for (i = 0; i < grp1->NumCerts; ++i)
1130	{
1131		char *err = NULL;
1132
1133		switch (grp1->CertGroupType)
1134		{
1135			case CSSM_CERTGROUP_DATA:
1136				ret = compare_CSSM_DATA(&grp1->GroupList.CertList[i],
1137										&grp2->GroupList.CertList[i]);
1138				break;
1139			/* damned if I can find an example of the others */
1140			case CSSM_CERTGROUP_ENCODED_CERT:
1141				/*
1142				 * This is apparently in use (see CertGroup in
1143				 * cdsa_utilities, cssmcert.{cpp,h}), but it's just a
1144				 * guess that it's implemented in the same way as
1145				 * CSSM_CERTGROUP_DATA...
1146				 */
1147				ret = compare_CSSM_ENCODED_CERT(&grp1->GroupList.EncodedCertList[i],
1148												&grp2->GroupList.EncodedCertList[i]);
1149				break;
1150			case CSSM_CERTGROUP_PARSED_CERT:
1151				err = "CSSM_CERTGROUP_PARSED_CERT unimplemented";
1152				ret = NOT_IMPLEMENTED;
1153				break;
1154			case CSSM_CERTGROUP_CERT_PAIR:
1155				err = "CSSM_CERTGROUP_CERT_PAIR unimplemented";
1156				ret = NOT_IMPLEMENTED;
1157				break;
1158			default:
1159				err = "unknown type";
1160				ret = UNKNOWN_TYPE;
1161				break;
1162		}
1163		if (ret != OK)
1164		{
1165			if (err)
1166				fprintf(stderr, "%s (%s)\n", func, err);
1167			else
1168				fprintf(stderr, "%s\n", func);
1169			return ret;
1170		}
1171	}
1172	return OK;
1173}
1174
1175int compare_CSSM_BASE_CERTS(CSSM_BASE_CERTS *bases1, CSSM_BASE_CERTS *bases2)
1176{
1177	const char *func = "compare_CSSM_BASE_CERTS()";
1178	int ret;
1179
1180	NULLCHECK(bases1, bases2, func);
1181	if (bases1->TPHandle != bases2->TPHandle ||
1182		bases1->CLHandle != bases2->CLHandle)
1183	{
1184		fprintf(stderr, "%s (mismatch)\n", func);
1185		return MISMATCH;
1186	}
1187	ret = compare_CSSM_CERTGROUP(&bases1->Certs, &bases2->Certs);
1188	if (ret != OK)
1189	{
1190		fprintf(stderr, "%s\n", func);
1191		return ret;
1192	}
1193	return OK;
1194}
1195
1196int compare_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds1,
1197									CSSM_ACCESS_CREDENTIALS *creds2)
1198{
1199	const char *func = "compare_CSSM_ACCESS_CREDENTIALS()";
1200	int ret;
1201
1202	NULLCHECK(creds1, creds2, func);
1203	if (memcmp(creds1->EntryTag, creds2->EntryTag, sizeof(CSSM_STRING)) ||
1204		creds1->Callback  != creds2->Callback                           ||
1205		creds1->CallerCtx != creds2->CallerCtx)
1206	{
1207		fprintf(stderr, "%s (mismatch)\n", func);
1208		return MISMATCH;
1209	}
1210	ret = compare_CSSM_BASE_CERTS(&creds1->BaseCerts, &creds2->BaseCerts);
1211	if (ret != OK)
1212	{
1213		fprintf(stderr, "%s\n", func);
1214		return ret;
1215	}
1216	ret = compare_CSSM_SAMPLEGROUP(&creds1->Samples, &creds2->Samples);
1217	if (ret != OK)
1218	{
1219		fprintf(stderr, "%s\n", func);
1220		return ret;
1221	}
1222	return OK;
1223}
1224
1225int compare_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp1,
1226									CSSM_AUTHORIZATIONGROUP *grp2)
1227{
1228	const char *func = "compare_CSSM_AUTHORIZATIONGROUP()";
1229
1230	NULLCHECK(grp1, grp2, func);
1231	if (grp1->NumberOfAuthTags != grp2->NumberOfAuthTags ||
1232		memcmp(grp1->AuthTags, grp2->AuthTags, grp1->NumberOfAuthTags*ALIGNSIZE(CSSM_ACL_AUTHORIZATION_TAG)))
1233	{
1234		fprintf(stderr, "%s (mismatch)\n", func);
1235		return MISMATCH;
1236	}
1237	return OK;
1238}
1239
1240int compare_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period1,
1241									 CSSM_ACL_VALIDITY_PERIOD *period2)
1242{
1243	const char *func = "compare_CSSM_ACL_VALIDITY_PERIOD()";
1244	int ret;
1245
1246	NULLCHECK(period1, period2, func);
1247	ret = compare_CSSM_DATA(&period1->StartDate, &period1->StartDate);
1248	if (ret != OK)
1249	{
1250		fprintf(stderr, "%s (StartDate)\n", func);
1251		return ret;
1252	}
1253	ret = compare_CSSM_DATA(&period1->EndDate, &period1->EndDate);
1254	if (ret != OK)
1255		fprintf(stderr, "%s (EndDate)\n", func);
1256	return ret;
1257}
1258
1259int compare_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto1,
1260									 CSSM_ACL_ENTRY_PROTOTYPE *proto2,
1261									 int skipGarbage)
1262{
1263	const char *func = "compare_CSSM_ACL_ENTRY_PROTOTYPE()";
1264	int ret;
1265
1266	NULLCHECK(proto1, proto2, func);
1267	ret = compare_CSSM_LIST(&proto1->TypedSubject, &proto2->TypedSubject);
1268	if (ret != OK)
1269	{
1270		fprintf(stderr, "%s\n", func);
1271		return ret;
1272	}
1273	if (!skipGarbage)
1274	{
1275		if (proto1->Delegate != proto2->Delegate)
1276		{
1277			fprintf(stderr, "%s (Delegate mismatch)\n", func);
1278			return MISMATCH;
1279		}
1280	}
1281	ret = compare_CSSM_AUTHORIZATIONGROUP(&proto1->Authorization, &proto2->Authorization);
1282	if (ret != OK)
1283	{
1284		fprintf(stderr, "%s\n", func);
1285		return ret;
1286	}
1287	if (!skipGarbage)
1288	{
1289		ret = compare_CSSM_ACL_VALIDITY_PERIOD(&proto1->TimeRange, &proto2->TimeRange);
1290		if (ret != OK)
1291		{
1292			fprintf(stderr, "%s\n", func);
1293			return ret;
1294		}
1295	}
1296	if (memcmp(proto1->EntryTag, proto2->EntryTag, sizeof(CSSM_STRING)))
1297	{
1298		fprintf(stderr, "%s (EntryTag mismatch)\n", func);
1299		return MISMATCH;
1300	}
1301	return OK;
1302}
1303
1304int compare_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto1,
1305									 CSSM_ACL_OWNER_PROTOTYPE *proto2)
1306{
1307	const char *func = "compare_CSSM_ACL_OWNER_PROTOTYPE()";
1308
1309	NULLCHECK(proto1, proto2, func);
1310	int ret = compare_CSSM_LIST(&proto1->TypedSubject, &proto2->TypedSubject);
1311	if (ret != OK)
1312	{
1313		fprintf(stderr, "%s\n", func);
1314		return ret;
1315	}
1316	if (proto1->Delegate != proto2->Delegate)
1317	{
1318		fprintf(stderr, "%s (Delegate mismatch)\n", func);
1319		return MISMATCH;
1320	}
1321	return OK;
1322}
1323
1324int compare_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input1,
1325								 CSSM_ACL_ENTRY_INPUT *input2)
1326{
1327	const char *func = "compare_CSSM_ACL_ENTRY_INPUT()";
1328	int ret, skipGarbage = 0;
1329
1330	NULLCHECK(input1, input2, func);
1331	ret = compare_CSSM_ACL_ENTRY_PROTOTYPE(&input1->Prototype,
1332										   &input2->Prototype,
1333										   skipGarbage);
1334	if (ret != OK)
1335	{
1336		fprintf(stderr, "%s\n", func);
1337		return ret;
1338	}
1339	if (input1->Callback      != input2->Callback      ||
1340		input1->CallerContext != input2->CallerContext)
1341	{
1342		fprintf(stderr, "%s (mismatch)\n", func);
1343		return MISMATCH;
1344	}
1345	return OK;
1346}
1347
1348int compare_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info1,
1349								CSSM_ACL_ENTRY_INFO *info2)
1350{
1351	const char *func = "compare_CSSM_ACL_ENTRY_INFO()";
1352	int ret, skipGarbage = 0;
1353
1354	NULLCHECK(info1, info2, func);
1355#if SECURITYD_SENDS_GARBAGE
1356	skipGarbage = 1;
1357	/* fprintf(stderr, "%s: skipping garbage\n", func); */
1358#endif
1359	ret = compare_CSSM_ACL_ENTRY_PROTOTYPE(&info1->EntryPublicInfo,
1360										   &info2->EntryPublicInfo,
1361										   skipGarbage);
1362	if (ret != OK)
1363	{
1364		fprintf(stderr, "%s\n", func);
1365		return ret;
1366	}
1367	if (info1->EntryHandle != info2->EntryHandle)
1368	{
1369		fprintf(stderr, "%s (EntryHandle mismatch)\n", func);
1370		return MISMATCH;
1371	}
1372	return OK;
1373}
1374
1375int compare_CSSM_DATE(CSSM_DATE *date1, CSSM_DATE *date2)
1376{
1377	const char *func = "compare_CSSM_DATE()";
1378
1379	NULLCHECK(date1, date2, func);
1380	if (memcmp(date1, date2, sizeof(CSSM_DATE)))
1381	{
1382		fprintf(stderr, "%s (mismatch)\n", func);
1383		return MISMATCH;
1384	}
1385	return OK;
1386}
1387
1388int compare_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr1, CSSM_KEYHEADER *hdr2)
1389{
1390	const char *func = "compare_CSSM_KEYHEADER()";
1391	int ret;
1392
1393	NULLCHECK(hdr1, hdr2, func);
1394	if (hdr1->HeaderVersion        != hdr2->HeaderVersion        ||
1395		memcmp(&hdr1->CspId, &hdr2->CspId, sizeof(CSSM_GUID))    ||
1396		hdr1->BlobType             != hdr2->BlobType             ||
1397		hdr1->Format               != hdr2->Format               ||
1398		hdr1->AlgorithmId          != hdr2->AlgorithmId          ||
1399		hdr1->KeyClass             != hdr2->KeyClass             ||
1400		hdr1->LogicalKeySizeInBits != hdr2->LogicalKeySizeInBits ||
1401		hdr1->KeyUsage             != hdr2->KeyUsage             ||
1402		hdr1->WrapAlgorithmId      != hdr2->WrapAlgorithmId      ||
1403		hdr1->WrapMode             != hdr2->WrapMode             ||
1404		hdr1->Reserved             != hdr2->Reserved)
1405	{
1406		fprintf(stderr, "%s (mismatch)\n", func);
1407		return MISMATCH;
1408	}
1409	if ((ret = compare_CSSM_DATE(&hdr1->StartDate, &hdr2->StartDate)) != OK)
1410	{
1411		fprintf(stderr, "%s\n", func);
1412		return ret;
1413	}
1414	if ((ret = compare_CSSM_DATE(&hdr1->EndDate, &hdr2->EndDate)) != OK)
1415	{
1416		fprintf(stderr, "%s\n", func);
1417		return ret;
1418	}
1419	return OK;
1420}
1421
1422int compare_CSSM_KEY(CSSM_KEY *key1, CSSM_KEY *key2)
1423{
1424	const char *func = "compare_CSSM_KEY()";
1425	int ret;
1426
1427	NULLCHECK(key1, key2, func);
1428	if ((ret = compare_CSSM_KEYHEADER(&key1->KeyHeader, &key1->KeyHeader)) != OK)
1429	{
1430		fprintf(stderr, "%s\n", func);
1431		return ret;
1432	}
1433	if ((ret = compare_CSSM_DATA(&key1->KeyData, &key2->KeyData)) != OK)
1434	{
1435		fprintf(stderr, "%s\n", func);
1436		return ret;
1437	}
1438	return OK;
1439}
1440
1441int compare_CSSM_RANGE(CSSM_RANGE *range1, CSSM_RANGE *range2)
1442{
1443	const char *func = "compare_CSSM_RANGE()";
1444
1445	NULLCHECK(range1, range2, func);
1446	if (memcmp(range1, range2, sizeof(CSSM_RANGE)))
1447	{
1448		fprintf(stderr, "%s (mismatch)\n", func);
1449		return MISMATCH;
1450	}
1451	return OK;
1452}
1453
1454int compare_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr1,
1455								   CSSM_CONTEXT_ATTRIBUTE *attr2)
1456{
1457	const char *func = "compare_CSSM_CONTEXT_ATTRIBUTE()";
1458	char *err = NULL;
1459	int ret = OK;
1460
1461	NULLCHECK(attr1, attr2, func);
1462	if (attr1->AttributeType   != attr2->AttributeType   ||
1463		attr1->AttributeLength != attr2->AttributeLength)
1464	{
1465		fprintf(stderr, "%s (mismatch)\n", func);
1466		return MISMATCH;
1467	}
1468	switch (attr1->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK)
1469	{
1470		case CSSM_ATTRIBUTE_DATA_UINT32:
1471			if (attr1->Attribute.Uint32 != attr2->Attribute.Uint32)
1472			{
1473				err = "Uint32 mismatch";
1474				ret = MISMATCH;
1475			}
1476			break;
1477		case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
1478			ret = compare_CSSM_DATA(attr1->Attribute.Data, attr2->Attribute.Data);
1479			break;
1480		case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
1481			ret = compare_CSSM_CRYPTO_DATA(attr1->Attribute.CryptoData, attr2->Attribute.CryptoData);
1482			break;
1483		case CSSM_ATTRIBUTE_DATA_KEY:
1484			ret = compare_CSSM_KEY(attr1->Attribute.Key, attr2->Attribute.Key);
1485			break;
1486		case CSSM_ATTRIBUTE_DATA_STRING:
1487			if (memcmp(attr1->Attribute.String, attr2->Attribute.String, attr1->AttributeLength))
1488			{
1489				err = "String mismatch";
1490				ret = MISMATCH;
1491			}
1492			break;
1493		case CSSM_ATTRIBUTE_DATA_DATE:
1494			ret = compare_CSSM_DATE(attr1->Attribute.Date, attr2->Attribute.Date);
1495			break;
1496		case CSSM_ATTRIBUTE_DATA_RANGE:
1497			ret = compare_CSSM_RANGE(attr1->Attribute.Range, attr2->Attribute.Range);
1498			break;
1499		case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
1500			ret = compare_CSSM_ACCESS_CREDENTIALS(attr1->Attribute.AccessCredentials,
1501												  attr2->Attribute.AccessCredentials);
1502			break;
1503		case CSSM_ATTRIBUTE_DATA_VERSION:
1504			if (memcmp(&attr1->Attribute.Version, &attr2->Attribute.Version, sizeof(CSSM_VERSION)))
1505			{
1506				err = "Version mismatch";
1507				ret = MISMATCH;
1508			}
1509			break;
1510		case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
1511			if (memcmp(&attr1->Attribute.DLDBHandle, &attr2->Attribute.DLDBHandle, sizeof(CSSM_DL_DB_HANDLE)))
1512			{
1513				err = "DLDBHandle mismatch";
1514				ret = MISMATCH;
1515			}
1516			break;
1517		/* _PADDING and _KR_PROFILE not supported? */
1518		default:
1519			err = "unknown type";
1520			ret = UNKNOWN_TYPE;
1521			break;
1522	}
1523	if (ret != OK)
1524	{
1525		if (err)
1526			fprintf(stderr, "%s (%s)\n", func, err);
1527		else
1528			fprintf(stderr, "%s\n", func);
1529		return ret;
1530	}
1531	return OK;
1532}
1533
1534int compare_CSSM_CONTEXT(CSSM_CONTEXT *ctx1, CSSM_CONTEXT *ctx2)
1535{
1536	const char *func = "compare_CSSM_CONTEXT()";
1537	u_int i, ret;
1538
1539	NULLCHECK(ctx1, ctx2, func);
1540	if (ctx1->ContextType          != ctx2->ContextType          ||
1541		ctx1->AlgorithmType        != ctx2->AlgorithmType        ||
1542		ctx1->NumberOfAttributes   != ctx2->NumberOfAttributes   ||
1543		ctx1->CSPHandle            != ctx2->CSPHandle            ||
1544		ctx1->Privileged           != ctx2->Privileged           ||
1545		ctx1->EncryptionProhibited != ctx2->EncryptionProhibited ||
1546		ctx1->WorkFactor           != ctx2->WorkFactor           ||
1547		ctx1->Reserved             != ctx2->Reserved)
1548	{
1549		fprintf(stderr, "%s (mismatch)\n", func);
1550		return MISMATCH;
1551	}
1552	for (i = 0; i < ctx1->NumberOfAttributes; ++i)
1553	{
1554		ret = compare_CSSM_CONTEXT_ATTRIBUTE(&ctx1->ContextAttributes[i],
1555											 &ctx2->ContextAttributes[i]);
1556		if (ret != OK)
1557		{
1558			fprintf(stderr, "%s\n", func);
1559			return ret;
1560		}
1561	}
1562	return OK;
1563}
1564
1565int compare_CSSM_OID(CSSM_OID *oid1, CSSM_OID *oid2)
1566{
1567	return compare_CSSM_DATA(reinterpret_cast<CSSM_DATA *>(oid1),
1568							 reinterpret_cast<CSSM_DATA *>(oid2));
1569}
1570
1571/* oy -- see cdsa_utilities, cssmdb.cpp: CompareAttributeInfos() */
1572int compare_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo1,
1573								   CSSM_DB_ATTRIBUTE_INFO *attrinfo2)
1574{
1575	const char *func = "compare_CSSM_DB_ATTRIBUTE_INFO()";
1576
1577	NULLCHECK(attrinfo1, attrinfo2, func);
1578	if (attrinfo1->AttributeNameFormat != attrinfo2->AttributeNameFormat ||
1579		attrinfo1->AttributeFormat     != attrinfo2->AttributeFormat)
1580	{
1581		fprintf(stderr, "%s (mismatch)\n", func);
1582		return MISMATCH;
1583	}
1584	switch(attrinfo1->AttributeNameFormat)
1585	{
1586		case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
1587			if (strcmp(attrinfo1->Label.AttributeName, attrinfo2->Label.AttributeName))
1588			{
1589				fprintf(stderr, "%s (string mismatch)\n", func);
1590				return MISMATCH;
1591			}
1592			break;
1593		case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
1594			return compare_CSSM_OID(&attrinfo1->Label.AttributeOID,
1595									&attrinfo2->Label.AttributeOID);
1596			break;
1597		case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
1598			if (attrinfo1->Label.AttributeID != attrinfo2->Label.AttributeID)
1599			{
1600				fprintf(stderr, "%s (integer mismatch)\n", func);
1601				return MISMATCH;
1602			}
1603			break;
1604		default:
1605			fprintf(stderr, "%s (unknown type)\n", func);
1606			return UNKNOWN_TYPE;
1607	}
1608	return OK;
1609}
1610
1611int compare_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata1,
1612								   CSSM_DB_ATTRIBUTE_DATA *attrdata2)
1613{
1614	const char *func = "compare_CSSM_DB_ATTRIBUTE_DATA()";
1615	int ret;
1616	uint32_t i;
1617
1618	NULLCHECK(attrdata1, attrdata2, func);
1619	ret = compare_CSSM_DB_ATTRIBUTE_INFO(&attrdata1->Info, &attrdata2->Info);
1620	if (ret != OK)
1621	{
1622		fprintf(stderr, "%s\n", func);
1623		return ret;
1624	}
1625	if (attrdata1->NumberOfValues != attrdata2->NumberOfValues)
1626	{
1627		fprintf(stderr, "%s (mismatch)\n", func);
1628		return MISMATCH;
1629	}
1630	for (i = 0; i < attrdata1->NumberOfValues; ++i)
1631	{
1632		ret = compare_CSSM_DATA(&attrdata1->Value[i], &attrdata2->Value[i]);
1633		if (ret != OK)
1634		{
1635			fprintf(stderr, "%s (Value %d)\n", func, i+1);
1636			return ret;
1637		}
1638	}
1639	return OK;
1640}
1641
1642int compare_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred1,
1643									 CSSM_SELECTION_PREDICATE *pred2)
1644{
1645	const char *func = "compare_CSSM_SELECTION_PREDICATE()";
1646	int ret;
1647
1648	NULLCHECK(pred1, pred2, func);
1649	if (pred1->DbOperator != pred2->DbOperator)
1650	{
1651		fprintf(stderr, "%s (mismatch)\n", func);
1652		return MISMATCH;
1653	}
1654	ret = compare_CSSM_DB_ATTRIBUTE_DATA(&pred1->Attribute, &pred2->Attribute);
1655	if (ret != OK)
1656		fprintf(stderr, "%s\n", func);
1657	return ret;
1658}
1659
1660int compare_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits1,
1661							  CSSM_QUERY_LIMITS *limits2)
1662{
1663	const char *func = "compare_CSSM_QUERY_LIMITS()";
1664
1665	NULLCHECK(limits1, limits2, func);
1666	if (limits1->TimeLimit != limits2->TimeLimit ||
1667		limits1->SizeLimit != limits2->SizeLimit)
1668	{
1669		fprintf(stderr, "%s (mismatch)\n", func);
1670		return MISMATCH;
1671	}
1672	return OK;
1673}
1674
1675int compare_CSSM_QUERY(CSSM_QUERY *query1, CSSM_QUERY *query2)
1676{
1677	const char *func = "compare_CSSM_QUERY()";
1678	int ret;
1679	uint32_t i;
1680
1681	NULLCHECK(query1, query2, func);
1682	if (query1->RecordType             != query2->RecordType             ||
1683		query1->Conjunctive            != query2->Conjunctive            ||
1684		query1->NumSelectionPredicates != query2->NumSelectionPredicates ||
1685		query1->QueryFlags             != query2->QueryFlags)
1686	{
1687		fprintf(stderr, "%s (mismatch)\n", func);
1688		return MISMATCH;
1689	}
1690	for (i = 0; i < query1->NumSelectionPredicates; ++i)
1691	{
1692		ret = compare_CSSM_SELECTION_PREDICATE(&query1->SelectionPredicate[i],
1693											   &query2->SelectionPredicate[i]);
1694	}
1695	ret = compare_CSSM_QUERY_LIMITS(&query1->QueryLimits, &query2->QueryLimits);
1696	if (ret != OK)
1697		fprintf(stderr, "%s\n", func);
1698	return ret;
1699}
1700
1701/**************************************************************************
1702 * Support routines for test_...() functions.
1703 **************************************************************************/
1704
1705CSSM_RETURN dummyACLSubjectCallback(const CSSM_LIST *subjectRequest,
1706									void *callerContext,
1707									const CSSM_MEMORY_FUNCS *MemFuncs)
1708{
1709	return CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED;	/* XXX/gh */
1710}
1711
1712/*
1713 * Dummy func to make sure CSSM_CRYPTO_DATA isn't being corrupted.  Kindly
1714 * note the requirement that "context" be a CSSM_CRYPTO_DATA.
1715 */
1716CSSM_RETURN dummyCSSMCallback(CSSM_DATA *data, void *context)
1717{
1718	CSSM_CRYPTO_DATA_PTR crypto = (CSSM_CRYPTO_DATA *)context;
1719	data->Length = crypto->Param.Length;
1720	data->Data = (uint8 *)malloc(data->Length);	/* XXX/gh  leaked */
1721	/* XXX/gh  yeah, should check if the malloc() failed */
1722	memcpy(data->Data, crypto->Param.Data, data->Length);
1723	return CSSM_OK;
1724}
1725
1726/**************************************************************************
1727 * test_CSSM_...() routines read sample data from disk (obtained from
1728 * securityd via the SecuritydDataSave class), set up the named
1729 * top-level structure by byte-reordering (if needed) and pointer
1730 * relocating (using libsecurity_utilities walkers), and let the
1731 * corresponding test_xdrwalk_...() routine test the XDR encoding/decoding
1732 * routines against themselves and against the equivalent walker-generated
1733 * output.
1734 *
1735 * General test methodology:
1736 *
1737 * encode/decode x 3, then compare (1) the encoded original vs. the decoded
1738 * copy, and (2) the flattened encoded version with the equivalent walker's
1739 * flattened output.
1740 **************************************************************************/
1741
1742/* TODO/gh  don't worry about this until we get smart cards working */
1743int test_CSSM_DB_RECORD_ATTRIBUTE_DATA(const char *srcfile)
1744{
1745	CSSM_DB_RECORD_ATTRIBUTE_DATA *data = NULL;
1746
1747	if (srcfile)
1748	{
1749		/* read binary data from disk */
1750	}
1751	else
1752	{
1753		/* dummy something up */
1754		data = (CSSM_DB_RECORD_ATTRIBUTE_DATA *)malloc(sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA));
1755		if (!data)
1756			return MEM_ERROR;
1757		data->DataRecordType = CSSM_DL_DB_RECORD_CERT;
1758		/* TODO/gh  pick up from here */
1759	}
1760	if (data)
1761		free(data);
1762	return NOT_IMPLEMENTED;		/* TODO/gh */
1763}
1764
1765int test_xdrwalk_CSSM_CONTEXT(CSSM_CONTEXT *ctx, int dbglvl)
1766{
1767	const char *func = "test_xdrwalk_CSSM_CONTEXT()";
1768	CSSM_CONTEXT *walkcopy, *xdrctxcopy = NULL;
1769	CSSM_CONTEXT_ATTRIBUTE *attrs;
1770	void *flattenedCtxPtr = NULL;
1771	u_int flattenedCtxLen = 0, i;
1772	int ret, iter;
1773	size_t attrsSize, walkedAttrsSize;
1774
1775	/*
1776	 * Reimplement Context::Builder so we control where the memory is
1777	 * allocated, thus what pointer values are.
1778	 */
1779	SizeWalker sizer;
1780	for (i = 0; i < ctx->NumberOfAttributes; ++i)
1781	{
1782		walk(sizer, ctx->ContextAttributes[i]);
1783	}
1784	attrsSize = ALIGNUP(ctx->NumberOfAttributes * sizeof(CSSM_CONTEXT_ATTRIBUTE));
1785	walkedAttrsSize = attrsSize + ALIGNUP(sizer);
1786
1787	/* create a *flat* copy of ctx for direct memcmp() w/ XDR copy */
1788	walkcopy = reinterpret_cast<CSSM_CONTEXT *>(calloc(1, sizeof(CSSM_CONTEXT) + walkedAttrsSize));
1789	if (walkcopy == NULL)
1790	{
1791		fprintf(stderr, "%s: error allocating walked context\n", func);
1792		return MEM_ERROR;
1793	}
1794	memcpy(walkcopy, ctx, sizeof(CSSM_CONTEXT));
1795	attrs = reinterpret_cast<CSSM_CONTEXT_ATTRIBUTE *>(reinterpret_cast<char *>(walkcopy) + sizeof(CSSM_CONTEXT));
1796	CopyWalker copier = LowLevelMemoryUtilities::increment(attrs, attrsSize);
1797	for (i = 0; i < ctx->NumberOfAttributes; ++i)
1798	{
1799		attrs[i] = ctx->ContextAttributes[i];	/* shallow copy */
1800		walk(copier, attrs[i]);					/* deep copy */
1801	}
1802	walkcopy->ContextAttributes = attrs;
1803
1804	for (iter = 0; iter < N_ITERS; ++iter)
1805	{
1806		if (!xdr_mem_encode(ctx, &flattenedCtxPtr, &flattenedCtxLen,
1807							(xdrproc_t)xdr_CSSM_CONTEXT))
1808		{
1809			fprintf(stderr, "%s, round %d (encode error)\n", func, iter+1);
1810			return XDR_ENCODE_ERROR;
1811		}
1812		/* always zero out memory before attempting a decode */
1813		if ((xdrctxcopy = (CSSM_CONTEXT *)calloc(1, sizeof(CSSM_CONTEXT))) == NULL)
1814		{
1815			fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1);
1816			return MEM_ERROR;
1817		}
1818		if (!xdr_mem_decode(flattenedCtxPtr, xdrctxcopy, flattenedCtxLen,
1819							(xdrproc_t)xdr_CSSM_CONTEXT))
1820		{
1821			fprintf(stderr, "%s, round %d (decode error)\n", func, iter+1);
1822			return XDR_DECODE_ERROR;
1823		}
1824		if (dbglvl >= 3)
1825			printf("comparing XDR-generated structs...\n");
1826		if ((ret = compare_CSSM_CONTEXT(ctx, xdrctxcopy)) != OK)
1827		{
1828			fprintf(stderr, "%s: CSSM_CONTEXT old/new XDR comparison, round %d, failed\n",
1829					func, iter+1);
1830			return ret;
1831		}
1832		if (dbglvl >= 3)
1833			printf("comparing walked- and XDR-generated structs...\n");
1834		if ((ret = compare_CSSM_CONTEXT(xdrctxcopy, walkcopy)) != OK)
1835		{
1836			fprintf(stderr, "%s: CSSM_CONTEXT XDR/walker comparison, round %d, failed\n",
1837					func, iter+1);
1838			return ret;
1839		}
1840		if (dbglvl >= 2)
1841			printf("CSSM_CONTEXT compared OK, round %d\n", iter+1);
1842#if 0
1843		if (dbglvl >= 3)
1844			printf("Starting XDR/walker comparison...\n");
1845		/*
1846		 * XXX/gh  xdrctxcopy and walkcopy should be identical except for
1847		 * pointer offsets.  However, xdrctxcopy has extra bytes following
1848		 * CSSM_CONTEXT's Reserved field; still investigating why.
1849		 */
1850		/* XXX/gh  relocate somebody's pointers */
1851		if (memcmp(walkcopy, xdrctxcopy, walkedAttrsSize+sizeof(CSSM_CONTEXT)))
1852		{
1853			fprintf(stderr, "%s, round %d (comparison failed)\n", func, iter+1);
1854			return MISMATCH;
1855		}
1856#endif
1857		if (iter > 0)
1858			free(ctx);
1859		ctx = xdrctxcopy;
1860		free(flattenedCtxPtr);
1861		flattenedCtxPtr = NULL;
1862		flattenedCtxLen = 0;
1863	}
1864	if (dbglvl >= 1)
1865		printf("Successfully finished CSSM_CONTEXT check\n");
1866	return OK;
1867}
1868
1869int test_CSSM_CONTEXT(int fd, int doflip, int dbglvl)
1870{
1871	const char *func = "test_CSSM_CONTEXT()";
1872	CSSM_CONTEXT ctx;
1873	CSSM_CONTEXT_ATTRIBUTE *attrs;
1874	int ret;
1875	CSSM_CRYPTO_DATA crypto;
1876
1877	if (fd > -1)	/* cheesy hack, but what ya gonna do? */
1878	{
1879		int csize, attrSize;
1880		u_int i;
1881		intptr_t attraddr;
1882		off_t offset;
1883		/*
1884		 * Saved format:
1885		 * - size (of CSSM_CONTEXT)
1886		 * - CSSM_CONTEXT
1887		 * - size (of starting address for attributes)
1888		 * - starting address for CSSM_CONTEXT_ATTRIBUTEs
1889		 * - total size of CSSM_CONTEXT_ATTRIBUTEs
1890		 * - CSSM_CONTEXT_ATTRIBUTEs (contiguous)
1891		 */
1892
1893		/* context size; not really needed */
1894		if (read(fd, &csize, sizeof(csize)) != static_cast<ssize_t>(sizeof(csize)))
1895		{
1896			fprintf(stderr, "%s: Error reading context size\n", func);
1897			return BAD_READ;
1898		}
1899		if (doflip) flip(&csize, sizeof(csize));
1900		if (read(fd, &ctx, csize) != static_cast<ssize_t>(csize))
1901		{
1902			fprintf(stderr, "Error reading context\n");
1903			return BAD_READ;
1904		}
1905		/* Defer reorder of CSSM_CONTEXT until attributes have been read */
1906		/* attribute array starting address */
1907		if (read(fd, &csize, sizeof(csize)) != static_cast<ssize_t>(sizeof(csize)))
1908		{
1909			fprintf(stderr, "Error reading attribute address size\n");
1910			return BAD_READ;
1911		}
1912		if (doflip) flip(&csize, sizeof(csize));
1913		if (read(fd, &attraddr, csize) != csize)
1914		{
1915			fprintf(stderr, "Error reading attribute address\n");
1916			return BAD_READ;
1917		}
1918		/*
1919		 * byte reorder of old attribute address, if needed, handled in
1920		 * hostorder_CSSM_CONTEXT()
1921		 */
1922		/* size of attributes */
1923		if (read(fd, &attrSize, sizeof(attrSize)) != static_cast<ssize_t>(sizeof(attrSize)))
1924		{
1925			fprintf(stderr, "Error reading attribute size\n");
1926			return BAD_READ;
1927		}
1928		if (doflip) flip(&attrSize, sizeof(attrSize));
1929		if ((attrs = (CSSM_CONTEXT_ATTRIBUTE *)malloc(attrSize)) == NULL)
1930			return MEM_ERROR;
1931		/* attributes */
1932		if (read(fd, attrs, attrSize) != attrSize)
1933		{
1934			fprintf(stderr, "Error reading attributes\n");
1935			return BAD_READ;
1936		}
1937		if (doflip)
1938		{
1939			ctx.ContextAttributes = reinterpret_cast<CSSM_CONTEXT_ATTRIBUTE *>(attraddr);
1940			hostorder_CSSM_CONTEXT(&ctx, attrs);
1941		}
1942		else
1943		{
1944			/* NB: this was the working code before byte-reordering */
1945			offset = reinterpret_cast<intptr_t>(attrs) - attraddr;
1946			ReconstituteWalker relocator(offset);
1947			for (i = 0; i < ctx.NumberOfAttributes; ++i)
1948			{
1949				walk(relocator, attrs[i]);
1950			}
1951			ctx.ContextAttributes = attrs;
1952		}
1953		(void)close(fd);
1954	}
1955	else
1956	{
1957		int err;
1958		uint32_t intattr;
1959
1960		/*
1961		 * dummy something up; this is from FakeContext usages in
1962		 * securityd/tests/
1963		 */
1964		ctx.ContextType = CSSM_ALGCLASS_KEYGEN;
1965		ctx.AlgorithmType = CSSM_ALGID_DES;
1966#define N_TEST_ATTRS	2
1967		ctx.NumberOfAttributes = N_TEST_ATTRS;
1968		attrs = (CSSM_CONTEXT_ATTRIBUTE *)malloc(N_TEST_ATTRS*sizeof(CSSM_CONTEXT_ATTRIBUTE));
1969		if (!attrs)
1970			return MEM_ERROR;
1971		ctx.ContextAttributes = attrs;
1972		intattr = 64;
1973		err = fill_CSSM_CONTEXT_ATTRIBUTE(&ctx.ContextAttributes[0],
1974										  CSSM_ATTRIBUTE_KEY_LENGTH,
1975										  sizeof(uint32_t),
1976										  &intattr);
1977		if (err != OK)
1978			return err;
1979		crypto.Param.Length = strlen(testString);
1980		crypto.Param.Data = (uint8 *)testString;
1981#if 0
1982		crypto.Callback = dummyCSSMCallback;
1983		crypto.CallerCtx = &crypto;	/* dummy cb needs crypto.Param */
1984#endif
1985		crypto.Callback = NULL;
1986		crypto.CallerCtx = NULL;	/* dummy cb needs crypto.Param */
1987		err = fill_CSSM_CONTEXT_ATTRIBUTE(&ctx.ContextAttributes[1],
1988										  CSSM_ATTRIBUTE_SEED,
1989										  sizeof(CSSM_CRYPTO_DATA),
1990										  (void *)&crypto);
1991		if (err != OK)
1992			return err;
1993		ctx.CSPHandle = 13;
1994		ctx.Privileged = CSSM_TRUE;	/* ! 0 */
1995		ctx.EncryptionProhibited = CSSM_TRUE;
1996		ctx.WorkFactor = 41;
1997		ctx.Reserved = 0xfeefee;	/* sentry value */
1998	}
1999
2000	if ((ret = test_xdrwalk_CSSM_CONTEXT(&ctx, dbglvl)) != OK)
2001	{
2002		fprintf(stderr, "%s\n", func);
2003		return ret;
2004	}
2005	return OK;
2006}
2007
2008int test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype,
2009										  int dbglvl)
2010{
2011	const char *func = "test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE()";
2012	CSSM_ACL_OWNER_PROTOTYPE *walkcopy, *xdrcopy;
2013	void *flattenedAclOwnerPtr = NULL;
2014	u_int flattenedAclOwnerLen = 0;
2015	int ret, iter;
2016
2017	/* save off aclOwnerPrototype because we're going to reuse the pointer */
2018	walkcopy = reinterpret_cast<CSSM_ACL_OWNER_PROTOTYPE *>(calloc(1, sizeof(CSSM_ACL_OWNER_PROTOTYPE)));
2019	if (walkcopy == NULL)
2020	{
2021		fprintf(stderr, "%s: error allocating walked CSSM_ACL_OWNER_PROTOTYPE\n", func);
2022		return MEM_ERROR;
2023	}
2024	memcpy(walkcopy, aclOwnerPrototype, sizeof(CSSM_ACL_OWNER_PROTOTYPE));
2025	/* aclOwnerPrototype *is* a walked copy, so no need to re-walk it */
2026
2027	for (iter = 0; iter < N_ITERS; ++iter)
2028	{
2029		if (!xdr_mem_encode(aclOwnerPrototype, &flattenedAclOwnerPtr,
2030							&flattenedAclOwnerLen,
2031							reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE)))
2032		{
2033			fprintf(stderr, "%s, round %d (encode error)\n", func, iter+1);
2034			return XDR_ENCODE_ERROR;
2035		}
2036		/* always zero out memory before attempting a decode */
2037		if ((xdrcopy = (CSSM_ACL_OWNER_PROTOTYPE *)calloc(1, sizeof(CSSM_ACL_OWNER_PROTOTYPE))) == NULL)
2038		{
2039			fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1);
2040			return MEM_ERROR;
2041		}
2042		if (!xdr_mem_decode(flattenedAclOwnerPtr, xdrcopy, flattenedAclOwnerLen,
2043							(xdrproc_t)xdr_CSSM_ACL_OWNER_PROTOTYPE))
2044		{
2045			fprintf(stderr, "%s, round %d (decode error)\n", func, iter+1);
2046			return XDR_DECODE_ERROR;
2047		}
2048		if (dbglvl >= 3)
2049			printf("comparing XDR-generated structs...\n");
2050		if ((ret = compare_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, xdrcopy)) != OK)
2051		{
2052			fprintf(stderr, "%s: CSSM_ACL_OWNER_PROTOTYPE old/new XDR comparison, round %d, failed\n",
2053					func, iter+1);
2054			return ret;
2055		}
2056		if (dbglvl >= 3)
2057			printf("comparing walked- and XDR-generated structs...\n");
2058		if ((ret = compare_CSSM_ACL_OWNER_PROTOTYPE(xdrcopy, walkcopy)) != OK)
2059		{
2060			fprintf(stderr, "%s: CSSM_ACL_OWNER_PROTOTYPE XDR/walker comparison, round %d, failed\n",
2061					func, iter+1);
2062			return ret;
2063		}
2064		if (dbglvl >= 2)
2065			printf("CSSM_ACL_OWNER_PROTOTYPE compared OK, round %d\n", iter+1);
2066		if (iter > 0)
2067			free(aclOwnerPrototype);
2068		aclOwnerPrototype = xdrcopy;
2069		free(flattenedAclOwnerPtr);
2070		flattenedAclOwnerPtr = NULL;
2071		flattenedAclOwnerLen = 0;
2072	}
2073
2074	if (dbglvl >= 1)
2075		printf("Successfully finished CSSM_ACL_OWNER_PROTOTYPE check\n");
2076	return OK;
2077}
2078
2079int test_CSSM_ACL_OWNER_PROTOTYPE(int fd, int doflip, int dbglvl)
2080{
2081	const char *func = "test_CSSM_ACL_OWNER_PROTOTYPE()";
2082	CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype;
2083	int ret;
2084
2085	if (fd > -1)	/* cheesy hack, but what ya gonna do? */
2086	{
2087		int aclsize;
2088		uint32_t ptrsize;	/* AKA mach_msg_type_number_t, AKA natural_t */
2089		intptr_t baseptr;
2090		off_t offset;
2091		/*
2092		 * Saved format:
2093		 * - sizeof(base pointer)
2094		 * - base pointer
2095		 * - length
2096		 * - CSSM_ACL_OWNER_PROTOTYPE
2097		 */
2098		if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast<ssize_t>(sizeof(ptrsize)))
2099		{
2100			fprintf(stderr, "%s: Error reading base pointer size\n", func);
2101			return BAD_READ;
2102		}
2103		if (doflip) flip(&ptrsize, sizeof(ptrsize));
2104		if (read(fd, &baseptr, ptrsize) < static_cast<ssize_t>(ptrsize))
2105		{
2106			fprintf(stderr, "%s: Error reading base pointer\n", func);
2107			return BAD_READ;
2108		}
2109		if (doflip) flip(&baseptr, sizeof(baseptr));
2110		if (read(fd, &aclsize, sizeof(aclsize)) < static_cast<ssize_t>(sizeof(aclsize)))
2111		{
2112			fprintf(stderr, "%s: Error reading AclOwnerPrototype size\n", func);
2113			return BAD_READ;
2114		}
2115		if (doflip) flip(&aclsize, sizeof(aclsize));
2116		aclOwnerPrototype = (CSSM_ACL_OWNER_PROTOTYPE *)malloc(aclsize);
2117		if (aclOwnerPrototype == NULL)
2118			return MEM_ERROR;
2119		if (read(fd, aclOwnerPrototype, aclsize) < aclsize)
2120		{
2121			fprintf(stderr, "Error reading CSSM_ACL_OWNER_PROTOTYPE\n");
2122			return BAD_READ;
2123		}
2124		offset = reinterpret_cast<intptr_t>(aclOwnerPrototype) - baseptr;
2125		if (doflip)
2126		{
2127			hostorder_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, offset);
2128		}
2129		else
2130		{
2131			ReconstituteWalker relocator(offset);
2132			walk(relocator, reinterpret_cast<AclOwnerPrototype *&>(baseptr));
2133		}
2134		(void)close(fd);
2135	}
2136	else
2137	{
2138		/* TODO/gh  cobble something up */
2139		return NOT_IMPLEMENTED;
2140	}
2141
2142	ret = test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, dbglvl);
2143	if (ret != OK)
2144		fprintf(stderr, "%s\n", func);
2145	free(aclOwnerPrototype);
2146	return ret;
2147}
2148
2149int test_xdrwalk_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *aclEntryInput,
2150									  int dbglvl)
2151{
2152	const char *func = "test_xdrwalk_CSSM_ACL_ENTRY_INPUT()";
2153	CSSM_ACL_ENTRY_INPUT *walkcopy, *xdrcopy;
2154	void *flattenedAclEIPtr = NULL;
2155	u_int flattenedAclEILen = 0;
2156	int ret, iter;
2157
2158	/* save off aclEntryInput because we're going to reuse the pointer */
2159	walkcopy = reinterpret_cast<CSSM_ACL_ENTRY_INPUT *>(calloc(1, sizeof(CSSM_ACL_ENTRY_INPUT)));
2160	if (walkcopy == NULL)
2161	{
2162		fprintf(stderr, "%s: error allocating walked CSSM_ACL_ENTRY_INPUT\n", func);
2163		return MEM_ERROR;
2164	}
2165	memcpy(walkcopy, aclEntryInput, sizeof(CSSM_ACL_ENTRY_INPUT));
2166	/* aclEntryInput *is* a walked copy, so no need to re-walk it */
2167
2168	for (iter = 0; iter < N_ITERS; ++iter)
2169	{
2170		if (!xdr_mem_encode(aclEntryInput, &flattenedAclEIPtr, &flattenedAclEILen,
2171							(xdrproc_t)xdr_CSSM_ACL_ENTRY_INPUT))
2172		{
2173			fprintf(stderr, "%s, round %d\n", func, iter+1);
2174			return XDR_ENCODE_ERROR;
2175		}
2176		/* always zero out memory before attempting a decode */
2177		if ((xdrcopy = (CSSM_ACL_ENTRY_INPUT *)calloc(1, sizeof(CSSM_ACL_ENTRY_INPUT))) == NULL)
2178		{
2179			fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1);
2180			return MEM_ERROR;
2181		}
2182		if (!xdr_mem_decode(flattenedAclEIPtr, xdrcopy, flattenedAclEILen,
2183							(xdrproc_t)xdr_CSSM_ACL_ENTRY_INPUT))
2184		{
2185			fprintf(stderr, "%s, round %d\n", func, iter+1);
2186			return XDR_DECODE_ERROR;
2187		}
2188		if (dbglvl >= 3)
2189			printf("comparing XDR-generated structs...\n");
2190		if ((ret = compare_CSSM_ACL_ENTRY_INPUT(aclEntryInput, xdrcopy)) != OK)
2191		{
2192			fprintf(stderr, "%s: CSSM_ACL_ENTRY_INPUT old/new XDR comparison, round %d, failed\n",
2193					func, iter+1);
2194			return ret;
2195		}
2196		if (dbglvl >= 3)
2197			printf("comparing walked- and XDR-generated structs...\n");
2198		if ((ret = compare_CSSM_ACL_ENTRY_INPUT(xdrcopy, walkcopy)) != OK)
2199		{
2200			fprintf(stderr, "%s: CSSM_ACL_ENTRY_INPUT XDR/walker comparison, round %d, failed\n",
2201					func, iter+1);
2202			return ret;
2203		}
2204		if (dbglvl >= 2)
2205			printf("CSSM_ACL_ENTRY_INPUT compared OK, round %d\n", iter+1);
2206		if (iter > 0)
2207			free(aclEntryInput);
2208		aclEntryInput = xdrcopy;
2209		free(flattenedAclEIPtr);
2210		flattenedAclEIPtr = NULL;
2211		flattenedAclEILen = 0;
2212	}
2213
2214	if (dbglvl >= 1)
2215		printf("Successfully finished CSSM_ACL_ENTRY_INPUT check\n");
2216	return OK;
2217}
2218
2219int test_CSSM_ACL_ENTRY_INPUT(int fd, int doflip, int dbglvl)
2220{
2221	const char *func = "test_CSSM_ACL_ENTRY_INPUT()";
2222	CSSM_ACL_ENTRY_INPUT *aclEntryInput;
2223	int ret;
2224
2225	if (fd > -1)	/* cheesy hack, but what ya gonna do? */
2226	{
2227		int aclsize;
2228		uint32_t ptrsize;	/* AKA mach_msg_type_number_t, AKA natural_t */
2229		intptr_t baseptr;
2230		off_t offset;
2231		/*
2232		 * Saved format:
2233		 * - sizeof(base pointer)
2234		 * - base pointer
2235		 * - length
2236		 * - CSSM_ACL_ENTRY_INPUT
2237		 */
2238		if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast<ssize_t>(sizeof(ptrsize)))
2239		{
2240			fprintf(stderr, "%s: Error reading base pointer size\n", func);
2241			return BAD_READ;
2242		}
2243		if (doflip) flip(&ptrsize, sizeof(ptrsize));
2244		if (read(fd, &baseptr, ptrsize) < static_cast<ssize_t>(ptrsize))
2245		{
2246			fprintf(stderr, "%s: Error reading base pointer\n", func);
2247			return BAD_READ;
2248		}
2249		if (doflip) flip(&baseptr, sizeof(baseptr));
2250		if (read(fd, &aclsize, sizeof(aclsize)) < static_cast<ssize_t>(sizeof(aclsize)))
2251		{
2252			fprintf(stderr, "%s: Error reading AclEntryInput size\n", func);
2253			return BAD_READ;
2254		}
2255		if (doflip) flip(&aclsize, sizeof(aclsize));
2256		aclEntryInput = (CSSM_ACL_ENTRY_INPUT *)malloc(aclsize);
2257		if (aclEntryInput == NULL)
2258			return MEM_ERROR;
2259		if (read(fd, aclEntryInput, aclsize) < aclsize)
2260		{
2261			fprintf(stderr, "Error reading CSSM_ACL_ENTRY_INPUT\n");
2262			return BAD_READ;
2263		}
2264		offset = reinterpret_cast<intptr_t>(aclEntryInput) - baseptr;
2265		if (doflip)
2266		{
2267			hostorder_CSSM_ACL_ENTRY_INPUT(aclEntryInput, offset);
2268		}
2269		else
2270		{
2271			ReconstituteWalker relocator(offset);
2272			walk(relocator, reinterpret_cast<AclEntryInput *&>(baseptr));
2273		}
2274		(void)close(fd);
2275	}
2276	else
2277	{
2278		/* TODO/gh  cobble something up */
2279		fprintf(stderr, "%s: hard-coded test not implemented yet\n", func);
2280		return NOT_IMPLEMENTED;
2281	}
2282
2283	if ((ret = test_xdrwalk_CSSM_ACL_ENTRY_INPUT(aclEntryInput, dbglvl)) != OK)
2284		fprintf(stderr, "%s\n", func);
2285	free(aclEntryInput);
2286	return ret;
2287}
2288
2289int test_xdrwalk_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *aclEntryInfo,
2290									 int dbglvl)
2291{
2292	const char *func = "test_xdrwalk_CSSM_ACL_ENTRY_INFO()";
2293
2294	CSSM_ACL_ENTRY_INFO *walkcopy, *xdrcopy;
2295	void *flattenedAclEIPtr = NULL;
2296	u_int flattenedAclEILen = 0;
2297	int ret, iter;
2298
2299	/* save off aclEntryInfo because we're going to reuse the pointer */
2300	walkcopy = reinterpret_cast<CSSM_ACL_ENTRY_INFO *>(calloc(1, sizeof(CSSM_ACL_ENTRY_INFO)));
2301	if (walkcopy == NULL)
2302	{
2303		fprintf(stderr, "%s: error allocating walked CSSM_ACL_ENTRY_INFO\n", func);
2304		return MEM_ERROR;
2305	}
2306	memcpy(walkcopy, aclEntryInfo, sizeof(CSSM_ACL_ENTRY_INFO));
2307	/* right now aclEntryInfo *is* a walked copy, so no need to re-walk it */
2308	for (iter = 0; iter < N_ITERS; ++iter)
2309	{
2310		if (!xdr_mem_encode(aclEntryInfo, &flattenedAclEIPtr, &flattenedAclEILen,
2311							(xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO))
2312		{
2313			fprintf(stderr, "%s, round %d\n", func, iter+1);
2314			return XDR_ENCODE_ERROR;
2315		}
2316		/* always zero out memory before attempting a decode */
2317		if ((xdrcopy = (CSSM_ACL_ENTRY_INFO *)calloc(1, sizeof(CSSM_ACL_ENTRY_INFO))) == NULL)
2318		{
2319			fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1);
2320			return MEM_ERROR;
2321		}
2322		if (!xdr_mem_decode(flattenedAclEIPtr, xdrcopy, flattenedAclEILen,
2323							(xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO))
2324		{
2325			fprintf(stderr, "%s, round %d\n", func, iter+1);
2326			return XDR_DECODE_ERROR;
2327		}
2328		if (dbglvl >= 3)
2329			printf("comparing XDR-generated structs...\n");
2330		if ((ret = compare_CSSM_ACL_ENTRY_INFO(aclEntryInfo, xdrcopy)) != OK)
2331		{
2332			fprintf(stderr, "%s: CSSM_ACL_ENTRY_INFO old/new XDR comparison, round %d, failed\n",
2333					func, iter+1);
2334			return ret;
2335		}
2336		if (dbglvl >= 3)
2337			printf("comparing walked- and XDR-generated structs...\n");
2338		if ((ret = compare_CSSM_ACL_ENTRY_INFO(xdrcopy, walkcopy)) != OK)
2339		{
2340			fprintf(stderr, "%s: CSSM_ACL_ENTRY_INFO XDR/walker comparison, round %d, failed\n",
2341					func, iter+1);
2342			return ret;
2343		}
2344		if (dbglvl >= 2)
2345			printf("CSSM_ACL_ENTRY_INFO compared OK, round %d\n", iter+1);
2346		if (iter > 0)
2347			free(aclEntryInfo);
2348		aclEntryInfo = xdrcopy;
2349		free(flattenedAclEIPtr);
2350		flattenedAclEIPtr = NULL;
2351		flattenedAclEILen = 0;
2352	}
2353	if (dbglvl >= 1)
2354		printf("Successfully finished CSSM_ACL_ENTRY_INFO check\n");
2355	return OK;
2356}
2357
2358int test_CSSM_ACL_ENTRY_INFO(int fd, int doflip, int dbglvl)
2359{
2360	const char *func = "test_CSSM_ACL_ENTRY_INFO()";
2361	CSSM_ACL_ENTRY_INFO *aclEntryInfo;
2362	int ret, aclsize;
2363
2364	if (fd > -1)	/* cheesy hack, but what ya gonna do? */
2365	{
2366		uint32_t ptrsize;	/* AKA mach_msg_type_number_t, AKA natural_t */
2367		intptr_t baseptr;
2368		off_t offset;
2369		/*
2370		 * Saved format (v. 1 of saved-data protocol):
2371		 * - preamble
2372		 * - sizeof(base pointer)
2373		 * - base pointer
2374		 * - length
2375		 * - CSSM_ACL_ENTRY_INFO
2376		 */
2377
2378		if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast<ssize_t>(sizeof(ptrsize)))
2379		{
2380			fprintf(stderr, "%s: Error reading base pointer size\n", func);
2381			return BAD_READ;
2382		}
2383		if (doflip) flip(&ptrsize, sizeof(ptrsize));
2384		if (read(fd, &baseptr, ptrsize) < static_cast<ssize_t>(ptrsize))
2385		{
2386			fprintf(stderr, "%s: Error reading base pointer\n", func);
2387			return BAD_READ;
2388		}
2389		if (doflip) flip(&baseptr, sizeof(baseptr));
2390		if (read(fd, &aclsize, sizeof(aclsize)) < static_cast<ssize_t>(sizeof(aclsize)))
2391		{
2392			fprintf(stderr, "%s: Error reading AclEntryInput size\n", func);
2393			return BAD_READ;
2394		}
2395		if (doflip) flip(&aclsize, sizeof(aclsize));
2396		aclEntryInfo = (CSSM_ACL_ENTRY_INFO *)malloc(aclsize);
2397		if (aclEntryInfo == NULL)
2398			return MEM_ERROR;
2399		if (read(fd, aclEntryInfo, aclsize) < aclsize)
2400		{
2401			fprintf(stderr, "Error reading CSSM_ACL_ENTRY_INFO\n");
2402			return BAD_READ;
2403		}
2404		offset = reinterpret_cast<intptr_t>(aclEntryInfo) - baseptr;
2405		if (doflip)
2406		{
2407			hostorder_CSSM_ACL_ENTRY_INFO(aclEntryInfo, offset);
2408		}
2409		else
2410		{
2411			ReconstituteWalker relocator(offset);
2412			walk(relocator, reinterpret_cast<AclEntryInput *&>(baseptr));
2413		}
2414		(void)close(fd);
2415	}
2416	else
2417	{
2418		/* TODO/gh  cobble something up */
2419		fprintf(stderr, "%s: hard-coded test not implemented yet\n", func);
2420		return NOT_IMPLEMENTED;
2421	}
2422	if ((ret = test_xdrwalk_CSSM_ACL_ENTRY_INFO(aclEntryInfo, dbglvl)) != OK)
2423		fprintf(stderr, "%s\n", func);
2424	free(aclEntryInfo);
2425	return ret;
2426}
2427
2428int test_xdrwalk_CSSM_QUERY(CSSM_QUERY *query, int dbglvl)
2429{
2430	const char *func = "test_xdrwalk_CSSM_QUERY()";
2431
2432	CSSM_QUERY *walkcopy, *xdrcopy;
2433	void *flattenedQueryPtr = NULL;
2434	u_int flattenedQueryLen = 0;
2435	int ret, iter;
2436
2437	/* save off query because we're going to reuse the pointer */
2438	walkcopy = reinterpret_cast<CSSM_QUERY *>(calloc(1, sizeof(CSSM_QUERY)));
2439	if (walkcopy == NULL)
2440	{
2441		fprintf(stderr, "%s: error allocating walked CSSM_QUERY\n", func);
2442		return MEM_ERROR;
2443	}
2444	memcpy(walkcopy, query, sizeof(CSSM_QUERY));
2445	/* right now query *is* a walked copy, so no need to re-walk it */
2446	for (iter = 0; iter < N_ITERS; ++iter)
2447	{
2448		if (!xdr_mem_encode(query, &flattenedQueryPtr, &flattenedQueryLen,
2449							(xdrproc_t)xdr_CSSM_QUERY))
2450		{
2451			fprintf(stderr, "%s, round %d\n", func, iter+1);
2452			return XDR_ENCODE_ERROR;
2453		}
2454		/* always zero out memory before attempting a decode */
2455		if ((xdrcopy = (CSSM_QUERY *)calloc(1, sizeof(CSSM_QUERY))) == NULL)
2456		{
2457			fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1);
2458			return MEM_ERROR;
2459		}
2460		if (!xdr_mem_decode(flattenedQueryPtr, xdrcopy, flattenedQueryLen,
2461							(xdrproc_t)xdr_CSSM_QUERY))
2462		{
2463			fprintf(stderr, "%s, round %d\n", func, iter+1);
2464			return XDR_DECODE_ERROR;
2465		}
2466		if (dbglvl >= 3)
2467			printf("comparing XDR-generated structs...\n");
2468		if ((ret = compare_CSSM_QUERY(query, xdrcopy)) != OK)
2469		{
2470			fprintf(stderr, "%s: CSSM_QUERY old/new XDR comparison, round %d, failed\n",
2471					func, iter+1);
2472			return ret;
2473		}
2474		if (dbglvl >= 3)
2475			printf("comparing walked- and XDR-generated structs...\n");
2476		if ((ret = compare_CSSM_QUERY(xdrcopy, walkcopy)) != OK)
2477		{
2478			fprintf(stderr, "%s: CSSM_QUERY XDR/walker comparison, round %d, failed\n",
2479					func, iter+1);
2480			return ret;
2481		}
2482		if (dbglvl >= 2)
2483			printf("CSSM_QUERY compared OK, round %d\n", iter+1);
2484		if (iter > 0)
2485			free(query);
2486		query = xdrcopy;
2487		free(flattenedQueryPtr);
2488		flattenedQueryPtr = NULL;
2489		flattenedQueryLen = 0;
2490	}
2491	if (dbglvl >= 1)
2492		printf("Successfully finished CSSM_QUERY check\n");
2493	return OK;
2494}
2495
2496int test_CSSM_QUERY(int fd, int doflip, int dbglvl)
2497{
2498	const char *func = "test_CSSM_QUERY()";
2499	CSSM_QUERY *query;
2500	int ret, querysize;
2501
2502	if (fd > -1)	/* cheesy hack, but what ya gonna do? */
2503	{
2504		uint32_t ptrsize;	/* AKA mach_msg_type_number_t, AKA natural_t */
2505		intptr_t baseptr;
2506		off_t offset;
2507		ssize_t readPtr;
2508		int nq = 0;		/* # of queries */
2509		/*
2510		 * Saved format (v. 1 of saved-data protocol):
2511		 * - preamble
2512		 * - sizeof(base pointer)
2513		 * - base pointer
2514		 * - length
2515		 * - CSSM_QUERY
2516		 */
2517		do
2518		{
2519			if (nq)		/* first readPreamble() was in main() */
2520			{
2521				/* dummy vars -- let the func params govern */
2522				uint32_t d1, d2, d3 = 0;
2523				if ((ret = readPreamble(fd, &d1, &d2, &d3)) != OK)
2524				{
2525					if (ret == READ_EOF)
2526					{
2527						readPtr = -1;
2528						continue;
2529					}
2530					return ret;
2531				}
2532			}
2533			readPtr = read(fd, &ptrsize, sizeof(ptrsize));
2534			if (readPtr == 0) break;	/* we're done */
2535			if (readPtr < static_cast<ssize_t>(sizeof(ptrsize)))
2536			{
2537				fprintf(stderr, "%s: Error reading base pointer size\n", func);
2538				return BAD_READ;
2539			}
2540			if (doflip) flip(&ptrsize, sizeof(ptrsize));
2541			if (read(fd, &baseptr, ptrsize) < static_cast<ssize_t>(ptrsize))
2542			{
2543				fprintf(stderr, "%s: Error reading base pointer\n", func);
2544				return BAD_READ;
2545			}
2546			if (doflip) flip(&baseptr, sizeof(baseptr));
2547			if (read(fd, &querysize, sizeof(querysize)) < static_cast<ssize_t>(sizeof(querysize)))
2548			{
2549				fprintf(stderr, "%s: Error reading CSSM_QUERY size\n", func);
2550				return BAD_READ;
2551			}
2552			if (doflip) flip(&querysize, sizeof(querysize));
2553			query = (CSSM_QUERY *)malloc(querysize);
2554			if (query == NULL)
2555				return MEM_ERROR;
2556			if (read(fd, query, querysize) < querysize)
2557			{
2558				fprintf(stderr, "Error reading CSSM_QUERY\n");
2559				return BAD_READ;
2560			}
2561			offset = reinterpret_cast<intptr_t>(query) - baseptr;
2562			if (doflip)
2563			{
2564				hostorder_CSSM_QUERY(query, offset);
2565			}
2566			else
2567			{
2568				ReconstituteWalker relocator(offset);
2569				walk(relocator, reinterpret_cast<CssmQuery *&>(baseptr));
2570			}
2571			++nq;
2572			if (dbglvl >= 2)
2573				printf("%s: read a new CSSM_QUERY (%d)\n", func, nq);
2574			if ((ret = test_xdrwalk_CSSM_QUERY(query, dbglvl)) != OK)
2575				fprintf(stderr, "%s\n", func);
2576			free(query);
2577		}
2578		while (readPtr != -1);
2579		(void)close(fd);
2580	}
2581	else
2582	{
2583		/* TODO/gh  cobble something up */
2584		fprintf(stderr, "%s: hard-coded test not implemented yet\n", func);
2585		return NOT_IMPLEMENTED;
2586	}
2587	return OK;
2588}
2589
2590void usage(const char *progname)
2591{
2592	fprintf(stderr, "Usage: %s [-c|-I|-i] <FILE>\n", progname);
2593	fprintf(stderr, "    FILE is binary data saved from securityd\n");
2594	fprintf(stderr, "    -c\trun hard-coded CSSM_CONTEXT test\n");
2595	fprintf(stderr, "    -i\trun hard-coded CSSM_ACL_ENTRY_INFO test\n");
2596	fprintf(stderr, "    -I\trun hard-coded CSSM_ACL_ENTRY_INPUT test\n");
2597	fprintf(stderr, "    -v\tverbose (more -v options mean more output\n");
2598	fprintf(stderr, "    If FILE is not provided, %s will try to run any requested hard-coded test\n", progname);
2599}
2600
2601int main(int ac, char **av)
2602{
2603	const char *optstring = "chIiv";
2604	char *infile = NULL;
2605	int c, fd, ret = OK, debuglevel = 0;
2606	uint32_t doflip, version, type = 0;
2607
2608	while ((c = getopt(ac, av, optstring)) != EOF)
2609	{
2610		switch(c)
2611		{
2612			case 'c':
2613				type = SecuritydDataSave::CONTEXT;
2614				break;
2615			case 'I':
2616				type = SecuritydDataSave::ACL_ENTRY_INPUT;
2617				break;
2618			case 'i':
2619				type = SecuritydDataSave::ACL_ENTRY_INFO;
2620				break;
2621			case 'h':
2622				usage(av[0]);
2623				exit(0);
2624				break;
2625			case 'v':
2626				debuglevel++;
2627				break;
2628			default:
2629				break;
2630		}
2631	}
2632	ac -= optind;
2633	av += optind;
2634	if (ac >= 1)
2635	{
2636		infile = av[0];		/* XXX/gh  need to validate av[0]? */
2637		if ((fd = open(infile, O_RDONLY, 0)) < 0)
2638		{
2639			fprintf(stderr, "Couldn't open %s (%s)\n", infile, strerror(errno));
2640			return 2;
2641		}
2642		if ((ret = readPreamble(fd, &doflip, &version, &type)) != OK)
2643			return ret;
2644	}
2645	else
2646	{
2647		fd = -1;				/* use a hard-coded test */
2648		if (!type)
2649		{
2650			type = SecuritydDataSave::CONTEXT;		/* the only test that has hard-coded data...*/
2651			fprintf(stderr, "*** running hard-coded CSSM_CONTEXT test\n");
2652		}
2653	}
2654	switch (type)
2655	{
2656		case SecuritydDataSave::CONTEXT:
2657			ret = test_CSSM_CONTEXT(fd, doflip, debuglevel);
2658			break;
2659		case SecuritydDataSave::ACL_OWNER_PROTOTYPE:
2660			ret = test_CSSM_ACL_OWNER_PROTOTYPE(fd, doflip, debuglevel);
2661			break;
2662		case SecuritydDataSave::ACL_ENTRY_INPUT:
2663			ret = test_CSSM_ACL_ENTRY_INPUT(fd, doflip, debuglevel);
2664			break;
2665		case SecuritydDataSave::ACL_ENTRY_INFO:
2666			ret = test_CSSM_ACL_ENTRY_INFO(fd, doflip, debuglevel);
2667			break;
2668		case SecuritydDataSave::QUERY:
2669			ret = test_CSSM_QUERY(fd, doflip, debuglevel);
2670			break;
2671		default:
2672			fprintf(stderr, "Unrecognized test\n");
2673			ret = NOT_IMPLEMENTED;
2674	}
2675	return ret;
2676}
2677