2 * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before using this file.
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
15 * Please see the License for the specific language governing rights and
16 * limitations under the License.
20 * CertParser.h - cert parser with autorelease of fetched fields
22 * Created 24 October 2003 by Doug Mitchell
25 #include "CertParser.h"
26 #import <AvailabilityMacros.h>
30 #define dprintf(args...) printf(args)
32 #define dprintf(args...)
35 #pragma mark --- CP_FetchedField ---
40 /* construct one fetched field (which will be stored in CertParser's
43 const CSSM_OID
&fieldOid
,
44 CSSM_DATA_PTR fieldData
,
45 CSSM_CL_HANDLE clHand
);
47 /* Free the field via CL */
51 CSSM_DATA_PTR mFieldData
;
52 CSSM_CL_HANDLE mClHand
;
55 CP_FetchedField::CP_FetchedField(
56 const CSSM_OID
&fieldOid
,
57 CSSM_DATA_PTR fieldData
,
58 CSSM_CL_HANDLE clHand
)
59 : mFieldOid(fieldOid
), mFieldData(fieldData
), mClHand(clHand
)
63 /* Free the field via CL */
64 CP_FetchedField::~CP_FetchedField()
66 CSSM_CL_FreeFieldValue(mClHand
, &mFieldOid
, mFieldData
);
69 #pragma mark --- CertParser implementation ---
71 /* Construct with or without data - you can add the data later with
72 * initWithData() to parse without exceptions */
73 CertParser::CertParser()
78 CertParser::CertParser(
79 CSSM_CL_HANDLE clHand
)
85 CertParser::CertParser(
86 CSSM_CL_HANDLE clHand
,
87 const CSSM_DATA
&certData
)
91 CSSM_RETURN crtn
= initWithData(certData
);
97 CertParser::CertParser(
98 SecCertificateRef secCert
)
101 OSStatus ortn
= initWithSecCert(secCert
);
107 /* frees all the fields we fetched */
108 CertParser::~CertParser()
110 if(mClHand
&& mCacheHand
) {
111 CSSM_RETURN crtn
= CSSM_CL_CertAbortCache(mClHand
, mCacheHand
);
113 /* almost certainly a bug */
114 printf("Internal Error: CertParser error on free.");
115 cssmPerror("CSSM_CL_CertAbortCache", crtn
);
118 vector
<CP_FetchedField
*>::iterator iter
;
119 for(iter
=mFetchedFields
.begin(); iter
!=mFetchedFields
.end(); iter
++) {
124 /* common init for all constructors */
125 void CertParser::initFields()
131 /*** NO MORE EXCEPTIONS ***/
134 * No cert- or CDSA-related exceptions thrown by remainder.
135 * This is the core initializer: have the CL parse and cache the cert.
137 CSSM_RETURN
CertParser::initWithData(
138 const CSSM_DATA
&certData
)
140 assert(mClHand
!= 0);
141 CSSM_RETURN crtn
= CSSM_CL_CertCache(mClHand
, &certData
, &mCacheHand
);
144 cssmPerror("CSSM_CL_CertCache", crtn
);
150 OSStatus
CertParser::initWithSecCert(
151 SecCertificateRef secCert
)
156 assert(mClHand
== 0);
157 ortn
= SecCertificateGetCLHandle(secCert
, &mClHand
);
161 ortn
= SecCertificateGetData(secCert
, &certData
);
165 return (OSStatus
)initWithData(certData
);
168 CSSM_RETURN
CertParser::initWithCFData(
173 cdata
.Data
= (uint8
*)CFDataGetBytePtr(cfData
);
174 cdata
.Length
= CFDataGetLength(cfData
);
175 return initWithData(cdata
);
179 * Obtain atrbitrary field from cached cert. This class takes care of freeing
180 * the field in its destructor.
182 * Returns NULL if field not found (not exception).
184 * Caller optionally specifies field length to check - specifying zero means
185 * "don't care, don't check". Actual field length always returned in fieldLength.
187 const void *CertParser::fieldForOid(
189 CSSM_SIZE
&fieldLength
) // IN/OUT
193 uint32 NumberOfFields
= 0;
194 CSSM_HANDLE resultHand
= 0;
195 CSSM_DATA_PTR fieldData
= NULL
;
197 assert(mClHand
!= 0);
198 assert(mCacheHand
!= 0);
199 crtn
= CSSM_CL_CertGetFirstCachedFieldValue(
207 /* not an error; just means that the cert doesn't have this field */
210 assert(NumberOfFields
== 1);
211 CSSM_CL_CertAbortQuery(mClHand
, resultHand
);
214 if(fieldLength
!= fieldData
->Length
) {
215 /* FIXME what's a good way to log in this situation? */
216 printf("***CertParser::fieldForOid: field length mismatch\n");
220 /* Store the OID and the field for autorelease */
221 CP_FetchedField
*cpField
= new CP_FetchedField(oid
, fieldData
, mClHand
);
222 mFetchedFields
.push_back(cpField
);
223 fieldLength
= fieldData
->Length
;
224 return fieldData
->Data
;
228 * Conveneince routine to fetch an extension we "know" the CL can parse.
229 * The return value gets cast to one of the CE_Data types.
231 const void *CertParser::extensionForOid(
234 CSSM_SIZE len
= sizeof(CSSM_X509_EXTENSION
);
235 CSSM_X509_EXTENSION
*cssmExt
=
236 (CSSM_X509_EXTENSION
*)fieldForOid(oid
, len
);
238 if(cssmExt
->format
!= CSSM_X509_DATAFORMAT_PARSED
) {
239 printf("***Badly formatted extension");
242 return cssmExt
->value
.parsedValue
;