]> git.saurik.com Git - apple/security.git/blob - cdsa/mds/MDSAttrUtils.cpp
Security-54.1.3.tar.gz
[apple/security.git] / cdsa / mds / MDSAttrUtils.cpp
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 <Security/cssmerrno.h>
29 #include <strings.h>
30
31 namespace Security
32 {
33
34 /*
35 * Fill in one CSSM_DB_ATTRIBUTE_DATA with specified data, type and attribute name.
36 * CSSM_DB_ATTRIBUTE_DATA.Value and its referent are new[]'d and copied.
37 * Assumes:
38 * -- AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING
39 * -- NumberOfValues = 1
40 */
41 void MDSRawValueToDbAttr(
42 const void *value,
43 size_t len,
44 CSSM_DB_ATTRIBUTE_FORMAT attrFormat, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc.
45 const char *attrName,
46 CSSM_DB_ATTRIBUTE_DATA &attr,
47 uint32 numValues)
48 {
49 CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo = &attr.Info;
50 attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
51 attrInfo->Label.AttributeName = const_cast<char *>(attrName);
52 attrInfo->AttributeFormat = attrFormat;
53 attr.NumberOfValues = numValues;
54 attr.Value = new CSSM_DATA[1];
55 attr.Value->Data = new uint8[len];
56 attr.Value->Length = len;
57 memcpy(attr.Value->Data, value, len);
58 }
59
60
61 /*
62 * Free data new[]'d in the above function.
63 */
64 void MDSFreeDbRecordAttrs(
65 CSSM_DB_ATTRIBUTE_DATA *attrs,
66 unsigned numAttrs)
67 {
68 uint32 i;
69 for(i=0; i<numAttrs; i++) {
70 assert(attrs->Value != NULL);
71 delete [] attrs->Value->Data;
72 attrs->Value->Data = NULL;
73 attrs->Value->Length = 0;
74 delete [] attrs->Value;
75 attrs->Value = NULL;
76 attrs++;
77 }
78 }
79
80 /* safely get a new[]'d C string from a CFString */
81 char *MDSCFStringToCString(
82 CFStringRef cfStr)
83 {
84 char *rtn = NULL;
85 unsigned len = CFStringGetLength(cfStr) + 1;
86 rtn = new char[len];
87 if(rtn) {
88 CFStringGetCString(cfStr, rtn, len, CFStringGetSystemEncoding());
89 }
90 return rtn;
91 }
92
93 /* copy a new[]'d C string from a C string */
94 char *MDSCopyCstring(
95 const char *inStr)
96 {
97 char *outStr = new char[::strlen(inStr) + 1];
98 strcpy(outStr, inStr);
99 return outStr;
100 }
101
102 /*
103 * Given a CFTypeRef which is either a CFString, a CFNumber, or a CFBoolean,
104 * do our best to convert it to a uint32. If it's a CFString, we'll use a
105 * MDSNameValuePair to convert it. CFStrings expressed as decimal numbers
106 * are also converted properly. (MAYBE we'll convert hex strings too...TBD...)
107 * Returns true if conversion was successful.
108 */
109 bool MDSCfTypeToInt(
110 CFTypeRef cfValue,
111 const MDSNameValuePair *nameValues, // optional for converting strings to numbers
112 const char *key, // for debug logging only
113 uint32 &iValue) // RETURNED
114 {
115 assert(cfValue != NULL);
116 CFTypeID valueType = CFGetTypeID(cfValue);
117 if(valueType == CFStringGetTypeID()) {
118 CSSM_RETURN crtn = MDSStringToUint32((CFStringRef)cfValue,
119 nameValues, iValue);
120 if(crtn) {
121 MPDebug("cfTypeToInt: key %s uint32 form, string data (%s), "
122 "bad conv", key,
123 CFStringGetCStringPtr((CFStringRef)cfValue,
124 CFStringGetSystemEncoding()));
125 return false;
126 }
127 return true;
128 } /* stored as string */
129 else if(valueType == CFNumberGetTypeID()) {
130 /* be paranoid - there is no unsigned type for CFNumber */
131 CFNumberRef cfNum = (CFNumberRef)cfValue;
132 CFNumberType numType = CFNumberGetType(cfNum);
133 switch(numType) {
134 case kCFNumberSInt8Type:
135 case kCFNumberSInt16Type:
136 case kCFNumberSInt32Type:
137 case kCFNumberCharType:
138 case kCFNumberShortType:
139 case kCFNumberIntType:
140 case kCFNumberLongType:
141 case kCFNumberSInt64Type: // apparently the default
142 /* OK */
143 break;
144 default:
145 MPDebug("MDS cfTypeToInt: Bad CFNumber type (%d) key %s", numType, key);
146 return false;
147 }
148 Boolean brtn = CFNumberGetValue(cfNum, kCFNumberLongType, &iValue);
149 if(!brtn) {
150 MPDebug("MDS cfTypeToInt: Bad CFNumber conversion");
151 return false;
152 }
153 return true;
154 } /* stored as number */
155 else if(valueType == CFBooleanGetTypeID()) {
156 Boolean b = CFBooleanGetValue((CFBooleanRef)cfValue);
157 iValue = b ? 1 : 0;
158 return true;
159 }
160 else {
161 MPDebug("MDS cfTypeToInt: key %s, uint32 form, bad CF type (%d)",
162 key, (int)valueType);
163 return false;
164 }
165 }
166
167 /*
168 * Insert a record, defined by a CSSM_DB_ATTRIBUTE_DATA array, into specified
169 * DL and DB. Returns true on success.
170 */
171 bool MDSInsertRecord(
172 const CSSM_DB_ATTRIBUTE_DATA *inAttr,
173 unsigned numAttrs,
174 CSSM_DB_RECORDTYPE recordType,
175 MDSSession &dl,
176 CSSM_DB_HANDLE dbHand)
177 {
178 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrData;
179 CSSM_DB_UNIQUE_RECORD_PTR uid = NULL;
180 bool ourRtn = true;
181
182 recordAttrData.DataRecordType = recordType;
183 recordAttrData.SemanticInformation = 0;
184 recordAttrData.NumberOfAttributes = numAttrs;
185 recordAttrData.AttributeData =
186 const_cast<CSSM_DB_ATTRIBUTE_DATA_PTR>(inAttr);
187
188 try {
189 dl.DataInsert(dbHand,
190 recordType,
191 &recordAttrData,
192 NULL,
193 uid);
194 }
195 catch (const CssmError &cerr) {
196 MPDebug("MDSInsertRecord: DataInsert: %s",
197 cssmErrorString(cerr).c_str());
198 ourRtn = false;
199 }
200 catch(...) {
201 MPDebug("MDSInsertRecord: DataInsert: unknown exception");
202 ourRtn = false;
203 }
204 if(uid != NULL) {
205 dl.FreeUniqueRecord(dbHand, *uid);
206 }
207 return ourRtn;
208 }
209
210 /*
211 * Convert a number expressed as a CFString to a uint32 using the specified
212 * name/value conversion table. The string may have multiple fields from that
213 * table, ORd together in normal C syntax. Like
214 *
215 * CSSM_SERVICE_CSP | CSSM_SERVICE_DL
216 *
217 * Individual tokens can also be expressed numerically, either in decimal or
218 * (if prefaced by "0x" hex. Numeric tokens and symbolic string tokens can
219 * be intermixed in the same incoming string.
220 *
221 * Individual tokens can be prefixed with "<<" indicating that the indicated
222 * value is to be shifted 16 bits. Cf. CL Primary Relation, {Cert,Crl}TypeFormat.
223 * This applies to both numeric and string tokens.
224 */
225 CSSM_RETURN MDSStringToUint32(
226 CFStringRef str,
227 const MDSNameValuePair *table, // optional, string must be decimal
228 uint32 &value)
229 {
230 char *cstr = MDSCFStringToCString(str);
231 if(cstr == NULL) {
232 /* should "never" happen...right? */
233 MPDebug("MDSStringToUint32: CFString conversion error");
234 return CSSMERR_CSSM_MDS_ERROR;
235 }
236
237 char tokenStr[200];
238 char *src = cstr;
239 char *dst = tokenStr;
240 char c;
241 CSSM_RETURN crtn = CSSM_OK;
242
243 value = 0;
244 while(*src != '\0') {
245 /* Get one token from src --> tokenStr[] */
246 /* First skip whitespace and '|' */
247 for( ; *src != '\0'; src++) {
248 c = *src;
249 if(!isspace(c) && (c != '|')) {
250 /* first char of token */
251 *dst++ = c;
252 src++;
253 break;
254 }
255 }
256 if((*src == '\0') && (dst == tokenStr)) {
257 /* done */
258 break;
259 }
260
261 /* dst[-1] is the first good character of token; copy until
262 * space or '|' */
263 for( ; *src != '\0'; src++) {
264 c = *src;
265 if(isspace(c) || (c == '|')) {
266 break;
267 }
268 else {
269 *dst++ = c;
270 }
271 }
272
273 /* NULL terminate token string, convert to numeric value */
274 *dst = '\0';
275 uint32 tokenVal = 0;
276 CSSM_RETURN crtn = MDSAttrNameToValue(tokenStr, table, tokenVal);
277 if(crtn) {
278 /* punt */
279 break;
280 }
281 value |= tokenVal;
282
283 /* restart */
284 dst = tokenStr;
285 }
286 delete [] cstr;
287 return crtn;
288 }
289
290 } // end namespace Security