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