]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecTrust.cpp
Security-57337.50.23.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecTrust.cpp
1 /*
2 * Copyright (c) 2002-2015 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 "SecBase.h"
29 #include "SecBridge.h"
30 #include "SecInternal.h"
31 #include "SecInternalP.h"
32 #include "SecTrustSettings.h"
33 #include "SecCertificatePriv.h"
34 #include "SecCertificateP.h"
35 #include "SecCertificatePrivP.h"
36 #include "SecPolicyPriv.h"
37 #include <security_utilities/cfutilities.h>
38 #include <security_utilities/cfmunge.h>
39 #include <CoreFoundation/CoreFoundation.h>
40 #include <syslog.h>
41
42 // forward declarations
43 #if !SECTRUST_OSX
44 CFArrayRef SecTrustCopyDetails(SecTrustRef trust);
45 static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix);
46 static void SecTrustCheckException(const void *key, const void *value, void *context);
47 #endif
48
49 typedef struct SecTrustCheckExceptionContext {
50 CFDictionaryRef exception;
51 bool exceptionNotFound;
52 } SecTrustCheckExceptionContext;
53
54 // public trust result constants
55 const CFStringRef kSecTrustEvaluationDate = CFSTR("TrustEvaluationDate");
56 const CFStringRef kSecTrustExtendedValidation = CFSTR("TrustExtendedValidation");
57 const CFStringRef kSecTrustOrganizationName = CFSTR("Organization");
58 const CFStringRef kSecTrustResultValue = CFSTR("TrustResultValue");
59 const CFStringRef kSecTrustRevocationChecked = CFSTR("TrustRevocationChecked");
60 const CFStringRef kSecTrustRevocationReason = CFSTR("TrustRevocationReason");
61 const CFStringRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate");
62 const CFStringRef kSecTrustResultDetails = CFSTR("TrustResultDetails");
63
64 //
65 // CF boilerplate
66 //
67 #if !SECTRUST_OSX
68 CFTypeID SecTrustGetTypeID(void)
69 {
70 BEGIN_SECAPI
71
72 return gTypes().Trust.typeID;
73
74 END_SECAPI1(_kCFRuntimeNotATypeID)
75 }
76 #endif
77
78 //
79 // Sec* API bridge functions
80 //
81 #if !SECTRUST_OSX
82 OSStatus SecTrustCreateWithCertificates(
83 CFTypeRef certificates,
84 CFTypeRef policies,
85 SecTrustRef *trustRef)
86 {
87 BEGIN_SECAPI
88 Required(trustRef);
89 *trustRef = (new Trust(certificates, policies))->handle();
90 END_SECAPI
91 }
92 #endif
93
94 #if !SECTRUST_OSX
95 OSStatus
96 SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
97 {
98 BEGIN_SECAPI
99 Trust::required(trustRef)->policies(policies);
100 END_SECAPI
101 }
102 #endif
103
104 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
105 OSStatus
106 SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options)
107 {
108 #if !SECTRUST_OSX
109 BEGIN_SECAPI
110 CSSM_APPLE_TP_ACTION_DATA actionData = {
111 CSSM_APPLE_TP_ACTION_VERSION,
112 (CSSM_APPLE_TP_ACTION_FLAGS)options
113 };
114 Trust *trust = Trust::required(trustRef);
115 CFDataRef actionDataRef = CFDataCreate(NULL,
116 (const UInt8 *)&actionData,
117 (CFIndex)sizeof(CSSM_APPLE_TP_ACTION_DATA));
118 trust->action(CSSM_TP_ACTION_DEFAULT);
119 trust->actionData(actionDataRef);
120 if (actionDataRef) CFRelease(actionDataRef);
121 END_SECAPI
122 #else
123 /* bridge to support API functionality for legacy callers */
124 OSStatus status = errSecSuccess;
125 #if 1
126 #warning STU: <rdar://21328005>
127 //%%% need to ensure that the exception covers only the requested options
128 #else
129 CFArrayRef details = SecTrustGetDetails(trustRef); // NOTE: performs the evaluation if not done already
130 CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
131 CFIndex ix;
132 for (ix = 0; ix < pathLength; ++ix) {
133 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
134 CFIndex detailCount = CFDictionaryGetCount(detail);
135 if (detailCount > 0) {
136 // see if we can ignore this error
137 syslog(LOG_ERR, "SecTrustSetOptions: examining detail dictionary items at ix %ld", (long)ix);
138 CFShow(detail);
139 }
140 }
141 syslog(LOG_ERR, "SecTrustSetOptions: creating trust exception");
142 #endif
143 CFDataRef exceptions = SecTrustCopyExceptions(trustRef);
144 if (exceptions) {
145 SecTrustSetExceptions(trustRef, exceptions);
146 CFRelease(exceptions);
147 }
148
149
150 #if SECTRUST_DEPRECATION_WARNINGS
151 bool displayModifyMsg = false;
152 bool displayNetworkMsg = false;
153 bool displayPolicyMsg = false;
154 const char *baseMsg = "WARNING: SecTrustSetOptions called with";
155 const char *modifyMsg = "Use SecTrustSetExceptions and SecTrustCopyExceptions to modify default trust results.";
156 const char *networkMsg = "Use SecTrustSetNetworkFetchAllowed to specify whether missing certificates can be fetched from the network.";
157 const char *policyMsg = "Use SecPolicyCreateRevocation to specify revocation policy requirements.";
158
159 if (options & kSecTrustOptionAllowExpired) {
160 syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpired");
161 displayModifyMsg = true;
162 }
163 if (options & kSecTrustOptionAllowExpiredRoot) {
164 syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpiredRoot");
165 displayModifyMsg = true;
166 }
167 if (options & kSecTrustOptionFetchIssuerFromNet) {
168 syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionFetchIssuerFromNet");
169 displayNetworkMsg = true;
170 }
171 if (options & kSecTrustOptionRequireRevPerCert) {
172 syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionRequireRevPerCert");
173 displayPolicyMsg = true;
174 }
175 if (displayModifyMsg || displayNetworkMsg || displayPolicyMsg) {
176 syslog(LOG_ERR, "%s %s %s",
177 (displayModifyMsg) ? modifyMsg : "",
178 (displayNetworkMsg) ? networkMsg : "",
179 (displayPolicyMsg) ? policyMsg : "");
180 }
181 #endif
182
183 return status;
184
185 #endif
186 }
187
188 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
189 OSStatus SecTrustSetParameters(
190 SecTrustRef trustRef,
191 CSSM_TP_ACTION action,
192 CFDataRef actionData)
193 {
194 #if !SECTRUST_OSX
195 BEGIN_SECAPI
196 Trust *trust = Trust::required(trustRef);
197 trust->action(action);
198 trust->actionData(actionData);
199 END_SECAPI
200 #else
201 /* bridge to support API functionality for legacy callers */
202 OSStatus status;
203 CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0;
204 if (actionData) {
205 CSSM_APPLE_TP_ACTION_DATA *actionDataPtr = (CSSM_APPLE_TP_ACTION_DATA *) CFDataGetBytePtr(actionData);
206 if (actionDataPtr) {
207 actionFlags = actionDataPtr->ActionFlags;
208 }
209 }
210 // note that SecTrustOptionFlags == CSSM_APPLE_TP_ACTION_FLAGS;
211 // both are sizeof(uint32) and the flag values have identical meanings
212 status = SecTrustSetOptions(trustRef, (SecTrustOptionFlags)actionFlags);
213
214 #if SECTRUST_DEPRECATION_WARNINGS
215 syslog(LOG_ERR, "WARNING: SecTrustSetParameters was deprecated in 10.7. Use SecTrustSetOptions instead.");
216 #endif
217
218 return status;
219
220 #endif
221 }
222
223 #if !SECTRUST_OSX
224 OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
225 {
226 BEGIN_SECAPI
227 Trust::required(trust)->anchors(anchorCertificates);
228 END_SECAPI
229 }
230 #endif
231
232 #if !SECTRUST_OSX
233 OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly)
234 {
235 BEGIN_SECAPI
236 Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns;
237 Trust::required(trust)->anchorPolicy(policy);
238 END_SECAPI
239 }
240 #endif
241
242 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
243 OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
244 {
245 #if !SECTRUST_OSX
246 BEGIN_SECAPI
247 StorageManager::KeychainList keychains;
248 // avoid unnecessary global initializations if an empty array is passed in
249 if (!( (keychainOrArray != NULL) &&
250 (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) &&
251 (CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) {
252 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
253 }
254 Trust::required(trust)->searchLibs(keychains);
255 END_SECAPI
256 #else
257 /* this function is currently unsupported in unified SecTrust */
258 // TODO: pull all certs out of the specified keychains for the evaluation?
259 #if SECTRUST_DEPRECATION_WARNINGS
260 syslog(LOG_ERR, "WARNING: SecTrustSetKeychains does nothing in 10.11. Use SecTrustSetAnchorCertificates{Only} to provide anchors.");
261 #endif
262 return errSecSuccess;
263 #endif
264 }
265
266 #if !SECTRUST_OSX
267 OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
268 {
269 BEGIN_SECAPI
270 Trust::required(trust)->time(verifyDate);
271 END_SECAPI
272 }
273 #endif
274
275 #if !SECTRUST_OSX
276 CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
277 {
278 CFAbsoluteTime verifyTime = 0;
279 OSStatus __secapiresult = errSecSuccess;
280 try {
281 CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
282 verifyTime = CFDateGetAbsoluteTime(verifyDate);
283 }
284 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
285 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
286 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
287 catch (...) { __secapiresult=errSecInternalComponent; }
288 return verifyTime;
289 }
290 #endif
291
292
293
294 #if !SECTRUST_OSX
295 OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP)
296 {
297 SecTrustResultType trustResult = kSecTrustResultInvalid;
298 CFArrayRef exceptions = NULL;
299 OSStatus __secapiresult = errSecSuccess;
300 try {
301 Trust *trustObj = Trust::required(trust);
302 trustObj->evaluate();
303 trustResult = trustObj->result();
304 exceptions = trustObj->exceptions();
305 }
306 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
307 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
308 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
309 catch (...) { __secapiresult=errSecInternalComponent; }
310
311 if (__secapiresult) {
312 return __secapiresult;
313 }
314
315 /* post-process trust result based on exceptions */
316 if (trustResult == kSecTrustResultUnspecified) {
317 /* If leaf is in exceptions -> proceed, otherwise unspecified. */
318 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
319 trustResult = kSecTrustResultProceed;
320 }
321 else if (trustResult == kSecTrustResultRecoverableTrustFailure && exceptions) {
322 /* If we have exceptions get details and match to exceptions. */
323 CFArrayRef details = SecTrustCopyDetails(trust);
324 if (details) {
325 CFIndex pathLength = CFArrayGetCount(details);
326 struct SecTrustCheckExceptionContext context = {};
327 CFIndex ix;
328 for (ix = 0; ix < pathLength; ++ix) {
329 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
330 // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
331 // trustResult = kSecTrustResultFatalTrustFailure;
332 context.exception = SecTrustGetExceptionForCertificateAtIndex(trust, ix);
333 CFDictionaryApplyFunction(detail, SecTrustCheckException, &context);
334 if (context.exceptionNotFound) {
335 break;
336 }
337 }
338 if (!context.exceptionNotFound)
339 trustResult = kSecTrustResultProceed;
340 }
341 }
342
343
344 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult);
345 if (resultP) {
346 *resultP = trustResult;
347 }
348 return __secapiresult;
349 }
350 #endif
351
352 #if !SECTRUST_OSX
353 OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
354 dispatch_queue_t queue, SecTrustCallback result)
355 {
356 BEGIN_SECAPI
357 dispatch_async(queue, ^{
358 try {
359 Trust *trustObj = Trust::required(trust);
360 trustObj->evaluate();
361 SecTrustResultType trustResult = trustObj->result();
362 result(trust, trustResult);
363 }
364 catch (...) {
365 result(trust, kSecTrustResultInvalid);
366 };
367 });
368 END_SECAPI
369 }
370 #endif
371
372 //
373 // Construct the "official" result evidence and return it
374 //
375 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
376 OSStatus SecTrustGetResult(
377 SecTrustRef trustRef,
378 SecTrustResultType *result,
379 CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain)
380 {
381 #if !SECTRUST_OSX
382 BEGIN_SECAPI
383 Trust *trust = Trust::required(trustRef);
384 if (result)
385 *result = trust->result();
386 if (certChain && statusChain)
387 trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain));
388 END_SECAPI
389 #else
390 /* bridge to support old functionality */
391 #if SECTRUST_DEPRECATION_WARNINGS
392 syslog(LOG_ERR, "WARNING: SecTrustGetResult has been deprecated since 10.7, and may not return a statusChain in 10.11. Please use SecTrustGetTrustResult instead.");
393 #endif
394 SecTrustResultType trustResult;
395 OSStatus status = SecTrustGetTrustResult(trustRef, &trustResult);
396 if (result) {
397 *result = trustResult;
398 }
399 if (certChain && !statusChain) {
400 /* This is the easy case; caller only wants cert chain and not status chain. */
401 CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
402 CFIndex idx, count = SecTrustGetCertificateCount(trustRef);
403 for (idx=0; idx < count; idx++) {
404 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx);
405 if (certificate) {
406 CFArrayAppendValue(certArray, certificate);
407 }
408 }
409 *certChain = certArray;
410 }
411 else if (certChain && statusChain) {
412 /*
413 * Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO* is tied to a
414 * Trust object and does not exist in the new unified world. Unfortunately, some clients are
415 * still calling this legacy API and grubbing through the info for StatusBits and StatusCodes.
416 * If they want this info, then we have to do a legacy evaluation to get it. The info struct
417 * goes away once the old-style object does, so we must keep the old-style object alive after
418 * returning from the function.
419 *
420 * TODO: keep a dictionary and figure out how to expire entries when no longer needed.,
421 * or build the evidence info ourselves: rdar://21005914
422 */
423 static CFMutableArrayRef sTrustArray = NULL;
424
425 // make array of Certificate instances from unified SecCertificateRefs
426 CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
427 CFIndex idx, count = SecTrustGetCertificateCount(trustRef);
428 for (idx=0; idx < count; idx++) {
429 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx);
430 if (certificate) {
431 SecCertificateRef itemImplRef = SecCertificateCreateItemImplInstance(certificate);
432 if (itemImplRef) {
433 CFArrayAppendValue(certArray, itemImplRef);
434 CFRelease(itemImplRef);
435 }
436 }
437 }
438 // make array of Policy instances from unified SecPolicyRefs
439 CFMutableArrayRef policyArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
440 CFArrayRef policies = NULL;
441 status = SecTrustCopyPolicies(trustRef, &policies);
442 count = (!status && policies) ? CFArrayGetCount(policies) : 0;
443 for (idx=0; idx < count; idx++) {
444 SecPolicyRef policy = (SecPolicyRef) CFArrayGetValueAtIndex(policies, idx);
445 if (policy) {
446 SecPolicyRef itemImplRef = SecPolicyCreateItemImplInstance(policy);
447 if (itemImplRef) {
448 CFArrayAppendValue(policyArray, itemImplRef);
449 CFRelease(itemImplRef);
450 }
451 }
452 }
453 // now make a Trust instance and evaluate it
454 try {
455 Trust *trustObj = new Trust(certArray, policyArray);
456 SecTrustRef trust = trustObj->handle();
457 if (!trust) {
458 MacOSError::throwMe(errSecTrustNotAvailable);
459 }
460 if (!sTrustArray) {
461 sTrustArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
462 if (!sTrustArray) {
463 MacOSError::throwMe(errSecAllocate);
464 }
465 }
466 // fetch the built cert chain and status chain
467 CFArrayRef itemImplCertArray = NULL;
468 trustObj->evaluate();
469 trustObj->buildEvidence(itemImplCertArray, TPEvidenceInfo::overlayVar(*statusChain));
470
471 // convert each Certificate in the built chain to a unified SecCertificateRef
472 CFMutableArrayRef outCertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
473 CFIndex idx, count = (itemImplCertArray) ? CFArrayGetCount(itemImplCertArray) : 0;
474 for (idx=0; idx < count; idx++) {
475 SecCertificateRef inCert = (SecCertificateRef) CFArrayGetValueAtIndex(itemImplCertArray, idx);
476 SecCertificateRef outCert = SecCertificateCreateFromItemImplInstance(inCert);
477 if (outCert) {
478 CFArrayAppendValue(outCertChain, outCert);
479 CFRelease(outCert);
480 }
481 }
482 *certChain = outCertChain;
483 if (itemImplCertArray) {
484 CFRelease(itemImplCertArray);
485 }
486 CFArrayAppendValue(sTrustArray, trust);
487 status = errSecSuccess;
488 }
489 catch (const MacOSError &err) { status=err.osStatus(); }
490 catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); }
491 catch (const std::bad_alloc &) { status=errSecAllocate; }
492 catch (...) { status=errSecInternalComponent; }
493
494 if (policyArray)
495 CFRelease(policyArray);
496 if (certArray)
497 CFRelease(certArray);
498 }
499 return status;
500 #endif
501 }
502
503 //
504 // Retrieve result of trust evaluation only
505 //
506 #if !SECTRUST_OSX
507 OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
508 SecTrustResultType *result)
509 {
510 BEGIN_SECAPI
511 Trust *trust = Trust::required(trustRef);
512 if (result) *result = trust->result();
513 END_SECAPI
514 }
515 #endif
516
517 //
518 // Retrieve extended validation trust results
519 //
520 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
521 OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
522 {
523 #if !SECTRUST_OSX
524 BEGIN_SECAPI
525 Trust *trustObj = Trust::required(trust);
526 if (result == nil)
527 return errSecParam;
528 trustObj->extendedResult(*result);
529 END_SECAPI
530 #else
531 /* bridge to support old functionality */
532 #if SECTRUST_DEPRECATION_WARNINGS
533 syslog(LOG_ERR, "WARNING: SecTrustCopyExtendedResult will be deprecated in an upcoming release. Please use SecTrustCopyResult instead.");
534 #endif
535 CFDictionaryRef resultDict = SecTrustCopyResult(trust);
536 if (result == nil) {
537 return errSecParam;
538 }
539 *result = resultDict;
540 return errSecSuccess;
541 #endif
542 }
543
544 //
545 // Retrieve CSSM-level information for those who want to dig down
546 //
547 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
548 OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result)
549 {
550 #if !SECTRUST_OSX
551 BEGIN_SECAPI
552 Required(result) = Trust::required(trust)->cssmResult();
553 END_SECAPI
554 #else
555 /* this function is unsupported in unified SecTrust */
556 #if SECTRUST_DEPRECATION_WARNINGS
557 syslog(LOG_ERR, "WARNING: SecTrustGetCssmResult has been deprecated since 10.7, and has no functional equivalent in 10.11. Please use SecTrustCopyResult instead.");
558 #endif
559 if (result) {
560 *result = NULL;
561 }
562 return errSecServiceNotAvailable;
563 #endif
564 }
565
566 #if SECTRUST_OSX
567 static void applyPropertyToCssmResultCode(const void *_key, const void *_value, void *context) {
568 CFStringRef key = (CFStringRef)_key;
569 CFStringRef value = (CFStringRef)_value;
570 OSStatus *result = (OSStatus *)context;
571 if (CFGetTypeID(_value) != CFStringGetTypeID()) {
572 return;
573 }
574 if (!CFEqual(CFSTR("value"), key)) {
575 return;
576 }
577 if (CFEqual(CFSTR("Invalid certificate chain linkage."), value)) {
578 *result = CSSMERR_APPLETP_INVALID_ID_LINKAGE;
579 } else if (CFEqual(CFSTR("One or more unsupported critical extensions found."), value)) {
580 *result = CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN;
581 } else if (CFEqual(CFSTR("Root certificate is not trusted."), value)) {
582 *result = CSSMERR_TP_NOT_TRUSTED;
583 } else if (CFEqual(CFSTR("Hostname mismatch."), value)) {
584 *result = CSSMERR_APPLETP_HOSTNAME_MISMATCH;
585 } else if (CFEqual(CFSTR("One or more certificates have expired or are not valid yet."), value)) {
586 *result = CSSMERR_TP_CERT_EXPIRED;
587 } else if (CFEqual(CFSTR("Policy requirements not met."), value)) {
588 *result = CSSMERR_TP_VERIFY_ACTION_FAILED;
589 }
590 }
591 #endif
592
593 //
594 // Retrieve CSSM_LEVEL TP return code
595 //
596 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
597 OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
598 {
599 #if !SECTRUST_OSX
600 BEGIN_SECAPI
601 Trust *trust = Trust::required(trustRef);
602 if (trust->result() == kSecTrustResultInvalid)
603 return errSecParam;
604 else
605 Required(result) = trust->cssmResultCode();
606 END_SECAPI
607 #else
608 /* bridge to support old functionality */
609 #if SECTRUST_DEPRECATION_WARNINGS
610 syslog(LOG_ERR, "WARNING: SecTrustGetCssmResultCode has been deprecated since 10.7, and will be removed in a future release. Please use SecTrustCopyProperties instead.");
611 #endif
612 if (!trustRef || !result) {
613 return errSecParam;
614 }
615 CFArrayRef properties = SecTrustCopyProperties(trustRef);
616 if (!properties) {
617 *result = 0;
618 return errSecSuccess;
619 }
620 OSStatus cssmResultCode = 0;
621 CFIndex ix, count = CFArrayGetCount(properties);
622 for (ix = 0; ix < count; ++ix) {
623 CFDictionaryRef property = (CFDictionaryRef)
624 CFArrayGetValueAtIndex(properties, ix);
625 CFDictionaryApplyFunction(property, applyPropertyToCssmResultCode, &cssmResultCode);
626 }
627 if (result) {
628 *result = cssmResultCode;
629 }
630 if (properties) {
631 CFRelease(properties);
632 }
633 return errSecSuccess;
634 #endif
635 }
636
637 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
638 OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
639 {
640 #if !SECTRUST_OSX
641 BEGIN_SECAPI
642 Required(handle) = Trust::required(trust)->getTPHandle();
643 END_SECAPI
644 #else
645 /* this function is unsupported in unified SecTrust */
646 #if SECTRUST_DEPRECATION_WARNINGS
647 syslog(LOG_ERR, "WARNING: SecTrustGetTPHandle has been deprecated since 10.7, and cannot return CSSM objects in 10.11. Please stop using it.");
648 #endif
649 if (handle) {
650 *handle = NULL;
651 }
652 return errSecServiceNotAvailable;
653 #endif
654 }
655
656 #if !SECTRUST_OSX
657 OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
658 {
659 BEGIN_SECAPI
660 CFArrayRef currentPolicies = Trust::required(trust)->policies();
661 if (currentPolicies != NULL)
662 {
663 CFRetain(currentPolicies);
664 }
665
666 Required(policies) = currentPolicies;
667 END_SECAPI
668 }
669 #endif
670
671 #if !SECTRUST_OSX
672 OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch)
673 {
674 BEGIN_SECAPI
675 Trust *trustObj = Trust::required(trust);
676 Trust::NetworkPolicy netPolicy = (allowFetch) ?
677 Trust::useNetworkEnabled : Trust::useNetworkDisabled;
678 trustObj->networkPolicy(netPolicy);
679 END_SECAPI
680 }
681 #endif
682
683 #if !SECTRUST_OSX
684 OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch)
685 {
686 BEGIN_SECAPI
687 Boolean allowed = false;
688 Trust *trustObj = Trust::required(trust);
689 Trust::NetworkPolicy netPolicy = trustObj->networkPolicy();
690 if (netPolicy == Trust::useNetworkDefault) {
691 // network fetch is enabled by default for SSL only
692 allowed = trustObj->policySpecified(trustObj->policies(), CSSMOID_APPLE_TP_SSL);
693 } else {
694 // caller has explicitly set the network policy
695 allowed = (netPolicy == Trust::useNetworkEnabled);
696 }
697 Required(allowFetch) = allowed;
698 END_SECAPI
699 }
700 #endif
701
702 #if !SECTRUST_OSX
703 OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData)
704 {
705 BEGIN_SECAPI
706 Trust::required(trust)->responses(responseData);
707 END_SECAPI
708 }
709 #endif
710
711 #if !SECTRUST_OSX
712 OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
713 {
714 BEGIN_SECAPI
715 CFArrayRef customAnchors = Trust::required(trust)->anchors();
716 Required(anchorCertificates) = (customAnchors) ?
717 (const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL;
718 END_SECAPI
719 }
720 #endif
721
722 //
723 // Get the user's default anchor certificate set
724 //
725 /* OS X only */
726 OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
727 {
728 BEGIN_SECAPI
729
730 return SecTrustSettingsCopyUnrestrictedRoots(
731 true, true, true, /* all domains */
732 anchorCertificates);
733
734 END_SECAPI
735 }
736
737 #if SECTRUST_OSX
738 /* We have an iOS-style SecTrustRef, but we need to return a CDSA-based SecKeyRef.
739 */
740 SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
741 {
742 SecKeyRef pubKey = NULL;
743 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, 0);
744 (void) SecCertificateCopyPublicKey(certificate, &pubKey);
745 return pubKey;
746 }
747 #else
748 /* new in 10.6 */
749 SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
750 {
751 SecKeyRef pubKey = NULL;
752 CFArrayRef certChain = NULL;
753 CFArrayRef evidenceChain = NULL;
754 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
755 OSStatus __secapiresult = errSecSuccess;
756 try {
757 Trust *trustObj = Trust::required(trust);
758 if (trustObj->result() == kSecTrustResultInvalid) {
759 // Trust hasn't been evaluated; attempt to retrieve public key from leaf.
760 SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0);
761 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
762 if (pubKey) {
763 return pubKey;
764 }
765 // Otherwise, we must evaluate first.
766 trustObj->evaluate();
767 if (trustObj->result() == kSecTrustResultInvalid) {
768 MacOSError::throwMe(errSecTrustNotAvailable);
769 }
770 }
771 if (trustObj->evidence() == nil) {
772 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
773 }
774 evidenceChain = trustObj->evidence();
775 }
776 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
777 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
778 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
779 catch (...) { __secapiresult=errSecInternalComponent; }
780
781 if (certChain)
782 CFRelease(certChain);
783
784 if (evidenceChain) {
785 if (CFArrayGetCount(evidenceChain) > 0) {
786 SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
787 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
788 }
789 // do not release evidenceChain, as it is owned by the trust object.
790 }
791 return pubKey;
792 }
793 #endif
794
795 #if !SECTRUST_OSX
796 /* new in 10.6 */
797 CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
798 {
799 CFIndex chainLen = 0;
800 CFArrayRef certChain = NULL;
801 CFArrayRef evidenceChain = NULL;
802 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
803 OSStatus __secapiresult = errSecSuccess;
804 try {
805 Trust *trustObj = Trust::required(trust);
806 if (trustObj->result() == kSecTrustResultInvalid) {
807 trustObj->evaluate();
808 if (trustObj->result() == kSecTrustResultInvalid)
809 MacOSError::throwMe(errSecTrustNotAvailable);
810 }
811 if (trustObj->evidence() == nil)
812 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
813 evidenceChain = trustObj->evidence();
814 }
815 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
816 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
817 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
818 catch (...) { __secapiresult=errSecInternalComponent; }
819
820 if (certChain)
821 CFRelease(certChain);
822
823 if (evidenceChain)
824 chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it.
825
826 return chainLen;
827 }
828 #endif
829
830 #if !SECTRUST_OSX
831 /* new in 10.6 */
832 SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
833 {
834 SecCertificateRef certificate = NULL;
835 CFArrayRef certChain = NULL;
836 CFArrayRef evidenceChain = NULL;
837 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
838 OSStatus __secapiresult = errSecSuccess;
839 try {
840 Trust *trustObj = Trust::required(trust);
841 if (trustObj->result() == kSecTrustResultInvalid) {
842 // If caller is asking for the leaf, we can return it without
843 // having to evaluate the entire chain. Note that we don't retain
844 // the cert as it's owned by the trust and this is a 'Get' API.
845 if (ix == 0) {
846 CFArrayRef certs = trustObj->certificates();
847 if (certs && (CFArrayGetCount(certs) > 0)) {
848 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(certs, 0);
849 if (certificate) {
850 return certificate;
851 }
852 }
853 }
854 // Otherwise, we must evaluate first.
855 trustObj->evaluate();
856 if (trustObj->result() == kSecTrustResultInvalid) {
857 MacOSError::throwMe(errSecTrustNotAvailable);
858 }
859 }
860 if (trustObj->evidence() == nil) {
861 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
862 }
863 evidenceChain = trustObj->evidence();
864 }
865 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
866 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
867 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
868 catch (...) { __secapiresult=errSecInternalComponent; }
869
870 if (certChain)
871 CFRelease(certChain);
872
873 if (evidenceChain) {
874 if (ix < CFArrayGetCount(evidenceChain)) {
875 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
876 // note: we do not retain this certificate. The assumption here is
877 // that the certificate is retained by the trust object, so it is
878 // valid unil the trust is released (or until re-evaluated.)
879 // also note: we do not release the evidenceChain, as it is owned
880 // by the trust object.
881 }
882 }
883 return certificate;
884 }
885 #endif
886
887
888 #if !SECTRUST_OSX
889 static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
890 static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes");
891
892 static void
893 _AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode)
894 {
895 if (!array)
896 return;
897 SInt32 num = statusCode;
898 CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num);
899 if (!numRef)
900 return;
901 CFArrayAppendValue(array, numRef);
902 CFRelease(numRef);
903 }
904 #endif
905
906 #if !SECTRUST_OSX
907 CFArrayRef SecTrustCopyDetails(SecTrustRef trust)
908 {
909 // This function returns an array of dictionaries, one per certificate,
910 // holding status info for each certificate in the evaluated chain.
911 //
912 CFIndex count, chainLen = 0;
913 CFArrayRef certChain = NULL;
914 CFMutableArrayRef details = NULL;
915 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
916 OSStatus __secapiresult = errSecSuccess;
917 try {
918 Trust *trustObj = Trust::required(trust);
919 if (trustObj->result() == kSecTrustResultInvalid) {
920 trustObj->evaluate();
921 if (trustObj->result() == kSecTrustResultInvalid)
922 MacOSError::throwMe(errSecTrustNotAvailable);
923 }
924 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
925 }
926 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
927 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
928 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
929 catch (...) { __secapiresult=errSecInternalComponent; }
930
931 if (certChain) {
932 chainLen = CFArrayGetCount(certChain);
933 CFRelease(certChain);
934 }
935 if (statusChain) {
936 details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks);
937 for (count = 0; count < chainLen; count++) {
938 CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
939 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
940 CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault,
941 0, &kCFTypeArrayCallBacks);
942 CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count];
943 CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits;
944
945 // translate status bits
946 if (statBits & CSSM_CERT_STATUS_EXPIRED)
947 _AppendStatusCode(statusCodes, errSecCertificateExpired);
948 if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET)
949 _AppendStatusCode(statusCodes, errSecCertificateNotValidYet);
950 if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY)
951 _AppendStatusCode(statusCodes, errSecTrustSettingDeny);
952
953 // translate status codes
954 unsigned int i;
955 for (i = 0; i < evInfo->NumStatusCodes; i++) {
956 CSSM_RETURN scode = evInfo->StatusCodes[i];
957 _AppendStatusCode(statusCodes, (OSStatus)scode);
958 }
959
960 CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes);
961 CFRelease(statusCodes);
962 CFArrayAppendValue(details, certDict);
963 CFRelease(certDict);
964 }
965 }
966 return details;
967 }
968 #endif
969
970 #if !SECTRUST_OSX
971 static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix)
972 {
973 CFArrayRef exceptions = NULL;
974 OSStatus __secapiresult = errSecSuccess;
975 try {
976 exceptions = Trust::required(trust)->exceptions();
977 }
978 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
979 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
980 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
981 catch (...) { __secapiresult=errSecInternalComponent; }
982
983 if (!exceptions || ix >= CFArrayGetCount(exceptions))
984 return NULL;
985 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
986 if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
987 return NULL;
988
989 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
990 if (!certificate)
991 return NULL;
992
993 /* If the exception contains the current certificate's sha1Digest in the
994 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
995 CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate);
996 CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest);
997 if (!digestValue || !CFEqual(sha1Digest, digestValue))
998 exception = NULL;
999
1000 return exception;
1001 }
1002 #endif
1003
1004 #if !SECTRUST_OSX
1005 static void SecTrustCheckException(const void *key, const void *value, void *context)
1006 {
1007 struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context;
1008 if (cec->exception) {
1009 CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key);
1010 if (!exceptionValue || !CFEqual(value, exceptionValue)) {
1011 cec->exceptionNotFound = true;
1012 }
1013 } else {
1014 cec->exceptionNotFound = true;
1015 }
1016 }
1017 #endif
1018
1019 #if !SECTRUST_OSX
1020 /* new in 10.9 */
1021 CFDataRef SecTrustCopyExceptions(SecTrustRef trust)
1022 {
1023 CFArrayRef details = SecTrustCopyDetails(trust);
1024 CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
1025 CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault,
1026 pathLength, &kCFTypeArrayCallBacks);
1027 CFIndex ix;
1028 for (ix = 0; ix < pathLength; ++ix) {
1029 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
1030 CFIndex detailCount = CFDictionaryGetCount(detail);
1031 CFMutableDictionaryRef exception;
1032 if (ix == 0 || detailCount > 0) {
1033 exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
1034 detailCount + 1, detail);
1035 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
1036 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
1037 if (digest) {
1038 CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
1039 }
1040 } else {
1041 /* Add empty exception dictionaries for non leaf certs which have no exceptions
1042 * to save space.
1043 */
1044 exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault,
1045 NULL, NULL, 0,
1046 &kCFTypeDictionaryKeyCallBacks,
1047 &kCFTypeDictionaryValueCallBacks);
1048 }
1049 CFArrayAppendValue(exceptions, exception);
1050 CFReleaseNull(exception);
1051 }
1052 CFReleaseSafe(details);
1053
1054 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
1055 since it will never be empty). */
1056 for (ix = pathLength; ix-- > 1;) {
1057 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
1058 if (CFDictionaryGetCount(exception) == 0) {
1059 CFArrayRemoveValueAtIndex(exceptions, ix);
1060 } else {
1061 break;
1062 }
1063 }
1064
1065 CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
1066 exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
1067 CFRelease(exceptions);
1068
1069 return encodedExceptions;
1070 }
1071 #endif
1072
1073 #if !SECTRUST_OSX
1074 /* new in 10.9 */
1075 bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions)
1076 {
1077 CFArrayRef exceptions;
1078 exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
1079 encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
1080 if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
1081 CFRelease(exceptions);
1082 exceptions = NULL;
1083 }
1084
1085 OSStatus __secapiresult = errSecSuccess;
1086 try {
1087 Trust::required(trust)->exceptions(exceptions);
1088 }
1089 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1090 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1091 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1092 catch (...) { __secapiresult=errSecInternalComponent; }
1093
1094 /* If there is a valid exception entry for our current leaf we're golden. */
1095 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
1096 return true;
1097
1098 /* The passed in exceptions didn't match our current leaf, so we discard it. */
1099 try {
1100 Trust::required(trust)->exceptions(NULL);
1101 __secapiresult = errSecSuccess;
1102 }
1103 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1104 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1105 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1106 catch (...) { __secapiresult=errSecInternalComponent; }
1107
1108 return false;
1109 }
1110 #endif
1111
1112 #if !SECTRUST_OSX
1113 /* new in 10.9 */
1114 CFDictionaryRef
1115 SecTrustCopyResult(SecTrustRef trust)
1116 {
1117 CFDictionaryRef result = NULL;
1118 try {
1119 result = Trust::required(trust)->results();
1120 // merge details into result
1121 CFArrayRef details = SecTrustCopyDetails(trust);
1122 if (details) {
1123 CFDictionarySetValue((CFMutableDictionaryRef)result,
1124 kSecTrustResultDetails, details);
1125 CFRelease(details);
1126 }
1127 }
1128 catch (...) {
1129 if (result) {
1130 CFRelease(result);
1131 result = NULL;
1132 }
1133 }
1134 return result;
1135 }
1136 #endif
1137
1138 #if !SECTRUST_OSX
1139 /* new in 10.7 */
1140 CFArrayRef
1141 SecTrustCopyProperties(SecTrustRef trust)
1142 {
1143 /* can't use SECAPI macros, since this function does not return OSStatus */
1144 CFArrayRef result = NULL;
1145 try {
1146 result = Trust::required(trust)->properties();
1147 }
1148 catch (...) {
1149 if (result) {
1150 CFRelease(result);
1151 result = NULL;
1152 }
1153 }
1154 return result;
1155 }
1156 #endif
1157
1158 /* deprecated in 10.5 */
1159 OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
1160 uint32 *cssmAnchorCount)
1161 {
1162 #if !SECTRUST_OSX
1163 BEGIN_SECAPI
1164 CertGroup certs;
1165 Trust::gStore().getCssmRootCertificates(certs);
1166 Required(cssmAnchors) = certs.blobCerts();
1167 Required(cssmAnchorCount) = certs.count();
1168 END_SECAPI
1169 #else
1170 /* this function is unsupported in unified SecTrust */
1171 #if SECTRUST_DEPRECATION_WARNINGS
1172 syslog(LOG_ERR, "WARNING: SecTrustGetCSSMAnchorCertificates has been deprecated since 10.5, and cannot return CSSM objects in 10.11. Please stop using it.");
1173 #endif
1174 if (cssmAnchors) {
1175 *cssmAnchors = NULL;
1176 }
1177 if (cssmAnchorCount) {
1178 *cssmAnchorCount = 0;
1179 }
1180 return errSecServiceNotAvailable;
1181 #endif
1182 }
1183
1184
1185 //
1186 // Get and set user trust settings. Deprecated in 10.5.
1187 // User Trust getter, deprecated, works as it always has.
1188 //
1189 OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
1190 SecPolicyRef policy, SecTrustUserSetting *trustSetting)
1191 {
1192 #if !SECTRUST_OSX
1193 BEGIN_SECAPI
1194 StorageManager::KeychainList searchList;
1195 globals().storageManager.getSearchList(searchList);
1196 Required(trustSetting) = Trust::gStore().find(
1197 Certificate::required(certificate),
1198 Policy::required(policy),
1199 searchList);
1200 END_SECAPI
1201 #else
1202 /* this function is unsupported in unified SecTrust */
1203 #if SECTRUST_DEPRECATION_WARNINGS
1204 syslog(LOG_ERR, "WARNING: SecTrustGetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1205 #endif
1206 return errSecServiceNotAvailable;
1207 #endif
1208 }
1209
1210 //
1211 // The public setter, also deprecated; it maps to the appropriate
1212 // Trust Settings call if possible, else throws errSecUnimplemented.
1213 //
1214 OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
1215 SecPolicyRef policy, SecTrustUserSetting trustSetting)
1216 {
1217 #if !SECTRUST_OSX
1218 SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
1219 OSStatus ortn;
1220 Boolean isRoot;
1221
1222 Policy::required(policy);
1223 switch(trustSetting) {
1224 case kSecTrustResultProceed:
1225 /* different SecTrustSettingsResult depending in root-ness */
1226 ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
1227 if(ortn) {
1228 return ortn;
1229 }
1230 if(isRoot) {
1231 tsResult = kSecTrustSettingsResultTrustRoot;
1232 }
1233 else {
1234 tsResult = kSecTrustSettingsResultTrustAsRoot;
1235 }
1236 break;
1237 case kSecTrustResultDeny:
1238 tsResult = kSecTrustSettingsResultDeny;
1239 break;
1240 default:
1241 return errSecUnimplemented;
1242 }
1243
1244 /* make a usage constraints dictionary */
1245 CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
1246 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
1247 CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
1248 if(tsResult != kSecTrustSettingsResultTrustRoot) {
1249 /* skip if we're specifying the default */
1250 SInt32 result = tsResult;
1251 CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
1252 CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
1253 CFRelease(cfNum);
1254 }
1255 return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
1256 usageDict);
1257 #else
1258 /* this function is unsupported in unified SecTrust */
1259 #if SECTRUST_DEPRECATION_WARNINGS
1260 syslog(LOG_ERR, "WARNING: SecTrustSetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1261 #endif
1262 return errSecServiceNotAvailable;
1263 #endif
1264 }
1265
1266 //
1267 // This one is the now-private version of what SecTrustSetUserTrust() used to
1268 // be. The public API can no longer manipulate User Trust settings, only
1269 // view them.
1270 //
1271 OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
1272 SecPolicyRef policy, SecTrustUserSetting trustSetting)
1273 {
1274 #if !SECTRUST_OSX
1275 BEGIN_SECAPI
1276 switch (trustSetting) {
1277 case kSecTrustResultProceed:
1278 case kSecTrustResultConfirm:
1279 case kSecTrustResultDeny:
1280 case kSecTrustResultUnspecified:
1281 break;
1282 default:
1283 MacOSError::throwMe(errSecInvalidTrustSetting);
1284 }
1285 Trust::gStore().assign(
1286 Certificate::required(certificate),
1287 Policy::required(policy),
1288 trustSetting);
1289 END_SECAPI
1290 #else
1291 /* this function is unsupported in unified SecTrust */
1292 #if SECTRUST_DEPRECATION_WARNINGS
1293 syslog(LOG_ERR, "WARNING: SecTrustSetUserTrustLegacy does nothing in 10.11. Please stop using it.");
1294 #endif
1295 return errSecServiceNotAvailable;
1296 #endif
1297 }