]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, 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 Apple Computer, 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, numType, &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 |