]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurityd/lib/dictionary.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurityd / lib / dictionary.cpp
1 /*
2 * Copyright (c) 2003-2006,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include "dictionary.h"
26 #include <ctype.h>
27 #include <syslog.h>
28
29 namespace Security {
30
31 static uint32_t GetUInt32(unsigned char*& finger)
32 {
33 uint32 result = 0;
34 unsigned i;
35
36 for (i = 0; i < sizeof(uint32); ++i)
37 {
38 result = (result << 8) | *finger++;
39 }
40
41 return result;
42 }
43
44
45
46 CssmData NameValuePair::CloneData (const CssmData &value)
47 {
48 void* clonedData = (void*) new unsigned char [value.length ()];
49 if (clonedData != NULL)
50 {
51 memcpy (clonedData, value.data (), value.length ());
52 return CssmData (clonedData, value.length ());
53 }
54 else
55 {
56 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
57 }
58 }
59
60
61
62 NameValuePair::NameValuePair (uint32 name, const CssmData &value) : mName (name), mValue (CloneData (value))
63 {
64 }
65
66
67
68 NameValuePair::NameValuePair (const CssmData &data)
69 {
70 // the first four bytes are the name
71 unsigned char* finger = (unsigned char*) data.data ();
72 mName = GetUInt32(finger);
73 uint32 length = GetUInt32(finger);
74
75 // what's left is the data
76 mValue = CloneData (CssmData (finger, length));
77 }
78
79
80
81 NameValuePair::~NameValuePair ()
82 {
83 delete (unsigned char*) mValue.data ();
84 }
85
86
87
88 void NameValuePair::Export (CssmData &data) const
89 {
90 // export the data in the format name length data
91 size_t outSize = 2 * sizeof (uint32) + mValue.length ();
92 unsigned char* d = (unsigned char*) malloc(outSize);
93 unsigned char* finger = d;
94
95 // export the name
96 uint32 intBuffer = mName;
97
98 int i;
99 for (i = sizeof (uint32) - 1; i >= 0; --i)
100 {
101 finger[i] = intBuffer & 0xFF;
102 intBuffer >>= 8;
103 }
104
105 // export the length
106 finger += sizeof (uint32);
107 intBuffer = (uint32)mValue.length ();
108 for (i = sizeof (uint32) - 1; i >= 0; --i)
109 {
110 finger[i] = intBuffer & 0xFF;
111 intBuffer >>= 8;
112 }
113
114 // export the data
115 finger += sizeof (uint32);
116 memcpy (finger, mValue.data (), mValue.length ());
117
118 data = CssmData (d, outSize);
119 }
120
121
122
123 NameValueDictionary::NameValueDictionary ()
124 {
125 }
126
127
128
129 NameValueDictionary::~NameValueDictionary ()
130 {
131 // to prevent leaks, delete all members of the vector
132 size_t i = mVector.size ();
133 while (i > 0)
134 {
135 delete mVector[--i];
136
137 mVector.erase (mVector.begin () + i);
138 }
139 }
140
141
142
143 // To work around 5964438, move code out of the constructor
144 void NameValueDictionary::MakeFromData(const CssmData &data)
145 {
146 // reconstruct a name value dictionary from a series of exported NameValuePair blobs
147 unsigned char* finger = (unsigned char*) data.data ();
148 unsigned char* target = finger + data.length ();
149
150 bool done = false;
151
152 do
153 {
154 // compute the length of data blob
155 unsigned int i;
156 uint32 length = 0;
157 for (i = sizeof (uint32); i < 2 * sizeof (uint32); ++i)
158 {
159 length = (length << 8) | finger[i];
160 }
161
162 if (length > data.length())
163 {
164 break;
165 }
166
167 // add the length of the "header"
168 length += 2 * sizeof (uint32);
169
170 // do some sanity checking on the data.
171 uint32 itemLength = 0;
172 unsigned char* fingerX = finger;
173
174 // extract the name in a printable format
175 char nameBuff[5];
176 char* nameFinger = nameBuff;
177
178 // work around a bug with invalid lengths coming from securityd
179 if (fingerX + sizeof(uint32) < target)
180 {
181 *nameFinger++ = (char) *fingerX++;
182 *nameFinger++ = (char) *fingerX++;
183 *nameFinger++ = (char) *fingerX++;
184 *nameFinger++ = (char) *fingerX++;
185 *nameFinger++ = 0;
186
187 itemLength = GetUInt32(fingerX);
188
189 if (fingerX + itemLength > target) // this is the bug
190 {
191 done = true;
192 }
193 }
194
195 // This shouldn't crash any more...
196 Insert (new NameValuePair (CssmData (finger, length)));
197
198 // skip to the next data
199 finger += length;
200 } while (!done && finger < target);
201 }
202
203
204
205 NameValueDictionary::NameValueDictionary (const CssmData &data)
206 {
207 MakeFromData(data);
208 }
209
210
211
212 void NameValueDictionary::Insert (NameValuePair* pair)
213 {
214 mVector.push_back (pair);
215 }
216
217
218
219 void NameValueDictionary::RemoveByName (uint32 name)
220 {
221 int which = FindPositionByName (name);
222 if (which != -1)
223 {
224 NameValuePair* nvp = mVector[which];
225 mVector.erase (mVector.begin () + which);
226 delete nvp;
227 }
228 }
229
230
231
232 int NameValueDictionary::FindPositionByName (uint32 name) const
233 {
234 int target = CountElements ();
235 int i;
236
237 for (i = 0; i < target; ++i)
238 {
239 if (mVector[i]->Name () == name)
240 {
241 return i;
242 }
243 }
244
245 return -1;
246 }
247
248
249
250 const NameValuePair* NameValueDictionary::FindByName (uint32 name) const
251 {
252 int which = FindPositionByName (name);
253 return which == -1 ? NULL : mVector[which];
254 }
255
256
257
258
259 int NameValueDictionary::CountElements () const
260 {
261 return (int)mVector.size ();
262 }
263
264
265
266 const NameValuePair* NameValueDictionary::GetElement (int which)
267 {
268 return mVector[which];
269 }
270
271
272
273 void NameValueDictionary::Export (CssmData &outData)
274 {
275 // get each element in the dictionary, and add it to the data blob
276 int i;
277 uint32 length = 0;
278 unsigned char* data = 0;
279
280 for (i = 0; i < CountElements (); ++i)
281 {
282 CssmData exportedData;
283 const NameValuePair *nvp = GetElement (i);
284 nvp->Export (exportedData);
285
286 uint32 oldLength = length;
287 length += exportedData.length ();
288 data = (unsigned char*) realloc (data, length);
289
290 memcpy (data + oldLength, exportedData.data (), exportedData.length ());
291
292 free(exportedData.data());
293 }
294
295 outData = CssmData (data, length);
296 }
297
298
299
300 void NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier (const DLDbIdentifier &identifier, NameValueDictionary &nvd)
301 {
302 // get the subserviceID
303 DLDbIdentifier d = identifier;
304
305 const CssmSubserviceUid &ssuid = identifier.ssuid ();
306 CSSM_SUBSERVICE_UID baseID = ssuid;
307 baseID.Version.Major = h2n (baseID.Version.Major);
308 baseID.Version.Minor = h2n (baseID.Version.Minor);
309 baseID.SubserviceId = h2n (baseID.SubserviceId);
310 baseID.SubserviceType = h2n (baseID.SubserviceType);
311
312 nvd.Insert (new NameValuePair (SSUID_KEY, CssmData::wrap(baseID)));
313
314 // get the name
315 const char* dbName = identifier.dbName ();
316 if (dbName != NULL)
317 {
318 nvd.Insert (new NameValuePair (DB_NAME, CssmData::wrap (dbName, strlen (dbName) + 1)));
319 }
320
321 // get the net address
322 const CSSM_NET_ADDRESS* add = identifier.dbLocation ();
323 if (add != NULL)
324 {
325 nvd.Insert (new NameValuePair (DB_LOCATION, CssmData::wrap (add)));
326 }
327 }
328
329
330
331 DLDbIdentifier NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (const NameValueDictionary &nvd)
332 {
333 /*
334 According to the code in MakeNameValueDictionaryFromDLDbIdentifier, SSUID_KEY
335 is required, but both DB_NAME and DB_LOCATION are allowed to be missing. In
336 all of these cases, it is possible that FindByName returns NULL.
337 */
338
339 const NameValuePair *nvpSSUID = nvd.FindByName (SSUID_KEY);
340 if (nvpSSUID == NULL)
341 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
342
343 CSSM_SUBSERVICE_UID* uid = (CSSM_SUBSERVICE_UID*) nvpSSUID->Value ().data ();
344 if (uid == NULL)
345 {
346 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
347 }
348
349 CSSM_SUBSERVICE_UID baseID = *uid;
350
351 baseID.Version.Major = n2h (baseID.Version.Major);
352 baseID.Version.Minor = n2h (baseID.Version.Minor);
353 baseID.SubserviceId = n2h (baseID.SubserviceId);
354 baseID.SubserviceType = n2h (baseID.SubserviceType);
355
356 const NameValuePair *nvpDBNAME = nvd.FindByName (DB_NAME);
357 char* name = nvpDBNAME ? (char*) nvpDBNAME->Value ().data () : NULL;
358
359 const NameValuePair* nvp = nvd.FindByName (DB_LOCATION);
360 CSSM_NET_ADDRESS* address = nvp ? (CSSM_NET_ADDRESS*) nvp->Value ().data () : NULL;
361
362 return DLDbIdentifier (baseID, name, address);
363 }
364
365 }; // end Security namespace