#include "CertParser.h"
#import <AvailabilityMacros.h>
#define CP_DEBUG 1
#if CP_DEBUG
#define dprintf(args...) printf(args)
#else
#define dprintf(args...)
#endif
#pragma mark --- CP_FetchedField ---
class CP_FetchedField
{
public:
CP_FetchedField(
const CSSM_OID &fieldOid,
CSSM_DATA_PTR fieldData,
CSSM_CL_HANDLE clHand);
~CP_FetchedField();
private:
CSSM_OID mFieldOid;
CSSM_DATA_PTR mFieldData;
CSSM_CL_HANDLE mClHand;
};
CP_FetchedField::CP_FetchedField(
const CSSM_OID &fieldOid,
CSSM_DATA_PTR fieldData,
CSSM_CL_HANDLE clHand)
: mFieldOid(fieldOid), mFieldData(fieldData), mClHand(clHand)
{
}
CP_FetchedField::~CP_FetchedField()
{
CSSM_CL_FreeFieldValue(mClHand, &mFieldOid, mFieldData);
}
#pragma mark --- CertParser implementation ---
CertParser::CertParser()
{
initFields();
}
CertParser::CertParser(
CSSM_CL_HANDLE clHand)
{
initFields();
mClHand = clHand;
}
CertParser::CertParser(
CSSM_CL_HANDLE clHand,
const CSSM_DATA &certData)
{
initFields();
mClHand = clHand;
CSSM_RETURN crtn = initWithData(certData);
if(crtn) {
throw ((int)crtn);
}
}
CertParser::CertParser(
SecCertificateRef secCert)
{
initFields();
OSStatus ortn = initWithSecCert(secCert);
if(ortn) {
throw ((int)ortn);
}
}
CertParser::~CertParser()
{
if(mClHand && mCacheHand) {
CSSM_RETURN crtn = CSSM_CL_CertAbortCache(mClHand, mCacheHand);
if(crtn) {
printf("Internal Error: CertParser error on free.");
cssmPerror("CSSM_CL_CertAbortCache", crtn);
}
}
vector<CP_FetchedField *>::iterator iter;
for(iter=mFetchedFields.begin(); iter!=mFetchedFields.end(); iter++) {
delete *iter;
}
}
void CertParser::initFields()
{
mClHand = 0;
mCacheHand = 0;
}
CSSM_RETURN CertParser::initWithData(
const CSSM_DATA &certData)
{
assert(mClHand != 0);
CSSM_RETURN crtn = CSSM_CL_CertCache(mClHand, &certData, &mCacheHand);
#if CP_DEBUG
if(crtn) {
cssmPerror("CSSM_CL_CertCache", crtn);
}
#endif
return crtn;
}
OSStatus CertParser::initWithSecCert(
SecCertificateRef secCert)
{
OSStatus ortn;
CSSM_DATA certData;
assert(mClHand == 0);
ortn = SecCertificateGetCLHandle(secCert, &mClHand);
if(ortn) {
return ortn;
}
ortn = SecCertificateGetData(secCert, &certData);
if(ortn) {
return ortn;
}
return (OSStatus)initWithData(certData);
}
CSSM_RETURN CertParser::initWithCFData(
CFDataRef cfData)
{
CSSM_DATA cdata;
cdata.Data = (uint8 *)CFDataGetBytePtr(cfData);
cdata.Length = CFDataGetLength(cfData);
return initWithData(cdata);
}
const void *CertParser::fieldForOid(
const CSSM_OID &oid,
CSSM_SIZE &fieldLength) {
CSSM_RETURN crtn;
uint32 NumberOfFields = 0;
CSSM_HANDLE resultHand = 0;
CSSM_DATA_PTR fieldData = NULL;
assert(mClHand != 0);
assert(mCacheHand != 0);
crtn = CSSM_CL_CertGetFirstCachedFieldValue(
mClHand,
mCacheHand,
&oid,
&resultHand,
&NumberOfFields,
&fieldData);
if(crtn) {
return NULL;
}
assert(NumberOfFields == 1);
CSSM_CL_CertAbortQuery(mClHand, resultHand);
if(fieldLength) {
if(fieldLength != fieldData->Length) {
printf("***CertParser::fieldForOid: field length mismatch\n");
return NULL;
}
}
CP_FetchedField *cpField = new CP_FetchedField(oid, fieldData, mClHand);
mFetchedFields.push_back(cpField);
fieldLength = fieldData->Length;
return fieldData->Data;
}
const void *CertParser::extensionForOid(
const CSSM_OID &oid)
{
CSSM_SIZE len = sizeof(CSSM_X509_EXTENSION);
CSSM_X509_EXTENSION *cssmExt =
(CSSM_X509_EXTENSION *)fieldForOid(oid, len);
if(cssmExt) {
if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) {
printf("***Badly formatted extension");
return NULL;
}
return cssmExt->value.parsedValue;
}
else {
return NULL;
}
}