1//
2// throw  C++-dependent stuff in here
3//
4#include <stdio.h>
5#include <Security/cssm.h>
6#include "common.h"
7#include <Security/SecBasePriv.h>
8#include <security_cdsa_client/keychainacl.h>
9#include <security_cdsa_utilities/cssmacl.h>
10#include <security_cdsa_client/aclclient.h>
11#include <security_cdsa_utilities/cssmdata.h>
12#include <security_cdsa_utilities/cssmalloc.h>
13#include <security_utilities/devrandom.h>
14#include <CoreFoundation/CFString.h>
15#include "cssmErrorStrings.h"		/* generated error string table */
16
17/*
18 * Log CSSM error.
19 */
20void printError(const char *op, CSSM_RETURN err)
21{
22	cssmPerror(op, err);
23}
24
25const char *cssmErrToStr(CSSM_RETURN err)
26{
27	const ErrString *esp;
28
29	for(esp=errStrings; esp->errStr!=NULL; esp++) {
30		if(esp->errCode == err) {
31			return esp->errStr;
32		}
33	}
34
35	static char outbuf[512];
36	sprintf(outbuf, "UNKNOWN ERROR CODE %d", (int)err);
37	return outbuf;
38}
39
40
41/*
42 * Open a DB, optionally:
43 *
44 *		-- ensuring it's empty
45 *		-- creating it
46 *		-- Specifying optional password to avoid SecurityAgent UI.
47 */
48CSSM_RETURN dbCreateOpen(
49	CSSM_DL_HANDLE		dlHand,			// from dlStartup()
50	const char 			*dbName,
51	CSSM_BOOL			doCreate,		// if false, must already exist
52	CSSM_BOOL			deleteExist,
53	const char			*pwd,			// optional
54	CSSM_DB_HANDLE		*dbHand)
55{
56	CSSM_RETURN		crtn;
57	CSSM_DBINFO		dbInfo;
58
59	if(deleteExist) {
60		/* first delete possible existing DB, ignore error */
61		crtn = dbDelete(dlHand, dbName);
62		switch(crtn) {
63			/* only allowed error is "no such file" */
64			case CSSM_OK:
65			case CSSMERR_DL_DATASTORE_DOESNOT_EXIST:
66				break;
67			default:
68				printError("CSSM_DL_DbDelete", crtn);
69				return crtn;
70		}
71		if(!doCreate) {
72			printf("***Hey! dbCreateOpen with deleteExist and !doCreate\n");
73			exit(1);
74		}
75	}
76	else {
77		/*
78		 * Try to open existing DB. This does not have a means
79		 * to specify password (yet).
80		 */
81		crtn = CSSM_DL_DbOpen(dlHand,
82			dbName,
83			NULL,			// DbLocation
84			CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
85			NULL, 			// CSSM_ACCESS_CREDENTIALS *AccessCred
86			NULL,			// void *OpenParameters
87			dbHand);
88		if(crtn == CSSM_OK) {
89			return crtn;
90		}
91		if(!doCreate) {
92			printError("CSSM_DL_DbOpen", crtn);
93			printf("Error opening %s\n", dbName);
94			return crtn;
95		}
96	}
97	memset(&dbInfo, 0, sizeof(CSSM_DBINFO));
98
99	/* now create it */
100	if(pwd) {
101		/*
102		 * This glorious code copied from crlRefresh. I didn't pretend
103		 * to understand it when I put it there either.
104		 */
105		Allocator &alloc = Allocator::standard();
106		CssmClient::AclFactory::PasswordChangeCredentials
107			pCreds((StringData(pwd)), alloc);
108		const AccessCredentials* aa = pCreds;
109		TypedList subject(alloc, CSSM_ACL_SUBJECT_TYPE_ANY);
110		AclEntryPrototype protoType(subject);
111		AuthorizationGroup &authGroup = protoType.authorization();
112		CSSM_ACL_AUTHORIZATION_TAG tag = CSSM_ACL_AUTHORIZATION_ANY;
113		authGroup.NumberOfAuthTags = 1;
114		authGroup.AuthTags = &tag;
115
116		const ResourceControlContext rcc(protoType,
117			const_cast<AccessCredentials *>(aa));
118
119		crtn = CSSM_DL_DbCreate(dlHand,
120			dbName,
121			NULL,						// DbLocation
122			&dbInfo,
123			// &Security::KeychainCore::Schema::DBInfo,
124			CSSM_DB_ACCESS_PRIVILEGED,
125			&rcc,						// CredAndAclEntry
126			NULL,						// OpenParameters
127			dbHand);
128	}
129	else {
130		crtn = CSSM_DL_DbCreate(dlHand,
131			dbName,
132			NULL,						// DbLocation
133			&dbInfo,
134			// &Security::KeychainCore::Schema::DBInfo,
135			CSSM_DB_ACCESS_PRIVILEGED,
136			NULL,						// CredAndAclEntry
137			NULL,						// OpenParameters
138			dbHand);
139	}
140	if(crtn) {
141		printError("CSSM_DL_DbCreate", crtn);
142	}
143	return crtn;
144}
145
146/*
147 * *The* way for all tests to get random data.
148 */
149void appGetRandomBytes(void *buf, unsigned len)
150{
151	try {
152		Security::DevRandomGenerator devRand(false);
153		devRand.random(buf, len);
154	}
155	catch(...) {
156		printf("***Hey! DevRandomGenerator threw an exception!\n");
157		/* Yes, exit - I'd really like to catch one of these */
158		exit(1);
159	}
160}
161