]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2007-2008,2010 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 | /* | |
25 | * SecTrustSettings.c - Implement trust settings for certificates | |
26 | */ | |
27 | ||
28 | #include "SecTrustSettings.h" | |
29 | #include "SecTrustSettingsPriv.h" | |
30 | #include <Security/SecCertificatePriv.h> | |
31 | #include <AssertMacros.h> | |
32 | #include <pthread.h> | |
427c49bc | 33 | #include <utilities/debugging.h> |
b1ab9ed8 A |
34 | #include "SecBasePriv.h" |
35 | #include <Security/SecInternal.h> | |
36 | #include <CoreFoundation/CFRuntime.h> | |
37 | ||
38 | #define trustSettingsDbg(args...) secdebug("trustSettings", ## args) | |
39 | #define trustSettingsEvalDbg(args...) secdebug("trustSettingsEval", ## args) | |
40 | ||
427c49bc A |
41 | // MARK: - |
42 | // MARK: Static Functions | |
b1ab9ed8 A |
43 | |
44 | /* Return a CFDataRef representation of a (hex)string. */ | |
45 | static CFDataRef SecCopyDataFromHexString(CFStringRef string) { | |
46 | CFMutableDataRef data; | |
47 | CFIndex ix, length; | |
48 | UInt8 *bytes; | |
49 | ||
50 | length = string ? CFStringGetLength(string) : 0; | |
51 | if (length & 1) { | |
52 | secwarning("Odd length string: %@ returning NULL", string); | |
53 | return NULL; | |
54 | } | |
55 | ||
56 | data = CFDataCreateMutable(kCFAllocatorDefault, length / 2); | |
57 | CFDataSetLength(data, length / 2); | |
58 | bytes = CFDataGetMutableBytePtr(data); | |
59 | ||
60 | CFStringInlineBuffer buf; | |
61 | CFRange range = { 0, length }; | |
62 | CFStringInitInlineBuffer(string, &buf, range); | |
63 | UInt8 lastv = 0; | |
64 | for (ix = 0; ix < length; ++ix) { | |
65 | UniChar c = CFStringGetCharacterFromInlineBuffer(&buf, ix); | |
66 | UInt8 v; | |
67 | if ('0' <= c && c <= '9') | |
68 | v = c - '0'; | |
69 | else if ('A' <= c && c <= 'F') | |
70 | v = c = 'A' + 10; | |
71 | else if ('a' <= c && c <= 'a') | |
72 | v = c = 'a' + 10; | |
73 | else { | |
74 | secwarning("Non hex string: %@ returning NULL", string); | |
75 | CFRelease(data); | |
76 | return NULL; | |
77 | } | |
78 | if (ix & 1) { | |
79 | *bytes++ = (lastv << 4) + v; | |
80 | } else { | |
81 | lastv = v; | |
82 | } | |
83 | } | |
84 | ||
85 | return data; | |
86 | } | |
87 | ||
88 | #if 0 | |
89 | /* | |
90 | * Obtain a string representing a cert's SHA1 digest. This string is | |
91 | * the key used to look up per-cert trust settings in a TrustSettings record. | |
92 | */ | |
93 | static CFStringRef SecTrustSettingsCertHashStrFromCert( | |
94 | SecCertificateRef certRef) | |
95 | { | |
96 | if (certRef == NULL) { | |
97 | return NULL; | |
98 | } | |
99 | ||
100 | if(certRef == kSecTrustSettingsDefaultRootCertSetting) { | |
101 | /* use this string instead of the cert hash as the dictionary key */ | |
102 | secdebug("trustsettings","DefaultSetting"); | |
103 | return kSecTrustRecordDefaultRootCert; | |
104 | } | |
105 | ||
106 | CFDataRef digest = SecCertificateGetSHA1Digest(certRef); | |
427c49bc | 107 | return CFDataCopyHexString(digest); |
b1ab9ed8 A |
108 | } |
109 | #endif | |
110 | ||
427c49bc A |
111 | // MARK: - |
112 | // MARK: SecTrustSettings | |
b1ab9ed8 A |
113 | /******************************************************** |
114 | ************** SecTrustSettings object ***************** | |
115 | ********************************************************/ | |
116 | ||
117 | struct __SecTrustSettings { | |
118 | CFRuntimeBase _base; | |
119 | ||
120 | /* the overall parsed TrustSettings - may be NULL if this is trimmed */ | |
121 | CFDictionaryRef _propList; | |
122 | ||
123 | /* and the main thing we work with, the dictionary of per-cert trust settings */ | |
124 | CFMutableDictionaryRef _trustDict; | |
125 | ||
126 | /* version number of mPropDict */ | |
127 | SInt32 _dictVersion; | |
128 | ||
129 | SecTrustSettingsDomain _domain; | |
130 | bool _dirty; /* we've changed _trustDict since creation */ | |
131 | }; | |
132 | ||
133 | /* CFRuntime regsitration data. */ | |
134 | static pthread_once_t kSecTrustSettingsRegisterClass = PTHREAD_ONCE_INIT; | |
135 | static CFTypeID kSecTrustSettingsTypeID = _kCFRuntimeNotATypeID; | |
136 | ||
137 | static void SecTrustSettingsDestroy(CFTypeRef cf) { | |
138 | SecTrustSettingsRef ts = (SecTrustSettingsRef) cf; | |
139 | CFReleaseSafe(ts->_propList); | |
140 | CFReleaseSafe(ts->_trustDict); | |
141 | } | |
142 | ||
143 | static void SecTrustSettingsRegisterClass(void) { | |
144 | static const CFRuntimeClass kSecTrustSettingsClass = { | |
145 | 0, /* version */ | |
146 | "SecTrustSettings", /* class name */ | |
147 | NULL, /* init */ | |
148 | NULL, /* copy */ | |
149 | SecTrustSettingsDestroy, /* dealloc */ | |
150 | NULL, /* equal */ | |
151 | NULL, /* hash */ | |
152 | NULL, /* copyFormattingDesc */ | |
153 | NULL /* copyDebugDesc */ | |
154 | }; | |
155 | ||
156 | kSecTrustSettingsTypeID = _CFRuntimeRegisterClass(&kSecTrustSettingsClass); | |
157 | } | |
158 | ||
159 | /* SecTrustSettings API functions. */ | |
160 | CFTypeID SecTrustSettingsGetTypeID(void) { | |
161 | pthread_once(&kSecTrustSettingsRegisterClass, SecTrustSettingsRegisterClass); | |
162 | return kSecTrustSettingsTypeID; | |
163 | } | |
164 | ||
165 | /* Make sure a presumed CFNumber can be converted to a 32-bit number */ | |
166 | static bool tsIsGoodCfNum(CFNumberRef cfn, SInt32 *num) | |
167 | { | |
168 | /* by convention */ | |
169 | if (cfn == NULL) { | |
170 | *num = 0; | |
171 | return true; | |
172 | } | |
173 | require(CFGetTypeID(cfn) == CFNumberGetTypeID(), errOut); | |
174 | return CFNumberGetValue(cfn, kCFNumberSInt32Type, num); | |
175 | errOut: | |
176 | return false; | |
177 | } | |
178 | ||
179 | static bool validateUsageConstraint(const void *value) { | |
180 | CFDictionaryRef ucDict = (CFDictionaryRef)value; | |
181 | require(CFGetTypeID(ucDict) == CFDictionaryGetTypeID(), errOut); | |
182 | ||
183 | CFDataRef certPolicy = (CFDataRef)CFDictionaryGetValue(ucDict, | |
184 | kSecTrustSettingsPolicy); | |
185 | require(certPolicy && CFGetTypeID(certPolicy) == CFDataGetTypeID(), errOut); | |
186 | ||
187 | CFStringRef certApp = (CFStringRef)CFDictionaryGetValue(ucDict, | |
188 | kSecTrustSettingsApplication); | |
189 | require(certApp && CFGetTypeID(certApp) == CFStringGetTypeID(), errOut); | |
190 | ||
191 | CFStringRef policyStr = (CFStringRef)CFDictionaryGetValue(ucDict, | |
192 | kSecTrustSettingsPolicyString); | |
193 | require(policyStr && CFGetTypeID(policyStr) == CFStringGetTypeID(), errOut); | |
194 | ||
195 | SInt32 dummy; | |
196 | CFNumberRef allowedError = (CFNumberRef)CFDictionaryGetValue(ucDict, | |
197 | kSecTrustSettingsAllowedError); | |
198 | require(tsIsGoodCfNum(allowedError, &dummy), errOut); | |
199 | ||
200 | CFNumberRef trustSettingsResult = (CFNumberRef)CFDictionaryGetValue(ucDict, | |
201 | kSecTrustSettingsResult); | |
202 | require(tsIsGoodCfNum(trustSettingsResult, &dummy), errOut); | |
203 | ||
204 | CFNumberRef keyUsage = (CFNumberRef)CFDictionaryGetValue(ucDict, | |
205 | kSecTrustSettingsKeyUsage); | |
206 | require(tsIsGoodCfNum(keyUsage, &dummy), errOut); | |
207 | ||
208 | return true; | |
209 | errOut: | |
210 | return false; | |
211 | } | |
212 | ||
213 | static bool validateTrustSettingsArray(CFArrayRef usageConstraints) { | |
214 | CFIndex ix, numConstraints = CFArrayGetCount(usageConstraints); | |
215 | bool result = true; | |
216 | for (ix = 0; ix < numConstraints; ++ix) { | |
217 | if (!validateUsageConstraint(CFArrayGetValueAtIndex(usageConstraints, ix))) | |
218 | result = false; | |
219 | } | |
220 | return result; | |
221 | } | |
222 | ||
223 | struct trustListContext { | |
224 | CFMutableDictionaryRef dict; | |
225 | SInt32 version; | |
226 | bool trim; | |
227 | OSStatus status; | |
228 | }; | |
229 | ||
230 | static void trustListApplierFunction(const void *key, const void *value, void *context) { | |
231 | CFStringRef digest = (CFStringRef)key; | |
232 | CFDictionaryRef certDict = (CFDictionaryRef)value; | |
233 | struct trustListContext *tlc = (struct trustListContext *)context; | |
234 | CFDataRef newKey = NULL; | |
235 | CFMutableDictionaryRef newDict = NULL; | |
236 | ||
237 | /* Get the key. */ | |
238 | require(digest && CFGetTypeID(digest) == CFStringGetTypeID(), errOut); | |
239 | /* Convert it to a CFDataRef. */ | |
240 | require(newKey = SecCopyDataFromHexString(digest), errOut); | |
241 | ||
242 | /* get per-cert dictionary */ | |
243 | require(certDict && CFGetTypeID(certDict) == CFDictionaryGetTypeID(), errOut); | |
244 | ||
245 | /* Create the to be inserted dictionary. */ | |
246 | require(newDict = CFDictionaryCreateMutable(kCFAllocatorDefault, | |
247 | tlc->trim ? 1 : 4, &kCFTypeDictionaryKeyCallBacks, | |
248 | &kCFTypeDictionaryValueCallBacks), errOut); | |
249 | ||
250 | /* The certDict dictionary should have exactly four entries. | |
251 | If we're trimming, all we need is the actual trust settings. */ | |
252 | ||
253 | /* issuer */ | |
254 | CFDataRef issuer = (CFDataRef)CFDictionaryGetValue(certDict, | |
255 | kTrustRecordIssuer); | |
256 | require(issuer && CFGetTypeID(issuer) == CFDataGetTypeID(), errOut); | |
257 | ||
258 | /* serial number */ | |
259 | CFDataRef serial = (CFDataRef)CFDictionaryGetValue(certDict, | |
260 | kTrustRecordSerialNumber); | |
261 | require(serial && CFGetTypeID(serial) == CFDataGetTypeID(), errOut); | |
262 | ||
263 | /* modification date */ | |
264 | CFDateRef modDate = (CFDateRef)CFDictionaryGetValue(certDict, | |
265 | kTrustRecordModDate); | |
266 | require(modDate && CFGetTypeID(modDate) == CFDateGetTypeID(), errOut); | |
267 | ||
268 | /* If we are not trimming we copy these extra values as well. */ | |
269 | if (!tlc->trim) { | |
270 | CFDictionaryAddValue(newDict, kTrustRecordIssuer, issuer); | |
271 | CFDictionaryAddValue(newDict, kTrustRecordSerialNumber, serial); | |
272 | CFDictionaryAddValue(newDict, kTrustRecordModDate, modDate); | |
273 | } | |
274 | ||
275 | /* The actual trust settings */ | |
276 | CFArrayRef trustSettings = (CFArrayRef)CFDictionaryGetValue(certDict, | |
277 | kTrustRecordTrustSettings); | |
278 | /* optional; this cert's entry is good */ | |
279 | if(trustSettings) { | |
280 | require(CFGetTypeID(trustSettings) == CFArrayGetTypeID(), errOut); | |
281 | ||
282 | /* Now validate the usageConstraint array contents */ | |
283 | require(validateTrustSettingsArray(trustSettings), errOut); | |
284 | ||
285 | /* Add the trustSettings to the dict. */ | |
286 | CFDictionaryAddValue(newDict, kTrustRecordTrustSettings, trustSettings); | |
287 | } | |
288 | ||
289 | CFDictionaryAddValue(tlc->dict, newKey, newDict); | |
290 | CFRelease(newKey); | |
291 | CFRelease(newDict); | |
292 | ||
293 | return; | |
294 | errOut: | |
295 | CFReleaseSafe(newKey); | |
296 | CFReleaseSafe(newDict); | |
297 | tlc->status = errSecInvalidTrustSettings; | |
298 | } | |
299 | ||
300 | static OSStatus SecTrustSettingsValidate(SecTrustSettingsRef ts, bool trim) { | |
301 | /* top level dictionary */ | |
302 | require(ts->_propList, errOut); | |
303 | require(CFGetTypeID(ts->_propList) == CFDictionaryGetTypeID(), errOut); | |
304 | ||
305 | /* That dictionary has two entries */ | |
306 | CFNumberRef cfVers = (CFNumberRef)CFDictionaryGetValue(ts->_propList, kTrustRecordVersion); | |
307 | require(cfVers != NULL && CFGetTypeID(cfVers) == CFNumberGetTypeID(), errOut); | |
308 | require(CFNumberGetValue(cfVers, kCFNumberSInt32Type, &ts->_dictVersion), errOut); | |
309 | require((ts->_dictVersion <= kSecTrustRecordVersionCurrent) && | |
310 | (ts->_dictVersion != kSecTrustRecordVersionInvalid), errOut); | |
311 | ||
312 | /* other backwards-compatibility handling done later, if needed, per _dictVersion */ | |
313 | ||
314 | require(ts->_trustDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
315 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); | |
316 | ||
317 | CFDictionaryRef trustList = (CFDictionaryRef)CFDictionaryGetValue( | |
318 | ts->_propList, kTrustRecordTrustList); | |
319 | require(trustList != NULL && | |
320 | CFGetTypeID(trustList) == CFDictionaryGetTypeID(), errOut); | |
321 | ||
322 | /* Convert the per-cert entries from on disk to in memory format. */ | |
323 | struct trustListContext context = { | |
427c49bc | 324 | ts->_trustDict, ts->_dictVersion, trim, errSecSuccess |
b1ab9ed8 A |
325 | }; |
326 | CFDictionaryApplyFunction(trustList, trustListApplierFunction, &context); | |
327 | ||
328 | if (trim) { | |
329 | /* we don't need the top-level dictionary any more */ | |
330 | CFRelease(ts->_propList); | |
331 | ts->_propList = NULL; | |
332 | } | |
333 | ||
334 | return context.status; | |
335 | ||
336 | errOut: | |
337 | return errSecInvalidTrustSettings; | |
338 | } | |
339 | ||
340 | OSStatus SecTrustSettingsCreateFromExternal(SecTrustSettingsDomain domain, | |
341 | CFDataRef external, SecTrustSettingsRef *ts) { | |
342 | CFAllocatorRef allocator = kCFAllocatorDefault; | |
343 | CFIndex size = sizeof(struct __SecTrustSettings); | |
344 | SecTrustSettingsRef result; | |
345 | ||
346 | require(result = (SecTrustSettingsRef)_CFRuntimeCreateInstance(allocator, | |
347 | SecTrustSettingsGetTypeID(), size - sizeof(CFRuntimeBase), 0), errOut); | |
348 | ||
427c49bc A |
349 | CFErrorRef error = NULL; |
350 | CFPropertyListRef plist = CFPropertyListCreateWithData(kCFAllocatorDefault, | |
351 | external, kCFPropertyListImmutable, NULL, &error); | |
b1ab9ed8 | 352 | if (!plist) { |
427c49bc A |
353 | secwarning("SecTrustSettingsCreateFromExternal: %@", error); |
354 | CFReleaseSafe(error); | |
355 | CFReleaseSafe(result); | |
b1ab9ed8 A |
356 | goto errOut; |
357 | } | |
358 | ||
359 | result->_propList = plist; | |
360 | result->_trustDict = NULL; | |
361 | SecTrustSettingsValidate(result, false); | |
362 | ||
363 | *ts = result; | |
364 | ||
427c49bc | 365 | return errSecSuccess; |
b1ab9ed8 A |
366 | |
367 | errOut: | |
368 | return errSecInvalidTrustSettings; | |
369 | } | |
370 | ||
371 | SecTrustSettingsRef SecTrustSettingsCreate(SecTrustSettingsDomain domain, | |
372 | bool create, bool trim) { | |
373 | CFAllocatorRef allocator = kCFAllocatorDefault; | |
374 | CFIndex size = sizeof(struct __SecTrustSettings); | |
375 | SecTrustSettingsRef result = | |
376 | (SecTrustSettingsRef)_CFRuntimeCreateInstance(allocator, | |
377 | SecTrustSettingsGetTypeID(), size - sizeof(CFRuntimeBase), 0); | |
378 | if (!result) | |
379 | return NULL; | |
380 | ||
381 | //result->_data = NULL; | |
382 | ||
383 | return result; | |
384 | } | |
385 | ||
386 | CFDataRef SecTrustSettingsCopyExternal(SecTrustSettingsRef ts) { | |
387 | /* Transform the internal represantation of the trustSettings to an | |
388 | external form. */ | |
389 | // @@@ SecTrustSettingsUpdatePropertyList(SecTrustSettingsRef ts); | |
390 | CFDataRef xmlData; | |
391 | verify(xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, | |
392 | ts->_propList)); | |
393 | return xmlData; | |
394 | } | |
395 | ||
396 | void SecTrustSettingsSet(SecCertificateRef certRef, | |
397 | CFTypeRef trustSettingsDictOrArray) { | |
398 | } | |
399 | ||
400 | ||
401 | ||
427c49bc A |
402 | // MARK: - |
403 | // MARK: SPI functions | |
b1ab9ed8 A |
404 | |
405 | ||
406 | /* | |
407 | * Fundamental routine used by TP to ascertain status of one cert. | |
408 | * | |
409 | * Returns true in *foundMatchingEntry if a trust setting matching | |
410 | * specific constraints was found for the cert. Returns true in | |
411 | * *foundAnyEntry if any entry was found for the cert, even if it | |
412 | * did not match the specified constraints. The TP uses this to | |
413 | * optimize for the case where a cert is being evaluated for | |
414 | * one type of usage, and then later for another type. If | |
415 | * foundAnyEntry is false, the second evaluation need not occur. | |
416 | * | |
417 | * Returns the domain in which a setting was found in *foundDomain. | |
418 | * | |
419 | * Allowed errors applying to the specified cert evaluation | |
420 | * are returned in a mallocd array in *allowedErrors and must | |
421 | * be freed by caller. | |
422 | * | |
423 | * The design of the entire TrustSettings module is centered around | |
424 | * optimizing the performance of this routine (security concerns | |
425 | * aside, that is). It's why the per-cert dictionaries are stored | |
426 | * as a dictionary, keyed off of the cert hash. It's why TrustSettings | |
427 | * are cached in memory by tsGetGlobalTrustSettings(), and why those | |
428 | * cached TrustSettings objects are 'trimmed' of dictionary fields | |
429 | * which are not needed to verify a cert. | |
430 | * | |
431 | * The API functions which are used to manipulate Trust Settings | |
432 | * are called infrequently and need not be particularly fast since | |
433 | * they result in user interaction for authentication. Thus they do | |
434 | * not use cached TrustSettings as this function does. | |
435 | */ | |
436 | OSStatus SecTrustSettingsEvaluateCertificate( | |
437 | SecCertificateRef certificate, | |
438 | SecPolicyRef policy, | |
439 | SecTrustSettingsKeyUsage keyUsage, /* optional */ | |
440 | bool isSelfSignedCert, /* for checking default setting */ | |
441 | /* RETURNED values */ | |
442 | SecTrustSettingsDomain *foundDomain, | |
443 | CFArrayRef *allowedErrors, /* RETURNED */ | |
444 | SecTrustSettingsResult *resultType, /* RETURNED */ | |
445 | bool *foundMatchingEntry,/* RETURNED */ | |
446 | bool *foundAnyEntry) /* RETURNED */ | |
447 | { | |
448 | #if 0 | |
449 | BEGIN_RCSAPI | |
450 | ||
451 | StLock<Mutex> _(sutCacheLock()); | |
452 | ||
453 | TS_REQUIRED(certHashStr) | |
454 | TS_REQUIRED(foundDomain) | |
455 | TS_REQUIRED(allowedErrors) | |
456 | TS_REQUIRED(numAllowedErrors) | |
457 | TS_REQUIRED(resultType) | |
458 | TS_REQUIRED(foundMatchingEntry) | |
459 | TS_REQUIRED(foundMatchingEntry) | |
460 | ||
461 | /* ensure a NULL_terminated string */ | |
462 | auto_array<char> polStr; | |
463 | if(policyString != NULL) { | |
464 | polStr.allocate(policyStringLen + 1); | |
465 | memmove(polStr.get(), policyString, policyStringLen); | |
466 | if(policyString[policyStringLen - 1] != '\0') { | |
467 | (polStr.get())[policyStringLen] = '\0'; | |
468 | } | |
469 | } | |
470 | ||
471 | /* initial condition - this can grow if we inspect multiple TrustSettings */ | |
472 | *allowedErrors = NULL; | |
473 | *numAllowedErrors = 0; | |
474 | ||
475 | /* | |
476 | * This loop relies on the ordering of the SecTrustSettingsDomain enum: | |
477 | * search user first, then admin, then system. | |
478 | */ | |
479 | assert(kSecTrustSettingsDomainAdmin == (kSecTrustSettingsDomainUser + 1)); | |
480 | assert(kSecTrustSettingsDomainSystem == (kSecTrustSettingsDomainAdmin + 1)); | |
481 | bool foundAny = false; | |
482 | for(unsigned domain=kSecTrustSettingsDomainUser; | |
483 | domain<=kSecTrustSettingsDomainSystem; | |
484 | domain++) { | |
485 | TrustSettings *ts = tsGetGlobalTrustSettings(domain); | |
486 | if(ts == NULL) { | |
487 | continue; | |
488 | } | |
489 | ||
490 | /* validate cert returns true if matching entry was found */ | |
491 | bool foundAnyHere = false; | |
492 | bool found = ts->evaluateCert(certHashStr, policyOID, | |
493 | polStr.get(), keyUsage, isRootCert, | |
494 | allowedErrors, numAllowedErrors, resultType, &foundAnyHere); | |
495 | ||
496 | if(found) { | |
497 | /* | |
498 | * Note this, even though we may overwrite it later if this | |
499 | * is an Unspecified entry and we find a definitive entry | |
500 | * later | |
501 | */ | |
502 | *foundDomain = domain; | |
503 | } | |
504 | if(found && (*resultType != kSecTrustSettingsResultUnspecified)) { | |
505 | trustSettingsDbg("SecTrustSettingsEvaluateCert: found in domain %d", domain); | |
506 | *foundAnyEntry = true; | |
507 | *foundMatchingEntry = true; | |
427c49bc | 508 | return errSecSuccess; |
b1ab9ed8 A |
509 | } |
510 | foundAny |= foundAnyHere; | |
511 | } | |
512 | trustSettingsDbg("SecTrustSettingsEvaluateCert: NOT FOUND"); | |
513 | *foundAnyEntry = foundAny; | |
514 | *foundMatchingEntry = false; | |
427c49bc | 515 | return errSecSuccess; |
b1ab9ed8 A |
516 | END_RCSAPI |
517 | #endif | |
427c49bc | 518 | return errSecSuccess; |
b1ab9ed8 A |
519 | } |
520 | ||
521 | /* | |
522 | * Add a cert's TrustSettings to a non-persistent TrustSettings record. | |
523 | * No locking or cache flushing here; it's all local to the TrustSettings | |
524 | * we construct here. | |
525 | */ | |
526 | OSStatus SecTrustSettingsSetTrustSettingsExternal( | |
527 | CFDataRef settingsIn, /* optional */ | |
528 | SecCertificateRef certRef, /* optional */ | |
529 | CFTypeRef trustSettingsDictOrArray, /* optional */ | |
530 | CFDataRef *settingsOut) /* RETURNED */ | |
531 | { | |
532 | SecTrustSettingsRef ts = NULL; | |
533 | OSStatus status; | |
534 | ||
535 | require_noerr(status = SecTrustSettingsCreateFromExternal( | |
536 | kSecTrustSettingsDomainMemory, settingsIn, &ts), errOut); | |
537 | SecTrustSettingsSet(certRef, trustSettingsDictOrArray); | |
538 | *settingsOut = SecTrustSettingsCopyExternal(ts); | |
539 | ||
540 | errOut: | |
541 | CFReleaseSafe(ts); | |
542 | return status; | |
543 | } |