int dbOpenCloseInit(TestParams *testParams)
{
	dlHand = cuDlStartup();
	if(dlHand == 0) {
		printf("***dbOpenCloseInit: Error connecting to DL\n");
		return -1;
	}
	
	int ourRtn = 0;
	
	/* Create the DB, deleting existing */
	CSSM_RETURN crtn;
	CSSM_DB_HANDLE dbHand = 0;
	crtn = dbCreateOpen(dlHand, DB_NAME, 
		CSSM_TRUE,		// doCreate
		CSSM_TRUE,		// delete exist
		"foobar",
		&dbHand);
	if(crtn) {
		printf("***Error creating %s. Aborting.\n", DB_NAME);
		ourRtn = -1;
	}
	return ourRtn;
}
/*
 * Verify a CRL against system anchors and intermediate certs. 
 */
CSSM_RETURN cuCrlVerify(
	CSSM_TP_HANDLE			tpHand, 
	CSSM_CL_HANDLE 			clHand,
	CSSM_CSP_HANDLE 		cspHand,
	const CSSM_DATA			*crlData,
	CSSM_DL_DB_HANDLE_PTR	certKeychain,	// intermediate certs
	const CSSM_DATA 		*anchors,		// optional - if NULL, use Trust Settings
	uint32 					anchorCount)
{
	/* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
	CSSM_TP_VERIFY_CONTEXT			vfyCtx;
	CSSM_TP_CALLERAUTH_CONTEXT		authCtx;
	
	memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
	memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
	
	/* CSSM_TP_CALLERAUTH_CONTEXT components */
	/* 
		typedef struct cssm_tp_callerauth_context {
			CSSM_TP_POLICYINFO Policy;
			CSSM_TIMESTRING VerifyTime;
			CSSM_TP_STOP_ON VerificationAbortOn;
			CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
			uint32 NumberOfAnchorCerts;
			CSSM_DATA_PTR AnchorCerts;
			CSSM_DL_DB_LIST_PTR DBList;
			CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
		} CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
	*/
	CSSM_FIELD	policyId;
	CSSM_APPLE_TP_CRL_OPTIONS crlOpts;
	policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL;
	policyId.FieldValue.Data = (uint8 *)&crlOpts;
	policyId.FieldValue.Length = sizeof(crlOpts);
	crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
	/* perhaps this should be user-specifiable */
	crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
	crlOpts.crlStore = NULL;

	authCtx.Policy.NumberOfPolicyIds = 1;
	authCtx.Policy.PolicyIds = &policyId;
	authCtx.Policy.PolicyControl = NULL;
	
	authCtx.VerifyTime = NULL;
	authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
	authCtx.CallbackWithVerifiedCert = NULL;
	
	/* anchors */
	authCtx.NumberOfAnchorCerts = anchorCount;
	authCtx.AnchorCerts = const_cast<CSSM_DATA_PTR>(anchors);
	
	/* DBList of intermediate certs, plus possible System.keychain and 
   	 * system roots */
	CSSM_DL_DB_HANDLE handles[3];
	unsigned numDbs = 0;
	CSSM_DL_HANDLE dlHand = 0;
	if(certKeychain != NULL) {
		handles[0] = *certKeychain;
		numDbs++;
	}
	if(anchors == NULL) {
		/* Trust Settings requires two more DBs */
		if(numDbs == 0) {
			/* new DL handle */
			dlHand = cuDlStartup();
			handles[numDbs].DLHandle = dlHand;
			handles[numDbs + 1].DLHandle = dlHand;
		}
		else {
			/* use the same one passed in for certKeychain */
			handles[numDbs].DLHandle = handles[0].DLHandle;
			handles[numDbs + 1].DLHandle = handles[0].DLHandle;
		}
		handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
			(char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
		numDbs++;
		
		handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
			(char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
		numDbs++;
	}
	CSSM_DL_DB_LIST dlDbList;
	dlDbList.DLDBHandle = handles;
	dlDbList.NumHandles = numDbs;
	
	authCtx.DBList = &dlDbList; 
	authCtx.CallerCredentials = NULL;
	
	/* CSSM_TP_VERIFY_CONTEXT */
	vfyCtx.ActionData.Data = NULL;
	vfyCtx.ActionData.Length = 0;
	vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
	vfyCtx.Cred = &authCtx;

	/* CSSM_APPLE_TP_ACTION_DATA */
	CSSM_APPLE_TP_ACTION_DATA tpAction;
	if(anchors == NULL) {
		/* enable Trust Settings */
		tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION;
		tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS;
		vfyCtx.ActionData.Data   = (uint8 *)&tpAction;
		vfyCtx.ActionData.Length = sizeof(tpAction);
	}
	
	/* cook up CSSM_ENCODED_CRL */
	CSSM_ENCODED_CRL encCrl;
	encCrl.CrlType = CSSM_CRL_TYPE_X_509v2;
	encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER;
	encCrl.CrlBlob = *crlData;
	
	/* CDSA API requires a SignerCertGroup; for us, all the certs are in
	 * certKeyChain... */
	CSSM_CERTGROUP certGroup;
	certGroup.CertType = CSSM_CERT_X_509v1;
	certGroup.CertEncoding = CSSM_CERT_ENCODING_DER;
	certGroup.NumCerts = 0;
	certGroup.GroupList.CertList = NULL;
	certGroup.CertGroupType = CSSM_CERTGROUP_DATA;
	
	CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand,
		clHand,
		cspHand,
		&encCrl,
		&certGroup,
		&vfyCtx,
		NULL);			// RevokerVerifyResult
	if(crtn) {
		cuPrintError("CSSM_TP_CrlVerify", crtn);
	}
	if(anchors == NULL) {
		/* close the DBs and maybe the DL we opened */
		unsigned dexToClose = (certKeychain == NULL) ? 0 : 1;
		CSSM_DL_DbClose(handles[dexToClose++]);
		CSSM_DL_DbClose(handles[dexToClose]);
		if(dlHand != 0) {
			cuDlDetachUnload(dlHand);
		}
	}
	return crtn;
}
int certVerify(CertVerifyArgs *vfyArgs)
{
	if(vfyArgs->version != CERT_VFY_ARGS_VERS) {
		printf("***CertVerifyArgs.Version mismatch. Clean and rebuild.\n");
		return -1;
	}
	
	/* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
	CSSM_TP_VERIFY_CONTEXT			vfyCtx;
	CSSM_TP_CALLERAUTH_CONTEXT		authCtx;
	CSSM_TP_VERIFY_CONTEXT_RESULT	vfyResult;
	CSSM_APPLE_TP_SSL_OPTIONS		sslOpts;
	CSSM_APPLE_TP_SMIME_OPTIONS		smimeOpts;
	
	memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
	memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
	
	/* CSSM_TP_CALLERAUTH_CONTEXT components */
	/* 
		typedef struct cssm_tp_callerauth_context {
			CSSM_TP_POLICYINFO Policy;
			CSSM_TIMESTRING VerifyTime;
			CSSM_TP_STOP_ON VerificationAbortOn;
			CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
			uint32 NumberOfAnchorCerts;
			CSSM_DATA_PTR AnchorCerts;
			CSSM_DL_DB_LIST_PTR DBList;
			CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
		} CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
	*/
	/* up to 3 policies */
	CSSM_FIELD	policyIds[3];
	CSSM_FIELD  *policyPtr = &policyIds[0];
	uint32 numPolicies = 0;
	memset(policyIds, 0, 3 * sizeof(CSSM_FIELD));

	switch(vfyArgs->vfyPolicy) {
		case CVP_SSL:
		case CVP_IPSec:
			if(vfyArgs->vfyPolicy == CVP_SSL) {
				policyPtr->FieldOid = CSSMOID_APPLE_TP_SSL;
			}
			else {
				policyPtr->FieldOid = CSSMOID_APPLE_TP_IP_SEC;
			}
			/* otherwise these policies are identical */
			/* sslOpts is optional */
			if((vfyArgs->sslHost != NULL) || vfyArgs->sslClient) {
				memset(&sslOpts, 0, sizeof(sslOpts));
				sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
				sslOpts.ServerName = vfyArgs->sslHost;
				if(vfyArgs->sslHost != NULL) {
					sslOpts.ServerNameLen = strlen(vfyArgs->sslHost) + 1;
				}
				if(vfyArgs->sslClient) {
					sslOpts.Flags |= CSSM_APPLE_TP_SSL_CLIENT;
				}
				policyPtr->FieldValue.Data = (uint8 *)&sslOpts;
				policyPtr->FieldValue.Length = sizeof(sslOpts);
			}
			break;
		case CVP_SMIME:
		case CVP_iChat:
			if(vfyArgs->vfyPolicy == CVP_SMIME) {
				policyPtr->FieldOid = CSSMOID_APPLE_TP_SMIME;
			}
			else {
				policyPtr->FieldOid = CSSMOID_APPLE_TP_ICHAT;
			}
			/* otherwise these policies are identical */
			/* smimeOpts is optional */
			if(vfyArgs->senderEmail != NULL) {
				smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION;
				smimeOpts.IntendedUsage = vfyArgs->intendedKeyUse;
				smimeOpts.SenderEmail = vfyArgs->senderEmail;
				smimeOpts.SenderEmailLen = strlen(vfyArgs->senderEmail) + 1;
				policyPtr->FieldValue.Data = (uint8 *)&smimeOpts;
				policyPtr->FieldValue.Length = sizeof(smimeOpts);
			}
			break;
		case CVP_Basic:
			policyPtr->FieldOid = CSSMOID_APPLE_X509_BASIC;
			break;
		case CVP_SWUpdateSign:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_SW_UPDATE_SIGNING;
			break;
		case CVP_ResourceSigning:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_RESOURCE_SIGN;
			break;
		case CVP_PKINIT_Server:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_SERVER;
			break;
		case CVP_PKINIT_Client:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_CLIENT;
			break;
		case CVP_AppleCodeSigning:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_CODE_SIGNING;
			break;
		case CVP_PackageSigning:
			/* no options */
			policyPtr->FieldOid = CSSMOID_APPLE_TP_PACKAGE_SIGNING;
			break;
		default:
			printf("***certVerify: bogus vfyPolicy\n");
			return 1;
	}
	if(verifySecPolicy(&policyPtr->FieldOid)) {
		return -1;
	}
	policyPtr++;
	numPolicies++;
	
	CSSM_APPLE_TP_CRL_OPTIONS crlOpts;
	if((vfyArgs->revokePolicy == CRP_CRL) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) {
		memset(&crlOpts, 0, sizeof(crlOpts));
		policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL;

		crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
		crlOpts.CrlFlags = 0;
		crlOpts.crlStore = NULL;
		policyPtr->FieldValue.Data = (uint8 *)&crlOpts;
		policyPtr->FieldValue.Length = sizeof(crlOpts);
		if(vfyArgs->requireCrlForAll) {
			crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT;
		}
		if(vfyArgs->crlNetFetchEnable) {
			crlOpts.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
		}
		if(vfyArgs->requireCrlIfPresent) {
			crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
		}
		crlOpts.crlStore = vfyArgs->crlDlDb;
		policyPtr++;
		numPolicies++;
	}
	
	CSSM_APPLE_TP_OCSP_OPTIONS ocspOpts;
	CSSM_DATA respUriData;
	CSSM_DATA respCertData = {vfyArgs->responderCertLen, 
			(uint8 *)vfyArgs->responderCert};
	if((vfyArgs->revokePolicy == CRP_OCSP) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) {
		memset(&ocspOpts, 0, sizeof(ocspOpts));
		policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_OCSP;

		crlOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
		policyPtr->FieldValue.Data = (uint8 *)&ocspOpts;
		policyPtr->FieldValue.Length = sizeof(ocspOpts);
		if(vfyArgs->requireOcspForAll) {
			ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT;
		}
		if(vfyArgs->requireOcspIfPresent) {
			ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
		}
		if(vfyArgs->disableCache) {
			ocspOpts.Flags |= (CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE |
						       CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE);
		}
		if(vfyArgs->disableOcspNet) {
			ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_DISABLE_NET;
		}
		if(vfyArgs->generateOcspNonce) {
			ocspOpts.Flags |= CSSM_TP_OCSP_GEN_NONCE;
		}
		if(vfyArgs->requireOcspRespNonce) {
			ocspOpts.Flags |= CSSM_TP_OCSP_REQUIRE_RESP_NONCE;
		}
		if(vfyArgs->responderURI != NULL) {
			respUriData.Data = (uint8 *)vfyArgs->responderURI;
			respUriData.Length = strlen(vfyArgs->responderURI);
			ocspOpts.LocalResponder = &respUriData;
		}
		if(vfyArgs->responderCert != NULL) {
			ocspOpts.LocalResponderCert = &respCertData;
		}
		/* other OCSP options here */
		policyPtr++;
		numPolicies++;
	}
	
	authCtx.Policy.NumberOfPolicyIds = numPolicies;

	authCtx.Policy.PolicyIds = policyIds;
	authCtx.Policy.PolicyControl = NULL;
	
	authCtx.VerifyTime = vfyArgs->vfyTime;			// may be NULL
	authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
	authCtx.CallbackWithVerifiedCert = NULL;
	
	/*
	 * DLDBs - the caller's optional set, plus two more we open
	 * if trust settings are enabled and we're told to use system
	 * anchors. (System anchors are normally passed in via 
	 * authCtx.AnchorCerts; they're passed in as DLDBs when
	 * using TrustSettings.)
	 */
	uint32 totalNumDbs = 0;
	uint32 numCallerDbs = 0;
	CSSM_BOOL weOpenedDbs = CSSM_FALSE;
	if(vfyArgs->dlDbList != NULL) {
		totalNumDbs = numCallerDbs = vfyArgs->dlDbList->NumHandles;
	}
	if(vfyArgs->useTrustSettings && vfyArgs->useSystemAnchors) {
		/* we'll cook up two more DBs and possible append them */	
		totalNumDbs += 2;
		weOpenedDbs = CSSM_TRUE;
	}
	CSSM_DL_DB_HANDLE dlDbHandles[totalNumDbs];
	CSSM_DL_DB_LIST dlDbList;
	CSSM_DL_HANDLE dlHand = 0;
	for(unsigned dex=0; dex<numCallerDbs; dex++) {
		dlDbHandles[dex] = vfyArgs->dlDbList->DLDBHandle[dex];
	}
	if(weOpenedDbs) {
		/* get a DL handle, somehow */
		if(numCallerDbs == 0) {
			/* new DL handle */
			dlHand = cuDlStartup();
			dlDbHandles[0].DLHandle = dlHand;
			dlDbHandles[1].DLHandle = dlHand;
		}
		else {
			/* use the same one caller passed in */
			dlDbHandles[numCallerDbs].DLHandle     = dlDbHandles[0].DLHandle;
			dlDbHandles[numCallerDbs + 1].DLHandle = dlDbHandles[0].DLHandle;
		}
		/* now open two DBs */
		dlDbHandles[numCallerDbs].DBHandle = 
			cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle,
				(char *)ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
		dlDbHandles[numCallerDbs + 1].DBHandle = 
			cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle,
				(char *)SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
	}
	dlDbList.DLDBHandle = dlDbHandles;
	dlDbList.NumHandles = totalNumDbs;
	authCtx.DBList = &dlDbList;

	CFArrayRef cfAnchors = NULL;
	CSSM_DATA *cssmAnchors = NULL;
	unsigned numAnchors = 0;

	if(vfyArgs->useSystemAnchors) {
		if(!vfyArgs->useTrustSettings) {
			/* standard system anchors - ingore error, I'm sure the
			 * current test will eventually fail */
			getSystemAnchors(&cfAnchors, &cssmAnchors, &numAnchors);
			authCtx.NumberOfAnchorCerts = numAnchors;
			authCtx.AnchorCerts = cssmAnchors;
		}
	}
	else {
		/* anchors are our caller's roots */
		if(vfyArgs->roots) {
			authCtx.NumberOfAnchorCerts = vfyArgs->roots->numBlobs();
			authCtx.AnchorCerts = vfyArgs->roots->blobList();
		}
	}
	authCtx.CallerCredentials = NULL;
	
	if(vfyArgs->crls) {
		/* cook up CRL group */
		CSSM_CRLGROUP_PTR cssmCrls = &vfyCtx.Crls;
		cssmCrls->CrlType = CSSM_CRL_TYPE_X_509v1;
		cssmCrls->CrlEncoding = CSSM_CRL_ENCODING_DER;
		cssmCrls->NumberOfCrls = vfyArgs->crls->numBlobs();
		cssmCrls->GroupCrlList.CrlList = vfyArgs->crls->blobList();
		cssmCrls->CrlGroupType = CSSM_CRLGROUP_DATA;
	}
	
	/* CSSM_APPLE_TP_ACTION_DATA */
	CSSM_APPLE_TP_ACTION_DATA tpAction;
	tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION;
	tpAction.ActionFlags = 0;
	if(vfyArgs->leafCertIsCA) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_LEAF_IS_CA;
	}
	if(vfyArgs->certNetFetchEnable) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
	}
	if(vfyArgs->allowExpiredRoot) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT;
	}
	if(!vfyArgs->allowUnverified) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;
	}
	if(vfyArgs->useTrustSettings) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
	}
	if(vfyArgs->implicitAnchors) {
		tpAction.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS;
	}
	
	/* CSSM_TP_VERIFY_CONTEXT */
	vfyCtx.ActionData.Data   = (uint8 *)&tpAction;
	vfyCtx.ActionData.Length = sizeof(tpAction);

	vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
	vfyCtx.Cred = &authCtx;
	
	/* cook up cert group */
	CSSM_CERTGROUP cssmCerts;
	cssmCerts.CertType = CSSM_CERT_X_509v3;
	cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER;
	cssmCerts.NumCerts = vfyArgs->certs->numBlobs();
	cssmCerts.GroupList.CertList = vfyArgs->certs->blobList();
	cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA;
	
	int ourRtn = 0;
	CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(vfyArgs->tpHand,
		vfyArgs->clHand,
		vfyArgs->cspHand,
		&cssmCerts,
		&vfyCtx,
		&vfyResult);
	if(vfyArgs->expectedErrStr != NULL) {
		const char *actRtn;
		if(crtn == CSSM_OK) {
			/* cssmErrorString munges this to "[ok]" */
			actRtn = "CSSM_OK";
		}
		else {
			actRtn = cssmErrToStr(crtn);
		}
		char *found = strstr(actRtn, vfyArgs->expectedErrStr);
		if(found) {
			if(!vfyArgs->quiet) {
				printf("...%s received as expected\n", vfyArgs->expectedErrStr);
			}
		}
		else {
			printf("***CSSM_TP_CertGroupVerify error\n");
			printf("   expected rtn : %s\n", vfyArgs->expectedErrStr);
			printf("     actual rtn : %s\n", actRtn);
			ourRtn = 1;
		}
	}
	else {
		if(crtn) {
			if(!vfyArgs->quiet) {
				printError("CSSM_TP_CertGroupVerify", crtn);
			}
			ourRtn = 1;
		}
		else if(!vfyArgs->quiet) {
			printf("...verify successful\n");
		}
	}
	if(vfyArgs->certErrors) {
		if(vfyCertErrors(&vfyResult, vfyArgs->numCertErrors, vfyArgs->certErrors, 
				vfyArgs->quiet)) {
			ourRtn = 1;
		}
	}
	if(vfyArgs->certStatus) {
		if(vfyCertStatus(&vfyResult, vfyArgs->numCertStatus, vfyArgs->certStatus,
				vfyArgs->quiet)) {
			ourRtn = 1;
		}
	}
	if(vfyArgs->verbose) {
		dumpVfyResult(&vfyResult);
	}
	freeVfyResult(&vfyResult);
	if(weOpenedDbs) {
		/* close the DBs and maybe the DL we opened */
		CSSM_DL_DbClose(dlDbHandles[numCallerDbs]);
		CSSM_DL_DbClose(dlDbHandles[numCallerDbs + 1]);
		if(dlHand != 0) {
			cuDlDetachUnload(dlHand);
		}
	}
	if(cfAnchors) {
		CFRelease(cfAnchors);
	}
	if(cssmAnchors) {
		free(cssmAnchors);
	}
	return ourRtn;
}