DSX509Relation.cpp [plain text]
#include <string.h>
#include "CommonCode.h"
#include "DSX509Relation.h"
#include <security_utilities/debugging.h>
#include "CommonCrypto/CommonDigest.h"
DSX509Tuple::DSX509Tuple (int numberOfValues) : mNumberOfValues (numberOfValues), mValues (NULL), mData (NULL)
{
mValues = new Value*[numberOfValues];
for (int i = 0; i < numberOfValues; ++i)
mValues[i] = NULL;
}
DSX509Tuple::~DSX509Tuple ()
{
for (int i = 0; i < mNumberOfValues; ++i)
if (mValues[i] != NULL) delete mValues[i];
delete [] mValues;
if (mData != NULL) delete mData;
}
void DSX509Tuple::SetValue (int i, Value* v)
{
mValues[i] = v;
}
Value* DSX509Tuple::GetValue (int i)
{
return mValues[i];
}
int DSX509Tuple::GetNumberOfValues ()
{
return mNumberOfValues;
}
void DSX509Tuple::GetData (CSSM_DATA &data)
{
size_t t;
const uint8* d = mData->GetRawValue (t);
data.Data = (uint8*) d;
data.Length = t;
}
void DSX509Tuple::SetData (BlobValue *value)
{
mData = value;
}
DSX509UniqueIdentifier::DSX509UniqueIdentifier (DSX509Tuple *t) :
UniqueIdentifier (CSSM_DL_DB_RECORD_X509_CERTIFICATE), mTuple (t)
{
}
DSX509UniqueIdentifier::~DSX509UniqueIdentifier ()
{
delete mTuple;
}
void DSX509UniqueIdentifier::Export (CSSM_DB_UNIQUE_RECORD &record)
{
memset (&record, 0, sizeof (CSSM_DB_UNIQUE_RECORD));
}
DSX509Tuple* DSX509UniqueIdentifier::GetTuple ()
{
return mTuple;
}
static void * appMalloc (CSSM_SIZE size, void *allocRef) {
return (malloc (size));
}
static void appFree (void *mem_ptr, void *allocRef) {
free (mem_ptr);
return;
}
static void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
return (realloc (ptr, size));
}
static void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
return (calloc (num, size));
}
static CSSM_API_MEMORY_FUNCS memFuncs = {
appMalloc,
appFree,
appRealloc,
appCalloc,
NULL
};
static void CheckResult (CSSM_RETURN result)
{
if (result != 0) throw CSSMError (result);
}
void DSX509Relation::InitializeCertLibrary ()
{
if (mCertificateLibrary != 0) return;
const CSSM_GUID* attachGuid = &gGuidAppleX509CL;
CSSM_VERSION version = {2, 0};
CSSM_RETURN result = CSSM_ModuleLoad (attachGuid, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
CheckResult (result);
result = CSSM_ModuleAttach (attachGuid, &version, &memFuncs, 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &mCertificateLibrary);
CheckResult (result);
}
DSX509Relation::DSX509Relation (CSSM_DB_RECORDTYPE recordType, int numberOfColumns, columnInfoLoader *theColumnInfo) : PartialRelation (CSSM_DL_DB_RECORD_X509_CERTIFICATE, kNumberOfX509Attributes,theColumnInfo), mCertificateLibrary (0)
{
mDirectoryService = new DirectoryService();
}
DSX509Relation::~DSX509Relation ()
{
if (mCertificateLibrary != 0)
CSSM_ModuleDetach (mCertificateLibrary);
}
Query* DSX509Relation::MakeQuery (const CSSM_QUERY* query)
{
return new DSX509Query (this, query);
}
Tuple* DSX509Relation::GetTupleFromUniqueIdentifier (UniqueIdentifier* uniqueID)
{
DSX509UniqueIdentifier *id = (DSX509UniqueIdentifier*) uniqueID;
return id->GetTuple ();
}
UniqueIdentifier* DSX509Relation::ImportUniqueIdentifier (CSSM_DB_UNIQUE_RECORD *uniqueRecord)
{
throw CSSMERR_DL_UNSUPPORTED_QUERY;
}
CSSM_CL_HANDLE DSX509Relation::GetCLHandle ()
{
InitializeCertLibrary ();
return mCertificateLibrary;
}
DSX509Query::DSX509Query (DSX509Relation* relation, const CSSM_QUERY *queryBase) :
Query (relation, queryBase), mRecordCount (0), mCurrentItem (1),
mRecordList (NULL), mNumberOfTuples (0), mNextTuple (0)
{
CSSM_RETURN error;
mRecordList = relation->mDirectoryService->translate_cssm_query_to_OD_query(queryBase, &error);
if(!mRecordList) throw CSSMERR_DL_ENDOFDATA;
}
DSX509Query::~DSX509Query ()
{
}
static bool CompareOIDs (const CSSM_OID &a, const CSSM_OID &b)
{
if (a.Length != b.Length) return false;
return memcmp (a.Data, b.Data, a.Length) == 0;
}
static CSSM_DATA GetValueFromFields (CSSM_FIELD *fields, uint32 numFields, const CSSM_OID& oid)
{
uint32 i;
for (i = 0; i < numFields; ++i)
if (CompareOIDs (fields[i].FieldOid, oid)) return fields[i].FieldValue;
throw CSSMERR_CSSM_INVALID_ATTRIBUTE;
}
static CSSM_DATA* GetAttributeFromX509Name (CSSM_X509_NAME *name, const CSSM_OID& oid)
{
uint32 i;
for (i = 0; i < name->numberOfRDNs; ++i) {
CSSM_X509_RDN &rdn = name->RelativeDistinguishedName[i];
uint32 j;
for (j = 0; j < rdn.numberOfPairs; ++j) {
CSSM_X509_TYPE_VALUE_PAIR &pair = rdn.AttributeTypeAndValue[j];
if (CompareOIDs (pair.type, oid))
return &pair.value;
}
}
return NULL;
}
Tuple* DSX509Query::GetNextTuple (UniqueIdentifier *&id)
{
DSX509Tuple* t;
CFStringRef original_search;
original_search = this->mRecordList->searchString;
CFDataRef certData = this->mDirectoryService->getNextCertFromResults(this->mRecordList);
if(!certData) return NULL;
DSX509Record record ((DSX509Relation*) mRelation);
t = record.GetTuple (certData, original_search, mTupleList, kMaxTuples);
mNextTuple++;
if (EvaluateTuple (t)) {
id = new DSX509UniqueIdentifier (t);
return t;
}
return NULL;
}
DSX509Tuple* DSX509Record::GetTuple (CFDataRef certData, CFStringRef original_search, DSX509Tuple *tupleList[], int maxTuples)
{
DSX509Tuple** tupleFinger = tupleList;
CSSM_CL_HANDLE clHandle = mRelation->GetCLHandle ();
CSSM_DATA cert;
cert.Data = (uint8 *) CFDataGetBytePtr(certData);
cert.Length = CFDataGetLength(certData);
CSSM_FIELD *fields;
uint32 numberOfFields;
CSSM_RETURN result = CSSM_CL_CertGetAllFields (clHandle, &cert, &numberOfFields, &fields);
CheckResult (result);
CSSM_DATA data;
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1Version);
DSX509Tuple* t = new DSX509Tuple (kNumberOfX509Attributes);
t->SetValue (kCertTypeID, new UInt32Value (*(uint32*) data.Data));
t->SetValue (kCertEncodingID, new UInt32Value (CSSM_CERT_ENCODING_DER));
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1SubjectNameCStruct);
CSSM_X509_NAME* namePtr = (CSSM_X509_NAME*) data.Data;
CSSM_DATA *dp;
dp = GetAttributeFromX509Name (namePtr, CSSMOID_CommonName);
t->SetValue (kCertPrintName, dp == NULL ? new BlobValue (original_search) : new BlobValue (*dp));
t->SetValue (kCertAlias, new BlobValue (original_search));
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1SubjectName);
t->SetValue (kCertSubject, new BlobValue (data));
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1IssuerName);
t->SetValue (kCertIssuer, new BlobValue (data));
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1SerialNumber);
t->SetValue (kCertSerialNumber, new BlobValue (data));
t->SetValue (kCertSubjectKeyIdentifier, NULL);
data = GetValueFromFields (fields, numberOfFields, CSSMOID_X509V1SubjectPublicKeyCStruct);
CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *publicKeyInfo = (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *) data.Data;
CC_SHA1_CTX context;
CC_SHA1_Init (&context);
CC_SHA1_Update (&context, publicKeyInfo->subjectPublicKey.Data, publicKeyInfo->subjectPublicKey.Length);
uint8 sha1Digest [20];
CC_SHA1_Final (sha1Digest, &context);
t->SetValue (kCertPublicKeyHash, new BlobValue (sha1Digest, 20));
CSSM_CL_FreeFields (clHandle, numberOfFields, &fields);
t->SetData (new BlobValue (cert));
*tupleFinger++ = t;
--maxTuples;
return t;
}