+++ /dev/null
-/*
- * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please
- * obtain a copy of the License at http://www.apple.com/publicsource and
- * read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- */
-
-/*
- * CertParser.h - cert parser with autorelease of fetched fields
- *
- * Created 24 October 2003 by Doug Mitchell
- */
-
-#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:
- /* construct one fetched field (which will be stored in CertParser's
- * mFetchedFields) */
- CP_FetchedField(
- const CSSM_OID &fieldOid,
- CSSM_DATA_PTR fieldData,
- CSSM_CL_HANDLE clHand);
-
- /* Free the field via CL */
- ~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)
-{
-}
-
-/* Free the field via CL */
-CP_FetchedField::~CP_FetchedField()
-{
- CSSM_CL_FreeFieldValue(mClHand, &mFieldOid, mFieldData);
-}
-
-#pragma mark --- CertParser implementation ---
-
-/* Construct with or without data - you can add the data later with
- * initWithData() to parse without exceptions */
-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);
- }
-}
-
-/* frees all the fields we fetched */
-CertParser::~CertParser()
-{
- if(mClHand && mCacheHand) {
- CSSM_RETURN crtn = CSSM_CL_CertAbortCache(mClHand, mCacheHand);
- if(crtn) {
- /* almost certainly a bug */
- 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;
- }
-}
-
-/* common init for all constructors */
-void CertParser::initFields()
-{
- mClHand = 0;
- mCacheHand = 0;
-}
-
-/*** NO MORE EXCEPTIONS ***/
-
-/*
- * No cert- or CDSA-related exceptions thrown by remainder.
- * This is the core initializer: have the CL parse and cache the cert.
- */
-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);
-}
-
-/*
- * Obtain atrbitrary field from cached cert. This class takes care of freeing
- * the field in its destructor.
- *
- * Returns NULL if field not found (not exception).
- *
- * Caller optionally specifies field length to check - specifying zero means
- * "don't care, don't check". Actual field length always returned in fieldLength.
- */
-const void *CertParser::fieldForOid(
- const CSSM_OID &oid,
- CSSM_SIZE &fieldLength) // IN/OUT
-{
- 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) {
- /* not an error; just means that the cert doesn't have this field */
- return NULL;
- }
- assert(NumberOfFields == 1);
- CSSM_CL_CertAbortQuery(mClHand, resultHand);
-
- if(fieldLength) {
- if(fieldLength != fieldData->Length) {
- /* FIXME what's a good way to log in this situation? */
- printf("***CertParser::fieldForOid: field length mismatch\n");
- return NULL;
- }
- }
- /* Store the OID and the field for autorelease */
- CP_FetchedField *cpField = new CP_FetchedField(oid, fieldData, mClHand);
- mFetchedFields.push_back(cpField);
- fieldLength = fieldData->Length;
- return fieldData->Data;
-}
-
-/*
- * Conveneince routine to fetch an extension we "know" the CL can parse.
- * The return value gets cast to one of the CE_Data types.
- */
-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;
- }
-}
-