cssmdb.cpp
  1  /*
  2   * Copyright (c) 2000-2004,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.cpp
 26  //
 27  //
 28  #include <security_cdsa_utilities/cssmdb.h>
 29  #include <CommonCrypto/CommonDigest.h>
 30  
 31  using namespace DataWalkers;
 32  
 33  bool 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;
 39  
 40      // This test will produce unreproducible results,
 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  
 72  bool 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  //
105  CssmDLPolyData::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  
118  CssmDLPolyData::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  //
131  CssmDbAttributeInfo::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  
139  CssmDbAttributeInfo::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  
147  CssmDbAttributeInfo::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  
156  bool
157  CssmDbAttributeInfo::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  
186  bool
187  CssmDbAttributeInfo::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  //
207  CssmDbAttributeData::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  }
217  CssmDbAttributeData::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  
225  CssmDbAttributeData::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  
236  CssmDbAttributeData::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  
244  CssmDbAttributeData::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  
252  CssmDbAttributeData::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  
260  CssmDbAttributeData::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  
268  CssmDbAttributeData::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  
282  void 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;
289  	Value[0].Data = inAllocator.alloc<uint8>((UInt32)inValue.Length);
290  	Value[0].Length = inValue.Length;
291  	memcpy(Value[0].Data, inValue.Data, inValue.Length);
292  	NumberOfValues = 1;
293  }
294  
295  void 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  
303  void 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  
318  void 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  
333  bool 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  
350  void
351  CssmDbAttributeData::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;
362  		Value[destIndex].Data = inAllocator.alloc<uint8>((UInt32)src.Value[srcIndex].Length);
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  
370  bool
371  CssmDbAttributeData::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  
395  void
396  CssmDbAttributeData::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  //
405  CssmDbAttributeData *
406  CssmDbRecordAttributeData::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  
418  bool
419  CssmDbRecordAttributeData::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  //
442  CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData()
443  {
444  	clear();
445  }
446  
447  void
448  CssmAutoDbRecordAttributeData::invalidate()
449  {
450  	NumberOfAttributes = 0;
451  }
452  
453  
454  
455  void
456  CssmAutoDbRecordAttributeData::clear()
457  {
458  	deleteValues();
459  	ArrayBuilder<CssmDbAttributeData>::clear();
460  }
461  
462  
463  
464  static 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  
501  CssmDbAttributeData* 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  
522  CssmDbAttributeData& 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  
542  CssmDbAttributeData &
543  CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info)
544  {
545  	CssmDbAttributeData& anAttr = getAttributeReference (info);
546  	anAttr.info(info);
547  	return anAttr;
548  }
549  
550  CssmDbAttributeData &
551  CssmAutoDbRecordAttributeData::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  
558  void
559  CssmAutoDbRecordAttributeData::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  
573  //
574  // CssmAutoQuery
575  //
576  CssmAutoQuery::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  
589  CssmAutoQuery::~CssmAutoQuery()
590  {
591  	clear();
592  }
593  
594  void
595  CssmAutoQuery::clear()
596  {
597  	deleteValues();
598  	ArrayBuilder<CssmSelectionPredicate>::clear();
599  }
600  
601  CssmSelectionPredicate &
602  CssmAutoQuery::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  }