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