1/* 2 * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// cssmdb.h 26// 27// classes for the DL related data structures 28// 29 30#ifndef _H_CDSA_UTILITIES_CSSMDB 31#define _H_CDSA_UTILITIES_CSSMDB 32 33#include <security_cdsa_utilities/cssmdata.h> 34#include <security_cdsa_utilities/cssmpods.h> 35#include <security_cdsa_utilities/cssmalloc.h> 36#include <security_cdsa_utilities/walkers.h> 37#include <security_cdsa_utilities/cssmdbname.h> 38 39 40namespace Security { 41 42 43// 44// Template class to build and maintain external arrays. 45// Feel free to add and vector<> member functions and behaviours as needed. 46// 47// This class differs from vector mainly because it does not construct or 48// destruct any of the elements it contains. Rather it zero fills the 49// storage and returns references to elements. 50// Also it does not implement insert(), erase() or assign(). It does implement 51// which is equivalent to calling *insert(end()) on a vector. 52// 53template <class _Tp> 54class ArrayBuilder { 55public: 56 typedef _Tp value_type; 57 typedef value_type* pointer; 58 typedef const value_type* const_pointer; 59 typedef value_type* iterator; 60 typedef const value_type* const_iterator; 61 typedef value_type& reference; 62 typedef const value_type& const_reference; 63 typedef uint32 size_type; 64 typedef ptrdiff_t difference_type; 65 66 typedef reverse_iterator<const_iterator> const_reverse_iterator; 67 typedef reverse_iterator<iterator> reverse_iterator; 68 69protected: 70 void insert_aux(iterator __position, const _Tp& __x); 71 void insert_aux(iterator __position); 72 73public: 74 iterator begin() { return mArray; } 75 const_iterator begin() const { return mArray; } 76 iterator end() { return &mArray[mSize]; } 77 const_iterator end() const { return &mArray[mSize]; } 78 79 reverse_iterator rbegin() 80 { return reverse_iterator(end()); } 81 const_reverse_iterator rbegin() const 82 { return const_reverse_iterator(end()); } 83 reverse_iterator rend() 84 { return reverse_iterator(begin()); } 85 const_reverse_iterator rend() const 86 { return const_reverse_iterator(begin()); } 87 88 // Must be defined in base class. 89 //size_type size() const 90 //{ return mSize; } 91 size_type max_size() const 92 { return size_type(-1) / sizeof(_Tp); } 93 size_type capacity() const 94 { return mCapacity; } 95 bool empty() const 96 { return begin() == end(); } 97 98 ArrayBuilder(pointer &array, size_type &size, size_type capacity = 0, Allocator &allocator = Allocator::standard()) : 99 mArray(array), mSize(size), mCapacity(capacity), mAllocator(allocator) 100 { 101#if BUG_GCC 102 mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity)); 103#else 104 mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity)); 105 //mArray = mAllocator.alloc(mCapacity); 106#endif 107 memset(mArray, 0, sizeof(value_type) * mCapacity); 108 mSize = 0; 109 } 110 ~ArrayBuilder() { mAllocator.free(mArray); } 111 112 reference front() { return *begin(); } 113 const_reference front() const { return *begin(); } 114 reference back() { return *(end() - 1); } 115 const_reference back() const { return *(end() - 1); } 116 117 void reserve(size_type newCapacity) 118 { 119 if (newCapacity > mCapacity) 120 { 121#if BUG_GCC 122 mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity)); 123#else 124 mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity)); 125 //mArray = mAllocator.realloc<value_type>(mArray, newCapacity)); 126#endif 127 memset(&mArray[mCapacity], 0, sizeof(value_type) * (newCapacity - mCapacity)); 128 mCapacity = newCapacity; 129 } 130 } 131 132 // XXX Replace by push_back and insert. 133 reference add() 134 { 135 if (mSize >= mCapacity) 136 reserve(max(mSize + 1, mCapacity ? 2 * mCapacity : 1)); 137 138 return mArray[mSize++]; 139 } 140 141 const_pointer get() const { return mArray; } 142 pointer release() { const_pointer array = mArray; mArray = NULL; return array; } 143 void clear() { if (mSize) { memset(mArray, 0, sizeof(value_type) * mSize); } mSize = 0; } 144 145 // Must be defined in base class. 146 //reference at(size_type ix) { return mArray[ix]; } 147 //const_reference at(size_type ix) const { return mArray[ix]; } 148 //reference operator[] (size_type ix) { assert(ix < size()); return at(ix); } 149 //const_reference operator[] (size_type ix) const { assert(ix < size()); return at(ix); } 150protected: 151 Allocator &allocator() const { return mAllocator; } 152 153private: 154 155 pointer &mArray; 156 size_type &mSize; 157 size_type mCapacity; 158 Allocator &mAllocator; 159}; 160 161 162// 163// A CSSM_DL_DB_LIST wrapper. 164// Note that there is a DLDBList class elsewhere that is quite 165// unrelated to this structure. 166// 167class CssmDlDbHandle : public PodWrapper<CssmDlDbHandle, CSSM_DL_DB_HANDLE> { 168public: 169 CssmDlDbHandle() { clearPod(); } 170 CssmDlDbHandle(CSSM_DL_HANDLE dl, CSSM_DB_HANDLE db) { DLHandle = dl; DBHandle = db; } 171 172 CSSM_DL_HANDLE dl() const { return DLHandle; } 173 CSSM_DB_HANDLE db() const { return DBHandle; } 174 175 operator bool() const { return DLHandle && DBHandle; } 176}; 177 178inline bool operator < (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) 179{ 180 return h1.DLHandle < h2.DLHandle 181 || (h1.DLHandle == h2.DLHandle && h1.DBHandle < h2.DBHandle); 182} 183 184inline bool operator == (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) 185{ 186 return h1.DLHandle == h2.DLHandle && h1.DBHandle == h2.DBHandle; 187} 188 189inline bool operator != (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) 190{ 191 return h1.DLHandle != h2.DLHandle || h1.DBHandle != h2.DBHandle; 192} 193 194 195class CssmDlDbList : public PodWrapper<CssmDlDbList, CSSM_DL_DB_LIST> { 196public: 197 uint32 count() const { return NumHandles; } 198 uint32 &count() { return NumHandles; } 199 CssmDlDbHandle *handles() const { return CssmDlDbHandle::overlay(DLDBHandle); } 200 CssmDlDbHandle * &handles() { return CssmDlDbHandle::overlayVar(DLDBHandle); } 201 202 CssmDlDbHandle &operator [] (uint32 ix) const 203 { assert(ix < count()); return CssmDlDbHandle::overlay(DLDBHandle[ix]); } 204 205 void setDlDbList(uint32 n, CSSM_DL_DB_HANDLE *list) 206 { count() = n; handles() = CssmDlDbHandle::overlay(list); } 207}; 208 209 210// 211// CssmDLPolyData 212// 213class CssmDLPolyData 214{ 215public: 216 CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format) 217 : mData(CssmData::overlay(data)) 218#ifndef NDEBUG 219 , mFormat(format) 220#endif 221 {} 222 223 // @@@ Don't use assert, but throw an exception. 224 // @@@ Do a size check on mData as well. 225 226 // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated. 227 operator const char *() const 228 { 229 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_STRING 230 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE); 231 return reinterpret_cast<const char *>(mData.Data); 232 } 233 operator bool() const 234 { 235 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32); 236 return *reinterpret_cast<uint32 *>(mData.Data); 237 } 238 operator uint32() const 239 { 240 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32); 241 return *reinterpret_cast<uint32 *>(mData.Data); 242 } 243 operator const uint32 *() const 244 { 245 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32); 246 return reinterpret_cast<const uint32 *>(mData.Data); 247 } 248 operator sint32() const 249 { 250 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32); 251 return *reinterpret_cast<sint32 *>(mData.Data); 252 } 253 operator double() const 254 { 255 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_REAL); 256 return *reinterpret_cast<double *>(mData.Data); 257 } 258 operator CSSM_DATE () const; 259 operator Guid () const; 260 operator const CssmData &() const 261 { 262 return mData; 263 } 264 265private: 266 const CssmData &mData; 267#ifndef NDEBUG 268 CSSM_DB_ATTRIBUTE_FORMAT mFormat; 269#endif 270}; 271 272 273// 274// CssmDbAttributeInfo pod wrapper for CSSM_DB_ATTRIBUTE_INFO 275// 276class CssmDbAttributeInfo : public PodWrapper<CssmDbAttributeInfo, CSSM_DB_ATTRIBUTE_INFO> 277{ 278public: 279 CssmDbAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &attr) 280 { assignPod(attr); } 281 282 CssmDbAttributeInfo(const char *name, 283 CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); 284 CssmDbAttributeInfo(const CSSM_OID &oid, 285 CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); 286 CssmDbAttributeInfo(uint32 id, 287 CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); 288 289 CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat() const { return AttributeNameFormat; } 290 void nameFormat(CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat) { AttributeNameFormat = nameFormat; } 291 292 CSSM_DB_ATTRIBUTE_FORMAT format() const { return AttributeFormat; } 293 void format(CSSM_DB_ATTRIBUTE_FORMAT format) { AttributeFormat = format; } 294 295 const char *stringName() const 296 { 297 assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_STRING); 298 return Label.AttributeName; 299 } 300 const CssmOid &oidName() const 301 { 302 assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_OID); 303 return CssmOid::overlay(Label.AttributeOID); 304 } 305 uint32 intName() const 306 { 307 assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER); 308 return Label.AttributeID; 309 } 310 311 operator const char *() const { return stringName(); } 312 operator const CssmOid &() const { return oidName(); } 313 operator uint32() const { return intName(); } 314 315 bool operator <(const CssmDbAttributeInfo& other) const; 316 bool operator ==(const CssmDbAttributeInfo& other) const; 317 bool operator !=(const CssmDbAttributeInfo& other) const 318 { return !(*this == other); } 319}; 320 321// 322// CssmDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO 323// 324class CssmDbRecordAttributeInfo : public PodWrapper<CssmDbRecordAttributeInfo, CSSM_DB_RECORD_ATTRIBUTE_INFO> 325{ 326public: 327 CssmDbRecordAttributeInfo() 328 { DataRecordType = CSSM_DL_DB_RECORD_ANY; } 329 330 CssmDbRecordAttributeInfo(CSSM_DB_RECORDTYPE recordType, uint32 numberOfAttributes, 331 CSSM_DB_ATTRIBUTE_INFO_PTR attributeInfo) 332 { 333 DataRecordType = recordType; 334 NumberOfAttributes = numberOfAttributes; 335 AttributeInfo = attributeInfo; 336 } 337 338 CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; } 339 void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; } 340 341 uint32 size() const { return NumberOfAttributes; } 342 343 // attribute access 344 CssmDbAttributeInfo *&attributes() 345 { return CssmDbAttributeInfo::overlayVar(AttributeInfo); } 346 CssmDbAttributeInfo *attributes() const 347 { return CssmDbAttributeInfo::overlay(AttributeInfo); } 348 CssmDbAttributeInfo &at(uint32 ix) const 349 { assert(ix < size()); return attributes()[ix]; } 350 351 CssmDbAttributeInfo &operator [] (uint32 ix) const { return at(ix); } 352}; 353 354// 355// CssmAutoDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO 356// 357class CssmAutoDbRecordAttributeInfo: public CssmDbRecordAttributeInfo, public ArrayBuilder<CssmDbAttributeInfo> 358{ 359public: 360 CssmAutoDbRecordAttributeInfo(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) : 361 CssmDbRecordAttributeInfo(), 362 ArrayBuilder<CssmDbAttributeInfo>(CssmDbAttributeInfo::overlayVar(AttributeInfo), 363 NumberOfAttributes, capacity, allocator) {} 364}; 365 366 367// 368// CssmDbAttributeData pod wrapper for CSSM_DB_ATTRIBUTE_DATA 369// 370class CssmDbAttributeData : public PodWrapper<CssmDbAttributeData, CSSM_DB_ATTRIBUTE_DATA> 371{ 372public: 373 CssmDbAttributeData() { NumberOfValues = 0; Value = NULL; } 374 CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_DATA &attr) 375 { assignPod(attr); } 376 CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_INFO &info) 377 { Info = info; NumberOfValues = 0; Value = NULL; } 378 379 CssmDbAttributeInfo &info() { return CssmDbAttributeInfo::overlay(Info); } 380 const CssmDbAttributeInfo &info() const { return CssmDbAttributeInfo::overlay(Info); } 381 void info (const CSSM_DB_ATTRIBUTE_INFO &inInfo) { Info = inInfo; } 382 383 CSSM_DB_ATTRIBUTE_FORMAT format() const { return info().format(); } 384 void format(CSSM_DB_ATTRIBUTE_FORMAT f) { info().format(f); } 385 386 uint32 size() const { return NumberOfValues; } 387 CssmData *&values() { return CssmData::overlayVar(Value); } 388 CssmData *values() const { return CssmData::overlay(Value); } 389 390 CssmData &at(unsigned int ix) const 391 { 392 if (ix >= size()) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE); 393 return values()[ix]; 394 } 395 396 CssmData &operator [] (unsigned int ix) const { return at(ix); } 397 398 template <class T> 399 T at(unsigned int ix) const { return CssmDLPolyData(Value[ix], format()); } 400 401 // this is intentionally unspecified since it could lead to bugs; the 402 // data is not guaranteed to be NULL-terminated 403 // operator const char *() const; 404 405 operator string() const; 406 operator const Guid &() const; 407 operator bool() const; 408 operator uint32() const; 409 operator const uint32 *() const; 410 operator sint32() const; 411 operator double() const; 412 operator const CssmData &() const; 413 414 // set values without allocation (caller owns the data contents) 415 void set(CssmData &data) { set(1, &data); } 416 void set(uint32 count, CssmData *datas) { NumberOfValues = count; Value = datas; } 417 418 // Set the value of this Attr (assuming it was not set before). 419 void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue, 420 Allocator &inAllocator); 421 422 // copy (just) the return-value part from another AttributeData to this one 423 void copyValues(const CssmDbAttributeData &source, Allocator &alloc); 424 425 // Set the value of this Attr (which must be unset so far) 426 void set(const CSSM_DB_ATTRIBUTE_DATA &source, Allocator &alloc) 427 { 428 info(source.Info); 429 copyValues(source, alloc); 430 } 431 432 // Add a value to this attribute. 433 void add(const CssmPolyData &inValue, Allocator &inAllocator); 434 435 void add(const char *value, Allocator &alloc) 436 { format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); } 437 438 void add(const std::string &value, Allocator &alloc) 439 { format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); } 440 441 void add(uint32 value, Allocator &alloc) 442 { format(CSSM_DB_ATTRIBUTE_FORMAT_UINT32); add(CssmPolyData(value), alloc); } 443 444 void add(sint32 value, Allocator &alloc) 445 { format(CSSM_DB_ATTRIBUTE_FORMAT_SINT32); add(CssmPolyData(value), alloc); } 446 447 void add(const CssmData &value, Allocator &alloc) 448 { format(CSSM_DB_ATTRIBUTE_FORMAT_BLOB); add(CssmPolyData(value), alloc); } 449 450 void add(const CssmDbAttributeData &src, Allocator &inAllocator); 451 452 // delete specific values if they are present in this attribute data 453 bool deleteValue(const CssmData &src, Allocator &inAllocator); 454 void deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator); 455 456 void deleteValues(Allocator &inAllocator); 457 458 bool operator <(const CssmDbAttributeData& other) const; 459}; 460 461 462// 463// CssmDbRecordAttributeData pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_DATA 464// 465class CssmDbRecordAttributeData : public PodWrapper<CssmDbRecordAttributeData, CSSM_DB_RECORD_ATTRIBUTE_DATA> 466{ 467public: 468 CssmDbRecordAttributeData() 469 { clearPod(); DataRecordType = CSSM_DL_DB_RECORD_ANY; } 470 471 CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; } 472 void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; } 473 474 uint32 semanticInformation() const { return SemanticInformation; } 475 void semanticInformation(uint32 semanticInformation) { SemanticInformation = semanticInformation; } 476 477 uint32 size() const { return NumberOfAttributes; } 478 CssmDbAttributeData *&attributes() 479 { return CssmDbAttributeData::overlayVar(AttributeData); } 480 CssmDbAttributeData *attributes() const 481 { return CssmDbAttributeData::overlay(AttributeData); } 482 483 // Attributes by position 484 CssmDbAttributeData &at(unsigned int ix) const 485 { assert(ix < size()); return attributes()[ix]; } 486 487 CssmDbAttributeData &operator [] (unsigned int ix) const { return at(ix); } 488 489 void deleteValues(Allocator &allocator) 490 { for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); } 491 492 CssmDbAttributeData *find(const CSSM_DB_ATTRIBUTE_INFO &inInfo); 493 494 bool operator <(const CssmDbRecordAttributeData& other) const; 495}; 496 497 498// 499// CssmAutoDbRecordAttributeData 500// 501class CssmAutoDbRecordAttributeData : public CssmDbRecordAttributeData, public ArrayBuilder<CssmDbAttributeData> 502{ 503public: 504 CssmAutoDbRecordAttributeData(uint32 capacity = 0, 505 Allocator &valueAllocator = Allocator::standard(), 506 Allocator &dataAllocator = Allocator::standard()) : 507 CssmDbRecordAttributeData(), 508 ArrayBuilder<CssmDbAttributeData>(CssmDbAttributeData::overlayVar(AttributeData), 509 NumberOfAttributes, capacity, dataAllocator), 510 mValueAllocator(valueAllocator) {} 511 ~CssmAutoDbRecordAttributeData(); 512 513 void clear(); 514 void deleteValues() { CssmDbRecordAttributeData::deleteValues(mValueAllocator); } 515 void invalidate(); 516 517 CssmDbAttributeData &add() { return ArrayBuilder<CssmDbAttributeData>::add(); } // XXX using doesn't work here. 518 CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info); 519 CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value); 520 521 // So clients can pass this as the allocator argument to add() 522 operator Allocator &() const { return mValueAllocator; } 523private: 524 Allocator &mValueAllocator; 525 526 CssmDbAttributeData* findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info); 527 CssmDbAttributeData& getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info); 528}; 529 530 531// 532// CssmSelectionPredicate a PodWrapper for CSSM_SELECTION_PREDICATE 533// 534class CssmSelectionPredicate : public PodWrapper<CssmSelectionPredicate, CSSM_SELECTION_PREDICATE> { 535public: 536 CssmSelectionPredicate() { clearPod(); } 537 538 CSSM_DB_OPERATOR dbOperator() const { return DbOperator; } 539 void dbOperator(CSSM_DB_OPERATOR dbOperator) { DbOperator = dbOperator; } 540 541 CssmSelectionPredicate(CSSM_DB_OPERATOR inDbOperator) 542 { dbOperator(inDbOperator); Attribute.NumberOfValues = 0; Attribute.Value = NULL; } 543 544 CssmDbAttributeData &attribute() { return CssmDbAttributeData::overlay(Attribute); } 545 const CssmDbAttributeData &attribute() const { return CssmDbAttributeData::overlay(Attribute); } 546 547 // Set the value of this CssmSelectionPredicate (assuming it was not set before). 548 void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, 549 const CssmPolyData &inValue, Allocator &inAllocator) 550 { attribute().set(inInfo, inValue, inAllocator); } 551 552 // Set the value of this CssmSelectionPredicate using another CssmSelectionPredicate's value. 553 void set(const CSSM_SELECTION_PREDICATE &other, Allocator &inAllocator) 554 { DbOperator = other.DbOperator; attribute().set(other.Attribute, inAllocator); } 555 556 // Add a value to the list of values for this CssmSelectionPredicate. 557 void add(const CssmPolyData &inValue, Allocator &inAllocator) 558 { attribute().add(inValue, inAllocator); } 559 560 void deleteValues(Allocator &inAllocator) { attribute().deleteValues(inAllocator); } 561}; 562 563class CssmQuery : public PodWrapper<CssmQuery, CSSM_QUERY> { 564public: 565 CssmQuery(CSSM_DB_RECORDTYPE type = CSSM_DL_DB_RECORD_ANY) 566 { clearPod(); RecordType = type; } 567 568 // copy or assign flat from CSSM_QUERY 569 CssmQuery(const CSSM_QUERY &q) { assignPod(q); } 570 CssmQuery &operator = (const CSSM_QUERY &q) { assignPod(q); return *this; } 571 572 // flat copy and change record type 573 CssmQuery(const CssmQuery &q, CSSM_DB_RECORDTYPE type) 574 { *this = q; RecordType = type; } 575 576 CSSM_DB_RECORDTYPE recordType() const { return RecordType; } 577 void recordType(CSSM_DB_RECORDTYPE recordType) { RecordType = recordType; } 578 579 CSSM_DB_CONJUNCTIVE conjunctive() const { return Conjunctive; } 580 void conjunctive(CSSM_DB_CONJUNCTIVE conjunctive) { Conjunctive = conjunctive; } 581 582 CSSM_QUERY_LIMITS queryLimits() const { return QueryLimits; } 583 void queryLimits(CSSM_QUERY_LIMITS queryLimits) { QueryLimits = queryLimits; } 584 585 CSSM_QUERY_FLAGS queryFlags() const { return QueryFlags; } 586 void queryFlags(CSSM_QUERY_FLAGS queryFlags) { QueryFlags = queryFlags; } 587 588 uint32 size() const { return NumSelectionPredicates; } 589 590 CssmSelectionPredicate *&predicates() 591 { return CssmSelectionPredicate::overlayVar(SelectionPredicate); } 592 CssmSelectionPredicate *predicates() const 593 { return CssmSelectionPredicate::overlay(SelectionPredicate); } 594 595 CssmSelectionPredicate &at(uint32 ix) const 596 { assert(ix < size()); return predicates()[ix]; } 597 598 CssmSelectionPredicate &operator[] (uint32 ix) const { return at(ix); } 599 600 void set(uint32 count, CSSM_SELECTION_PREDICATE *preds) 601 { NumSelectionPredicates = count; SelectionPredicate = preds; } 602 603 void deleteValues(Allocator &allocator) 604 { for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); } 605}; 606 607 608class CssmAutoQuery : public CssmQuery, public ArrayBuilder<CssmSelectionPredicate> { 609public: 610 CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator = Allocator::standard()); 611 CssmAutoQuery(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) : 612 ArrayBuilder<CssmSelectionPredicate>(CssmSelectionPredicate::overlayVar(SelectionPredicate), 613 NumSelectionPredicates, 614 capacity, allocator) {} 615 ~CssmAutoQuery(); 616 void clear(); 617 void deleteValues() { CssmQuery::deleteValues(allocator()); } 618 619 CssmSelectionPredicate &add() { return ArrayBuilder<CssmSelectionPredicate>::add(); } 620 CssmSelectionPredicate &add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value); 621 622 // So clients can pass this as the allocator argument to add() 623 operator Allocator &() const { return allocator(); } 624}; 625 626 627// 628// DLDbIdentifier 629// 630class DLDbIdentifier 631{ 632protected: 633 class Impl : public RefCount 634 { 635 NOCOPY(Impl) 636 public: 637 Impl(const CSSM_SUBSERVICE_UID &ssuid,const char *DbName,const CSSM_NET_ADDRESS *DbLocation) : 638 mCssmSubserviceUid(ssuid),mDbName(DbName,DbLocation) {} 639 640 ~Impl() {} // Must be public since RefPointer uses it. 641 642 // Accessors 643 const CssmSubserviceUid &ssuid() const { return mCssmSubserviceUid; } 644 const char *dbName() const { return mDbName.dbName(); } 645 const CssmNetAddress *dbLocation() const { return mDbName.dbLocation(); } 646 647 // comparison (simple lexicographic) 648 bool operator < (const Impl &other) const; 649 bool operator == (const Impl &other) const; 650 private: 651 // Private member variables 652 CssmSubserviceUid mCssmSubserviceUid; 653 DbName mDbName; 654 }; 655 656public: 657 // Constructors 658 DLDbIdentifier() {} 659 DLDbIdentifier(const CSSM_SUBSERVICE_UID &ssuid, const char *DbName, const CSSM_NET_ADDRESS *DbLocation) 660 : mImpl(new Impl(ssuid, DbName, DbLocation)) {} 661 DLDbIdentifier(const char *name, const Guid &guid, uint32 ssid, uint32 sstype, 662 const CSSM_NET_ADDRESS *location = NULL) 663 : mImpl(new Impl(CssmSubserviceUid(guid, NULL, ssid, sstype), name, location)) { } 664 665 // Conversion Operators 666 bool operator !() const { return !mImpl; } 667 operator bool() const { return mImpl; } 668 669 // Operators 670 bool operator <(const DLDbIdentifier &other) const 671 { return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl.get() < other.mImpl.get(); } 672 bool operator ==(const DLDbIdentifier &other) const 673 { return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl.get() == other.mImpl.get(); } 674 DLDbIdentifier &operator =(const DLDbIdentifier &other) 675 { mImpl = other.mImpl; return *this; } 676 677 // Accessors 678 const CssmSubserviceUid &ssuid() const { return mImpl->ssuid(); } 679 const char *dbName() const { return mImpl->dbName(); } 680 const CssmNetAddress *dbLocation() const { return mImpl->dbLocation(); } 681 bool IsImplEmpty() const {return mImpl == NULL;} 682 683 RefPointer<Impl> mImpl; 684}; 685 686// Wrappers for index-related CSSM objects. 687 688class CssmDbIndexInfo : public PodWrapper<CssmDbIndexInfo, CSSM_DB_INDEX_INFO> 689{ 690public: 691 CssmDbIndexInfo(const CSSM_DB_INDEX_INFO &attr) 692 { (CSSM_DB_INDEX_INFO &)*this = attr; } 693 694 CSSM_DB_INDEX_TYPE indexType() const { return IndexType; } 695 void indexType(CSSM_DB_INDEX_TYPE indexType) { IndexType = indexType; } 696 697 CSSM_DB_INDEXED_DATA_LOCATION dataLocation() const { return IndexedDataLocation; } 698 void dataLocation(CSSM_DB_INDEXED_DATA_LOCATION dataLocation) 699 { 700 IndexedDataLocation = dataLocation; 701 } 702 703 const CssmDbAttributeInfo &attributeInfo() const 704 { 705 return CssmDbAttributeInfo::overlay(Info); 706 } 707}; 708 709 710namespace DataWalkers { 711 712 713// 714// DLDbIdentifiers don't walk directly because they have Impl structure and use strings. 715// Happily, they are easily transcribed into a walkable form. 716// 717struct DLDbFlatIdentifier { 718 CssmSubserviceUid *uid; // module reference 719 char *name; // string name 720 CssmNetAddress *address; // optional network address 721 722 DLDbFlatIdentifier(const DLDbIdentifier &ident) : 723 uid(const_cast<CssmSubserviceUid *>(&ident.ssuid())), 724 name(const_cast<char *>(ident.dbName())), 725 address(const_cast<CssmNetAddress *>(ident.dbLocation())) 726 { } 727 728 operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); } 729}; 730 731template<class Action> 732DLDbFlatIdentifier *walk(Action &operate, DLDbFlatIdentifier * &ident) 733{ 734 operate(ident); 735 if (ident->uid) 736 walk(operate, ident->uid); 737 walk(operate, ident->name); 738 if (ident->address) 739 walk(operate, ident->address); 740 return ident; 741} 742 743 744// 745// Walkers for the byzantine data structures of the DL universe. 746// Geez, what WERE they smoking when they invented this? 747// 748 749// DbAttributeInfos 750template<class Action> 751void enumerate(Action &operate, CssmDbAttributeInfo &info) 752{ 753 switch (info.nameFormat()) { 754 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: 755 walk(operate, info.Label.AttributeName); 756 break; 757 case CSSM_DB_ATTRIBUTE_NAME_AS_OID: 758 walk(operate, info.Label.AttributeOID); 759 break; 760 default: 761 break; 762 } 763} 764 765template <class Action> 766void walk(Action &operate, CssmDbAttributeInfo &info) 767{ 768 operate(info); 769 enumerate(operate, info); 770} 771 772template <class Action> 773CssmDbAttributeInfo *walk(Action &operate, CssmDbAttributeInfo * &info) 774{ 775 operate(info); 776 enumerate(operate, *info); 777 return info; 778} 779 780// DbRecordAttributeInfo 781template <class Action> 782void walk(Action &operate, CssmDbRecordAttributeInfo &info) 783{ 784 operate(info); 785 enumerateArray(operate, info, &CssmDbRecordAttributeInfo::attributes); 786} 787 788template <class Action> 789CssmDbRecordAttributeInfo *walk(Action &operate, CssmDbRecordAttributeInfo * &info) 790{ 791 operate(info); 792 enumerateArray(operate, *info, &CssmDbRecordAttributeInfo::attributes); 793 return info; 794} 795 796// DbAttributeData (Info + value vector) 797template <class Action> 798void walk(Action &operate, CssmDbAttributeData &data) 799{ 800 operate(data); 801 walk(operate, data.info()); 802 enumerateArray(operate, data, &CssmDbAttributeData::values); 803} 804 805template <class Action> 806CssmDbAttributeData *walk(Action &operate, CssmDbAttributeData * &data) 807{ 808 operate(data); 809 walk(operate, data->info()); 810 enumerateArray(operate, *data, &CssmDbAttributeData::values); 811 return data; 812} 813 814// DbRecordAttributeData (array of ...datas) 815template <class Action> 816void walk(Action &operate, CssmDbRecordAttributeData &data) 817{ 818 operate(data); 819 enumerateArray(operate, data, &CssmDbRecordAttributeData::attributes); 820} 821 822template <class Action> 823CssmDbRecordAttributeData *walk(Action &operate, CssmDbRecordAttributeData * &data) 824{ 825 operate(data); 826 enumerateArray(operate, *data, &CssmDbRecordAttributeData::attributes); 827 return data; 828} 829 830// SelectionPredicates 831template <class Action> 832CssmSelectionPredicate *walk(Action &operate, CssmSelectionPredicate * &predicate) 833{ 834 operate(predicate); 835 walk(operate, predicate->attribute()); 836 return predicate; 837} 838 839template<class Action> 840void walk(Action &operate, CssmSelectionPredicate &predicate) 841{ 842 operate(predicate); 843 walk(operate, predicate.attribute()); 844} 845 846// Queries 847template <class Action> 848void walk(Action &operate, CssmQuery &query) 849{ 850 operate(query); 851 enumerateArray(operate, query, &CssmQuery::predicates); 852} 853 854template <class Action> 855CssmQuery *walk(Action &operate, CssmQuery * &query) 856{ 857 operate(query); 858 enumerateArray(operate, *query, &CssmQuery::predicates); 859 return query; 860} 861 862template <class Action> 863CSSM_QUERY *walk(Action &operate, CSSM_QUERY * &query) 864{ 865 return walk(operate, CssmQuery::overlayVar(query)); 866} 867 868 869} // end namespace DataWalkers 870} // end namespace Security 871 872 873#endif // _H_CDSA_UTILITIES_CSSMDB 874