#include "dictionary.h"
#include <ctype.h>
#include <syslog.h>
namespace Security {
static uint32_t GetUInt32(unsigned char*& finger)
{
uint32 result = 0;
unsigned i;
for (i = 0; i < sizeof(uint32); ++i)
{
result = (result << 8) | *finger++;
}
return result;
}
CssmData NameValuePair::CloneData (const CssmData &value)
{
void* clonedData = (void*) new unsigned char [value.length ()];
if (clonedData != NULL)
{
memcpy (clonedData, value.data (), value.length ());
return CssmData (clonedData, value.length ());
}
else
{
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
}
}
NameValuePair::NameValuePair (uint32 name, const CssmData &value) : mName (name), mValue (CloneData (value))
{
}
NameValuePair::NameValuePair (const CssmData &data)
{
unsigned char* finger = (unsigned char*) data.data ();
mName = GetUInt32(finger);
uint32 length = GetUInt32(finger);
mValue = CloneData (CssmData (finger, length));
}
NameValuePair::~NameValuePair ()
{
delete (unsigned char*) mValue.data ();
}
void NameValuePair::Export (CssmData &data) const
{
uint32 outSize = 2 * sizeof (uint32) + mValue.length ();
unsigned char* d = (unsigned char*) malloc(outSize);
unsigned char* finger = d;
uint32 intBuffer = mName;
int i;
for (i = sizeof (uint32) - 1; i >= 0; --i)
{
finger[i] = intBuffer & 0xFF;
intBuffer >>= 8;
}
finger += sizeof (uint32);
intBuffer = mValue.length ();
for (i = sizeof (uint32) - 1; i >= 0; --i)
{
finger[i] = intBuffer & 0xFF;
intBuffer >>= 8;
}
finger += sizeof (uint32);
memcpy (finger, mValue.data (), mValue.length ());
data = CssmData (d, outSize);
}
NameValueDictionary::NameValueDictionary ()
{
}
NameValueDictionary::~NameValueDictionary ()
{
int i = mVector.size ();
while (i > 0)
{
delete mVector[--i];
mVector.erase (mVector.begin () + i);
}
}
void NameValueDictionary::MakeFromData(const CssmData &data)
{
unsigned char* finger = (unsigned char*) data.data ();
unsigned char* target = finger + data.length ();
bool done = false;
do
{
unsigned int i;
uint32 length = 0;
for (i = sizeof (uint32); i < 2 * sizeof (uint32); ++i)
{
length = (length << 8) | finger[i];
}
if (length > data.length())
{
break;
}
length += 2 * sizeof (uint32);
uint32 itemLength = 0;
unsigned char* fingerX = finger;
char nameBuff[5];
char* nameFinger = nameBuff;
if (fingerX + sizeof(uint32) < target)
{
*nameFinger++ = (char) *fingerX++;
*nameFinger++ = (char) *fingerX++;
*nameFinger++ = (char) *fingerX++;
*nameFinger++ = (char) *fingerX++;
*nameFinger++ = 0;
itemLength = GetUInt32(fingerX);
if (fingerX + itemLength > target) {
done = true;
}
}
Insert (new NameValuePair (CssmData (finger, length)));
finger += length;
} while (!done && finger < target);
}
NameValueDictionary::NameValueDictionary (const CssmData &data)
{
MakeFromData(data);
}
void NameValueDictionary::Insert (NameValuePair* pair)
{
mVector.push_back (pair);
}
void NameValueDictionary::RemoveByName (uint32 name)
{
int which = FindPositionByName (name);
if (which != -1)
{
NameValuePair* nvp = mVector[which];
mVector.erase (mVector.begin () + which);
delete nvp;
}
}
int NameValueDictionary::FindPositionByName (uint32 name) const
{
int target = CountElements ();
int i;
for (i = 0; i < target; ++i)
{
if (mVector[i]->Name () == name)
{
return i;
}
}
return -1;
}
const NameValuePair* NameValueDictionary::FindByName (uint32 name) const
{
int which = FindPositionByName (name);
return which == -1 ? NULL : mVector[which];
}
int NameValueDictionary::CountElements () const
{
return mVector.size ();
}
const NameValuePair* NameValueDictionary::GetElement (int which)
{
return mVector[which];
}
void NameValueDictionary::Export (CssmData &outData)
{
int i;
uint32 length = 0;
unsigned char* data = 0;
for (i = 0; i < CountElements (); ++i)
{
CssmData exportedData;
const NameValuePair *nvp = GetElement (i);
nvp->Export (exportedData);
uint32 oldLength = length;
length += exportedData.length ();
data = (unsigned char*) realloc (data, length);
memcpy (data + oldLength, exportedData.data (), exportedData.length ());
free(exportedData.data());
}
outData = CssmData (data, length);
}
void NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier (const DLDbIdentifier &identifier, NameValueDictionary &nvd)
{
DLDbIdentifier d = identifier;
const CssmSubserviceUid &ssuid = identifier.ssuid ();
CSSM_SUBSERVICE_UID baseID = ssuid;
baseID.Version.Major = h2n (baseID.Version.Major);
baseID.Version.Minor = h2n (baseID.Version.Minor);
baseID.SubserviceId = h2n (baseID.SubserviceId);
baseID.SubserviceType = h2n (baseID.SubserviceType);
nvd.Insert (new NameValuePair (SSUID_KEY, CssmData::wrap(baseID)));
const char* dbName = identifier.dbName ();
if (dbName != NULL)
{
nvd.Insert (new NameValuePair (DB_NAME, CssmData::wrap (dbName, strlen (dbName) + 1)));
}
const CSSM_NET_ADDRESS* add = identifier.dbLocation ();
if (add != NULL)
{
nvd.Insert (new NameValuePair (DB_LOCATION, CssmData::wrap (add)));
}
}
DLDbIdentifier NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (const NameValueDictionary &nvd)
{
const NameValuePair *nvpSSUID = nvd.FindByName (SSUID_KEY);
if (nvpSSUID == NULL)
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
CSSM_SUBSERVICE_UID* uid = (CSSM_SUBSERVICE_UID*) nvpSSUID->Value ().data ();
if (uid == NULL)
{
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
}
CSSM_SUBSERVICE_UID baseID = *uid;
baseID.Version.Major = n2h (baseID.Version.Major);
baseID.Version.Minor = n2h (baseID.Version.Minor);
baseID.SubserviceId = n2h (baseID.SubserviceId);
baseID.SubserviceType = n2h (baseID.SubserviceType);
const NameValuePair *nvpDBNAME = nvd.FindByName (DB_NAME);
char* name = nvpDBNAME ? (char*) nvpDBNAME->Value ().data () : NULL;
const NameValuePair* nvp = nvd.FindByName (DB_LOCATION);
CSSM_NET_ADDRESS* address = nvp ? (CSSM_NET_ADDRESS*) nvp->Value ().data () : NULL;
return DLDbIdentifier (baseID, name, address);
}
};