]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_mds/lib/MDSAttrUtils.cpp
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_mds / lib / MDSAttrUtils.cpp
1 /*
2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 File: MDSAttrUtils.cpp
21
22 Contains: Stateless functions used by MDSAttrParser.
23
24 Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved.
25 */
26
27 #include "MDSAttrUtils.h"
28 #include <strings.h>
29
30 namespace Security
31 {
32
33 /*
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.
36 * Assumes:
37 * -- AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING
38 * -- NumberOfValues = 1
39 */
40 void MDSRawValueToDbAttr(
41 const void *value,
42 size_t len,
43 CSSM_DB_ATTRIBUTE_FORMAT attrFormat, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc.
44 const char *attrName,
45 CSSM_DB_ATTRIBUTE_DATA &attr,
46 uint32 numValues)
47 {
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);
57 }
58
59
60 /*
61 * Free data new[]'d in the above function.
62 */
63 void MDSFreeDbRecordAttrs(
64 CSSM_DB_ATTRIBUTE_DATA *attrs,
65 unsigned numAttrs)
66 {
67 uint32 i;
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;
74 attrs->Value = NULL;
75 attrs++;
76 }
77 }
78
79 /* safely get a new[]'d C string from a CFString */
80 char *MDSCFStringToCString(
81 CFStringRef cfStr)
82 {
83 char *rtn = NULL;
84 CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfStr), kCFStringEncodingUTF8) + 1/*nul terminator*/;
85 rtn = new char[len];
86 if(rtn) {
87 CFStringGetCString(cfStr, rtn, len, kCFStringEncodingUTF8);
88 }
89 return rtn;
90 }
91
92 /* copy a new[]'d C string from a C string */
93 char *MDSCopyCstring(
94 const char *inStr)
95 {
96 char *outStr = new char[::strlen(inStr) + 1];
97 strcpy(outStr, inStr);
98 return outStr;
99 }
100
101 /*
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.
107 */
108 bool MDSCfTypeToUInt32(
109 CFTypeRef cfValue,
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
114 {
115 assert(cfValue != NULL);
116 CFTypeID valueType = CFGetTypeID(cfValue);
117 if(valueType == CFStringGetTypeID()) {
118 uint32 tmpValue = 0;
119 CSSM_RETURN crtn = MDSStringToUint32((CFStringRef)cfValue,
120 nameValues, tmpValue);
121 if(crtn) {
122 MPDebug("cfTypeToInt: key %s uint32 form, string data (%s), "
123 "bad conv", key,
124 CFStringGetCStringPtr((CFStringRef)cfValue,
125 kCFStringEncodingUTF8));
126 return false;
127 }
128 iValue = tmpValue;
129 iValueLen = sizeof(tmpValue);
130 return true;
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);
137 switch(numType) {
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;
157 default:
158 MPDebug("MDS cfTypeToInt: Bad CFNumber type (%ld) key %s", numType, key);
159 return false;
160 }
161 Boolean brtn = CFNumberGetValue(cfNum, kCFNumberSInt64Type, &tmpValue);
162 if(!brtn) {
163 MPDebug("MDS cfTypeToInt: Bad CFNumber conversion");
164 return false;
165 }
166 iValue = uint32(tmpValue);
167 return true;
168 } /* stored as number */
169 else if(valueType == CFBooleanGetTypeID()) {
170 Boolean b = CFBooleanGetValue((CFBooleanRef)cfValue);
171 iValue = b ? 1 : 0;
172 iValueLen = sizeof(iValue);
173 return true;
174 }
175 else {
176 MPDebug("MDS cfTypeToInt: key %s, uint64 form, bad CF type (%d)",
177 key, (int)valueType);
178 return false;
179 }
180 }
181
182 /*
183 * Insert a record, defined by a CSSM_DB_ATTRIBUTE_DATA array, into specified
184 * DL and DB. Returns true on success.
185 */
186 bool MDSInsertRecord(
187 const CSSM_DB_ATTRIBUTE_DATA *inAttr,
188 unsigned numAttrs,
189 CSSM_DB_RECORDTYPE recordType,
190 MDSSession &dl,
191 CSSM_DB_HANDLE dbHand)
192 {
193 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrData;
194 CSSM_DB_UNIQUE_RECORD_PTR uid = NULL;
195 bool ourRtn = true;
196
197 recordAttrData.DataRecordType = recordType;
198 recordAttrData.SemanticInformation = 0;
199 recordAttrData.NumberOfAttributes = numAttrs;
200 recordAttrData.AttributeData =
201 const_cast<CSSM_DB_ATTRIBUTE_DATA_PTR>(inAttr);
202
203 try {
204 dl.DataInsert(dbHand,
205 recordType,
206 &recordAttrData,
207 NULL,
208 uid);
209 }
210 catch (const CssmError &cerr) {
211 MPDebug("MDSInsertRecord: DataInsert: %d", cerr.error);
212 ourRtn = false;
213 }
214 catch(...) {
215 MPDebug("MDSInsertRecord: DataInsert: unknown exception");
216 ourRtn = false;
217 }
218 if(uid != NULL) {
219 dl.FreeUniqueRecord(dbHand, *uid);
220 }
221 return ourRtn;
222 }
223
224 /*
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
228 *
229 * CSSM_SERVICE_CSP | CSSM_SERVICE_DL
230 *
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.
234 *
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.
238 */
239 CSSM_RETURN MDSStringToUint32(
240 CFStringRef str,
241 const MDSNameValuePair *table, // optional, string must be decimal
242 uint32 &value)
243 {
244 char *cstr = MDSCFStringToCString(str);
245 if(cstr == NULL) {
246 /* should "never" happen...right? */
247 MPDebug("MDSStringToUint32: CFString conversion error");
248 return CSSMERR_CSSM_MDS_ERROR;
249 }
250
251 char tokenStr[200];
252 char *src = cstr;
253 char *dst = tokenStr;
254 char c;
255 CSSM_RETURN crtn = CSSM_OK;
256
257 value = 0;
258 while(*src != '\0') {
259 /* Get one token from src --> tokenStr[] */
260 /* First skip whitespace and '|' */
261 for( ; *src != '\0'; src++) {
262 c = *src;
263 if(!isspace(c) && (c != '|')) {
264 /* first char of token */
265 *dst++ = c;
266 src++;
267 break;
268 }
269 }
270 if((*src == '\0') && (dst == tokenStr)) {
271 /* done */
272 break;
273 }
274
275 /* dst[-1] is the first good character of token; copy until
276 * space or '|' */
277 for( ; *src != '\0'; src++) {
278 c = *src;
279 if(isspace(c) || (c == '|')) {
280 break;
281 }
282 else {
283 *dst++ = c;
284 }
285 }
286
287 /* NULL terminate token string, convert to numeric value */
288 *dst = '\0';
289 uint32 tokenVal = 0;
290 CSSM_RETURN crtn = MDSAttrNameToValue(tokenStr, table, tokenVal);
291 if(crtn) {
292 /* punt */
293 break;
294 }
295 value |= tokenVal;
296
297 /* restart */
298 dst = tokenStr;
299 }
300 delete [] cstr;
301 return crtn;
302 }
303
304 } // end namespace Security