]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/SecTrust.cpp
be9b7000c426d932ba4810a191dd2e4f9cc6f2d8
[apple/security.git] / libsecurity_keychain / lib / SecTrust.cpp
1 /*
2 * Copyright (c) 2002-2010,2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include "SecTrust.h"
25 #include "SecTrustPriv.h"
26 #include "Trust.h"
27 #include <security_keychain/SecTrustSettingsPriv.h>
28 #include "SecBridge.h"
29 #include "SecInternal.h"
30 #include "SecTrustSettings.h"
31 #include "SecCertificatePriv.h"
32 #include <security_utilities/cfutilities.h>
33 #include <security_utilities/cfmunge.h>
34 #include <CoreFoundation/CoreFoundation.h>
35
36 // forward declarations
37 CFArrayRef SecTrustCopyDetails(SecTrustRef trust);
38 static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix);
39 static void SecTrustCheckException(const void *key, const void *value, void *context);
40
41 typedef struct SecTrustCheckExceptionContext {
42 CFDictionaryRef exception;
43 bool exceptionNotFound;
44 } SecTrustCheckExceptionContext;
45
46 // public trust result constants
47 CFTypeRef kSecTrustEvaluationDate = CFSTR("TrustEvaluationDate");
48 CFTypeRef kSecTrustExtendedValidation = CFSTR("TrustExtendedValidation");
49 CFTypeRef kSecTrustOrganizationName = CFSTR("Organization");
50 CFTypeRef kSecTrustResultValue = CFSTR("TrustResultValue");
51 CFTypeRef kSecTrustRevocationChecked = CFSTR("TrustRevocationChecked");
52 CFTypeRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate");
53 CFTypeRef kSecTrustResultDetails = CFSTR("TrustResultDetails");
54
55 //
56 // CF boilerplate
57 //
58 CFTypeID SecTrustGetTypeID(void)
59 {
60 BEGIN_SECAPI
61
62 return gTypes().Trust.typeID;
63
64 END_SECAPI1(_kCFRuntimeNotATypeID)
65 }
66
67
68 //
69 // Sec* API bridge functions
70 //
71 OSStatus SecTrustCreateWithCertificates(
72 CFTypeRef certificates,
73 CFTypeRef policies,
74 SecTrustRef *trustRef)
75 {
76 BEGIN_SECAPI
77 Required(trustRef);
78 *trustRef = (new Trust(certificates, policies))->handle();
79 END_SECAPI
80 }
81
82 OSStatus
83 SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
84 {
85 BEGIN_SECAPI
86 Trust::required(trustRef)->policies(policies);
87 END_SECAPI
88 }
89
90 OSStatus
91 SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options)
92 {
93 BEGIN_SECAPI
94 CSSM_APPLE_TP_ACTION_DATA actionData = {
95 CSSM_APPLE_TP_ACTION_VERSION,
96 (CSSM_APPLE_TP_ACTION_FLAGS)options
97 };
98 Trust *trust = Trust::required(trustRef);
99 CFDataRef actionDataRef = CFDataCreate(NULL,
100 (const UInt8 *)&actionData,
101 (CFIndex)sizeof(CSSM_APPLE_TP_ACTION_DATA));
102 trust->action(CSSM_TP_ACTION_DEFAULT);
103 trust->actionData(actionDataRef);
104 if (actionDataRef) CFRelease(actionDataRef);
105 END_SECAPI
106 }
107
108 OSStatus SecTrustSetParameters(
109 SecTrustRef trustRef,
110 CSSM_TP_ACTION action,
111 CFDataRef actionData)
112 {
113 BEGIN_SECAPI
114 Trust *trust = Trust::required(trustRef);
115 trust->action(action);
116 trust->actionData(actionData);
117 END_SECAPI
118 }
119
120
121 OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
122 {
123 BEGIN_SECAPI
124 Trust::required(trust)->anchors(anchorCertificates);
125 END_SECAPI
126 }
127
128 OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly)
129 {
130 BEGIN_SECAPI
131 Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns;
132 Trust::required(trust)->anchorPolicy(policy);
133 END_SECAPI
134 }
135
136 OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
137 {
138 BEGIN_SECAPI
139 StorageManager::KeychainList keychains;
140 // avoid unnecessary global initializations if an empty array is passed in
141 if (!( (keychainOrArray != NULL) &&
142 (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) &&
143 (CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) {
144 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
145 }
146 Trust::required(trust)->searchLibs(keychains);
147 END_SECAPI
148 }
149
150
151 OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
152 {
153 BEGIN_SECAPI
154 Trust::required(trust)->time(verifyDate);
155 END_SECAPI
156 }
157
158
159 CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
160 {
161 CFAbsoluteTime verifyTime = 0;
162 OSStatus __secapiresult = errSecSuccess;
163 try {
164 CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
165 verifyTime = CFDateGetAbsoluteTime(verifyDate);
166 }
167 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
168 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
169 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
170 catch (...) { __secapiresult=errSecInternalComponent; }
171 return verifyTime;
172 }
173
174
175
176 OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP)
177 {
178 SecTrustResultType trustResult = kSecTrustResultInvalid;
179 CFArrayRef exceptions = NULL;
180 OSStatus __secapiresult = errSecSuccess;
181 try {
182 Trust *trustObj = Trust::required(trust);
183 trustObj->evaluate();
184 trustResult = trustObj->result();
185 exceptions = trustObj->exceptions();
186 }
187 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
188 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
189 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
190 catch (...) { __secapiresult=errSecInternalComponent; }
191
192 if (__secapiresult) {
193 return __secapiresult;
194 }
195
196 /* post-process trust result based on exceptions */
197 if (trustResult == kSecTrustResultUnspecified) {
198 /* If leaf is in exceptions -> proceed, otherwise unspecified. */
199 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
200 trustResult = kSecTrustResultProceed;
201 }
202 else if (trustResult == kSecTrustResultRecoverableTrustFailure && exceptions) {
203 /* If we have exceptions get details and match to exceptions. */
204 CFArrayRef details = SecTrustCopyDetails(trust);
205 if (details) {
206 CFIndex pathLength = CFArrayGetCount(details);
207 struct SecTrustCheckExceptionContext context = {};
208 CFIndex ix;
209 for (ix = 0; ix < pathLength; ++ix) {
210 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
211 // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
212 // trustResult = kSecTrustResultFatalTrustFailure;
213 context.exception = SecTrustGetExceptionForCertificateAtIndex(trust, ix);
214 CFDictionaryApplyFunction(detail, SecTrustCheckException, &context);
215 if (context.exceptionNotFound) {
216 break;
217 }
218 }
219 if (!context.exceptionNotFound)
220 trustResult = kSecTrustResultProceed;
221 }
222 }
223
224
225 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult);
226 if (resultP) {
227 *resultP = trustResult;
228 }
229 return __secapiresult;
230 }
231
232 OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
233 dispatch_queue_t queue, SecTrustCallback result)
234 {
235 BEGIN_SECAPI
236 dispatch_async(queue, ^{
237 try {
238 Trust *trustObj = Trust::required(trust);
239 trustObj->evaluate();
240 SecTrustResultType trustResult = trustObj->result();
241 result(trust, trustResult);
242 }
243 catch (...) {
244 result(trust, kSecTrustResultInvalid);
245 };
246 });
247 END_SECAPI
248 }
249
250 //
251 // Construct the "official" result evidence and return it
252 //
253 OSStatus SecTrustGetResult(
254 SecTrustRef trustRef,
255 SecTrustResultType *result,
256 CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain)
257 {
258 BEGIN_SECAPI
259 Trust *trust = Trust::required(trustRef);
260 if (result)
261 *result = trust->result();
262 if (certChain && statusChain)
263 trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain));
264 END_SECAPI
265 }
266
267 //
268 // Retrieve result of trust evaluation only
269 //
270 OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
271 SecTrustResultType *result)
272 {
273 BEGIN_SECAPI
274 Trust *trust = Trust::required(trustRef);
275 if (result) *result = trust->result();
276 END_SECAPI
277 }
278
279 //
280 // Retrieve extended validation trust results
281 //
282 OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
283 {
284 BEGIN_SECAPI
285 Trust *trustObj = Trust::required(trust);
286 if (result == nil)
287 return errSecParam;
288 trustObj->extendedResult(*result);
289 END_SECAPI
290 }
291
292 //
293 // Retrieve CSSM-level information for those who want to dig down
294 //
295 OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result)
296 {
297 BEGIN_SECAPI
298 Required(result) = Trust::required(trust)->cssmResult();
299 END_SECAPI
300 }
301
302 //
303 // Retrieve CSSM_LEVEL TP return code
304 //
305 OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
306 {
307 BEGIN_SECAPI
308 Trust *trust = Trust::required(trustRef);
309 if (trust->result() == kSecTrustResultInvalid)
310 return errSecParam;
311 else
312 Required(result) = trust->cssmResultCode();
313 END_SECAPI
314 }
315
316 OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
317 {
318 BEGIN_SECAPI
319 Required(handle) = Trust::required(trust)->getTPHandle();
320 END_SECAPI
321 }
322
323 OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
324 {
325 BEGIN_SECAPI
326 CFArrayRef currentPolicies = Trust::required(trust)->policies();
327 if (currentPolicies != NULL)
328 {
329 CFRetain(currentPolicies);
330 }
331
332 Required(policies) = currentPolicies;
333 END_SECAPI
334 }
335
336 OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch)
337 {
338 BEGIN_SECAPI
339 Trust *trustObj = Trust::required(trust);
340 Trust::NetworkPolicy netPolicy = (allowFetch) ?
341 Trust::useNetworkEnabled : Trust::useNetworkDisabled;
342 trustObj->networkPolicy(netPolicy);
343 END_SECAPI
344 }
345
346 OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch)
347 {
348 BEGIN_SECAPI
349 Boolean allowed = false;
350 Trust *trustObj = Trust::required(trust);
351 Trust::NetworkPolicy netPolicy = trustObj->networkPolicy();
352 if (netPolicy == Trust::useNetworkDefault) {
353 // network fetch is enabled by default for SSL only
354 allowed = trustObj->policySpecified(trustObj->policies(), CSSMOID_APPLE_TP_SSL);
355 } else {
356 // caller has explicitly set the network policy
357 allowed = (netPolicy == Trust::useNetworkEnabled);
358 }
359 Required(allowFetch) = allowed;
360 END_SECAPI
361 }
362
363 OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData)
364 {
365 BEGIN_SECAPI
366 Trust::required(trust)->responses(responseData);
367 END_SECAPI
368 }
369
370 OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
371 {
372 BEGIN_SECAPI
373 CFArrayRef customAnchors = Trust::required(trust)->anchors();
374 Required(anchorCertificates) = (customAnchors) ?
375 (const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL;
376 END_SECAPI
377 }
378
379 //
380 // Get the user's default anchor certificate set
381 //
382 OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
383 {
384 BEGIN_SECAPI
385
386 return SecTrustSettingsCopyUnrestrictedRoots(
387 true, true, true, /* all domains */
388 anchorCertificates);
389
390 END_SECAPI
391 }
392
393 /* new in 10.6 */
394 SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
395 {
396 SecKeyRef pubKey = NULL;
397 CFArrayRef certChain = NULL;
398 CFArrayRef evidenceChain = NULL;
399 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
400 OSStatus __secapiresult = errSecSuccess;
401 try {
402 Trust *trustObj = Trust::required(trust);
403 if (trustObj->result() == kSecTrustResultInvalid)
404 MacOSError::throwMe(errSecTrustNotAvailable);
405 if (trustObj->evidence() == nil)
406 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
407 evidenceChain = trustObj->evidence();
408 }
409 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
410 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
411 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
412 catch (...) { __secapiresult=errSecInternalComponent; }
413
414 if (certChain)
415 CFRelease(certChain);
416
417 if (evidenceChain) {
418 if (CFArrayGetCount(evidenceChain) > 0) {
419 SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
420 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
421 }
422 // do not release evidenceChain, as it is owned by the trust object.
423 }
424 return pubKey;
425 }
426
427 /* new in 10.6 */
428 CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
429 {
430 CFIndex chainLen = 0;
431 CFArrayRef certChain = NULL;
432 CFArrayRef evidenceChain = NULL;
433 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
434 OSStatus __secapiresult = errSecSuccess;
435 try {
436 Trust *trustObj = Trust::required(trust);
437 if (trustObj->result() == kSecTrustResultInvalid) {
438 trustObj->evaluate();
439 if (trustObj->result() == kSecTrustResultInvalid)
440 MacOSError::throwMe(errSecTrustNotAvailable);
441 }
442 if (trustObj->evidence() == nil)
443 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
444 evidenceChain = trustObj->evidence();
445 }
446 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
447 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
448 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
449 catch (...) { __secapiresult=errSecInternalComponent; }
450
451 if (certChain)
452 CFRelease(certChain);
453
454 if (evidenceChain)
455 chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it.
456
457 return chainLen;
458 }
459
460 /* new in 10.6 */
461 SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
462 {
463 SecCertificateRef certificate = NULL;
464 CFArrayRef certChain = NULL;
465 CFArrayRef evidenceChain = NULL;
466 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
467 OSStatus __secapiresult = errSecSuccess;
468 try {
469 Trust *trustObj = Trust::required(trust);
470 if (trustObj->result() == kSecTrustResultInvalid) {
471 trustObj->evaluate();
472 if (trustObj->result() == kSecTrustResultInvalid)
473 MacOSError::throwMe(errSecTrustNotAvailable);
474 }
475 if (trustObj->evidence() == nil)
476 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
477 evidenceChain = trustObj->evidence();
478 }
479 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
480 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
481 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
482 catch (...) { __secapiresult=errSecInternalComponent; }
483
484 if (certChain)
485 CFRelease(certChain);
486
487 if (evidenceChain) {
488 if (ix < CFArrayGetCount(evidenceChain)) {
489 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
490 // note: we do not retain this certificate. The assumption here is
491 // that the certificate is retained by the trust object, so it is
492 // valid unil the trust is released (or until re-evaluated.)
493 // also note: we do not release the evidenceChain, as it is owned
494 // by the trust object.
495 }
496 }
497 return certificate;
498 }
499
500
501 static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
502 static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes");
503
504 static void
505 _AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode)
506 {
507 if (!array)
508 return;
509 SInt32 num = statusCode;
510 CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num);
511 if (!numRef)
512 return;
513 CFArrayAppendValue(array, numRef);
514 CFRelease(numRef);
515 }
516
517 CFArrayRef SecTrustCopyDetails(SecTrustRef trust)
518 {
519 // This function returns an array of dictionaries, one per certificate,
520 // holding status info for each certificate in the evaluated chain.
521 //
522 CFIndex count, chainLen = 0;
523 CFArrayRef certChain = NULL;
524 CFMutableArrayRef details = NULL;
525 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
526 OSStatus __secapiresult = errSecSuccess;
527 try {
528 Trust *trustObj = Trust::required(trust);
529 if (trustObj->result() == kSecTrustResultInvalid) {
530 trustObj->evaluate();
531 if (trustObj->result() == kSecTrustResultInvalid)
532 MacOSError::throwMe(errSecTrustNotAvailable);
533 }
534 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
535 }
536 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
537 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
538 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
539 catch (...) { __secapiresult=errSecInternalComponent; }
540
541 if (certChain) {
542 chainLen = CFArrayGetCount(certChain);
543 CFRelease(certChain);
544 }
545 if (statusChain) {
546 details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks);
547 for (count = 0; count < chainLen; count++) {
548 CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
549 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
550 CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault,
551 0, &kCFTypeArrayCallBacks);
552 CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count];
553 CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits;
554
555 // translate status bits
556 if (statBits & CSSM_CERT_STATUS_EXPIRED)
557 _AppendStatusCode(statusCodes, errSecCertificateExpired);
558 if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET)
559 _AppendStatusCode(statusCodes, errSecCertificateNotValidYet);
560 if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY)
561 _AppendStatusCode(statusCodes, errSecTrustSettingDeny);
562
563 // translate status codes
564 unsigned int i;
565 for (i = 0; i < evInfo->NumStatusCodes; i++) {
566 CSSM_RETURN scode = evInfo->StatusCodes[i];
567 _AppendStatusCode(statusCodes, (OSStatus)scode);
568 }
569
570 CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes);
571 CFRelease(statusCodes);
572 CFArrayAppendValue(details, certDict);
573 CFRelease(certDict);
574 }
575 }
576 return details;
577 }
578
579 static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix)
580 {
581 CFArrayRef exceptions = NULL;
582 OSStatus __secapiresult = errSecSuccess;
583 try {
584 exceptions = Trust::required(trust)->exceptions();
585 }
586 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
587 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
588 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
589 catch (...) { __secapiresult=errSecInternalComponent; }
590
591 if (!exceptions || ix >= CFArrayGetCount(exceptions))
592 return NULL;
593 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
594 if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
595 return NULL;
596
597 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
598 if (!certificate)
599 return NULL;
600
601 /* If the exception contains the current certificate's sha1Digest in the
602 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
603 CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate);
604 CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest);
605 if (!digestValue || !CFEqual(sha1Digest, digestValue))
606 exception = NULL;
607
608 return exception;
609 }
610
611 static void SecTrustCheckException(const void *key, const void *value, void *context)
612 {
613 struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context;
614 if (cec->exception) {
615 CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key);
616 if (!exceptionValue || !CFEqual(value, exceptionValue)) {
617 cec->exceptionNotFound = true;
618 }
619 } else {
620 cec->exceptionNotFound = true;
621 }
622 }
623
624 /* new in 10.9 */
625 CFDataRef SecTrustCopyExceptions(SecTrustRef trust)
626 {
627 CFArrayRef details = SecTrustCopyDetails(trust);
628 CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
629 CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault,
630 pathLength, &kCFTypeArrayCallBacks);
631 CFIndex ix;
632 for (ix = 0; ix < pathLength; ++ix) {
633 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
634 CFIndex detailCount = CFDictionaryGetCount(detail);
635 CFMutableDictionaryRef exception;
636 if (ix == 0 || detailCount > 0) {
637 exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
638 detailCount + 1, detail);
639 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
640 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
641 if (digest) {
642 CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
643 }
644 } else {
645 /* Add empty exception dictionaries for non leaf certs which have no exceptions
646 * to save space.
647 */
648 exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault,
649 NULL, NULL, 0,
650 &kCFTypeDictionaryKeyCallBacks,
651 &kCFTypeDictionaryValueCallBacks);
652 }
653 CFArrayAppendValue(exceptions, exception);
654 CFReleaseNull(exception);
655 }
656 CFReleaseSafe(details);
657
658 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
659 since it will never be empty). */
660 for (ix = pathLength; ix-- > 1;) {
661 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
662 if (CFDictionaryGetCount(exception) == 0) {
663 CFArrayRemoveValueAtIndex(exceptions, ix);
664 } else {
665 break;
666 }
667 }
668
669 CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
670 exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
671 CFRelease(exceptions);
672
673 return encodedExceptions;
674 }
675
676 /* new in 10.9 */
677 bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions)
678 {
679 CFArrayRef exceptions;
680 exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
681 encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
682 if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
683 CFRelease(exceptions);
684 exceptions = NULL;
685 }
686
687 OSStatus __secapiresult = errSecSuccess;
688 try {
689 Trust::required(trust)->exceptions(exceptions);
690 }
691 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
692 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
693 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
694 catch (...) { __secapiresult=errSecInternalComponent; }
695
696 /* If there is a valid exception entry for our current leaf we're golden. */
697 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
698 return true;
699
700 /* The passed in exceptions didn't match our current leaf, so we discard it. */
701 try {
702 Trust::required(trust)->exceptions(NULL);
703 __secapiresult = errSecSuccess;
704 }
705 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
706 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
707 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
708 catch (...) { __secapiresult=errSecInternalComponent; }
709
710 return false;
711 }
712
713 /* new in 10.9 */
714 CFDictionaryRef
715 SecTrustCopyResult(SecTrustRef trust)
716 {
717 CFDictionaryRef result = NULL;
718 try {
719 result = Trust::required(trust)->results();
720 // merge details into result
721 CFArrayRef details = SecTrustCopyDetails(trust);
722 if (details) {
723 CFDictionarySetValue((CFMutableDictionaryRef)result,
724 kSecTrustResultDetails, details);
725 CFRelease(details);
726 }
727 }
728 catch (...) {
729 if (result) {
730 CFRelease(result);
731 result = NULL;
732 }
733 }
734 return result;
735 }
736
737 /* new in 10.7 */
738 CFArrayRef
739 SecTrustCopyProperties(SecTrustRef trust)
740 {
741 /* can't use SECAPI macros, since this function does not return OSStatus */
742 CFArrayRef result = NULL;
743 try {
744 result = Trust::required(trust)->properties();
745 }
746 catch (...) {
747 if (result) {
748 CFRelease(result);
749 result = NULL;
750 }
751 }
752 return result;
753 }
754
755
756 /* deprecated in 10.5 */
757 OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
758 uint32 *cssmAnchorCount)
759 {
760 BEGIN_SECAPI
761 CertGroup certs;
762 Trust::gStore().getCssmRootCertificates(certs);
763 Required(cssmAnchors) = certs.blobCerts();
764 Required(cssmAnchorCount) = certs.count();
765 END_SECAPI
766 }
767
768
769 //
770 // Get and set user trust settings. Deprecated in 10.5.
771 // User Trust getter, deprecated, works as it always has.
772 //
773 OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
774 SecPolicyRef policy, SecTrustUserSetting *trustSetting)
775 {
776 BEGIN_SECAPI
777 StorageManager::KeychainList searchList;
778 globals().storageManager.getSearchList(searchList);
779 Required(trustSetting) = Trust::gStore().find(
780 Certificate::required(certificate),
781 Policy::required(policy),
782 searchList);
783 END_SECAPI
784 }
785
786 //
787 // The public setter, also deprecated; it maps to the appropriate
788 // Trust Settings call if possible, else throws errSecUnimplemented.
789 //
790 OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
791 SecPolicyRef policy, SecTrustUserSetting trustSetting)
792 {
793 SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
794 OSStatus ortn;
795 Boolean isRoot;
796
797 Policy::required(policy);
798 switch(trustSetting) {
799 case kSecTrustResultProceed:
800 /* different SecTrustSettingsResult depending in root-ness */
801 ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
802 if(ortn) {
803 return ortn;
804 }
805 if(isRoot) {
806 tsResult = kSecTrustSettingsResultTrustRoot;
807 }
808 else {
809 tsResult = kSecTrustSettingsResultTrustAsRoot;
810 }
811 break;
812 case kSecTrustResultDeny:
813 tsResult = kSecTrustSettingsResultDeny;
814 break;
815 default:
816 return errSecUnimplemented;
817 }
818
819 /* make a usage constraints dictionary */
820 CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
821 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
822 CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
823 if(tsResult != kSecTrustSettingsResultTrustRoot) {
824 /* skip if we're specifying the default */
825 SInt32 result = tsResult;
826 CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
827 CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
828 CFRelease(cfNum);
829 }
830 return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
831 usageDict);
832 }
833
834 //
835 // This one is the now-private version of what SecTrustSetUserTrust() used to
836 // be. The public API can no longer manipulate User Trust settings, only
837 // view them.
838 //
839 OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
840 SecPolicyRef policy, SecTrustUserSetting trustSetting)
841 {
842 BEGIN_SECAPI
843 switch (trustSetting) {
844 case kSecTrustResultProceed:
845 case kSecTrustResultConfirm:
846 case kSecTrustResultDeny:
847 case kSecTrustResultUnspecified:
848 break;
849 default:
850 MacOSError::throwMe(errSecInvalidTrustSetting);
851 }
852 Trust::gStore().assign(
853 Certificate::required(certificate),
854 Policy::required(policy),
855 trustSetting);
856 END_SECAPI
857 }
858
859 /* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface,
860 but could be useful in the future.
861 */
862 /*
863 CSSM_TP_HANDLE
864 SecGetAppleTPHandle()
865 {
866 BEGIN_SECAPI
867 return TP(gGuidAppleX509TP)->handle();
868 END_SECAPI1(NULL);
869 }
870 */
871
872