]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2002-2003,2011-2012,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
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. | |
7 | * Please obtain a copy of the License at http://www.apple.com/publicsource | |
8 | * and read it before using this file. | |
9 | * | |
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 | |
16 | * and limitations under the License. | |
17 | */ | |
18 | ||
19 | /* | |
20 | File: cuDbUtils.cpp | |
21 | ||
22 | Description: CDSA DB access utilities | |
23 | ||
24 | Author: dmitch | |
25 | */ | |
26 | ||
27 | #include "cuCdsaUtils.h" | |
28 | #include "cuTimeStr.h" | |
29 | #include "cuDbUtils.h" | |
30 | #include "cuPrintCert.h" | |
31 | #include <stdlib.h> | |
32 | #include <stdio.h> | |
33 | #include <Security/SecCertificate.h> | |
34 | #include <Security/SecCertificatePriv.h> /* private SecInferLabelFromX509Name() */ | |
35 | #include <Security/cssmapple.h> /* for cssmPerror() */ | |
36 | #include <Security/oidscert.h> | |
37 | #include <Security/oidscrl.h> | |
38 | #include <Security/oidsattr.h> | |
39 | #include <strings.h> | |
40 | #include <security_cdsa_utilities/Schema.h> /* private API */ | |
41 | ||
42 | #ifndef NDEBUG | |
43 | #define dprintf(args...) printf(args) | |
44 | #else | |
45 | #define dprintf(args...) | |
46 | #endif | |
47 | ||
48 | /* | |
49 | * Add a certificate to an open DLDB. | |
50 | */ | |
51 | CSSM_RETURN cuAddCertToDb( | |
52 | CSSM_DL_DB_HANDLE dlDbHand, | |
53 | const CSSM_DATA *cert, | |
54 | CSSM_CERT_TYPE certType, | |
55 | CSSM_CERT_ENCODING certEncoding, | |
56 | const char *printName, // C string | |
57 | const CSSM_DATA *publicKeyHash) | |
58 | { | |
59 | CSSM_DB_ATTRIBUTE_DATA attrs[6]; | |
60 | CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; | |
61 | CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; | |
62 | CSSM_DATA certTypeData; | |
63 | CSSM_DATA certEncData; | |
64 | CSSM_DATA printNameData; | |
65 | CSSM_RETURN crtn; | |
66 | CSSM_DB_UNIQUE_RECORD_PTR recordPtr; | |
67 | ||
68 | /* issuer and serial number required, fake 'em */ | |
69 | CSSM_DATA issuer = {6, (uint8 *)"issuer"}; | |
70 | CSSM_DATA serial = {6, (uint8 *)"serial"}; | |
71 | ||
72 | /* we spec six attributes, skipping alias */ | |
73 | certTypeData.Data = (uint8 *)&certType; | |
74 | certTypeData.Length = sizeof(CSSM_CERT_TYPE); | |
75 | certEncData.Data = (uint8 *)&certEncoding; | |
76 | certEncData.Length = sizeof(CSSM_CERT_ENCODING); | |
77 | printNameData.Data = (uint8 *)printName; | |
78 | printNameData.Length = strlen(printName) + 1; | |
79 | ||
80 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
81 | attr->Info.Label.AttributeName = (char*) "CertType"; | |
82 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
83 | attr->NumberOfValues = 1; | |
84 | attr->Value = &certTypeData; | |
85 | ||
86 | attr++; | |
87 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
88 | attr->Info.Label.AttributeName = (char*) "CertEncoding"; | |
89 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
90 | attr->NumberOfValues = 1; | |
91 | attr->Value = &certEncData; | |
92 | ||
93 | attr++; | |
94 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
95 | attr->Info.Label.AttributeName = (char*) "PrintName"; | |
96 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
97 | attr->NumberOfValues = 1; | |
98 | attr->Value = &printNameData; | |
99 | ||
100 | attr++; | |
101 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
102 | attr->Info.Label.AttributeName = (char*) "PublicKeyHash"; | |
103 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
104 | attr->NumberOfValues = 1; | |
105 | attr->Value = (CSSM_DATA_PTR)publicKeyHash; | |
106 | ||
107 | attr++; | |
108 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
109 | attr->Info.Label.AttributeName = (char*) "Issuer"; | |
110 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
111 | attr->NumberOfValues = 1; | |
112 | attr->Value = &issuer; | |
113 | ||
114 | attr++; | |
115 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
116 | attr->Info.Label.AttributeName = (char*) "SerialNumber"; | |
117 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
118 | attr->NumberOfValues = 1; | |
119 | attr->Value = &serial; | |
120 | ||
121 | recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; | |
122 | recordAttrs.SemanticInformation = 0; | |
123 | recordAttrs.NumberOfAttributes = 6; | |
124 | recordAttrs.AttributeData = attrs; | |
125 | ||
126 | crtn = CSSM_DL_DataInsert(dlDbHand, | |
127 | CSSM_DL_DB_RECORD_X509_CERTIFICATE, | |
128 | &recordAttrs, | |
129 | cert, | |
130 | &recordPtr); | |
131 | if(crtn) { | |
132 | cuPrintError("CSSM_DL_DataInsert", crtn); | |
133 | } | |
134 | else { | |
135 | CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); | |
136 | } | |
137 | return crtn; | |
138 | } | |
139 | ||
140 | static CSSM_RETURN cuAddCrlSchema( | |
141 | CSSM_DL_DB_HANDLE dlDbHand); | |
142 | ||
143 | static void cuInferCrlLabel( | |
144 | const CSSM_X509_NAME *x509Name, | |
145 | CSSM_DATA *label) // not mallocd; contents are from the x509Name | |
146 | { | |
147 | /* use private API for common "infer label" logic */ | |
148 | const CSSM_DATA *printValue = SecInferLabelFromX509Name(x509Name); | |
149 | if(printValue == NULL) { | |
150 | /* punt! */ | |
151 | label->Data = (uint8 *)"X509 CRL"; | |
152 | label->Length = 8; | |
153 | } | |
154 | else { | |
155 | *label = *printValue; | |
156 | } | |
157 | } | |
158 | ||
159 | /* | |
160 | * Search extensions for specified OID, assumed to have underlying | |
161 | * value type of uint32; returns the value and true if found. | |
162 | */ | |
163 | static bool cuSearchNumericExtension( | |
164 | const CSSM_X509_EXTENSIONS *extens, | |
165 | const CSSM_OID *oid, | |
166 | uint32 *val) | |
167 | { | |
168 | for(uint32 dex=0; dex<extens->numberOfExtensions; dex++) { | |
169 | const CSSM_X509_EXTENSION *exten = &extens->extensions[dex]; | |
170 | if(!cuCompareOid(&exten->extnId, oid)) { | |
171 | continue; | |
172 | } | |
173 | if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { | |
174 | dprintf("***Malformed extension\n"); | |
175 | continue; | |
176 | } | |
177 | *val = *((uint32 *)exten->value.parsedValue); | |
178 | return true; | |
179 | } | |
180 | return false; | |
181 | } | |
182 | ||
183 | /* | |
184 | * Add a CRL to an existing DL/DB. | |
185 | */ | |
186 | #define MAX_CRL_ATTRS 9 | |
187 | ||
188 | CSSM_RETURN cuAddCrlToDb( | |
189 | CSSM_DL_DB_HANDLE dlDbHand, | |
190 | CSSM_CL_HANDLE clHand, | |
191 | const CSSM_DATA *crl, | |
192 | const CSSM_DATA *URI) // optional | |
193 | { | |
194 | CSSM_DB_ATTRIBUTE_DATA attrs[MAX_CRL_ATTRS]; | |
195 | CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; | |
196 | CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; | |
197 | CSSM_DATA crlTypeData; | |
198 | CSSM_DATA crlEncData; | |
199 | CSSM_DATA printNameData; | |
200 | CSSM_RETURN crtn; | |
201 | CSSM_DB_UNIQUE_RECORD_PTR recordPtr; | |
202 | CSSM_DATA_PTR issuer = NULL; // mallocd by CL | |
203 | CSSM_DATA_PTR crlValue = NULL; // ditto | |
204 | uint32 numFields; | |
205 | CSSM_HANDLE result; | |
206 | CSSM_CRL_ENCODING crlEnc = CSSM_CRL_ENCODING_DER; | |
207 | const CSSM_X509_SIGNED_CRL *signedCrl; | |
208 | const CSSM_X509_TBS_CERTLIST *tbsCrl; | |
209 | CSSM_CRL_TYPE crlType; | |
210 | CSSM_DATA thisUpdateData = {0, NULL}; | |
211 | CSSM_DATA nextUpdateData = {0, NULL}; | |
212 | char *thisUpdate = NULL; | |
213 | char *nextUpdate = NULL; | |
214 | unsigned timeLen; | |
215 | uint32 crlNumber; | |
216 | uint32 deltaCrlNumber; | |
217 | CSSM_DATA crlNumberData; | |
218 | CSSM_DATA deltaCrlNumberData; | |
219 | bool crlNumberPresent = false; | |
220 | bool deltaCrlPresent = false; | |
221 | CSSM_DATA attrUri; | |
222 | ||
223 | /* get normalized issuer name as Issuer attr */ | |
224 | crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, | |
225 | crl, | |
226 | &CSSMOID_X509V1IssuerName, | |
227 | &result, | |
228 | &numFields, | |
229 | &issuer); | |
230 | if(crtn) { | |
231 | cuPrintError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); | |
232 | return crtn; | |
233 | } | |
234 | CSSM_CL_CrlAbortQuery(clHand, result); | |
235 | ||
236 | /* get parsed CRL from the CL */ | |
237 | crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, | |
238 | crl, | |
239 | &CSSMOID_X509V2CRLSignedCrlCStruct, | |
240 | &result, | |
241 | &numFields, | |
242 | &crlValue); | |
243 | if(crtn) { | |
244 | cuPrintError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); | |
245 | goto errOut; | |
246 | } | |
247 | CSSM_CL_CrlAbortQuery(clHand, result); | |
248 | if(crlValue == NULL) { | |
249 | dprintf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n"); | |
250 | crtn = CSSMERR_CL_INVALID_CRL_POINTER; | |
251 | goto errOut; | |
252 | } | |
253 | if((crlValue->Data == NULL) || | |
254 | (crlValue->Length != sizeof(CSSM_X509_SIGNED_CRL))) { | |
255 | dprintf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); | |
256 | crtn = CSSMERR_CL_INVALID_CRL_POINTER; | |
257 | goto errOut; | |
258 | } | |
259 | signedCrl = (const CSSM_X509_SIGNED_CRL *)crlValue->Data; | |
260 | tbsCrl = &signedCrl->tbsCertList; | |
261 | ||
262 | /* CrlType inferred from version */ | |
263 | if(tbsCrl->version.Length == 0) { | |
264 | /* should never happen... */ | |
265 | crlType = CSSM_CRL_TYPE_X_509v1; | |
266 | } | |
267 | else { | |
268 | uint8 vers = tbsCrl->version.Data[tbsCrl->version.Length - 1]; | |
269 | switch(vers) { | |
270 | case 0: | |
271 | crlType = CSSM_CRL_TYPE_X_509v1; | |
272 | break; | |
273 | case 1: | |
274 | crlType = CSSM_CRL_TYPE_X_509v2; | |
275 | break; | |
276 | default: | |
277 | dprintf("***Unknown version in CRL (%u)\n", vers); | |
278 | crlType = CSSM_CRL_TYPE_X_509v1; | |
279 | break; | |
280 | } | |
281 | } | |
282 | crlTypeData.Data = (uint8 *)&crlType; | |
283 | crlTypeData.Length = sizeof(CSSM_CRL_TYPE); | |
284 | /* encoding more-or-less assumed here */ | |
285 | crlEncData.Data = (uint8 *)&crlEnc; | |
286 | crlEncData.Length = sizeof(CSSM_CRL_ENCODING); | |
287 | ||
288 | /* printName inferred from issuer */ | |
289 | cuInferCrlLabel(&tbsCrl->issuer, &printNameData); | |
290 | ||
291 | /* cook up CSSM_TIMESTRING versions of this/next update */ | |
292 | thisUpdate = cuX509TimeToCssmTimestring(&tbsCrl->thisUpdate, &timeLen); | |
293 | if(thisUpdate == NULL) { | |
294 | dprintf("***Badly formatted thisUpdate\n"); | |
295 | } | |
296 | else { | |
297 | thisUpdateData.Data = (uint8 *)thisUpdate; | |
298 | thisUpdateData.Length = timeLen; | |
299 | } | |
300 | if(tbsCrl->nextUpdate.time.Data != NULL) { | |
301 | nextUpdate = cuX509TimeToCssmTimestring(&tbsCrl->nextUpdate, &timeLen); | |
302 | if(nextUpdate == NULL) { | |
303 | dprintf("***Badly formatted nextUpdate\n"); | |
304 | } | |
305 | else { | |
306 | nextUpdateData.Data = (uint8 *)nextUpdate; | |
307 | nextUpdateData.Length = timeLen; | |
308 | } | |
309 | } | |
310 | else { | |
311 | /* | |
312 | * NextUpdate not present; fake it by using "virtual end of time" | |
313 | */ | |
314 | CSSM_X509_TIME tempTime = { 0, // timeType, not used | |
315 | { strlen(CSSM_APPLE_CRL_END_OF_TIME), | |
316 | (uint8 *)CSSM_APPLE_CRL_END_OF_TIME} }; | |
317 | nextUpdate = cuX509TimeToCssmTimestring(&tempTime, &timeLen); | |
318 | nextUpdateData.Data = (uint8 *)nextUpdate; | |
319 | nextUpdateData.Length = CSSM_TIME_STRLEN; | |
320 | } | |
321 | ||
322 | /* optional CrlNumber and DeltaCrlNumber */ | |
323 | if(cuSearchNumericExtension(&tbsCrl->extensions, | |
324 | &CSSMOID_CrlNumber, | |
325 | &crlNumber)) { | |
326 | crlNumberData.Data = (uint8 *)&crlNumber; | |
327 | crlNumberData.Length = sizeof(uint32); | |
328 | crlNumberPresent = true; | |
329 | } | |
330 | if(cuSearchNumericExtension(&tbsCrl->extensions, | |
331 | &CSSMOID_DeltaCrlIndicator, | |
332 | &deltaCrlNumber)) { | |
333 | deltaCrlNumberData.Data = (uint8 *)&deltaCrlNumber; | |
334 | deltaCrlNumberData.Length = sizeof(uint32); | |
335 | deltaCrlPresent = true; | |
336 | } | |
337 | ||
338 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
339 | attr->Info.Label.AttributeName = (char*) "CrlType"; | |
340 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
341 | attr->NumberOfValues = 1; | |
342 | attr->Value = &crlTypeData; | |
343 | attr++; | |
344 | ||
345 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
346 | attr->Info.Label.AttributeName = (char*) "CrlEncoding"; | |
347 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
348 | attr->NumberOfValues = 1; | |
349 | attr->Value = &crlEncData; | |
350 | attr++; | |
351 | ||
352 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
353 | attr->Info.Label.AttributeName = (char*) "PrintName"; | |
354 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
355 | attr->NumberOfValues = 1; | |
356 | attr->Value = &printNameData; | |
357 | attr++; | |
358 | ||
359 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
360 | attr->Info.Label.AttributeName = (char*) "Issuer"; | |
361 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
362 | attr->NumberOfValues = 1; | |
363 | attr->Value = issuer; | |
364 | attr++; | |
365 | ||
366 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
367 | attr->Info.Label.AttributeName = (char*) "ThisUpdate"; | |
368 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
369 | attr->NumberOfValues = 1; | |
370 | attr->Value = &thisUpdateData; | |
371 | attr++; | |
372 | ||
373 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
374 | attr->Info.Label.AttributeName = (char*) "NextUpdate"; | |
375 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
376 | attr->NumberOfValues = 1; | |
377 | attr->Value = &nextUpdateData; | |
378 | attr++; | |
379 | ||
380 | /* now the optional attributes */ | |
381 | if(crlNumberPresent) { | |
382 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
383 | attr->Info.Label.AttributeName = (char*) "CrlNumber"; | |
384 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
385 | attr->NumberOfValues = 1; | |
386 | attr->Value = &crlNumberData; | |
387 | attr++; | |
388 | } | |
389 | if(deltaCrlPresent) { | |
390 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
391 | attr->Info.Label.AttributeName = (char*) "DeltaCrlNumber"; | |
392 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; | |
393 | attr->NumberOfValues = 1; | |
394 | attr->Value = &deltaCrlNumberData; | |
395 | attr++; | |
396 | } | |
397 | if(URI) { | |
398 | /* ensure URI string does not contain NULL */ | |
399 | attrUri = *URI; | |
400 | if((attrUri.Length != 0) && | |
401 | (attrUri.Data[attrUri.Length - 1] == 0)) { | |
402 | attrUri.Length--; | |
403 | } | |
404 | attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; | |
405 | attr->Info.Label.AttributeName = (char*) "URI"; | |
406 | attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; | |
407 | attr->NumberOfValues = 1; | |
408 | attr->Value = &attrUri; | |
409 | attr++; | |
410 | } | |
411 | recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL; | |
412 | recordAttrs.SemanticInformation = 0; | |
427c49bc | 413 | recordAttrs.NumberOfAttributes = (uint32)(attr - attrs); |
b1ab9ed8 A |
414 | recordAttrs.AttributeData = attrs; |
415 | ||
416 | crtn = CSSM_DL_DataInsert(dlDbHand, | |
417 | CSSM_DL_DB_RECORD_X509_CRL, | |
418 | &recordAttrs, | |
419 | crl, | |
420 | &recordPtr); | |
421 | if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) { | |
422 | /* gross hack of inserting this "new" schema that Keychain didn't specify */ | |
423 | crtn = cuAddCrlSchema(dlDbHand); | |
424 | if(crtn == CSSM_OK) { | |
425 | /* Retry with a fully capable DLDB */ | |
426 | crtn = CSSM_DL_DataInsert(dlDbHand, | |
427 | CSSM_DL_DB_RECORD_X509_CRL, | |
428 | &recordAttrs, | |
429 | crl, | |
430 | &recordPtr); | |
431 | } | |
432 | } | |
433 | if(crtn == CSSM_OK) { | |
434 | CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); | |
435 | } | |
436 | ||
437 | errOut: | |
438 | /* free all the stuff we allocated to get here */ | |
439 | if(issuer) { | |
440 | CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuer); | |
441 | } | |
442 | if(crlValue) { | |
443 | CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V2CRLSignedCrlCStruct, crlValue); | |
444 | } | |
445 | if(thisUpdate) { | |
446 | free(thisUpdate); | |
447 | } | |
448 | if(nextUpdate) { | |
449 | free(nextUpdate); | |
450 | } | |
451 | return crtn; | |
452 | } | |
453 | ||
454 | ||
455 | /* | |
456 | * Update an existing DLDB to be CRL-capable. | |
457 | */ | |
458 | static CSSM_RETURN cuAddCrlSchema( | |
459 | CSSM_DL_DB_HANDLE dlDbHand) | |
460 | { | |
461 | return CSSM_DL_CreateRelation(dlDbHand, | |
462 | CSSM_DL_DB_RECORD_X509_CRL, | |
463 | "CSSM_DL_DB_RECORD_X509_CRL", | |
464 | Security::KeychainCore::Schema::X509CrlSchemaAttributeCount, | |
465 | Security::KeychainCore::Schema::X509CrlSchemaAttributeList, | |
466 | Security::KeychainCore::Schema::X509CrlSchemaIndexCount, | |
467 | Security::KeychainCore::Schema::X509CrlSchemaIndexList); | |
468 | } | |
469 | ||
470 | /* | |
471 | * Search DB for all records of type CRL or cert, calling appropriate | |
472 | * parse/print routine for each record. | |
473 | */ | |
474 | CSSM_RETURN cuDumpCrlsCerts( | |
475 | CSSM_DL_DB_HANDLE dlDbHand, | |
476 | CSSM_CL_HANDLE clHand, | |
477 | CSSM_BOOL isCert, | |
478 | unsigned &numItems, // returned | |
479 | CSSM_BOOL verbose) | |
480 | { | |
481 | CSSM_QUERY query; | |
482 | CSSM_DB_UNIQUE_RECORD_PTR record = NULL; | |
483 | CSSM_HANDLE resultHand; | |
484 | CSSM_RETURN crtn; | |
485 | CSSM_DATA certCrl; | |
486 | const char *itemStr; | |
487 | ||
488 | numItems = 0; | |
489 | itemStr = isCert ? "Certificate" : "CRL"; | |
490 | ||
491 | /* just search by recordType, no predicates, no attributes */ | |
492 | if(isCert) { | |
493 | query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; | |
494 | } | |
495 | else { | |
496 | query.RecordType = CSSM_DL_DB_RECORD_X509_CRL; | |
497 | } | |
498 | query.Conjunctive = CSSM_DB_NONE; | |
499 | query.NumSelectionPredicates = 0; | |
500 | query.SelectionPredicate = NULL; | |
501 | query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? | |
502 | query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? | |
503 | query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? | |
504 | ||
505 | certCrl.Data = NULL; | |
506 | certCrl.Length = 0; | |
507 | crtn = CSSM_DL_DataGetFirst(dlDbHand, | |
508 | &query, | |
509 | &resultHand, | |
510 | NULL, // no attrs | |
511 | &certCrl, | |
512 | &record); | |
513 | switch(crtn) { | |
514 | case CSSM_OK: | |
515 | break; // proceed | |
516 | case CSSMERR_DL_ENDOFDATA: | |
517 | /* no data, otherwise OK */ | |
518 | return CSSM_OK; | |
519 | case CSSMERR_DL_INVALID_RECORDTYPE: | |
520 | /* invalid record type just means "this hasn't been set up | |
521 | * for certs yet". */ | |
522 | return crtn; | |
523 | default: | |
524 | cuPrintError("DataGetFirst", crtn); | |
525 | return crtn; | |
526 | } | |
527 | ||
528 | /* got one; print it */ | |
529 | dprintf("%s %u:\n", itemStr, numItems); | |
530 | if(isCert) { | |
427c49bc | 531 | printCert(certCrl.Data, (unsigned)certCrl.Length, verbose); |
b1ab9ed8 A |
532 | } |
533 | else { | |
427c49bc | 534 | printCrl(certCrl.Data, (unsigned)certCrl.Length, verbose); |
b1ab9ed8 A |
535 | } |
536 | CSSM_DL_FreeUniqueRecord(dlDbHand, record); | |
537 | APP_FREE(certCrl.Data); | |
538 | certCrl.Data = NULL; | |
539 | certCrl.Length = 0; | |
540 | numItems++; | |
541 | ||
542 | /* get the rest */ | |
543 | for(;;) { | |
544 | crtn = CSSM_DL_DataGetNext(dlDbHand, | |
545 | resultHand, | |
546 | NULL, | |
547 | &certCrl, | |
548 | &record); | |
549 | switch(crtn) { | |
550 | case CSSM_OK: | |
551 | dprintf("%s %u:\n", itemStr, numItems); | |
552 | if(isCert) { | |
427c49bc | 553 | printCert(certCrl.Data, (unsigned)certCrl.Length, verbose); |
b1ab9ed8 A |
554 | } |
555 | else { | |
427c49bc | 556 | printCrl(certCrl.Data, (unsigned)certCrl.Length, verbose); |
b1ab9ed8 A |
557 | } |
558 | CSSM_DL_FreeUniqueRecord(dlDbHand, record); | |
559 | APP_FREE(certCrl.Data); | |
560 | certCrl.Data = NULL; | |
561 | certCrl.Length = 0; | |
562 | numItems++; | |
563 | break; // and go again | |
564 | case CSSMERR_DL_ENDOFDATA: | |
565 | /* normal termination */ | |
566 | return CSSM_OK; | |
567 | default: | |
568 | cuPrintError("DataGetNext", crtn); | |
569 | return crtn; | |
570 | } | |
571 | } | |
572 | /* NOT REACHED */ | |
573 | } | |
574 |