/* * 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. */ /* File: MDSAttrUtils.cpp Contains: Stateless functions used by MDSAttrParser. Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. */ #include "MDSAttrUtils.h" #include #include namespace Security { /* * Fill in one CSSM_DB_ATTRIBUTE_DATA with specified data, type and attribute name. * CSSM_DB_ATTRIBUTE_DATA.Value and its referent are new[]'d and copied. * Assumes: * -- AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING * -- NumberOfValues = 1 */ void MDSRawValueToDbAttr( const void *value, size_t len, CSSM_DB_ATTRIBUTE_FORMAT attrFormat, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc. const char *attrName, CSSM_DB_ATTRIBUTE_DATA &attr, uint32 numValues) { CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo = &attr.Info; attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; attrInfo->Label.AttributeName = const_cast(attrName); attrInfo->AttributeFormat = attrFormat; attr.NumberOfValues = numValues; attr.Value = new CSSM_DATA[1]; attr.Value->Data = new uint8[len]; attr.Value->Length = len; memcpy(attr.Value->Data, value, len); } /* * Free data new[]'d in the above function. */ void MDSFreeDbRecordAttrs( CSSM_DB_ATTRIBUTE_DATA *attrs, unsigned numAttrs) { uint32 i; for(i=0; iValue != NULL); delete [] attrs->Value->Data; attrs->Value->Data = NULL; attrs->Value->Length = 0; delete [] attrs->Value; attrs->Value = NULL; attrs++; } } /* safely get a new[]'d C string from a CFString */ char *MDSCFStringToCString( CFStringRef cfStr) { char *rtn = NULL; unsigned len = CFStringGetLength(cfStr) + 1; rtn = new char[len]; if(rtn) { CFStringGetCString(cfStr, rtn, len, CFStringGetSystemEncoding()); } return rtn; } /* copy a new[]'d C string from a C string */ char *MDSCopyCstring( const char *inStr) { char *outStr = new char[::strlen(inStr) + 1]; strcpy(outStr, inStr); return outStr; } /* * Given a CFTypeRef which is either a CFString, a CFNumber, or a CFBoolean, * do our best to convert it to a uint32. If it's a CFString, we'll use a * MDSNameValuePair to convert it. CFStrings expressed as decimal numbers * are also converted properly. (MAYBE we'll convert hex strings too...TBD...) * Returns true if conversion was successful. */ bool MDSCfTypeToInt( CFTypeRef cfValue, const MDSNameValuePair *nameValues, // optional for converting strings to numbers const char *key, // for debug logging only uint32 &iValue) // RETURNED { assert(cfValue != NULL); CFTypeID valueType = CFGetTypeID(cfValue); if(valueType == CFStringGetTypeID()) { CSSM_RETURN crtn = MDSStringToUint32((CFStringRef)cfValue, nameValues, iValue); if(crtn) { MPDebug("cfTypeToInt: key %s uint32 form, string data (%s), " "bad conv", key, CFStringGetCStringPtr((CFStringRef)cfValue, CFStringGetSystemEncoding())); return false; } return true; } /* stored as string */ else if(valueType == CFNumberGetTypeID()) { /* be paranoid - there is no unsigned type for CFNumber */ CFNumberRef cfNum = (CFNumberRef)cfValue; CFNumberType numType = CFNumberGetType(cfNum); switch(numType) { case kCFNumberSInt8Type: case kCFNumberSInt16Type: case kCFNumberSInt32Type: case kCFNumberCharType: case kCFNumberShortType: case kCFNumberIntType: case kCFNumberLongType: case kCFNumberSInt64Type: // apparently the default /* OK */ break; default: MPDebug("MDS cfTypeToInt: Bad CFNumber type (%d) key %s", numType, key); return false; } Boolean brtn = CFNumberGetValue(cfNum, kCFNumberLongType, &iValue); if(!brtn) { MPDebug("MDS cfTypeToInt: Bad CFNumber conversion"); return false; } return true; } /* stored as number */ else if(valueType == CFBooleanGetTypeID()) { Boolean b = CFBooleanGetValue((CFBooleanRef)cfValue); iValue = b ? 1 : 0; return true; } else { MPDebug("MDS cfTypeToInt: key %s, uint32 form, bad CF type (%d)", key, (int)valueType); return false; } } /* * Insert a record, defined by a CSSM_DB_ATTRIBUTE_DATA array, into specified * DL and DB. Returns true on success. */ bool MDSInsertRecord( const CSSM_DB_ATTRIBUTE_DATA *inAttr, unsigned numAttrs, CSSM_DB_RECORDTYPE recordType, MDSSession &dl, CSSM_DB_HANDLE dbHand) { CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrData; CSSM_DB_UNIQUE_RECORD_PTR uid = NULL; bool ourRtn = true; recordAttrData.DataRecordType = recordType; recordAttrData.SemanticInformation = 0; recordAttrData.NumberOfAttributes = numAttrs; recordAttrData.AttributeData = const_cast(inAttr); try { dl.DataInsert(dbHand, recordType, &recordAttrData, NULL, uid); } catch (const CssmError &cerr) { MPDebug("MDSInsertRecord: DataInsert: %s", cssmErrorString(cerr).c_str()); ourRtn = false; } catch(...) { MPDebug("MDSInsertRecord: DataInsert: unknown exception"); ourRtn = false; } if(uid != NULL) { dl.FreeUniqueRecord(dbHand, *uid); } return ourRtn; } /* * Convert a number expressed as a CFString to a uint32 using the specified * name/value conversion table. The string may have multiple fields from that * table, ORd together in normal C syntax. Like * * CSSM_SERVICE_CSP | CSSM_SERVICE_DL * * Individual tokens can also be expressed numerically, either in decimal or * (if prefaced by "0x" hex. Numeric tokens and symbolic string tokens can * be intermixed in the same incoming string. * * Individual tokens can be prefixed with "<<" indicating that the indicated * value is to be shifted 16 bits. Cf. CL Primary Relation, {Cert,Crl}TypeFormat. * This applies to both numeric and string tokens. */ CSSM_RETURN MDSStringToUint32( CFStringRef str, const MDSNameValuePair *table, // optional, string must be decimal uint32 &value) { char *cstr = MDSCFStringToCString(str); if(cstr == NULL) { /* should "never" happen...right? */ MPDebug("MDSStringToUint32: CFString conversion error"); return CSSMERR_CSSM_MDS_ERROR; } char tokenStr[200]; char *src = cstr; char *dst = tokenStr; char c; CSSM_RETURN crtn = CSSM_OK; value = 0; while(*src != '\0') { /* Get one token from src --> tokenStr[] */ /* First skip whitespace and '|' */ for( ; *src != '\0'; src++) { c = *src; if(!isspace(c) && (c != '|')) { /* first char of token */ *dst++ = c; src++; break; } } if((*src == '\0') && (dst == tokenStr)) { /* done */ break; } /* dst[-1] is the first good character of token; copy until * space or '|' */ for( ; *src != '\0'; src++) { c = *src; if(isspace(c) || (c == '|')) { break; } else { *dst++ = c; } } /* NULL terminate token string, convert to numeric value */ *dst = '\0'; uint32 tokenVal = 0; CSSM_RETURN crtn = MDSAttrNameToValue(tokenStr, table, tokenVal); if(crtn) { /* punt */ break; } value |= tokenVal; /* restart */ dst = tokenStr; } delete [] cstr; return crtn; } } // end namespace Security