2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
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
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.
20 // dlclient - client interface to CSSM DLs and their operations
23 #ifndef _H_CDSA_CLIENT_DLCLIENT
24 #define _H_CDSA_CLIENT_DLCLIENT 1
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>
41 #define CSSM_DB_ATTR(ATTR) ATTR
42 #define CSSM_DB_ATTR_SCHEMA(ATTR) ATTR ## Schema
44 #define CSSM_DB_INDEX(ATTR) ATTR ## Index
45 #define CSSM_DB_UNIQUE(ATTR) ATTR ## Unique
48 // Helper macro for declaring and defining a Db index unique and non-unique attributes
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)
55 // Use this macro for defining a non-unique attribute
57 #define CSSM_DB_INDEX_DEF(ATTR) \
58 const CSSM_DB_INDEX_INFO CSSM_DB_INDEX(ATTR) = \
60 CSSM_DB_INDEX_NONUNIQUE, \
61 CSSM_DB_INDEX_ON_ATTRIBUTE, \
66 // Use this macro for defining a unique attribute
69 #define CSSM_DB_UNIQUE_DEF(ATTR) \
70 const CSSM_DB_INDEX_INFO CSSM_DB_UNIQUE(ATTR) = \
72 CSSM_DB_INDEX_UNIQUE, \
73 CSSM_DB_INDEX_ON_ATTRIBUTE, \
80 // Helper macro for declaring and defining a Db schema attributes
81 // Use this macro in your header to declare each attribute you require.
83 #define CSSM_DB_ATTR_DECL(ATTR) \
84 static const CSSM_DB_ATTRIBUTE_INFO CSSM_DB_ATTR(ATTR); \
85 static const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR)
88 // Don't directly use this macro use one of the below instead.
90 #define CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
91 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR) = \
95 { OID_LEN, OID_DATA }, \
96 CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
101 // Use one of the following macros to defined each declared attribute required by your application.
104 // Use this macro to define attributes which are looked up by integer AttributeID.
106 #define CSSM_DB_INTEGER_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
107 const CSSM_DB_ATTRIBUTE_INFO ATTR = \
109 CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, \
111 CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
114 CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
117 // Use this macro to define attributes which are looked up by string AttributeName.
119 #define CSSM_DB_NAME_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
120 const CSSM_DB_ATTRIBUTE_INFO ATTR = \
122 CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \
124 CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
127 CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
130 // Use this macro to define attributes which are looked up by OID AttributeNameID.
131 // XXX This does not work yet.
133 #define CSSM_DB_OID_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \
134 const CSSM_DB_ATTRIBUTE_INFO ATTR = \
136 CSSM_DB_ATTRIBUTE_NAME_AS_OID, \
137 {{OID_LEN, OID_DATA}}, \
138 CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
141 CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
145 // Use this macro to define attributes which are part of the primary key.
147 #define CSSM_DB_PRIMARKEY_ATTR(ATTR, NAME) \
148 const CSSM_DB_ATTRIBUTE_INFO ATTR = \
150 CSSM_DB_INDEX_UNIQUE, \
151 CSSM_DB_INDEX_ON_ATTRIBUTE, \
152 CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \
155 CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE)
160 // Maker interfaces used by various Impl objects
163 // DbMaker -- someone who can create a new DbImpl.
169 virtual DbImpl
*newDb(const char *inDbName
, const CSSM_NET_ADDRESS
*inDbLocation
) = 0;
172 // DbCursorMaker -- someone who can create a new DbCursorImpl.
177 virtual ~DbCursorMaker();
178 virtual DbCursorImpl
*newDbCursor(const CSSM_QUERY
&query
, Allocator
&allocator
) = 0;
179 virtual DbCursorImpl
*newDbCursor(uint32 capacity
, Allocator
&allocator
) = 0;
182 // DbUniqueRecordMaker -- someone who can create a new DbUniqueRecordImpl.
183 class DbUniqueRecordImpl
;
184 class DbUniqueRecordMaker
187 virtual ~DbUniqueRecordMaker();
188 virtual DbUniqueRecordImpl
*newDbUniqueRecord() = 0;
195 class DLImpl
: public AttachmentImpl
, public DbMaker
198 DLImpl(const Guid
&guid
);
199 DLImpl(const Module
&module);
202 virtual void getDbNames(char **);
203 virtual void freeNameList(char **);
206 virtual DbImpl
*newDb(const char *inDbName
, const CSSM_NET_ADDRESS
*inDbLocation
);
210 class DL
: public Attachment
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)) {}
220 Impl
*operator ->() const { return &impl
<Impl
>(); }
221 Impl
&operator *() const { return impl
<Impl
>(); }
223 // Conversion to DbMaker.
224 operator DbMaker
&() const { return impl
<Impl
>(); }
229 class DbUniqueRecord
;
234 // A CSSM_DLDB handle.
235 // Dbs always belong to DLs (DL attachments)
237 class DbImpl
: public ObjectImpl
, public AclBearer
,
238 public DbCursorMaker
, public DbUniqueRecordMaker
241 DbImpl(const DL
&dl
, const char *inDbName
= NULL
, const CSSM_NET_ADDRESS
*inDbLocation
= NULL
);
244 DL
dl() const { return parent
<DL
>(); }
245 Module
module() const { return dl()->module(); }
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()
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
);
265 virtual DbUniqueRecord
insert(CSSM_DB_RECORDTYPE recordType
,
266 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
267 const CSSM_DATA
*data
);
269 virtual DbUniqueRecord
insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType
,
270 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
273 const CSSM_DL_DB_HANDLE
&handle() { StLock
<Mutex
> _(mActivateMutex
); activate(); return mHandle
; }
275 const DbName
&dbName() { return mDbName
; }
276 void dbName(const DbName
&dbName
) { mDbName
= dbName
; }
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.
282 const CSSM_NET_ADDRESS
*dbLocation() const { return mDbName
.dbLocation(); }
284 CSSM_DB_ACCESS_TYPE
accessRequest() const { return mAccessRequest
; }
285 void accessRequest(CSSM_DB_ACCESS_TYPE inAccessRequest
)
286 { mAccessRequest
= inAccessRequest
; }
288 const CSSM_ACCESS_CREDENTIALS
*accessCredentials() const
289 { return mAccessCredentials
; }
290 void accessCredentials(const CSSM_ACCESS_CREDENTIALS
*inAccessCredentials
)
291 { mAccessCredentials
= inAccessCredentials
; }
293 const void *openParameters() const { return mOpenParameters
; }
294 void openParameters(const void *inOpenParameters
)
295 { mOpenParameters
= inOpenParameters
; }
297 const CSSM_DBINFO
*dbInfo() const { return mDbInfo
; }
298 void dbInfo(const CSSM_DBINFO
*inDbInfo
) { mDbInfo
= inDbInfo
; }
300 const ResourceControlContext
*resourceControlContext() const
301 { return mResourceControlContext
; }
302 void resourceControlContext(const CSSM_RESOURCE_CONTROL_CONTEXT
*inResourceControlContext
)
303 { mResourceControlContext
= ResourceControlContext::overlay(inResourceControlContext
); }
305 void passThrough(uint32 passThroughId
, const void *in
, void **out
= NULL
);
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
); }
311 // Passthrough functions (only implemented by AppleCSPDL).
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
);
325 // Get the version of this database's encoding
326 virtual uint32
dbBlobVersion();
328 // Attempt to recode this database to the new version
329 virtual uint32
recodeDbToVersion(uint32 version
);
331 // Declare that the recode operation is complete
332 virtual void recodeFinished();
334 // Try to take or release the file lock on the underlying database.
335 // You _must_ call these as a pair. They start a transaction on the
336 // underlying DL object, and that transaction is only finished when release
337 // is called. Pass success=true if you want the transaction to commit; otherwise
338 // it will roll back.
339 virtual void takeFileLock();
340 virtual void releaseFileLock(bool success
);
342 // Make a backup of this database on the filesystem
343 virtual void makeBackup();
345 // Make a copy of this database on the filesystem
346 // Throws a UnixError if anything goes wrong
347 virtual void makeCopy(const char* path
);
349 // Make a clone of this database in a new location.
350 // This method handles telling securityd about the clone, and copying the
352 virtual Db
cloneTo(const DLDbIdentifier
& dldbidentifier
);
354 // Transfer this database to a new location. If the database is open in
355 // securityd, transfer the lock status as well.
356 virtual void transferTo(const DLDbIdentifier
& dldbidentifier
);
358 // This will attempt to delete the file underlying this database.
359 // Don't call this unless you really, really mean to.
360 virtual void deleteFile();
364 // Always use the dbName and dbLocation that were passed in during
366 virtual DLDbIdentifier
dlDbIdentifier();
369 virtual DbCursorImpl
*newDbCursor(const CSSM_QUERY
&query
, Allocator
&allocator
);
370 virtual DbCursorImpl
*newDbCursor(uint32 capacity
, Allocator
&allocator
);
372 // DbUniqueRecordMaker
373 virtual DbUniqueRecordImpl
*newDbUniqueRecord();
376 void getAcl(AutoAclEntryInfoList
&aclInfos
, const char *selectionTag
= NULL
) const;
377 void changeAcl(const CSSM_ACL_EDIT
&aclEdit
,
378 const CSSM_ACCESS_CREDENTIALS
*accessCred
);
380 // Acl owner manipulation
381 void getOwner(AutoAclOwnerPrototype
&owner
) const;
382 void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE
&newOwner
,
383 const CSSM_ACCESS_CREDENTIALS
*accessCred
= NULL
);
385 // default-credential hook
386 class DefaultCredentialsMaker
{
388 virtual ~DefaultCredentialsMaker();
389 virtual const AccessCredentials
*makeCredentials() = 0;
392 void defaultCredentials(DefaultCredentialsMaker
*maker
); // NULL to turn off
400 CSSM_DL_DB_HANDLE mHandle
; // CSSM DLDB handle
403 bool mUseNameFromHandle
; // false if CSSM_DL_GetDbNameFromHandle failed
404 char *mNameFromHandle
; // Cached CSSM_DL_GetDbNameFromHandle result.
405 CSSM_DB_ACCESS_TYPE mAccessRequest
;
406 const CSSM_ACCESS_CREDENTIALS
*mAccessCredentials
;
407 DefaultCredentialsMaker
*mDefaultCredentials
;
408 const void *mOpenParameters
;
410 // Arguments to create
411 const CSSM_DBINFO
*mDbInfo
;
412 const ResourceControlContext
*mResourceControlContext
;
416 class Db
: public Object
, public DLAccess
420 typedef Impl::DefaultCredentialsMaker DefaultCredentialsMaker
;
422 explicit Db(Impl
*impl
) : Object(impl
) {}
423 Db() : Object(NULL
) {}
424 Db(DbMaker
&maker
, const char *inDbName
, const CSSM_NET_ADDRESS
*inDbLocation
= NULL
)
425 : Object(maker
.newDb(inDbName
, inDbLocation
)) {}
427 Impl
*operator ->() const { return &impl
<Impl
>(); }
428 Impl
&operator *() const { return impl
<Impl
>(); }
430 // Conversion to DbCursorMaker.
431 operator DbCursorMaker
&() const { return impl
<Impl
>(); }
432 // Conversion to DbUniqueRecordMaker.
433 operator DbUniqueRecordMaker
&() const { return impl
<Impl
>(); }
435 const CSSM_DL_DB_HANDLE
&handle() { return impl
<Impl
>().handle(); }
439 CSSM_HANDLE
dlGetFirst(const CSSM_QUERY
&query
,
440 CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
, CSSM_DATA
*data
,
441 CSSM_DB_UNIQUE_RECORD
*&id
);
442 bool dlGetNext(CSSM_HANDLE handle
,
443 CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
, CSSM_DATA
*data
,
444 CSSM_DB_UNIQUE_RECORD
*&id
);
445 void dlAbortQuery(CSSM_HANDLE handle
);
446 void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD
*id
);
447 void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD
*id
);
448 Allocator
&allocator();
455 // This class is still abstract. You must subclass it in order to be able to instantiate an instance.
456 class DbCursorImpl
: public ObjectImpl
, public CssmAutoQuery
459 DbCursorImpl(const Object
&parent
, const CSSM_QUERY
&query
, Allocator
&allocator
);
460 DbCursorImpl(const Object
&parent
, uint32 capacity
, Allocator
&allocator
);
462 virtual Allocator
&allocator() const;
463 virtual void allocator(Allocator
&alloc
);
465 virtual bool next(DbAttributes
*attributes
, ::CssmDataContainer
*data
, DbUniqueRecord
&uniqueId
) = 0;
466 void abort() { deactivate(); }
469 class DbCursor
: public Object
472 typedef DbCursorImpl Impl
;
474 explicit DbCursor(Impl
*impl
) : Object(impl
) {}
475 DbCursor() : Object(NULL
) {}
476 DbCursor(DbCursorMaker
&maker
, const CSSM_QUERY
&query
,
477 Allocator
&allocator
= Allocator::standard())
478 : Object(maker
.newDbCursor(query
, allocator
)) {}
479 DbCursor(DbCursorMaker
&maker
, uint32 capacity
= 0,
480 Allocator
&allocator
= Allocator::standard())
481 : Object(maker
.newDbCursor(capacity
, allocator
)) {}
483 Impl
*operator ->() const { return &impl
<Impl
>(); }
484 Impl
&operator *() const { return impl
<Impl
>(); }
491 class DbUniqueRecordImpl
: public ObjectImpl
494 DbUniqueRecordImpl(const Db
&db
);
495 virtual ~DbUniqueRecordImpl();
497 virtual void deleteRecord();
498 virtual void modify(CSSM_DB_RECORDTYPE recordType
,
499 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
500 const CSSM_DATA
*data
,
501 CSSM_DB_MODIFY_MODE modifyMode
);
503 virtual void modifyWithoutEncryption (CSSM_DB_RECORDTYPE recordType
,
504 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
505 const CSSM_DATA
*data
,
506 CSSM_DB_MODIFY_MODE modifyMode
);
508 virtual void get(DbAttributes
*attributes
, ::CssmDataContainer
*data
);
510 virtual void getWithoutEncryption(DbAttributes
*attributes
, ::CssmDataContainer
*data
);
512 Db
database() const { return parent
<Db
>(); }
514 void free() { deactivate(); }
516 // Client must call activate() after calling this function if mUniqueId is successfully set.
517 operator CSSM_DB_UNIQUE_RECORD_PTR
*() { if (mActive
) free(); return &mUniqueId
; }
519 operator CSSM_DB_UNIQUE_RECORD
*() { return mUniqueId
; }
520 operator const CSSM_DB_UNIQUE_RECORD
*() const { return mUniqueId
; }
524 void getRecordIdentifier(CSSM_DATA
&data
);
526 void setUniqueRecordPtr (CSSM_DB_UNIQUE_RECORD_PTR uniquePtr
); // because cast overloading is evil!
531 CSSM_DB_UNIQUE_RECORD_PTR mUniqueId
;
533 RecursiveMutex mActivateMutex
;
536 class DbUniqueRecord
: public Object
539 typedef DbUniqueRecordImpl Impl
;
541 explicit DbUniqueRecord(Impl
*impl
) : Object(impl
) {}
542 DbUniqueRecord() : Object(NULL
) {}
543 DbUniqueRecord(DbUniqueRecordMaker
&maker
) : Object(maker
.newDbUniqueRecord()) {}
545 Impl
*operator ->() { return &impl
<Impl
>(); }
546 Impl
&operator *() { return impl
<Impl
>(); }
547 const Impl
&operator *() const { return impl
<Impl
>(); }
549 // Conversion operators must be here.
551 // Client must activate after calling this function if mUniqueId is successfully set.
552 operator CSSM_DB_UNIQUE_RECORD_PTR
*() { return **this; }
554 operator CSSM_DB_UNIQUE_RECORD
*() { return **this; }
555 operator const CSSM_DB_UNIQUE_RECORD
*() const { return **this; }
562 class DbAttributes
: public CssmAutoDbRecordAttributeData
566 DbAttributes(const Db
&db
, uint32 capacity
= 0, Allocator
&allocator
= Allocator::standard());
568 // Similar to CssmAutoDbRecordAttributeData::updateWith, but a different
569 // signature. Will canonicalize the elements in both this and the newValues dbAttributes.
570 void updateWithDbAttributes(DbAttributes
* newValues
);
572 // Try to change the infos in this database to a canonicalized form
578 // DbDbCursor -- concrete subclass of DbCursorImpl for querying Db's
580 class DbDbCursorImpl
: public DbCursorImpl
583 DbDbCursorImpl(const Db
&db
, const CSSM_QUERY
&query
, Allocator
&allocator
);
584 DbDbCursorImpl(const Db
&db
, uint32 capacity
, Allocator
&allocator
);
585 virtual ~DbDbCursorImpl();
587 bool next(DbAttributes
*attributes
, ::CssmDataContainer
*data
, DbUniqueRecord
&uniqueId
);
590 Db
database() { return parent
<Db
>(); }
596 CSSM_HANDLE mResultsHandle
;
597 RecursiveMutex mActivateMutex
;
600 } // end namespace CssmClient
602 } // end namespace Security
604 #endif // _H_CDSA_CLIENT_DLCLIENT