2 * Copyright (c) 2004-2005,2008 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * ocspdTool.cpp - basic ocspdtool
26 * Created 11 July 2004 by Doug Mitchell.
31 #include <utilLib/common.h>
32 #include <Security/Security.h>
33 #include <security_ocspd/ocspdDbSchema.h>
34 #include <security_ocspd/ocspdUtils.h>
35 #include <security_ocspd/ocspdClient.h>
36 #include <security_cdsa_utils/cuCdsaUtils.h>
37 #include <security_cdsa_utils/cuTimeStr.h>
38 #include <Security/SecAsn1Coder.h>
39 #include <Security/ocspTemplates.h>
41 static void usage(char **argv
)
43 printf("Usage: op [option..]\n");
45 printf(" d dump database\n");
46 printf(" f flush stale entries\n");
47 printf(" F flush ALL\n");
53 #define OCSP_DB_FILE "/private/var/db/crls/ocspcache.db"
55 static CSSM_DL_DB_HANDLE dlDbHandle
= {0, 0};
57 static CSSM_API_MEMORY_FUNCS memFuncs
= {
65 static CSSM_VERSION vers
= {2, 0};
68 static CSSM_RETURN
dlAttach()
70 if(dlDbHandle
.DLHandle
!= 0) {
73 if(cuCssmStartup() == CSSM_FALSE
) {
74 return CSSMERR_CSSM_ADDIN_LOAD_FAILED
;
76 CSSM_RETURN crtn
= CSSM_ModuleLoad(&gGuidAppleFileDL
,
77 CSSM_KEY_HIERARCHY_NONE
,
79 NULL
); // AppNotifyCallbackCtx
81 return CSSMERR_CSSM_ADDIN_LOAD_FAILED
;
83 crtn
= CSSM_ModuleAttach (&gGuidAppleFileDL
,
85 &memFuncs
, // memFuncs
89 CSSM_KEY_HIERARCHY_NONE
,
90 NULL
, // FunctionTable
93 &dlDbHandle
.DLHandle
);
95 return CSSMERR_CSSM_ADDIN_LOAD_FAILED
;
100 static CSSM_RETURN
dbAttach(const char *dbFile
)
102 CSSM_RETURN crtn
= dlAttach();
106 if(dlDbHandle
.DBHandle
!= 0) {
109 return CSSM_DL_DbOpen(dlDbHandle
.DLHandle
,
113 NULL
, // CSSM_ACCESS_CREDENTIALS *AccessCred
114 NULL
, // void *OpenParameters
115 &dlDbHandle
.DBHandle
);
118 static const char *months
[] = {
119 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
120 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
123 static void printTimeStr(const CSSM_DATA
*cssmTime
)
127 /* ignore cssmTime->timeType for now */
128 if(cuTimeStringToTm((char *)cssmTime
->Data
, cssmTime
->Length
, &tm
)) {
129 printf("***Bad time string format***\n");
133 printf("***Bad time string format***\n");
136 printf("%02d:%02d:%02d %s %d, %04d\n",
137 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
,
138 months
[tm
.tm_mon
], tm
.tm_mday
, tm
.tm_year
+ 1900);
142 static void freeAttrData(
143 CSSM_DB_ATTRIBUTE_DATA
*attrData
,
146 if(attrData
== NULL
) {
149 for(unsigned dex
=0; dex
<numAttrs
; dex
++) {
150 CSSM_DB_ATTRIBUTE_DATA
*a
= &attrData
[dex
];
151 if(a
->Value
== NULL
) {
154 for(unsigned i
=0; i
<a
->NumberOfValues
; i
++) {
155 CSSM_DATA_PTR d
= &a
->Value
[i
];
164 static void printString(
166 const CSSM_DATA
*str
)
169 printf("%s: %lu bytes: ", title
, str
? str
->Length
: 0);
170 if((str
== NULL
) || (str
->Length
== 0)) {
174 char *cp
= (char *)str
->Data
;
175 for(i
=0; i
<str
->Length
; i
++) {
181 static void printData(
185 printf("%s: %lu bytes: ", title
, d
? d
->Length
: 0);
186 if((d
== NULL
) || (d
->Length
== 0)) {
190 unsigned toPrint
= 20;
191 bool ellipsis
= false;
192 if(d
->Length
< toPrint
) {
195 else if(d
->Length
> toPrint
) {
198 for(unsigned dex
=0; dex
<toPrint
; dex
++) {
199 printf("%02X", d
->Data
[dex
]);
212 static void printCertID(
213 const CSSM_DATA
&certID
)
215 SecAsn1CoderRef coder
;
216 SecAsn1CoderCreate(&coder
);
217 SecAsn1OCSPCertID asn1CertID
;
218 memset(&asn1CertID
, 0, sizeof(SecAsn1OCSPCertID
));
219 if(SecAsn1DecodeData(coder
, &certID
, kSecAsn1OCSPCertIDTemplate
, &asn1CertID
)) {
220 printf("***ERROR decoding stored CertID\n");
224 printf(" --- Parsed CertID ---\n");
225 printf(" "); printData("issuerNameHash ", &asn1CertID
.issuerNameHash
);
226 printf(" "); printData("issuerPubKeyHash", &asn1CertID
.issuerPubKeyHash
);
227 printf(" "); printData("serialNumber ", &asn1CertID
.serialNumber
);
228 SecAsn1CoderRelease(coder
);
230 static void printRecord(
231 const CSSM_DB_ATTRIBUTE_DATA
*attrData
,
233 const CSSM_DATA
*recordData
)
235 printf("===== printRecord: %u attributes, %lu bytes of data =====\n", numAttrs
,
236 recordData
? recordData
->Length
: 0);
237 for(unsigned dex
=0; dex
<numAttrs
; dex
++) {
238 const CSSM_DB_ATTRIBUTE_DATA
*a
= &attrData
[dex
];
239 char *attrName
= a
->Info
.Label
.AttributeName
;
240 CSSM_DB_ATTRIBUTE_FORMAT form
= a
->Info
.AttributeFormat
;
241 if(a
->NumberOfValues
== 0) {
242 printf("++++++++ zero values for attribute %s ++++++++\n", attrName
);
244 for(unsigned v
=0; v
<a
->NumberOfValues
; v
++) {
245 if(!memcmp(attrName
, "Expiration", 10)) {
246 const CSSM_DATA
*td
= &a
->Value
[v
];
247 printf("Expiration: ");
252 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
:
253 printString(attrName
, &a
->Value
[v
]);
255 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
:
256 printData(attrName
, &a
->Value
[v
]);
259 printf("Help! How do you print format %u\n", (unsigned)form
);
262 if(!memcmp(attrName
, "CertID", 6)) {
263 printCertID(a
->Value
[v
]);
270 static void dumpOcspdDb(char *dbFile
)
273 CSSM_DB_UNIQUE_RECORD_PTR recordPtr
= NULL
;
275 CSSM_HANDLE resultHand
;
276 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs
;
277 CSSM_DATA recordData
= {0, NULL
};
278 CSSM_DB_ATTRIBUTE_DATA attrData
[OCSPD_NUM_DB_ATTRS
];
279 CSSM_DB_ATTRIBUTE_INFO certIDInfo
= OCSPD_DBATTR_CERT_ID
;
280 CSSM_DB_ATTRIBUTE_INFO uriInfo
= OCSPD_DBATTR_URI
;
281 CSSM_DB_ATTRIBUTE_INFO expireInfo
= OCSPD_DBATTR_EXPIRATION
;
283 if(dbAttach(dbFile
)) {
284 printf("***Error opening %s. Aborting.\n", dbFile
);
288 recordAttrs
.DataRecordType
= OCSPD_DB_RECORDTYPE
;
289 recordAttrs
.NumberOfAttributes
= OCSPD_NUM_DB_ATTRS
;
290 recordAttrs
.AttributeData
= attrData
;
291 attrData
[0].Info
= certIDInfo
;
292 attrData
[1].Info
= uriInfo
;
293 attrData
[2].Info
= expireInfo
;
295 /* just search by recordType, no predicates */
296 query
.RecordType
= OCSPD_DB_RECORDTYPE
;
297 query
.Conjunctive
= CSSM_DB_NONE
;
298 query
.NumSelectionPredicates
= 0;
299 query
.SelectionPredicate
= NULL
;
300 query
.QueryLimits
.TimeLimit
= 0; // FIXME - meaningful?
301 query
.QueryLimits
.SizeLimit
= 1; // FIXME - meaningful?
302 query
.QueryFlags
= CSSM_QUERY_RETURN_DATA
;
304 crtn
= CSSM_DL_DataGetFirst(dlDbHandle
,
313 case CSSMERR_DL_ENDOFDATA
:
314 printf("***No records found in %s.\n", dbFile
);
318 printError("DataGetFirst", crtn
);
322 printRecord(attrData
, OCSPD_NUM_DB_ATTRS
, &recordData
);
323 freeAttrData(attrData
, 3);
324 CSSM_DL_FreeUniqueRecord(dlDbHandle
, recordPtr
);
325 if(recordData
.Data
) {
326 APP_FREE(recordData
.Data
);
327 recordData
.Data
= NULL
;
330 /* now the rest of them */
332 crtn
= CSSM_DL_DataGetNext(dlDbHandle
,
339 printRecord(attrData
, OCSPD_NUM_DB_ATTRS
, &recordData
);
340 freeAttrData(attrData
, 3);
341 CSSM_DL_FreeUniqueRecord(dlDbHandle
, recordPtr
);
342 if(recordData
.Data
) {
343 APP_FREE(recordData
.Data
);
344 recordData
.Data
= NULL
;
346 break; // and go again
347 case CSSMERR_DL_ENDOFDATA
:
348 /* normal termination */
351 printError("DataGetNext", crtn
);
354 if(crtn
!= CSSM_OK
) {
358 CSSM_DL_DataAbortQuery(dlDbHandle
, resultHand
);
362 static void cleanOcspdDb(char *dbFile
)
365 CSSM_DB_UNIQUE_RECORD_PTR recordPtr
= NULL
;
367 CSSM_HANDLE resultHand
;
368 unsigned numRecords
= 0;
370 if(dbAttach(dbFile
)) {
371 printf("***Error opening %s. Aborting.\n", dbFile
);
375 /* just search by recordType, no predicates, no returned attrs, no returned data*/
376 query
.RecordType
= OCSPD_DB_RECORDTYPE
;
377 query
.Conjunctive
= CSSM_DB_NONE
;
378 query
.NumSelectionPredicates
= 0;
379 query
.SelectionPredicate
= NULL
;
380 query
.QueryLimits
.TimeLimit
= 0; // FIXME - meaningful?
381 query
.QueryLimits
.SizeLimit
= 1; // FIXME - meaningful?
382 query
.QueryFlags
= 0;
384 crtn
= CSSM_DL_DataGetFirst(dlDbHandle
,
393 case CSSMERR_DL_ENDOFDATA
:
394 printf("***No records found in %s.\n", dbFile
);
398 printError("DataGetFirst", crtn
);
402 crtn
= CSSM_DL_DataDelete(dlDbHandle
, recordPtr
);
404 cssmPerror("CSSM_DL_DataDelete", crtn
);
406 CSSM_DL_FreeUniqueRecord(dlDbHandle
, recordPtr
);
412 /* now the rest of them */
414 crtn
= CSSM_DL_DataGetNext(dlDbHandle
,
421 crtn
= CSSM_DL_DataDelete(dlDbHandle
, recordPtr
);
423 cssmPerror("CSSM_DL_DataDelete", crtn
);
425 CSSM_DL_FreeUniqueRecord(dlDbHandle
, recordPtr
);
430 break; // and go again
431 case CSSMERR_DL_ENDOFDATA
:
432 /* normal termination */
435 printError("DataGetNext", crtn
);
438 if(crtn
!= CSSM_OK
) {
442 CSSM_DL_DataAbortQuery(dlDbHandle
, resultHand
);
443 printf("...%u records deleted\n", numRecords
);
447 int main(int argc
, char **argv
)
454 // extern char *optarg;
458 while ((arg
= getopt(argc
, argv
, "h")) != -1) {
469 switch (argv
[1][0]) {
471 dumpOcspdDb((char *)OCSP_DB_FILE
);
474 ocspdCacheFlushStale();
475 printf("...stale entries flushed\n");
478 cleanOcspdDb((char *)OCSP_DB_FILE
);