2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 File: MDSAttrUtils.cpp
22 Contains: Stateless functions used by MDSAttrParser.
24 Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved.
27 #include "MDSAttrUtils.h"
34 * Fill in one CSSM_DB_ATTRIBUTE_DATA with specified data, type and attribute name.
35 * CSSM_DB_ATTRIBUTE_DATA.Value and its referent are new[]'d and copied.
37 * -- AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING
38 * -- NumberOfValues = 1
40 void MDSRawValueToDbAttr(
43 CSSM_DB_ATTRIBUTE_FORMAT attrFormat
, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc.
45 CSSM_DB_ATTRIBUTE_DATA
&attr
,
48 CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo
= &attr
.Info
;
49 attrInfo
->AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
50 attrInfo
->Label
.AttributeName
= const_cast<char *>(attrName
);
51 attrInfo
->AttributeFormat
= attrFormat
;
52 attr
.NumberOfValues
= numValues
;
53 attr
.Value
= new CSSM_DATA
[1];
54 attr
.Value
->Data
= new uint8
[len
];
55 attr
.Value
->Length
= len
;
56 memcpy(attr
.Value
->Data
, value
, len
);
61 * Free data new[]'d in the above function.
63 void MDSFreeDbRecordAttrs(
64 CSSM_DB_ATTRIBUTE_DATA
*attrs
,
68 for(i
=0; i
<numAttrs
; i
++) {
69 assert(attrs
->Value
!= NULL
);
70 delete [] attrs
->Value
->Data
;
71 attrs
->Value
->Data
= NULL
;
72 attrs
->Value
->Length
= 0;
73 delete [] attrs
->Value
;
79 /* safely get a new[]'d C string from a CFString */
80 char *MDSCFStringToCString(
84 CFIndex len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfStr
), kCFStringEncodingUTF8
) + 1/*nul terminator*/;
87 CFStringGetCString(cfStr
, rtn
, len
, kCFStringEncodingUTF8
);
92 /* copy a new[]'d C string from a C string */
96 char *outStr
= new char[::strlen(inStr
) + 1];
97 strcpy(outStr
, inStr
);
102 * Given a CFTypeRef which is either a CFString, a CFNumber, or a CFBoolean,
103 * do our best to convert it to a uint32. If it's a CFString, we'll use a
104 * MDSNameValuePair to convert it. CFStrings expressed as decimal numbers
105 * are also converted properly. (MAYBE we'll convert hex strings too...TBD...)
106 * Returns true if conversion was successful.
108 bool MDSCfTypeToUInt32(
110 const MDSNameValuePair
*nameValues
, // optional for converting strings to numbers
111 const char *key
, // for debug logging only
112 uint32
&iValue
, // RETURNED
113 size_t &iValueLen
) // RETURNED
115 assert(cfValue
!= NULL
);
116 CFTypeID valueType
= CFGetTypeID(cfValue
);
117 if(valueType
== CFStringGetTypeID()) {
119 CSSM_RETURN crtn
= MDSStringToUint32((CFStringRef
)cfValue
,
120 nameValues
, tmpValue
);
122 MPDebug("cfTypeToInt: key %s uint32 form, string data (%s), "
124 CFStringGetCStringPtr((CFStringRef
)cfValue
,
125 kCFStringEncodingUTF8
));
129 iValueLen
= sizeof(tmpValue
);
131 } /* stored as string */
132 else if(valueType
== CFNumberGetTypeID()) {
133 int64_t tmpValue
= 0;
134 /* be paranoid - there is no unsigned type for CFNumber */
135 CFNumberRef cfNum
= (CFNumberRef
)cfValue
;
136 CFNumberType numType
= CFNumberGetType(cfNum
);
138 case kCFNumberSInt8Type
:
139 iValueLen
= 1; break;
140 case kCFNumberSInt16Type
:
141 iValueLen
= 2; break;
142 case kCFNumberSInt32Type
:
143 iValueLen
= 4; break;
144 case kCFNumberSInt64Type
: // apparently the default
145 // There are no 64-bit types in CDSA, so assume this is how
146 // CF encoded an unsigned 32-bit int whose high bit was set.
147 iValueLen
= 4; break;
148 case kCFNumberCharType
:
149 iValueLen
= sizeof(char); break;
150 case kCFNumberShortType
:
151 iValueLen
= sizeof(short); break;
152 case kCFNumberIntType
:
153 iValueLen
= sizeof(int); break;
154 case kCFNumberLongType
:
155 MPDebug("Warning: MDS key %s encoded kCFNumberLongType", key
);
156 iValueLen
= sizeof(long); break;
158 MPDebug("MDS cfTypeToInt: Bad CFNumber type (%ld) key %s", numType
, key
);
161 Boolean brtn
= CFNumberGetValue(cfNum
, kCFNumberSInt64Type
, &tmpValue
);
163 MPDebug("MDS cfTypeToInt: Bad CFNumber conversion");
166 iValue
= uint32(tmpValue
);
168 } /* stored as number */
169 else if(valueType
== CFBooleanGetTypeID()) {
170 Boolean b
= CFBooleanGetValue((CFBooleanRef
)cfValue
);
172 iValueLen
= sizeof(iValue
);
176 MPDebug("MDS cfTypeToInt: key %s, uint64 form, bad CF type (%d)",
177 key
, (int)valueType
);
183 * Insert a record, defined by a CSSM_DB_ATTRIBUTE_DATA array, into specified
184 * DL and DB. Returns true on success.
186 bool MDSInsertRecord(
187 const CSSM_DB_ATTRIBUTE_DATA
*inAttr
,
189 CSSM_DB_RECORDTYPE recordType
,
191 CSSM_DB_HANDLE dbHand
)
193 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrData
;
194 CSSM_DB_UNIQUE_RECORD_PTR uid
= NULL
;
197 recordAttrData
.DataRecordType
= recordType
;
198 recordAttrData
.SemanticInformation
= 0;
199 recordAttrData
.NumberOfAttributes
= numAttrs
;
200 recordAttrData
.AttributeData
=
201 const_cast<CSSM_DB_ATTRIBUTE_DATA_PTR
>(inAttr
);
204 dl
.DataInsert(dbHand
,
210 catch (const CssmError
&cerr
) {
211 MPDebug("MDSInsertRecord: DataInsert: %d", cerr
.error
);
215 MPDebug("MDSInsertRecord: DataInsert: unknown exception");
219 dl
.FreeUniqueRecord(dbHand
, *uid
);
225 * Convert a number expressed as a CFString to a uint32 using the specified
226 * name/value conversion table. The string may have multiple fields from that
227 * table, ORd together in normal C syntax. Like
229 * CSSM_SERVICE_CSP | CSSM_SERVICE_DL
231 * Individual tokens can also be expressed numerically, either in decimal or
232 * (if prefaced by "0x" hex. Numeric tokens and symbolic string tokens can
233 * be intermixed in the same incoming string.
235 * Individual tokens can be prefixed with "<<" indicating that the indicated
236 * value is to be shifted 16 bits. Cf. CL Primary Relation, {Cert,Crl}TypeFormat.
237 * This applies to both numeric and string tokens.
239 CSSM_RETURN
MDSStringToUint32(
241 const MDSNameValuePair
*table
, // optional, string must be decimal
244 char *cstr
= MDSCFStringToCString(str
);
246 /* should "never" happen...right? */
247 MPDebug("MDSStringToUint32: CFString conversion error");
248 return CSSMERR_CSSM_MDS_ERROR
;
253 char *dst
= tokenStr
;
255 CSSM_RETURN crtn
= CSSM_OK
;
258 while(*src
!= '\0') {
259 /* Get one token from src --> tokenStr[] */
260 /* First skip whitespace and '|' */
261 for( ; *src
!= '\0'; src
++) {
263 if(!isspace(c
) && (c
!= '|')) {
264 /* first char of token */
270 if((*src
== '\0') && (dst
== tokenStr
)) {
275 /* dst[-1] is the first good character of token; copy until
277 for( ; *src
!= '\0'; src
++) {
279 if(isspace(c
) || (c
== '|')) {
287 /* NULL terminate token string, convert to numeric value */
290 CSSM_RETURN crtn
= MDSAttrNameToValue(tokenStr
, table
, tokenVal
);
304 } // end namespace Security