1/*
2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// dlclient - client interface to CSSM DLs and their operations
21//
22
23#ifndef _H_CDSA_CLIENT_DLCLIENT
24#define _H_CDSA_CLIENT_DLCLIENT  1
25
26#include <security_cdsa_client/cssmclient.h>
27#include <security_cdsa_client/dliterators.h>
28#include <security_cdsa_client/aclclient.h>
29#include <security_cdsa_client/DLDBList.h>
30#include <security_cdsa_utilities/cssmacl.h>
31#include <security_cdsa_utilities/cssmdb.h>
32#include <security_cdsa_utilities/cssmdata.h>
33
34
35namespace Security
36{
37
38namespace CssmClient
39{
40
41#define CSSM_DB_ATTR(ATTR) ATTR
42#define CSSM_DB_ATTR_SCHEMA(ATTR) ATTR ## Schema
43
44#define CSSM_DB_INDEX(ATTR) ATTR ## Index
45#define CSSM_DB_UNIQUE(ATTR) ATTR ## Unique
46
47//
48// Helper macro for declaring and defining a Db index unique and non-unique attributes
49//
50#define CSSM_DB_INDEX_DECL(ATTR)  static const CSSM_DB_INDEX_INFO CSSM_DB_INDEX(ATTR)
51#define CSSM_DB_UNIQUE_DECL(ATTR)  static const CSSM_DB_INDEX_INFO CSSM_DB_UNIQUE(ATTR)
52
53
54//
55// Use this macro for defining a non-unique attribute
56//
57#define CSSM_DB_INDEX_DEF(ATTR) \
58const CSSM_DB_INDEX_INFO CSSM_DB_INDEX(ATTR) = \
59{ \
60	CSSM_DB_INDEX_NONUNIQUE, \
61	CSSM_DB_INDEX_ON_ATTRIBUTE, \
62	CSSM_DB_ATTR(ATTR) \
63}
64
65//
66//  Use this macro for defining a unique attribute
67
68//
69#define CSSM_DB_UNIQUE_DEF(ATTR) \
70const CSSM_DB_INDEX_INFO CSSM_DB_UNIQUE(ATTR) = \
71{ \
72	CSSM_DB_INDEX_UNIQUE, \
73	CSSM_DB_INDEX_ON_ATTRIBUTE, \
74	CSSM_DB_ATTR(ATTR) \
75}
76
77
78
79//
80// Helper macro for declaring and defining a Db schema attributes
81// Use this macro in your header to declare each attribute you require.
82//
83#define CSSM_DB_ATTR_DECL(ATTR) \
84static const CSSM_DB_ATTRIBUTE_INFO CSSM_DB_ATTR(ATTR); \
85static const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR)
86
87//
88// Don't directly use this macro use one of the below instead.
89//
90#define CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
91const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR) = \
92{ \
93	INTEGER, \
94	NAME, \
95	{ OID_LEN, OID_DATA }, \
96	CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
97}
98
99
100//
101// Use one of the following macros to defined each declared attribute required by your application.
102//
103//
104// Use this macro to define attributes which are looked up by integer AttributeID.
105//
106#define CSSM_DB_INTEGER_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
107const CSSM_DB_ATTRIBUTE_INFO ATTR = \
108{ \
109    CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, \
110    {(char *)INTEGER}, \
111    CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
112};\
113\
114CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
115
116//
117// Use this macro to define attributes which are looked up by string AttributeName.
118//
119#define CSSM_DB_NAME_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
120const CSSM_DB_ATTRIBUTE_INFO ATTR = \
121{ \
122    CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \
123    {NAME}, \
124    CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
125};\
126\
127CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
128
129//
130// Use this macro to define attributes which are looked up by OID AttributeNameID.
131// XXX This does not work yet.
132//
133#define CSSM_DB_OID_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
134const CSSM_DB_ATTRIBUTE_INFO ATTR = \
135{ \
136    CSSM_DB_ATTRIBUTE_NAME_AS_OID, \
137    {{OID_LEN, OID_DATA}}, \
138    CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
139};\
140\
141CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
142
143
144//
145// Use this macro to define attributes which are part of the primary key.
146//
147#define CSSM_DB_PRIMARKEY_ATTR(ATTR, NAME) \
148const CSSM_DB_ATTRIBUTE_INFO ATTR = \
149{ \
150    CSSM_DB_INDEX_UNIQUE, \
151    CSSM_DB_INDEX_ON_ATTRIBUTE, \
152    CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
153};\
154\
155CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
156
157
158
159//
160// Maker interfaces used by various Impl objects
161//
162
163// DbMaker -- someone who can create a new DbImpl.
164class DbImpl;
165class DbMaker
166{
167public:
168	virtual ~DbMaker();
169	virtual DbImpl *newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) = 0;
170};
171
172// DbCursorMaker -- someone who can create a new DbCursorImpl.
173class DbCursorImpl;
174class DbCursorMaker
175{
176public:
177	virtual ~DbCursorMaker();
178	virtual DbCursorImpl *newDbCursor(const CSSM_QUERY &query, Allocator &allocator) = 0;
179	virtual DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator) = 0;
180};
181
182// DbUniqueRecordMaker -- someone who can create a new DbUniqueRecordImpl.
183class DbUniqueRecordImpl;
184class DbUniqueRecordMaker
185{
186public:
187	virtual ~DbUniqueRecordMaker();
188	virtual DbUniqueRecordImpl *newDbUniqueRecord() = 0;
189};
190
191
192//
193// A DL attachment
194//
195class DLImpl : public AttachmentImpl, public DbMaker
196{
197public:
198	DLImpl(const Guid &guid);
199	DLImpl(const Module &module);
200	virtual ~DLImpl();
201
202	virtual void getDbNames(char **);
203	virtual void freeNameList(char **);
204
205	// DbMaker
206	virtual DbImpl *newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation);
207private:
208};
209
210class DL : public Attachment
211{
212public:
213	typedef DLImpl Impl;
214
215	explicit DL(Impl *impl) : Attachment(impl) {}
216	DL() : Attachment(NULL) {}
217	DL(const Guid &guid) : Attachment(new Impl(guid)) {}
218	DL(const Module &module) : Attachment(new Impl(module)) {}
219
220	Impl *operator ->() const { return &impl<Impl>(); }
221	Impl &operator *() const { return impl<Impl>(); }
222
223	// Conversion to DbMaker.
224	operator DbMaker &() const { return impl<Impl>(); }
225};
226
227
228class DbAttributes;
229class DbUniqueRecord;
230class Db;
231
232
233//
234// A CSSM_DLDB handle.
235// Dbs always belong to DLs (DL attachments)
236//
237class DbImpl : public ObjectImpl, public AclBearer,
238	public DbCursorMaker, public DbUniqueRecordMaker
239{
240public:
241	DbImpl(const DL &dl, const char *inDbName = NULL, const CSSM_NET_ADDRESS *inDbLocation = NULL);
242	virtual ~DbImpl();
243
244	DL dl() const { return parent<DL>(); }
245	Module module() const { return dl()->module(); }
246
247	virtual void open();
248	virtual void create();
249	virtual void createWithBlob (CssmData &blob);
250	virtual void close();
251	virtual void deleteDb();
252	virtual void rename(const char *newName);
253	virtual void authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest,
254								const CSSM_ACCESS_CREDENTIALS *inAccessCredentials);
255	virtual void name(char *&outName);	// CSSM_DL_GetDbNameFromHandle()
256
257	virtual void createRelation(CSSM_DB_RECORDTYPE inRelationID,
258								const char *inRelationName,
259								uint32 inNumberOfAttributes,
260								const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo,
261								uint32 inNumberOfIndexes,
262								const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo);
263	virtual void destroyRelation(CSSM_DB_RECORDTYPE inRelationID);
264
265	virtual DbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType,
266									const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
267									const CSSM_DATA *data);
268
269	virtual DbUniqueRecord insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType,
270													const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
271													CSSM_DATA *data);
272
273	const CSSM_DL_DB_HANDLE &handle() { activate(); return mHandle; }
274
275	const DbName &dbName() { return mDbName; }
276	void dbName(const DbName &dbName) { mDbName = dbName; }
277
278	// Attempt to get a (cached) name from CSSM_DL_GetDbNameFromHandle(), falls
279	// back to the name passed in to the constructor if this fails.
280	const char *name();
281
282	const CSSM_NET_ADDRESS *dbLocation() const { return mDbName.dbLocation(); }
283
284	CSSM_DB_ACCESS_TYPE accessRequest() const { return mAccessRequest; }
285	void accessRequest(CSSM_DB_ACCESS_TYPE inAccessRequest)
286	{ mAccessRequest = inAccessRequest; }
287
288	const CSSM_ACCESS_CREDENTIALS *accessCredentials() const
289	{ return mAccessCredentials; }
290	void accessCredentials(const CSSM_ACCESS_CREDENTIALS *inAccessCredentials)
291	{ mAccessCredentials = inAccessCredentials; }
292
293	const void *openParameters() const { return mOpenParameters; }
294	void openParameters(const void *inOpenParameters)
295	{ mOpenParameters = inOpenParameters; }
296
297	const CSSM_DBINFO *dbInfo() const { return mDbInfo; }
298	void dbInfo(const CSSM_DBINFO *inDbInfo) { mDbInfo = inDbInfo; }
299
300	const ResourceControlContext *resourceControlContext() const
301	{ return mResourceControlContext; }
302	void resourceControlContext(const CSSM_RESOURCE_CONTROL_CONTEXT *inResourceControlContext)
303	{ mResourceControlContext = ResourceControlContext::overlay(inResourceControlContext); }
304
305	void passThrough(uint32 passThroughId, const void *in, void **out = NULL);
306
307	template <class TIn, class TOut>
308	void passThrough(uint32 passThroughId, const TIn *in, TOut *out = NULL)
309	{ passThrough(passThroughId, (const void *)in, (void **)out); }
310
311	// Passthrough functions (only implemented by AppleCSPDL).
312	virtual void lock();
313	virtual void unlock();
314	virtual void unlock(const CSSM_DATA &password);
315    virtual void stash();
316    virtual void stashCheck();
317	virtual void getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep);
318	virtual void setSettings(uint32 inIdleTimeout, bool inLockOnSleep);
319	virtual bool isLocked();
320	virtual void changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred);
321	virtual void recode(const CSSM_DATA &data, const CSSM_DATA &extraData);
322	virtual void copyBlob(CssmData &data);
323	virtual void setBatchMode(Boolean mode, Boolean rollback);
324
325	// Utility methods
326
327	// Always use the dbName and dbLocation that were passed in during
328	// construction.
329	virtual DLDbIdentifier dlDbIdentifier();
330
331	// DbCursorMaker
332	virtual DbCursorImpl *newDbCursor(const CSSM_QUERY &query, Allocator &allocator);
333	virtual DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator);
334
335	// DbUniqueRecordMaker
336	virtual DbUniqueRecordImpl *newDbUniqueRecord();
337
338	// Acl manipulation
339	void getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag = NULL) const;
340	void changeAcl(const CSSM_ACL_EDIT &aclEdit,
341		const CSSM_ACCESS_CREDENTIALS *accessCred);
342
343	// Acl owner manipulation
344	void getOwner(AutoAclOwnerPrototype &owner) const;
345	void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner,
346		const CSSM_ACCESS_CREDENTIALS *accessCred = NULL);
347
348	// default-credential hook
349	class DefaultCredentialsMaker {
350	public:
351		virtual ~DefaultCredentialsMaker();
352		virtual const AccessCredentials *makeCredentials() = 0;
353	};
354
355	void defaultCredentials(DefaultCredentialsMaker *maker);	// NULL to turn off
356
357	void activate();
358
359protected:
360	void deactivate();
361
362private:
363	CSSM_DL_DB_HANDLE mHandle;			// CSSM DLDB handle
364
365	DbName mDbName;
366	bool mUseNameFromHandle; // false if CSSM_DL_GetDbNameFromHandle failed
367	char *mNameFromHandle; // Cached CSSM_DL_GetDbNameFromHandle result.
368	CSSM_DB_ACCESS_TYPE mAccessRequest;
369	const CSSM_ACCESS_CREDENTIALS *mAccessCredentials;
370	DefaultCredentialsMaker *mDefaultCredentials;
371	const void *mOpenParameters;
372
373	// Arguments to create
374	const CSSM_DBINFO *mDbInfo;
375	const ResourceControlContext *mResourceControlContext;
376};
377
378
379class Db : public Object, public DLAccess
380{
381public:
382	typedef DbImpl Impl;
383	typedef Impl::DefaultCredentialsMaker DefaultCredentialsMaker;
384
385	explicit Db(Impl *impl) : Object(impl) {}
386	Db() : Object(NULL) {}
387	Db(DbMaker &maker, const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation = NULL)
388	: Object(maker.newDb(inDbName, inDbLocation)) {}
389
390	Impl *operator ->() const { return &impl<Impl>(); }
391	Impl &operator *() const { return impl<Impl>(); }
392
393	// Conversion to DbCursorMaker.
394	operator DbCursorMaker &() const { return impl<Impl>(); }
395	// Conversion to DbUniqueRecordMaker.
396	operator DbUniqueRecordMaker &() const { return impl<Impl>(); }
397
398	const CSSM_DL_DB_HANDLE &handle() { return impl<Impl>().handle(); }
399
400protected:
401	// DLAccess adapters
402	CSSM_HANDLE dlGetFirst(const CSSM_QUERY &query,
403		CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data,
404		CSSM_DB_UNIQUE_RECORD *&id);
405	bool dlGetNext(CSSM_HANDLE handle,
406		CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data,
407		 CSSM_DB_UNIQUE_RECORD *&id);
408	void dlAbortQuery(CSSM_HANDLE handle);
409	void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id);
410	void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id);
411	Allocator &allocator();
412};
413
414//
415// DbCursor
416//
417
418// This class is still abstract.  You must subclass it in order to be able to instantiate an instance.
419class DbCursorImpl : public ObjectImpl, public CssmAutoQuery
420{
421public:
422	DbCursorImpl(const Object &parent, const CSSM_QUERY &query, Allocator &allocator);
423	DbCursorImpl(const Object &parent, uint32 capacity, Allocator &allocator);
424
425	virtual Allocator &allocator() const;
426	virtual void allocator(Allocator &alloc);
427
428	virtual bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) = 0;
429	void abort() { deactivate(); }
430};
431
432class DbCursor : public Object
433{
434public:
435	typedef DbCursorImpl Impl;
436
437	explicit DbCursor(Impl *impl) : Object(impl) {}
438	DbCursor() : Object(NULL) {}
439	DbCursor(DbCursorMaker &maker, const CSSM_QUERY &query,
440			 Allocator &allocator = Allocator::standard())
441	: Object(maker.newDbCursor(query, allocator)) {}
442	DbCursor(DbCursorMaker &maker, uint32 capacity = 0,
443			 Allocator &allocator = Allocator::standard())
444	: Object(maker.newDbCursor(capacity, allocator)) {}
445
446	Impl *operator ->() const { return &impl<Impl>(); }
447	Impl &operator *() const { return impl<Impl>(); }
448};
449
450
451//
452// DbUniqueRecord
453//
454class DbUniqueRecordImpl : public ObjectImpl
455{
456public:
457	DbUniqueRecordImpl(const Db &db);
458	virtual ~DbUniqueRecordImpl();
459
460	virtual void deleteRecord();
461	virtual void modify(CSSM_DB_RECORDTYPE recordType,
462						const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
463						const CSSM_DATA *data,
464						CSSM_DB_MODIFY_MODE modifyMode);
465
466	virtual void modifyWithoutEncryption (CSSM_DB_RECORDTYPE recordType,
467											const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
468											const CSSM_DATA *data,
469											CSSM_DB_MODIFY_MODE modifyMode);
470
471	virtual void get(DbAttributes *attributes, ::CssmDataContainer *data);
472
473	virtual void getWithoutEncryption(DbAttributes *attributes, ::CssmDataContainer *data);
474
475	Db database() const { return parent<Db>(); }
476
477	void free() { deactivate(); }
478
479	// Client must call activate() after calling this function if mUniqueId is successfully set.
480	operator CSSM_DB_UNIQUE_RECORD_PTR *() { if (mActive) free(); return &mUniqueId; }
481
482	operator CSSM_DB_UNIQUE_RECORD *() { return mUniqueId; }
483	operator const CSSM_DB_UNIQUE_RECORD *() const { return mUniqueId; }
484
485	void activate();
486
487	void getRecordIdentifier(CSSM_DATA &data);
488
489	void setUniqueRecordPtr (CSSM_DB_UNIQUE_RECORD_PTR uniquePtr); // because cast overloading is evil!
490
491protected:
492	void deactivate();
493
494	CSSM_DB_UNIQUE_RECORD_PTR mUniqueId;
495	bool mDestroyID;
496    RecursiveMutex mActivateMutex;
497};
498
499class DbUniqueRecord : public Object
500{
501public:
502	typedef DbUniqueRecordImpl Impl;
503
504	explicit DbUniqueRecord(Impl *impl) : Object(impl) {}
505	DbUniqueRecord() : Object(NULL) {}
506	DbUniqueRecord(DbUniqueRecordMaker &maker) : Object(maker.newDbUniqueRecord()) {}
507
508	Impl *operator ->() { return &impl<Impl>(); }
509	Impl &operator *() { return impl<Impl>(); }
510	const Impl &operator *() const { return impl<Impl>(); }
511
512	// Conversion operators must be here.
513
514	// Client must activate after calling this function if mUniqueId is successfully set.
515	operator CSSM_DB_UNIQUE_RECORD_PTR *() { return **this; }
516
517	operator CSSM_DB_UNIQUE_RECORD *() { return **this; }
518	operator const CSSM_DB_UNIQUE_RECORD *() const { return **this; }
519};
520
521
522//
523// DbAttributes
524//
525class DbAttributes : public CssmAutoDbRecordAttributeData
526{
527public:
528	DbAttributes();
529	DbAttributes(const Db &db, uint32 capacity = 0, Allocator &allocator = Allocator::standard());
530};
531
532
533//
534// DbDbCursor -- concrete subclass of DbCursorImpl for querying Db's
535//
536class DbDbCursorImpl : public DbCursorImpl
537{
538public:
539	DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, Allocator &allocator);
540	DbDbCursorImpl(const Db &db, uint32 capacity, Allocator &allocator);
541	virtual ~DbDbCursorImpl();
542
543	bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId);
544
545protected:
546	Db database() { return parent<Db>(); }
547
548	void activate();
549	void deactivate();
550
551private:
552	CSSM_HANDLE mResultsHandle;
553    RecursiveMutex mActivateMutex;
554};
555
556} // end namespace CssmClient
557
558} // end namespace Security
559
560#endif // _H_CDSA_CLIENT_DLCLIENT
561