]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utilities / lib / cssmdb.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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.cpp
26//
27//
28#include <security_cdsa_utilities/cssmdb.h>
e3d460c9
A
29#include <CommonCrypto/CommonDigest.h>
30
31using namespace DataWalkers;
b1ab9ed8
A
32
33bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl &other) const
34{
35 if (mCssmSubserviceUid < other.mCssmSubserviceUid)
36 return true;
37 if (mCssmSubserviceUid != other.mCssmSubserviceUid) // i.e. greater than
38 return false;
d8f41ccd
A
39
40 // This test will produce unreproducible results,
b1ab9ed8
A
41 // depending on what items are being compared. To do this properly, we need to
42 // assign a lexical value to NULL.
43 //
44 // if (mDbName.canonicalName() == NULL || other.mDbName.canonicalName() == NULL)
45 // {
46 // return false;
47 // }
48
49 // this is the correct way
50 const char* a = mDbName.canonicalName();
51 const char* b = other.mDbName.canonicalName();
52
53 if (a == NULL && b != NULL)
54 {
55 return true; // NULL is always < something
56 }
57
58 if (a != NULL && b == NULL)
59 {
60 return false; // something is always >= NULL
61 }
62
63 if (a == NULL && b == NULL)
64 {
65 return false; // since == is not <
66 }
67
68 // if we get to this point, both are not null. No crash and the lexical value is correct.
69 return strcmp(a, b) < 0;
70}
71
72bool DLDbIdentifier::Impl::operator == (const Impl &other) const
73{
74 bool subserviceIdEqual = mCssmSubserviceUid == other.mCssmSubserviceUid;
75 if (!subserviceIdEqual)
76 {
77 return false;
78 }
79
80 const char* a = mDbName.canonicalName();
81 const char* b = other.mDbName.canonicalName();
82
83 if (a == NULL && b != NULL)
84 {
85 return false;
86 }
87
88 if (a != NULL && b == NULL)
89 {
90 return false;
91 }
92
93 if (a == NULL && b == NULL)
94 {
95 return true;
96 }
97
98 bool namesEqual = strcmp(a, b) == 0;
99 return namesEqual;
100}
101
102//
103// CssmDLPolyData
104//
105CssmDLPolyData::operator CSSM_DATE () const
106{
107 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB);
108 if (mData.Length != 8)
109 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
110
111 CSSM_DATE date;
112 memcpy(date.Year, mData.Data, 4);
113 memcpy(date.Month, mData.Data + 4, 2);
114 memcpy(date.Day, mData.Data + 6, 2);
115 return date;
116}
117
118CssmDLPolyData::operator Guid () const
119{
120 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB);
121 if (mData.Length != Guid::stringRepLength + 1)
122 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
123
124 return Guid(reinterpret_cast<const char *>(mData.Data));
125}
126
127
128//
129// CssmDbAttributeInfo
130//
131CssmDbAttributeInfo::CssmDbAttributeInfo(const char *name, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
132{
133 clearPod();
134 AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
135 Label.AttributeName = const_cast<char *>(name); // silly CDSA
136 AttributeFormat = vFormat;
137}
138
139CssmDbAttributeInfo::CssmDbAttributeInfo(const CSSM_OID &oid, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
140{
141 clearPod();
142 AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_OID;
143 Label.AttributeOID = oid;
144 AttributeFormat = vFormat;
145}
146
147CssmDbAttributeInfo::CssmDbAttributeInfo(uint32 id, CSSM_DB_ATTRIBUTE_FORMAT vFormat)
148{
149 clearPod();
150 AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER;
151 Label.AttributeID = id;
152 AttributeFormat = vFormat;
153}
154
155
156bool
157CssmDbAttributeInfo::operator <(const CssmDbAttributeInfo& other) const
158{
159 if (nameFormat() < other.nameFormat()) return true;
160 if (other.nameFormat() < nameFormat()) return false;
161 // nameFormat's are equal.
162 switch (nameFormat())
163 {
164 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
165 {
166 int res = strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
167 if (res < 0) return true;
168 if (res > 0) return false;
169 break;
170 }
171 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
172 if (static_cast<const CssmOid &>(*this) < static_cast<const CssmOid &>(other)) return true;
173 if (static_cast<const CssmOid &>(other) < static_cast<const CssmOid &>(*this)) return false;
174 break;
175 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
176 if (static_cast<uint32>(*this) < static_cast<uint32>(other)) return true;
177 if (static_cast<uint32>(other) < static_cast<uint32>(*this)) return false;
178 break;
179 default:
180 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
181 }
182
183 return format() < other.format();
184}
185
186bool
187CssmDbAttributeInfo::operator ==(const CssmDbAttributeInfo& other) const
188{
189 if (nameFormat() != other.nameFormat()) return false;
190 if (format() != other.format()) return false;
191 switch (nameFormat())
192 {
193 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
194 return !strcmp(static_cast<const char *>(*this), static_cast<const char *>(other));
195 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
196 return static_cast<const CssmOid &>(*this) == static_cast<const CssmOid &>(other);
197 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
198 return static_cast<uint32>(*this) == static_cast<uint32>(other);
199 default:
200 CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME);
201 }
202}
203
204//
205// CssmDbAttributeData
206//
207CssmDbAttributeData::operator string() const
208{
209 switch (format()) {
210 case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
211 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
212 return at(0).toString();
213 default:
214 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
215 }
216}
217CssmDbAttributeData::operator const Guid &() const
218{
219 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_BLOB)
220 return *at(0).interpretedAs<Guid>();
221 else
222 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
223}
224
225CssmDbAttributeData::operator bool() const
226{
227 switch (format()) {
228 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
229 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
230 return *at(0).interpretedAs<uint32>();
231 default:
232 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
233 }
234}
235
236CssmDbAttributeData::operator uint32() const
237{
238 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32)
239 return *at(0).interpretedAs<uint32>();
240 else
241 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
242}
243
244CssmDbAttributeData::operator const uint32 *() const
245{
246 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32)
247 return reinterpret_cast<const uint32 *>(Value[0].Data);
248 else
249 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
250}
251
252CssmDbAttributeData::operator sint32() const
253{
254 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32)
255 return *at(0).interpretedAs<sint32>();
256 else
257 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
258}
259
260CssmDbAttributeData::operator double() const
261{
262 if (format() == CSSM_DB_ATTRIBUTE_FORMAT_REAL)
263 return *at(0).interpretedAs<double>();
264 else
265 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
266}
267
268CssmDbAttributeData::operator const CssmData &() const
269{
270 switch (format()) {
271 case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
272 case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
273 case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
274 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
275 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
276 return at(0);
277 default:
278 CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT);
279 }
280}
281
282void CssmDbAttributeData::set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue,
283 Allocator &inAllocator)
284{
285 info(inInfo);
286 NumberOfValues = 0;
287 Value = inAllocator.alloc<CSSM_DATA>();
288 Value[0].Length = 0;
427c49bc 289 Value[0].Data = inAllocator.alloc<uint8>((UInt32)inValue.Length);
b1ab9ed8
A
290 Value[0].Length = inValue.Length;
291 memcpy(Value[0].Data, inValue.Data, inValue.Length);
292 NumberOfValues = 1;
293}
294
295void CssmDbAttributeData::add(const CssmPolyData &inValue, Allocator &inAllocator)
296{
297 Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value, sizeof(*Value) * (NumberOfValues + 1)));
298 CssmAutoData valueCopy(inAllocator, inValue);
299 Value[NumberOfValues++] = valueCopy.release();
300}
301
302
303void CssmDbAttributeData::copyValues(const CssmDbAttributeData &source, Allocator &alloc)
304{
305 assert(size() == 0); // must start out empty
306
307 // we're too lazy to arrange for exception safety here
308 CssmData *vector = alloc.alloc<CssmData>(source.size());
309 for (uint32 n = 0; n < source.size(); n++)
310 vector[n] = CssmAutoData(alloc, source[n]).release();
311
312 // atomic set results
313 info().format(source.info().format());
314 NumberOfValues = source.size();
315 values() = vector;
316}
317
318void CssmDbAttributeData::deleteValues(Allocator &alloc)
319{
320 // Loop over all values and delete each one.
321 if (values())
322 {
323 for (uint32 n = 0; n < size(); n++)
324 {
325 alloc.free(at(n).data());
326 }
327 alloc.free(values());
328 }
329 NumberOfValues = 0;
330 values() = NULL;
331}
332
333bool CssmDbAttributeData::operator <(const CssmDbAttributeData &other) const
334{
335 if (info() < other.info()) return true;
336 if (other.info() < info()) return false;
337
338 uint32 minSize = min(size(), other.size());
339 for (uint32 ix = 0; ix < minSize; ++ix)
340 {
341 if (at<const CssmData &>(ix) < other.at<const CssmData &>(ix))
342 return true;
343 if (other.at<const CssmData &>(ix) < at<const CssmData &>(ix))
344 return false;
345 }
346
347 return size() < other.size();
348}
349
350void
351CssmDbAttributeData::add(const CssmDbAttributeData &src, Allocator &inAllocator)
352{
353 // Add all the values from another attribute into this attribute.
354
355 Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value,
356 sizeof(*Value) * (NumberOfValues + src.NumberOfValues)));
357
358 for (uint32 srcIndex = 0; srcIndex < src.NumberOfValues; srcIndex++) {
359 uint32 destIndex = NumberOfValues + srcIndex;
360
361 Value[destIndex].Length = 0;
427c49bc 362 Value[destIndex].Data = inAllocator.alloc<uint8>((UInt32)src.Value[srcIndex].Length);
b1ab9ed8
A
363 Value[destIndex].Length = src.Value[srcIndex].Length;
364 memcpy(Value[destIndex].Data, src.Value[srcIndex].Data, src.Value[srcIndex].Length);
365 }
366
367 NumberOfValues += src.NumberOfValues;
368}
369
370bool
371CssmDbAttributeData::deleteValue(const CssmData &src, Allocator &inAllocator)
372{
373 // Delete a single value from this attribute, if it is present.
374
375 for (uint32 i = 0; i < NumberOfValues; i++)
376 if (CssmData::overlay(Value[i]) == src)
377 {
378 inAllocator.free(Value[i].Data);
379 Value[i].Length = 0;
380
381 NumberOfValues--;
382 Value[i].Data = Value[NumberOfValues].Data;
383 Value[i].Length = Value[NumberOfValues].Length;
384
385 return true;
386 }
387
388 return false;
389}
390
391// Delete those values found in src from this object, if they are present.
392// Warning: This is O(N^2) worst case; if this becomes a performance bottleneck
393// then it will need to be changed.
394
395void
396CssmDbAttributeData::deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator)
397{
398 for (uint32 i = 0; i < src.NumberOfValues; i++)
399 deleteValue(CssmData::overlay(src.Value[i]), inAllocator);
400}
401
402//
403// CssmDbRecordAttributeData
404//
405CssmDbAttributeData *
406CssmDbRecordAttributeData::find(const CSSM_DB_ATTRIBUTE_INFO &inInfo)
407{
408 const CssmDbAttributeInfo &anInfo = CssmDbAttributeInfo::overlay(inInfo);
409 for (uint32 ix = 0; ix < size(); ++ix)
410 {
411 if (at(ix).info() == anInfo)
412 return &at(ix);
413 }
414
415 return NULL;
416}
417
418bool
419CssmDbRecordAttributeData::operator <(const CssmDbRecordAttributeData &other) const
420{
421 if (recordType() < other.recordType()) return true;
422 if (other.recordType() < recordType()) return false;
423 if (semanticInformation() < other.semanticInformation()) return true;
424 if (other.semanticInformation() < semanticInformation()) return false;
425
426 uint32 minSize = min(size(), other.size());
427 for (uint32 ix = 0; ix < minSize; ++ix)
428 {
429 if (at(ix) < other.at(ix))
430 return true;
431 if (other.at(ix) < at(ix))
432 return false;
433 }
434
435 return size() < other.size();
436}
437
438
439//
440// CssmAutoDbRecordAttributeData
441//
442CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData()
443{
444 clear();
445}
446
447void
448CssmAutoDbRecordAttributeData::invalidate()
449{
450 NumberOfAttributes = 0;
451}
452
453
454
455void
456CssmAutoDbRecordAttributeData::clear()
457{
458 deleteValues();
459 ArrayBuilder<CssmDbAttributeData>::clear();
460}
461
462
463
464static bool CompareAttributeInfos (const CSSM_DB_ATTRIBUTE_INFO &a, const CSSM_DB_ATTRIBUTE_INFO &b)
465{
466 // check the format of the names
467 if (a.AttributeNameFormat != b.AttributeNameFormat)
468 {
469 return false;
470 }
471
472 switch (a.AttributeNameFormat)
473 {
474 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
475 {
476 return strcmp (a.Label.AttributeName, b.Label.AttributeName) == 0;
477 }
478
479 case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
480 {
481 if (a.Label.AttributeOID.Length != b.Label.AttributeOID.Length)
482 {
483 return false;
484 }
485
486 return memcmp (a.Label.AttributeOID.Data, b.Label.AttributeOID.Data, a.Label.AttributeOID.Length) == 0;
487 }
488
489
490 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
491 {
492 return a.Label.AttributeID == b.Label.AttributeID;
493 }
494 }
495
496 return true; // just to keep the compiler from complaining
497}
498
499
500
501CssmDbAttributeData* CssmAutoDbRecordAttributeData::findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info)
502{
503 // walk through the data, looking for an attribute of the same type
504 unsigned i;
505 for (i = 0; i < size (); ++i)
506 {
507 CssmDbAttributeData& d = at (i);
508 CSSM_DB_ATTRIBUTE_INFO &inInfo = d.info ();
509
510 if (CompareAttributeInfos (info, inInfo))
511 {
512 return &d;
513 }
514 }
515
516 // found nothing?
517 return NULL;
518}
519
520
521
522CssmDbAttributeData& CssmAutoDbRecordAttributeData::getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info)
523{
524 // Either find an existing reference to an attribute in the list, or make a new one.
525 CssmDbAttributeData *anAttr = findAttribute (info);
526 if (anAttr) // was this already in the list?
527 {
528 // clean it up
529 anAttr->deleteValues (mValueAllocator);
530 }
531 else
532 {
533 // make a new one
534 anAttr = &add();
535 }
536
537 return *anAttr;
538}
539
540
541
542CssmDbAttributeData &
543CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info)
544{
545 CssmDbAttributeData& anAttr = getAttributeReference (info);
546 anAttr.info(info);
547 return anAttr;
548}
549
550CssmDbAttributeData &
551CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
552{
553 CssmDbAttributeData &anAttr = getAttributeReference (info);
554 anAttr.set(info, value, mValueAllocator);
555 return anAttr;
556}
557
e3d460c9
A
558void
559CssmAutoDbRecordAttributeData::updateWith(const CssmAutoDbRecordAttributeData* newValues) {
560 if(!newValues) {
561 return;
562 }
563 for(int i = 0; i < newValues->size(); i++) {
564 CssmDbAttributeData& c = newValues->at(i);
565 CssmDbAttributeData& target = add(c.info());
566
567 target.info(c.info());
568 target.copyValues(c, mValueAllocator);
569 //.set(c, mValueAllocator);
570 }
571}
572
b1ab9ed8
A
573//
574// CssmAutoQuery
575//
576CssmAutoQuery::CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator)
577: ArrayBuilder<CssmSelectionPredicate>(CssmSelectionPredicate::overlayVar(SelectionPredicate),
578 NumSelectionPredicates,
579 query.NumSelectionPredicates, allocator)
580{
581 RecordType = query.RecordType;
582 Conjunctive = query.Conjunctive;
583 QueryLimits = query.QueryLimits;
584 QueryFlags = query.QueryFlags;
585 for (uint32 ix = 0; ix < query.NumSelectionPredicates; ++ix)
586 add().set(query.SelectionPredicate[ix], allocator);
587}
588
589CssmAutoQuery::~CssmAutoQuery()
590{
591 clear();
592}
593
594void
595CssmAutoQuery::clear()
596{
597 deleteValues();
598 ArrayBuilder<CssmSelectionPredicate>::clear();
599}
600
601CssmSelectionPredicate &
602CssmAutoQuery::add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value)
603{
604 CssmSelectionPredicate &predicate = add();
605 predicate.dbOperator(dbOperator);
606 predicate.set(info, value, allocator());
607 return predicate;
608}