2 * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
28 #include <security_cdsa_utilities/cssmdb.h>
30 bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl
&other
) const
32 if (mCssmSubserviceUid
< other
.mCssmSubserviceUid
)
34 if (mCssmSubserviceUid
!= other
.mCssmSubserviceUid
) // i.e. greater than
37 // This test will produce unreproducible results,
38 // depending on what items are being compared. To do this properly, we need to
39 // assign a lexical value to NULL.
41 // if (mDbName.canonicalName() == NULL || other.mDbName.canonicalName() == NULL)
46 // this is the correct way
47 const char* a
= mDbName
.canonicalName();
48 const char* b
= other
.mDbName
.canonicalName();
50 if (a
== NULL
&& b
!= NULL
)
52 return true; // NULL is always < something
55 if (a
!= NULL
&& b
== NULL
)
57 return false; // something is always >= NULL
60 if (a
== NULL
&& b
== NULL
)
62 return false; // since == is not <
65 // if we get to this point, both are not null. No crash and the lexical value is correct.
66 return strcmp(a
, b
) < 0;
69 bool DLDbIdentifier::Impl::operator == (const Impl
&other
) const
71 bool subserviceIdEqual
= mCssmSubserviceUid
== other
.mCssmSubserviceUid
;
72 if (!subserviceIdEqual
)
77 const char* a
= mDbName
.canonicalName();
78 const char* b
= other
.mDbName
.canonicalName();
80 if (a
== NULL
&& b
!= NULL
)
85 if (a
!= NULL
&& b
== NULL
)
90 if (a
== NULL
&& b
== NULL
)
95 bool namesEqual
= strcmp(a
, b
) == 0;
102 CssmDLPolyData::operator CSSM_DATE () const
104 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_BLOB
);
105 if (mData
.Length
!= 8)
106 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
109 memcpy(date
.Year
, mData
.Data
, 4);
110 memcpy(date
.Month
, mData
.Data
+ 4, 2);
111 memcpy(date
.Day
, mData
.Data
+ 6, 2);
115 CssmDLPolyData::operator Guid () const
117 assert(mFormat
== CSSM_DB_ATTRIBUTE_FORMAT_BLOB
);
118 if (mData
.Length
!= Guid::stringRepLength
+ 1)
119 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
121 return Guid(reinterpret_cast<const char *>(mData
.Data
));
126 // CssmDbAttributeInfo
128 CssmDbAttributeInfo::CssmDbAttributeInfo(const char *name
, CSSM_DB_ATTRIBUTE_FORMAT vFormat
)
131 AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
132 Label
.AttributeName
= const_cast<char *>(name
); // silly CDSA
133 AttributeFormat
= vFormat
;
136 CssmDbAttributeInfo::CssmDbAttributeInfo(const CSSM_OID
&oid
, CSSM_DB_ATTRIBUTE_FORMAT vFormat
)
139 AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_OID
;
140 Label
.AttributeOID
= oid
;
141 AttributeFormat
= vFormat
;
144 CssmDbAttributeInfo::CssmDbAttributeInfo(uint32 id
, CSSM_DB_ATTRIBUTE_FORMAT vFormat
)
147 AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
;
148 Label
.AttributeID
= id
;
149 AttributeFormat
= vFormat
;
154 CssmDbAttributeInfo::operator <(const CssmDbAttributeInfo
& other
) const
156 if (nameFormat() < other
.nameFormat()) return true;
157 if (other
.nameFormat() < nameFormat()) return false;
158 // nameFormat's are equal.
159 switch (nameFormat())
161 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING
:
163 int res
= strcmp(static_cast<const char *>(*this), static_cast<const char *>(other
));
164 if (res
< 0) return true;
165 if (res
> 0) return false;
168 case CSSM_DB_ATTRIBUTE_NAME_AS_OID
:
169 if (static_cast<const CssmOid
&>(*this) < static_cast<const CssmOid
&>(other
)) return true;
170 if (static_cast<const CssmOid
&>(other
) < static_cast<const CssmOid
&>(*this)) return false;
172 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
:
173 if (static_cast<uint32
>(*this) < static_cast<uint32
>(other
)) return true;
174 if (static_cast<uint32
>(other
) < static_cast<uint32
>(*this)) return false;
177 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME
);
180 return format() < other
.format();
184 CssmDbAttributeInfo::operator ==(const CssmDbAttributeInfo
& other
) const
186 if (nameFormat() != other
.nameFormat()) return false;
187 if (format() != other
.format()) return false;
188 switch (nameFormat())
190 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING
:
191 return !strcmp(static_cast<const char *>(*this), static_cast<const char *>(other
));
192 case CSSM_DB_ATTRIBUTE_NAME_AS_OID
:
193 return static_cast<const CssmOid
&>(*this) == static_cast<const CssmOid
&>(other
);
194 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
:
195 return static_cast<uint32
>(*this) == static_cast<uint32
>(other
);
197 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME
);
202 // CssmDbAttributeData
204 CssmDbAttributeData::operator string() const
207 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
:
208 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
:
209 return at(0).toString();
211 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
214 CssmDbAttributeData::operator const Guid
&() const
216 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_BLOB
)
217 return *at(0).interpretedAs
<Guid
>();
219 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
222 CssmDbAttributeData::operator bool() const
225 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32
:
226 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32
:
227 return *at(0).interpretedAs
<uint32
>();
229 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
233 CssmDbAttributeData::operator uint32() const
235 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32
)
236 return *at(0).interpretedAs
<uint32
>();
238 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
241 CssmDbAttributeData::operator const uint32
*() const
243 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
)
244 return reinterpret_cast<const uint32
*>(Value
[0].Data
);
246 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
249 CssmDbAttributeData::operator sint32() const
251 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32
)
252 return *at(0).interpretedAs
<sint32
>();
254 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
257 CssmDbAttributeData::operator double() const
259 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_REAL
)
260 return *at(0).interpretedAs
<double>();
262 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
265 CssmDbAttributeData::operator const CssmData
&() const
268 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
:
269 case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM
:
270 case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
:
271 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
:
272 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
:
275 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT
);
279 void CssmDbAttributeData::set(const CSSM_DB_ATTRIBUTE_INFO
&inInfo
, const CssmPolyData
&inValue
,
280 Allocator
&inAllocator
)
284 Value
= inAllocator
.alloc
<CSSM_DATA
>();
286 Value
[0].Data
= inAllocator
.alloc
<uint8
>((UInt32
)inValue
.Length
);
287 Value
[0].Length
= inValue
.Length
;
288 memcpy(Value
[0].Data
, inValue
.Data
, inValue
.Length
);
292 void CssmDbAttributeData::add(const CssmPolyData
&inValue
, Allocator
&inAllocator
)
294 Value
= reinterpret_cast<CSSM_DATA
*>(inAllocator
.realloc(Value
, sizeof(*Value
) * (NumberOfValues
+ 1)));
295 CssmAutoData
valueCopy(inAllocator
, inValue
);
296 Value
[NumberOfValues
++] = valueCopy
.release();
300 void CssmDbAttributeData::copyValues(const CssmDbAttributeData
&source
, Allocator
&alloc
)
302 assert(size() == 0); // must start out empty
304 // we're too lazy to arrange for exception safety here
305 CssmData
*vector
= alloc
.alloc
<CssmData
>(source
.size());
306 for (uint32 n
= 0; n
< source
.size(); n
++)
307 vector
[n
] = CssmAutoData(alloc
, source
[n
]).release();
309 // atomic set results
310 info().format(source
.info().format());
311 NumberOfValues
= source
.size();
315 void CssmDbAttributeData::deleteValues(Allocator
&alloc
)
317 // Loop over all values and delete each one.
320 for (uint32 n
= 0; n
< size(); n
++)
322 alloc
.free(at(n
).data());
324 alloc
.free(values());
330 bool CssmDbAttributeData::operator <(const CssmDbAttributeData
&other
) const
332 if (info() < other
.info()) return true;
333 if (other
.info() < info()) return false;
335 uint32 minSize
= min(size(), other
.size());
336 for (uint32 ix
= 0; ix
< minSize
; ++ix
)
338 if (at
<const CssmData
&>(ix
) < other
.at
<const CssmData
&>(ix
))
340 if (other
.at
<const CssmData
&>(ix
) < at
<const CssmData
&>(ix
))
344 return size() < other
.size();
348 CssmDbAttributeData::add(const CssmDbAttributeData
&src
, Allocator
&inAllocator
)
350 // Add all the values from another attribute into this attribute.
352 Value
= reinterpret_cast<CSSM_DATA
*>(inAllocator
.realloc(Value
,
353 sizeof(*Value
) * (NumberOfValues
+ src
.NumberOfValues
)));
355 for (uint32 srcIndex
= 0; srcIndex
< src
.NumberOfValues
; srcIndex
++) {
356 uint32 destIndex
= NumberOfValues
+ srcIndex
;
358 Value
[destIndex
].Length
= 0;
359 Value
[destIndex
].Data
= inAllocator
.alloc
<uint8
>((UInt32
)src
.Value
[srcIndex
].Length
);
360 Value
[destIndex
].Length
= src
.Value
[srcIndex
].Length
;
361 memcpy(Value
[destIndex
].Data
, src
.Value
[srcIndex
].Data
, src
.Value
[srcIndex
].Length
);
364 NumberOfValues
+= src
.NumberOfValues
;
368 CssmDbAttributeData::deleteValue(const CssmData
&src
, Allocator
&inAllocator
)
370 // Delete a single value from this attribute, if it is present.
372 for (uint32 i
= 0; i
< NumberOfValues
; i
++)
373 if (CssmData::overlay(Value
[i
]) == src
)
375 inAllocator
.free(Value
[i
].Data
);
379 Value
[i
].Data
= Value
[NumberOfValues
].Data
;
380 Value
[i
].Length
= Value
[NumberOfValues
].Length
;
388 // Delete those values found in src from this object, if they are present.
389 // Warning: This is O(N^2) worst case; if this becomes a performance bottleneck
390 // then it will need to be changed.
393 CssmDbAttributeData::deleteValues(const CssmDbAttributeData
&src
, Allocator
&inAllocator
)
395 for (uint32 i
= 0; i
< src
.NumberOfValues
; i
++)
396 deleteValue(CssmData::overlay(src
.Value
[i
]), inAllocator
);
400 // CssmDbRecordAttributeData
402 CssmDbAttributeData
*
403 CssmDbRecordAttributeData::find(const CSSM_DB_ATTRIBUTE_INFO
&inInfo
)
405 const CssmDbAttributeInfo
&anInfo
= CssmDbAttributeInfo::overlay(inInfo
);
406 for (uint32 ix
= 0; ix
< size(); ++ix
)
408 if (at(ix
).info() == anInfo
)
416 CssmDbRecordAttributeData::operator <(const CssmDbRecordAttributeData
&other
) const
418 if (recordType() < other
.recordType()) return true;
419 if (other
.recordType() < recordType()) return false;
420 if (semanticInformation() < other
.semanticInformation()) return true;
421 if (other
.semanticInformation() < semanticInformation()) return false;
423 uint32 minSize
= min(size(), other
.size());
424 for (uint32 ix
= 0; ix
< minSize
; ++ix
)
426 if (at(ix
) < other
.at(ix
))
428 if (other
.at(ix
) < at(ix
))
432 return size() < other
.size();
437 // CssmAutoDbRecordAttributeData
439 CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData()
445 CssmAutoDbRecordAttributeData::invalidate()
447 NumberOfAttributes
= 0;
453 CssmAutoDbRecordAttributeData::clear()
456 ArrayBuilder
<CssmDbAttributeData
>::clear();
461 static bool CompareAttributeInfos (const CSSM_DB_ATTRIBUTE_INFO
&a
, const CSSM_DB_ATTRIBUTE_INFO
&b
)
463 // check the format of the names
464 if (a
.AttributeNameFormat
!= b
.AttributeNameFormat
)
469 switch (a
.AttributeNameFormat
)
471 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING
:
473 return strcmp (a
.Label
.AttributeName
, b
.Label
.AttributeName
) == 0;
476 case CSSM_DB_ATTRIBUTE_NAME_AS_OID
:
478 if (a
.Label
.AttributeOID
.Length
!= b
.Label
.AttributeOID
.Length
)
483 return memcmp (a
.Label
.AttributeOID
.Data
, b
.Label
.AttributeOID
.Data
, a
.Label
.AttributeOID
.Length
) == 0;
487 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
:
489 return a
.Label
.AttributeID
== b
.Label
.AttributeID
;
493 return true; // just to keep the compiler from complaining
498 CssmDbAttributeData
* CssmAutoDbRecordAttributeData::findAttribute (const CSSM_DB_ATTRIBUTE_INFO
&info
)
500 // walk through the data, looking for an attribute of the same type
502 for (i
= 0; i
< size (); ++i
)
504 CssmDbAttributeData
& d
= at (i
);
505 CSSM_DB_ATTRIBUTE_INFO
&inInfo
= d
.info ();
507 if (CompareAttributeInfos (info
, inInfo
))
519 CssmDbAttributeData
& CssmAutoDbRecordAttributeData::getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO
&info
)
521 // Either find an existing reference to an attribute in the list, or make a new one.
522 CssmDbAttributeData
*anAttr
= findAttribute (info
);
523 if (anAttr
) // was this already in the list?
526 anAttr
->deleteValues (mValueAllocator
);
539 CssmDbAttributeData
&
540 CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO
&info
)
542 CssmDbAttributeData
& anAttr
= getAttributeReference (info
);
547 CssmDbAttributeData
&
548 CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO
&info
, const CssmPolyData
&value
)
550 CssmDbAttributeData
&anAttr
= getAttributeReference (info
);
551 anAttr
.set(info
, value
, mValueAllocator
);
558 CssmAutoQuery::CssmAutoQuery(const CSSM_QUERY
&query
, Allocator
&allocator
)
559 : ArrayBuilder
<CssmSelectionPredicate
>(CssmSelectionPredicate::overlayVar(SelectionPredicate
),
560 NumSelectionPredicates
,
561 query
.NumSelectionPredicates
, allocator
)
563 RecordType
= query
.RecordType
;
564 Conjunctive
= query
.Conjunctive
;
565 QueryLimits
= query
.QueryLimits
;
566 QueryFlags
= query
.QueryFlags
;
567 for (uint32 ix
= 0; ix
< query
.NumSelectionPredicates
; ++ix
)
568 add().set(query
.SelectionPredicate
[ix
], allocator
);
571 CssmAutoQuery::~CssmAutoQuery()
577 CssmAutoQuery::clear()
580 ArrayBuilder
<CssmSelectionPredicate
>::clear();
583 CssmSelectionPredicate
&
584 CssmAutoQuery::add(CSSM_DB_OPERATOR dbOperator
, const CSSM_DB_ATTRIBUTE_INFO
&info
, const CssmPolyData
&value
)
586 CssmSelectionPredicate
&predicate
= add();
587 predicate
.dbOperator(dbOperator
);
588 predicate
.set(info
, value
, allocator());