2 * Copyright (c) 2003-2006,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "dictionary.h"
31 static uint32_t GetUInt32(unsigned char*& finger
)
36 for (i
= 0; i
< sizeof(uint32
); ++i
)
38 result
= (result
<< 8) | *finger
++;
46 CssmData
NameValuePair::CloneData (const CssmData
&value
)
48 void* clonedData
= (void*) new unsigned char [value
.length ()];
49 if (clonedData
!= NULL
)
51 memcpy (clonedData
, value
.data (), value
.length ());
52 return CssmData (clonedData
, value
.length ());
56 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
62 NameValuePair::NameValuePair (uint32 name
, const CssmData
&value
) : mName (name
), mValue (CloneData (value
))
68 NameValuePair::NameValuePair (const CssmData
&data
)
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
);
75 // what's left is the data
76 mValue
= CloneData (CssmData (finger
, length
));
81 NameValuePair::~NameValuePair ()
83 delete (unsigned char*) mValue
.data ();
88 void NameValuePair::Export (CssmData
&data
) const
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
;
96 uint32 intBuffer
= mName
;
99 for (i
= sizeof (uint32
) - 1; i
>= 0; --i
)
101 finger
[i
] = intBuffer
& 0xFF;
106 finger
+= sizeof (uint32
);
107 intBuffer
= (uint32
)mValue
.length ();
108 for (i
= sizeof (uint32
) - 1; i
>= 0; --i
)
110 finger
[i
] = intBuffer
& 0xFF;
115 finger
+= sizeof (uint32
);
116 memcpy (finger
, mValue
.data (), mValue
.length ());
118 data
= CssmData (d
, outSize
);
123 NameValueDictionary::NameValueDictionary ()
129 NameValueDictionary::~NameValueDictionary ()
131 // to prevent leaks, delete all members of the vector
132 size_t i
= mVector
.size ();
137 mVector
.erase (mVector
.begin () + i
);
143 // To work around 5964438, move code out of the constructor
144 void NameValueDictionary::MakeFromData(const CssmData
&data
)
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 ();
154 // compute the length of data blob
157 for (i
= sizeof (uint32
); i
< 2 * sizeof (uint32
); ++i
)
159 length
= (length
<< 8) | finger
[i
];
162 if (length
> data
.length())
167 // add the length of the "header"
168 length
+= 2 * sizeof (uint32
);
170 // do some sanity checking on the data.
171 uint32 itemLength
= 0;
172 unsigned char* fingerX
= finger
;
174 // extract the name in a printable format
176 char* nameFinger
= nameBuff
;
178 // work around a bug with invalid lengths coming from securityd
179 if (fingerX
+ sizeof(uint32
) < target
)
181 *nameFinger
++ = (char) *fingerX
++;
182 *nameFinger
++ = (char) *fingerX
++;
183 *nameFinger
++ = (char) *fingerX
++;
184 *nameFinger
++ = (char) *fingerX
++;
187 itemLength
= GetUInt32(fingerX
);
189 if (fingerX
+ itemLength
> target
) // this is the bug
195 // This shouldn't crash any more...
196 Insert (new NameValuePair (CssmData (finger
, length
)));
198 // skip to the next data
200 } while (!done
&& finger
< target
);
205 NameValueDictionary::NameValueDictionary (const CssmData
&data
)
212 void NameValueDictionary::Insert (NameValuePair
* pair
)
214 mVector
.push_back (pair
);
219 void NameValueDictionary::RemoveByName (uint32 name
)
221 int which
= FindPositionByName (name
);
224 NameValuePair
* nvp
= mVector
[which
];
225 mVector
.erase (mVector
.begin () + which
);
232 int NameValueDictionary::FindPositionByName (uint32 name
) const
234 int target
= CountElements ();
237 for (i
= 0; i
< target
; ++i
)
239 if (mVector
[i
]->Name () == name
)
250 const NameValuePair
* NameValueDictionary::FindByName (uint32 name
) const
252 int which
= FindPositionByName (name
);
253 return which
== -1 ? NULL
: mVector
[which
];
259 int NameValueDictionary::CountElements () const
261 return (int)mVector
.size ();
266 const NameValuePair
* NameValueDictionary::GetElement (int which
)
268 return mVector
[which
];
273 void NameValueDictionary::Export (CssmData
&outData
)
275 // get each element in the dictionary, and add it to the data blob
278 unsigned char* data
= 0;
280 for (i
= 0; i
< CountElements (); ++i
)
282 CssmData exportedData
;
283 const NameValuePair
*nvp
= GetElement (i
);
284 nvp
->Export (exportedData
);
286 uint32 oldLength
= length
;
287 length
+= exportedData
.length ();
288 data
= (unsigned char*) realloc (data
, length
);
290 memcpy (data
+ oldLength
, exportedData
.data (), exportedData
.length ());
292 free(exportedData
.data());
295 outData
= CssmData (data
, length
);
300 void NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier (const DLDbIdentifier
&identifier
, NameValueDictionary
&nvd
)
302 // get the subserviceID
303 DLDbIdentifier d
= identifier
;
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
);
312 nvd
.Insert (new NameValuePair (SSUID_KEY
, CssmData::wrap(baseID
)));
315 const char* dbName
= identifier
.dbName ();
318 nvd
.Insert (new NameValuePair (DB_NAME
, CssmData::wrap (dbName
, strlen (dbName
) + 1)));
321 // get the net address
322 const CSSM_NET_ADDRESS
* add
= identifier
.dbLocation ();
325 nvd
.Insert (new NameValuePair (DB_LOCATION
, CssmData::wrap (add
)));
331 DLDbIdentifier
NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (const NameValueDictionary
&nvd
)
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.
339 const NameValuePair
*nvpSSUID
= nvd
.FindByName (SSUID_KEY
);
340 if (nvpSSUID
== NULL
)
341 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
343 CSSM_SUBSERVICE_UID
* uid
= (CSSM_SUBSERVICE_UID
*) nvpSSUID
->Value ().data ();
346 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
349 CSSM_SUBSERVICE_UID baseID
= *uid
;
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
);
356 const NameValuePair
*nvpDBNAME
= nvd
.FindByName (DB_NAME
);
357 char* name
= nvpDBNAME
? (char*) nvpDBNAME
->Value ().data () : NULL
;
359 const NameValuePair
* nvp
= nvd
.FindByName (DB_LOCATION
);
360 CSSM_NET_ADDRESS
* address
= nvp
? (CSSM_NET_ADDRESS
*) nvp
->Value ().data () : NULL
;
362 return DLDbIdentifier (baseID
, name
, address
);
365 }; // end Security namespace