X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_filedb/lib/MetaRecord.cpp?ds=sidebyside diff --git a/libsecurity_filedb/lib/MetaRecord.cpp b/libsecurity_filedb/lib/MetaRecord.cpp deleted file mode 100644 index 9fc54a90..00000000 --- a/libsecurity_filedb/lib/MetaRecord.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS - * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT - * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the - * specific language governing rights and limitations under the License. - */ - - -// -// MetaRecord.cpp -// - -#include "MetaRecord.h" -#include -#include - - -MetaRecord::MetaRecord(CSSM_DB_RECORDTYPE inRecordType) : - mRecordType(inRecordType) -{ -} - -MetaRecord::MetaRecord(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo) -: mRecordType(inInfo.DataRecordType) -{ - try - { - setRecordAttributeInfo(inInfo); - } - catch (...) - { - for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); - } -} - -MetaRecord::MetaRecord(CSSM_DB_RECORDTYPE inRelationID, - uint32 inNumberOfAttributes, - const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo) : - mRecordType(inRelationID) -{ - try { - for (uint32 anIndex = 0; anIndex < inNumberOfAttributes; anIndex++) - { - string aName; - if (inAttributeInfo[anIndex].AttributeName) - aName = string(inAttributeInfo[anIndex].AttributeName); - - const CssmData *aNameID = NULL; - if (inAttributeInfo[anIndex].AttributeNameID.Length > 0) - aNameID = &CssmData::overlay(inAttributeInfo[anIndex].AttributeNameID); - - uint32 aNumber = inAttributeInfo[anIndex].AttributeId; - createAttribute( - inAttributeInfo[anIndex].AttributeName ? &aName : NULL, - aNameID, aNumber, - inAttributeInfo[anIndex].DataType); - } - } - catch (...) - { - for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); - } -} - -MetaRecord::~MetaRecord() -{ - // for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); - AttributeVector::iterator it = mAttributeVector.begin(); - while (it != mAttributeVector.end()) - { - MetaAttribute* mat = *it++; - if (mat != NULL) - { - delete mat; - } - } -} - -void -MetaRecord::setRecordAttributeInfo(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo) -{ - for (uint32 anIndex = 0; anIndex < inInfo.NumberOfAttributes; anIndex++) - { - switch (inInfo.AttributeInfo[anIndex].AttributeNameFormat) - { - case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: - { - string aName(inInfo.AttributeInfo[anIndex].Label.AttributeName); - createAttribute(&aName, nil, anIndex, - inInfo.AttributeInfo[anIndex].AttributeFormat); - break; - } - case CSSM_DB_ATTRIBUTE_NAME_AS_OID: - { - const CssmData &aNameID = CssmOid::overlay(inInfo.AttributeInfo[anIndex].Label.AttributeOID); - createAttribute(nil, &aNameID, anIndex, - inInfo.AttributeInfo[anIndex].AttributeFormat); - break; - } - case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: - { - uint32 aNumber = inInfo.AttributeInfo[anIndex].Label.AttributeID; - createAttribute(nil, nil, aNumber, - inInfo.AttributeInfo[anIndex].AttributeFormat); - break; - } - default: - CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); - break; - } - } -} - -void -MetaRecord::createAttribute(const string *inAttributeName, - const CssmOid *inAttributeOID, - uint32 inAttributeID, - CSSM_DB_ATTRIBUTE_FORMAT inAttributeFormat) -{ - // Index of new element is current size of vector - uint32 anAttributeIndex = (uint32)mAttributeVector.size(); - bool aInsertedAttributeName = false; - bool aInsertedAttributeOID = false; - bool aInsertedAttributeID = false; - - if (inAttributeName) - { - if (!mNameStringMap.insert(NameStringMap::value_type(*inAttributeName, anAttributeIndex)).second) - CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); - aInsertedAttributeName = true; - } - try - { - if (inAttributeOID) - { - if (!mNameOIDMap.insert(NameOIDMap::value_type(*inAttributeOID, anAttributeIndex)).second) - CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); - aInsertedAttributeOID = true; - } - - if (!mNameIntMap.insert(NameIntMap::value_type(inAttributeID, anAttributeIndex)).second) - CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); - aInsertedAttributeID = true; - - // Note: this no longer throws INVALID_FIELD_NAME since the attribute will always have - // an attribute ID by which it is known - - mAttributeVector.push_back(MetaAttribute::create(inAttributeFormat, - anAttributeIndex, inAttributeID)); - } - catch(...) - { - if (aInsertedAttributeName) - mNameStringMap.erase(*inAttributeName); - if (aInsertedAttributeOID) - mNameOIDMap.erase(*inAttributeOID); - if (inAttributeID) - mNameIntMap.erase(inAttributeID); - - throw; - } -} - - -// Create a packed record from the given inputs. -void -MetaRecord::packRecord(WriteSection &inWriteSection, - const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, - const CssmData *inData) const -{ - uint32 aDataSize; - if (inData) - aDataSize = (uint32)inData->Length; - else - aDataSize = 0; - - inWriteSection.put(OffsetDataSize, aDataSize); - uint32 anOffset = (uint32)(OffsetAttributeOffsets + AtomSize * mAttributeVector.size()); - if (aDataSize) - anOffset = inWriteSection.put(anOffset, aDataSize, inData->Data); - - vector aNumValues(mAttributeVector.size(), ~(uint32)0); - vector aValues(mAttributeVector.size()); - uint32 anIndex; - - if (inAttributes == NULL) - inWriteSection.put(OffsetSemanticInformation, 0); - else - { - inWriteSection.put(OffsetSemanticInformation, inAttributes->SemanticInformation); - - // Put the supplied attribute values into the list of attributes - // and values. - anIndex = inAttributes->NumberOfAttributes; - // Make sure that AttributeData is a valid array. - if (anIndex > 0) - Required(inAttributes->AttributeData); - - while (anIndex-- > 0) - { - CSSM_DB_ATTRIBUTE_DATA &anAttribute = inAttributes->AttributeData[anIndex]; - uint32 anAttributeIndex = attributeIndex(anAttribute.Info); - // Make sure that the caller specified the attribute values in the correct format. - if (anAttribute.Info.AttributeFormat != mAttributeVector[anAttributeIndex]->attributeFormat()) - CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); - - // If this attribute was specified before, throw. - if (aNumValues[anAttributeIndex] != ~(uint32)0) - CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); - - aNumValues[anAttributeIndex] = anAttribute.NumberOfValues; - aValues[anAttributeIndex] = anAttribute.Value; - } - } - - for (anIndex = 0; anIndex < mAttributeVector.size(); ++anIndex) - { - const MetaAttribute &aMetaAttribute = *mAttributeVector[anIndex]; - uint32 aNumberOfValues = aNumValues[anIndex]; - // Now call the parsingmodule for each attribute that - // wasn't explicitly specified and that has a parsingmodule. - if (aNumberOfValues == ~(uint32)0) - aNumberOfValues = aDataSize == 0 ? 0 : aMetaAttribute.parse(*inData, aValues[anIndex]); - - // XXX When do we throw CSSMERR_DL_MISSING_VALUE? Maybe if an - // attribute is part of a unique index. - - // Now we have a valuelist for this attribute. Let's encode it. - aMetaAttribute.packAttribute(inWriteSection, anOffset, aNumberOfValues, aValues[anIndex]); - } - - inWriteSection.put(OffsetRecordSize, anOffset); - inWriteSection.size(anOffset); -} - -inline void -MetaRecord::unpackAttribute(const ReadSection &inReadSection, - Allocator &inAllocator, - CSSM_DB_ATTRIBUTE_DATA &inoutAttribute) const -{ - const MetaAttribute &aMetaAttribute = metaAttribute(inoutAttribute.Info); - // XXX: See ISSUES on whether AttributeFormat should be an outputvalue or not. - inoutAttribute.Info.AttributeFormat = aMetaAttribute.attributeFormat(); - aMetaAttribute.unpackAttribute(inReadSection, inAllocator, - inoutAttribute.NumberOfValues, - inoutAttribute.Value); -} - -void -MetaRecord::unpackRecord(const ReadSection &inReadSection, - Allocator &inAllocator, - CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, - CssmData *inoutData, - CSSM_QUERY_FLAGS inQueryFlags) const -{ - // XXX Use POD wrapper for inoutAttributes here. - TrackingAllocator anAllocator(inAllocator); - - try - { - if (inoutData) - { - // XXX Treat KEY records specially. - - // If inQueryFlags & CSSM_QUERY_RETURN_DATA is true return the raw - // key bits in the CSSM_KEY structure - Range aDataRange = dataRange(inReadSection); - inoutData->Length = aDataRange.mSize; - inoutData->Data = inReadSection.allocCopyRange(aDataRange, anAllocator); - } - - if (inoutAttributes) - { - inoutAttributes->DataRecordType = dataRecordType(); - inoutAttributes->SemanticInformation = semanticInformation(inReadSection); - uint32 anIndex = inoutAttributes->NumberOfAttributes; - - // Make sure that AttributeData is a valid array. - if (anIndex > 0 && inoutAttributes->AttributeData == NULL) - CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); - - while (anIndex-- > 0) - { - unpackAttribute(inReadSection, anAllocator, - inoutAttributes->AttributeData[anIndex]); - } - } - } - catch (CssmError e) - { - if (e.osStatus() != CSSMERR_DL_DATABASE_CORRUPT) - { - // clear all pointers so that nothing dangles back to the user - if (inoutData) - { - inoutData->Data = NULL; - } - - if (inoutAttributes) - { - unsigned i; - for (i = 0; i < inoutAttributes->NumberOfAttributes; ++i) - { - CSSM_DB_ATTRIBUTE_DATA& data = inoutAttributes->AttributeData[i]; - - unsigned j; - for (j = 0; j < data.NumberOfValues; ++j) - { - data.Value[j].Data = NULL; - } - - data.Value = NULL; - - if (data.Info.AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_STRING) - { - data.Info.Label.AttributeName = NULL; - } - } - } - } - - throw; - } - catch (...) - { - // clear all pointers so that nothing dangles back to the user - if (inoutData) - { - inoutData->Data = NULL; - } - - if (inoutAttributes) - { - unsigned i; - for (i = 0; i < inoutAttributes->NumberOfAttributes; ++i) - { - CSSM_DB_ATTRIBUTE_DATA& data = inoutAttributes->AttributeData[i]; - - unsigned j; - for (j = 0; j < data.NumberOfValues; ++j) - { - data.Value[j].Data = NULL; - } - - data.Value = NULL; - - if (data.Info.AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_STRING) - { - data.Info.Label.AttributeName = NULL; - } - } - } - - throw; - } - - - // Don't free anything the trackingAllocator allocated when it is destructed. - anAllocator.commit(); -} - -// Return the index (0 though NumAttributes - 1) of the attribute -// represented by inAttributeInfo - -#ifndef NDEBUG -#define LOG_NAME_AS_STRING_FAIL -#endif -uint32 -MetaRecord::attributeIndex(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const -{ - uint32 anIndex; - switch (inAttributeInfo.AttributeNameFormat) - { - case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: - { - string aName(inAttributeInfo.Label.AttributeName); - assert(aName.size() < 500); // MDS leak debug - NameStringMap::const_iterator it = mNameStringMap.find(aName); - if (it == mNameStringMap.end()) { - #ifdef LOG_NAME_AS_STRING_FAIL - printf("NAME_AS_STRING failure; attrName %s\n", - inAttributeInfo.Label.AttributeName); - for(it = mNameStringMap.begin(); - it != mNameStringMap.end(); - it++) { - printf("name %s val %d\n", it->first.c_str(), it->second); - } - #endif - CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); - } - anIndex = it->second; - break; - } - case CSSM_DB_ATTRIBUTE_NAME_AS_OID: - { - const CssmOid &aName = CssmOid::overlay(inAttributeInfo.Label.AttributeOID); - NameOIDMap::const_iterator it = mNameOIDMap.find(aName); - if (it == mNameOIDMap.end()) - CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); - anIndex = it->second; - break; - } - case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: - { - uint32 aName = inAttributeInfo.Label.AttributeID; - NameIntMap::const_iterator it = mNameIntMap.find(aName); - if (it == mNameIntMap.end()) - CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); - anIndex = it->second; - break; - } - default: - CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); - break; - } - - return anIndex; -} - -const MetaAttribute & -MetaRecord::metaAttribute(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const -{ - return *mAttributeVector[attributeIndex(inAttributeInfo)]; -} - -// Create a packed record from the given inputs and the old packed record inReadSection. -void -MetaRecord::updateRecord(const ReadSection &inReadSection, - WriteSection &inWriteSection, - const CssmDbRecordAttributeData *inAttributes, - const CssmData *inData, - CSSM_DB_MODIFY_MODE inModifyMode) const -{ - TrackingAllocator anAllocator(Allocator::standard()); - - // modify the opaque data associated with the record - - uint32 aDataSize; - const uint8 *aDataData = NULL; - - if (inData) - { - // prepare to write new data - aDataSize = (uint32)inData->Length; - aDataData = inData->Data; - } - else - { - // prepare to copy old data - Range aDataRange = dataRange(inReadSection); - aDataSize = aDataRange.mSize; - if (aDataSize) - aDataData = inReadSection.range(aDataRange); - } - - // compute the data offset; this will keep a running total of the record size - uint32 anOffset = (uint32)(OffsetAttributeOffsets + AtomSize * mAttributeVector.size()); - - // write the appropriate data to the new record - inWriteSection.put(OffsetDataSize, aDataSize); - if (aDataSize) - anOffset = inWriteSection.put(anOffset, aDataSize, aDataData); - - // unpack the old attributes since some of them may need to be preserved - - auto_array attributeData(mAttributeVector.size()); - - for (size_t anAttributeIndex = mAttributeVector.size(); anAttributeIndex-- > 0; ) - { - // unpack the old attribute data for this attribute index - const MetaAttribute &attribute = *mAttributeVector[anAttributeIndex]; - attribute.unpackAttribute(inReadSection, anAllocator, - attributeData[anAttributeIndex].NumberOfValues, - attributeData[anAttributeIndex].Value); - } - - // retrieve the currrent semantic information - - uint32 oldSemanticInformation = semanticInformation(inReadSection); - - // process each input attribute as necessary, based on the modification mode - - if (inAttributes == NULL) - { - // make sure the modification mode is NONE, otherwise it's an - // error accordining to the spec - if (inModifyMode != CSSM_DB_MODIFY_ATTRIBUTE_NONE) - CssmError::throwMe(CSSMERR_DL_INVALID_MODIFY_MODE); - } - - else { - - // modify the semantic information - - uint32 inSemanticInformation = inAttributes ? inAttributes->SemanticInformation : 0; - - if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_ADD) - oldSemanticInformation |= inSemanticInformation; - - else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_DELETE) - oldSemanticInformation &= ~inSemanticInformation; - - else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_REPLACE) - oldSemanticInformation = inSemanticInformation; - - uint32 anIndex = inAttributes->NumberOfAttributes; - if (anIndex > 0) - Required(inAttributes->AttributeData); - - // modify the attributes - - while (anIndex-- > 0) { - - const CssmDbAttributeData &anAttribute = inAttributes->at(anIndex); - uint32 anAttributeIndex = attributeIndex(anAttribute.info()); - if (anAttribute.format() != mAttributeVector[anAttributeIndex]->attributeFormat()) - CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); - - CssmDbAttributeData &oldAttribute = attributeData[anAttributeIndex]; - - // if the modify mode is ADD, merge new values with pre-existing values - - if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_ADD) - oldAttribute.add(anAttribute, anAllocator); - - // if the modify mode is DELETE, remove the indicated values, or remove - // all values if none are specified - - else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_DELETE) - { - if (anAttribute.size() == 0) - oldAttribute.deleteValues(anAllocator); - else - oldAttribute.deleteValues(anAttribute, anAllocator); - } - - // if the modify mode is REPLACE, then replace the specified values, or - // delete all values if no values are specified - - else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_REPLACE) - { - oldAttribute.deleteValues(anAllocator); - if (anAttribute.size() > 0) - oldAttribute.add(anAttribute, anAllocator); - else - // The spec says "all values are deleted or the the value is replaced - // with the default" but doesn't say which. We could call the parsing - // module for the attribute here...if they were implemented! But instead - // we choose "all values are deleted" and leave it at that. - ; - } - } - } - - // write the resulting attributes into the new record - - inWriteSection.put(OffsetSemanticInformation, oldSemanticInformation); - - for (uint32 anIndex = 0; anIndex < mAttributeVector.size(); ++anIndex) - { - const MetaAttribute &metaAttribute = *mAttributeVector[anIndex]; - metaAttribute.packAttribute(inWriteSection, anOffset, - attributeData[anIndex].NumberOfValues, - attributeData[anIndex].Value); - } - - inWriteSection.put(OffsetRecordSize, anOffset); - inWriteSection.size(anOffset); -} -