]> git.saurik.com Git - apple/security.git/blob - trust/trustd/trustd.c
Security-59754.41.1.tar.gz
[apple/security.git] / trust / trustd / trustd.c
1 /*
2 * Copyright (c) 2017-2020 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 <AssertMacros.h>
25 #include <sandbox.h>
26 #include <dirhelper_priv.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <pwd.h>
30 #include <notify.h>
31 #include <xpc/private.h>
32 #include <xpc/xpc.h>
33 #include <CoreFoundation/CFStream.h>
34 #include <os/assumes.h>
35
36 #include <Security/SecuritydXPC.h>
37 #include <Security/SecTrustStore.h>
38 #include <Security/SecCertificateInternal.h>
39 #include <Security/SecEntitlements.h>
40 #include <Security/SecTrustInternal.h>
41 #include <Security/SecPolicyPriv.h>
42 #include <Security/SecItem.h>
43 #include <Security/SecItemPriv.h>
44
45 #include <ipc/securityd_client.h>
46 #include <ipc/server_entitlement_helpers.h>
47 #include <utilities/SecCFWrappers.h>
48 #include <utilities/SecDb.h>
49 #include <utilities/SecFileLocations.h>
50 #include <utilities/debugging.h>
51 #include <utilities/SecXPCError.h>
52 #include "trust/trustd/SecOCSPCache.h"
53 #include "trust/trustd/SecTrustStoreServer.h"
54 #include "trust/trustd/SecPinningDb.h"
55 #include "trust/trustd/SecPolicyServer.h"
56 #include "trust/trustd/SecRevocationDb.h"
57 #include "trust/trustd/SecTrustServer.h"
58 #include "keychain/securityd/spi.h"
59 #include "trust/trustd/SecTrustLoggingServer.h"
60 #if TARGET_OS_IPHONE
61 #include "trust/trustd/SecTrustExceptionResetCount.h"
62 #endif
63
64 #if TARGET_OS_OSX
65 #include <Security/SecTaskPriv.h>
66 #include <login/SessionAgentStatusCom.h>
67 #include "trust/trustd/macOS/SecTrustOSXEntryPoints.h"
68 #endif
69
70 #include "OTATrustUtilities.h"
71 #include "trustd_spi.h"
72
73 static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, CFArrayRef path, CFErrorRef *error) {
74 if (!path)
75 return true;
76 __block xpc_object_t xpc_chain = NULL;
77 require_action_quiet(xpc_chain = xpc_array_create(NULL, 0), exit, SecError(errSecParam, error, CFSTR("xpc_array_create failed")));
78 CFArrayForEach(path, ^(const void *value) {
79 SecCertificateRef cert = (SecCertificateRef)value;
80 if (xpc_chain && !SecCertificateAppendToXPCArray(cert, xpc_chain, error)) {
81 xpc_release(xpc_chain);
82 xpc_chain = NULL;
83 }
84 });
85
86 exit:
87 if (!xpc_chain)
88 return false;
89
90 xpc_dictionary_set_value(message, key, xpc_chain);
91 xpc_release(xpc_chain);
92 return true;
93 }
94
95 static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) {
96 size_t length = 0;
97 const void *bytes = xpc_dictionary_get_data(message, key, &length);
98 if (bytes) {
99 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length);
100 if (certificate)
101 return certificate;
102 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key);
103 } else {
104 SecError(errSecParam, error, CFSTR("object for key %s missing"), key);
105 }
106 return NULL;
107 }
108
109 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
110 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
111 if (!xpc_certificates)
112 return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key);
113 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
114 return *certificates;
115 }
116
117 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
118 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
119 if (!xpc_certificates) {
120 *certificates = NULL;
121 return true;
122 }
123 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
124 return *certificates;
125 }
126
127 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) {
128 xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key);
129 if (!xpc_policies) {
130 if (policies)
131 *policies = NULL;
132 return true;
133 }
134 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error);
135 return *policies != NULL;
136 }
137
138 // Returns error if entitlement isn't present.
139 static bool
140 EntitlementPresentAndTrue(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
141 {
142 if (!SecTaskGetBooleanValueForEntitlement(clientTask, entitlement)) {
143 SecError(errSecMissingEntitlement, error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)op), clientTask, entitlement);
144 return false;
145 }
146 return true;
147 }
148
149 static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) {
150 SecTrustStoreRef ts = NULL;
151 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error);
152 if (domain) {
153 ts = SecTrustStoreForDomainName(domain, error);
154 CFRelease(domain);
155 }
156 return ts;
157 }
158
159 static bool SecXPCTrustStoreContains(SecurityClient * __unused client, xpc_object_t event,
160 xpc_object_t reply, CFErrorRef *error) {
161 bool result = false;
162 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error);
163 if (ts) {
164 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error);
165 if (digest) {
166 bool contains;
167 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, error)) {
168 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, contains);
169 result = true;
170 }
171 CFReleaseNull(digest);
172 }
173 }
174 return result;
175 }
176
177 static bool SecXPCTrustStoreSetTrustSettings(SecurityClient * __unused client, xpc_object_t event,
178 xpc_object_t reply, CFErrorRef *error) {
179 bool noError = false;
180 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error);
181 if (ts) {
182 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, error);
183 if (certificate) {
184 CFTypeRef trustSettingsDictOrArray = NULL;
185 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, error)) {
186 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, error);
187 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result);
188 noError = true;
189 CFReleaseSafe(trustSettingsDictOrArray);
190 }
191 CFReleaseNull(certificate);
192 }
193 }
194 return noError;
195 }
196
197 static bool SecXPCTrustStoreRemoveCertificate(SecurityClient * __unused client, xpc_object_t event,
198 xpc_object_t reply, CFErrorRef *error) {
199 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error);
200 if (ts) {
201 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error);
202 if (digest) {
203 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, error);
204 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result);
205 CFReleaseNull(digest);
206 return true;
207 }
208 }
209 return false;
210 }
211
212 static bool SecXPCTrustStoreCopyAll(SecurityClient * __unused client, xpc_object_t event,
213 xpc_object_t reply, CFErrorRef *error) {
214 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error);
215 if (ts) {
216 CFArrayRef trustStoreContents = NULL;
217 if(_SecTrustStoreCopyAll(ts, &trustStoreContents, error) && trustStoreContents) {
218 SecXPCDictionarySetPList(reply, kSecXPCKeyResult, trustStoreContents, error);
219 CFReleaseNull(trustStoreContents);
220 return true;
221 }
222 }
223 return false;
224 }
225
226 static bool SecXPCTrustStoreCopyUsageConstraints(SecurityClient * __unused client, xpc_object_t event,
227 xpc_object_t reply, CFErrorRef *error) {
228 bool result = false;
229 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error);
230 if (ts) {
231 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error);
232 if (digest) {
233 CFArrayRef usageConstraints = NULL;
234 if(_SecTrustStoreCopyUsageConstraints(ts, digest, &usageConstraints, error) && usageConstraints) {
235 SecXPCDictionarySetPList(reply, kSecXPCKeyResult, usageConstraints, error);
236 CFReleaseNull(usageConstraints);
237 result = true;
238 }
239 CFReleaseNull(digest);
240 }
241 }
242 return result;
243 }
244
245 static bool SecXPC_OCSPCacheFlush(SecurityClient * __unused client, xpc_object_t __unused event,
246 xpc_object_t __unused reply, CFErrorRef *error) {
247 if(SecOCSPCacheFlush(error)) {
248 return true;
249 }
250 return false;
251 }
252
253 static bool SecXPC_OTAPKI_GetCurrentTrustStoreVersion(SecurityClient * __unused client, xpc_object_t __unused event,
254 xpc_object_t reply, CFErrorRef *error) {
255 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecOTAPKIGetCurrentTrustStoreVersion(error));
256 return true;
257 }
258
259 static bool SecXPC_OTAPKI_GetCurrentAssetVersion(SecurityClient * __unused client, xpc_object_t __unused event,
260 xpc_object_t reply, CFErrorRef *error) {
261 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecOTAPKIGetCurrentAssetVersion(error));
262 return true;
263 }
264
265 static bool SecXPC_OTAPKI_GetEscrowCertificates(SecurityClient * __unused client, xpc_object_t event,
266 xpc_object_t reply, CFErrorRef *error) {
267 bool result = false;
268 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
269 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, error);
270 if (array) {
271 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
272 xpc_dictionary_set_value(reply, kSecXPCKeyResult, xpc_array);
273 xpc_release(xpc_array);
274 result = true;
275 }
276 CFReleaseNull(array);
277 return result;
278 }
279
280 static bool SecXPC_OTAPKI_GetNewAsset(SecurityClient * __unused client, xpc_object_t __unused event,
281 xpc_object_t reply, CFErrorRef *error) {
282 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecOTAPKISignalNewAsset(error));
283 return true;
284 }
285
286 static bool SecXPC_OTASecExperiment_GetNewAsset(SecurityClient * __unused client, xpc_object_t __unused event,
287 xpc_object_t reply, CFErrorRef *error) {
288 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecOTASecExperimentGetNewAsset(error));
289 return true;
290 }
291
292 static bool SecXPC_OTASecExperiment_GetAsset(SecurityClient * __unused client, xpc_object_t __unused event,
293 xpc_object_t reply, CFErrorRef *error) {
294 bool result = false;
295 CFDictionaryRef asset = SecOTASecExperimentCopyAsset(error);
296 if (asset) {
297 xpc_object_t xpc_dict = _CFXPCCreateXPCObjectFromCFObject(asset);
298 if (xpc_dict) {
299 xpc_dictionary_set_value(reply, kSecXPCKeyResult, xpc_dict);
300 xpc_release(xpc_dict);
301 result = true;
302 }
303 }
304 CFReleaseNull(asset);
305 return result;
306 }
307
308 static bool SecXPC_OTAPKI_CopyTrustedCTLogs(SecurityClient * __unused client, xpc_object_t __unused event,
309 xpc_object_t reply, CFErrorRef *error) {
310 bool result = false;
311 CFDictionaryRef trustedLogs = SecOTAPKICopyCurrentTrustedCTLogs(error);
312 if (trustedLogs) {
313 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(trustedLogs);
314 if (xpc_dictionary) {
315 xpc_dictionary_set_value(reply, kSecXPCKeyResult, xpc_dictionary);
316 xpc_release(xpc_dictionary);
317 result = true;
318 }
319 }
320 CFReleaseNull(trustedLogs);
321 return result;
322 }
323
324 static bool SecXPC_OTAPKI_CopyCTLogForKeyID(SecurityClient * __unused client, xpc_object_t event,
325 xpc_object_t reply, CFErrorRef *error) {
326 bool result = false;
327 size_t length = 0;
328 const void *bytes = xpc_dictionary_get_data(event, kSecXPCData, &length);
329 CFDataRef keyID = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorNull);
330 if (keyID) {
331 CFDictionaryRef logDict = SecOTAPKICopyCTLogForKeyID(keyID, error);
332 if (logDict) {
333 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(logDict);
334 xpc_dictionary_set_value(reply, kSecXPCKeyResult, xpc_dictionary);
335 xpc_release(xpc_dictionary);
336 CFReleaseNull(logDict);
337 result = true;
338 }
339 CFReleaseNull(keyID);
340 }
341 return result;
342 }
343
344 static bool SecXPC_Networking_AnalyticsReport(SecurityClient * __unused client, xpc_object_t event,
345 xpc_object_t reply, CFErrorRef *error) {
346 xpc_object_t attributes = xpc_dictionary_get_dictionary(event, kSecTrustEventAttributesKey);
347 CFStringRef eventName = SecXPCDictionaryCopyString(event, kSecTrustEventNameKey, error);
348 bool result = false;
349 if (attributes && eventName) {
350 result = SecNetworkingAnalyticsReport(eventName, attributes, error);
351 }
352 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result);
353 CFReleaseNull(eventName);
354 return result;
355 }
356
357 static bool SecXPCTrustStoreSetCTExceptions(SecurityClient *client, xpc_object_t event,
358 xpc_object_t reply, CFErrorRef *error) {
359 CFStringRef appID = NULL;
360 CFDictionaryRef exceptions = NULL;
361 if (!SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error) || !appID) {
362 /* We always want to set the app ID with the exceptions */
363 appID = SecTaskCopyApplicationIdentifier(client->task);
364 }
365 (void)SecXPCDictionaryCopyDictionaryOptional(event, kSecTrustExceptionsKey, &exceptions, error);
366 bool result = _SecTrustStoreSetCTExceptions(appID, exceptions, error);
367 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result);
368 CFReleaseNull(exceptions);
369 CFReleaseNull(appID);
370 return false;
371 }
372
373 static bool SecXPCTrustStoreCopyCTExceptions(SecurityClient * __unused client, xpc_object_t event,
374 xpc_object_t reply, CFErrorRef *error) {
375 CFStringRef appID = NULL;
376 (void)SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error);
377 CFDictionaryRef exceptions = _SecTrustStoreCopyCTExceptions(appID, error);
378 SecXPCDictionarySetPListOptional(reply, kSecTrustExceptionsKey, exceptions, error);
379 CFReleaseNull(exceptions);
380 CFReleaseNull(appID);
381 return false;
382 }
383
384 static bool SecXPCTrustStoreSetCARevocationAdditions(SecurityClient *client, xpc_object_t event,
385 xpc_object_t reply, CFErrorRef *error) {
386 CFStringRef appID = NULL;
387 CFDictionaryRef additions = NULL;
388 if (!SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error) || !appID) {
389 /* We always want to set the app ID with the additions */
390 appID = SecTaskCopyApplicationIdentifier(client->task);
391 }
392 (void)SecXPCDictionaryCopyDictionaryOptional(event, kSecTrustRevocationAdditionsKey, &additions, error);
393 bool result = _SecTrustStoreSetCARevocationAdditions(appID, additions, error);
394 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result);
395 CFReleaseNull(additions);
396 CFReleaseNull(appID);
397 return false;
398 }
399
400 static bool SecXPCTrustStoreCopyCARevocationAdditions(SecurityClient * __unused client, xpc_object_t event,
401 xpc_object_t reply, CFErrorRef *error) {
402 CFStringRef appID = NULL;
403 (void)SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error);
404 CFDictionaryRef additions = _SecTrustStoreCopyCARevocationAdditions(appID, error);
405 SecXPCDictionarySetPListOptional(reply, kSecTrustRevocationAdditionsKey, additions, error);
406 CFReleaseNull(additions);
407 CFReleaseNull(appID);
408 return false;
409 }
410
411 #if TARGET_OS_IPHONE
412 static bool SecXPCTrustGetExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) {
413 uint64_t exceptionResetCount = SecTrustServerGetExceptionResetCount(error);
414 if (error && *error) {
415 return false;
416 }
417
418 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, exceptionResetCount);
419 return true;
420 }
421
422 static bool SecXPCTrustIncrementExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) {
423 OSStatus status = errSecInternal;
424 bool result = SecTrustServerIncrementExceptionResetCount(error);
425 if (result && (!error || (error && !*error))) {
426 status = errSecSuccess;
427 }
428
429 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, status);
430 return result;
431 }
432 #endif
433
434 static bool SecXPC_Valid_Update(SecurityClient * __unused client, xpc_object_t __unused event,
435 xpc_object_t reply, CFErrorRef *error) {
436 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecRevocationDbUpdate(error));
437 return true;
438 }
439
440 typedef bool(*SecXPCOperationHandler)(SecurityClient *client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error);
441
442 typedef struct {
443 CFStringRef entitlement;
444 SecXPCOperationHandler handler;
445 } SecXPCServerOperation;
446
447 struct trustd_operations {
448 SecXPCServerOperation trust_store_contains;
449 SecXPCServerOperation trust_store_set_trust_settings;
450 SecXPCServerOperation trust_store_remove_certificate;
451 SecXPCServerOperation trust_store_copy_all;
452 SecXPCServerOperation trust_store_copy_usage_constraints;
453 SecXPCServerOperation ocsp_cache_flush;
454 SecXPCServerOperation ota_pki_trust_store_version;
455 SecXPCServerOperation ota_pki_asset_version;
456 SecXPCServerOperation ota_pki_get_escrow_certs;
457 SecXPCServerOperation ota_pki_get_new_asset;
458 SecXPCServerOperation ota_pki_copy_trusted_ct_logs;
459 SecXPCServerOperation ota_pki_copy_ct_log_for_keyid;
460 SecXPCServerOperation networking_analytics_report;
461 SecXPCServerOperation trust_store_set_ct_exceptions;
462 SecXPCServerOperation trust_store_copy_ct_exceptions;
463 SecXPCServerOperation ota_secexperiment_get_asset;
464 SecXPCServerOperation ota_secexperiment_get_new_asset;
465 #if TARGET_OS_IPHONE
466 SecXPCServerOperation trust_get_exception_reset_count;
467 SecXPCServerOperation trust_increment_exception_reset_count;
468 #endif
469 SecXPCServerOperation trust_store_set_ca_revocation_additions;
470 SecXPCServerOperation trust_store_copy_ca_revocation_additions;
471 SecXPCServerOperation valid_update;
472 };
473
474 static struct trustd_operations trustd_ops = {
475 .trust_store_contains = { NULL, SecXPCTrustStoreContains },
476 .trust_store_set_trust_settings = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetTrustSettings },
477 .trust_store_remove_certificate = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreRemoveCertificate },
478 .trust_store_copy_all = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyAll },
479 .trust_store_copy_usage_constraints = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyUsageConstraints },
480 .ocsp_cache_flush = { NULL, SecXPC_OCSPCacheFlush },
481 .ota_pki_trust_store_version = { NULL, SecXPC_OTAPKI_GetCurrentTrustStoreVersion },
482 .ota_pki_asset_version = { NULL, SecXPC_OTAPKI_GetCurrentAssetVersion },
483 .ota_pki_get_escrow_certs = { NULL, SecXPC_OTAPKI_GetEscrowCertificates },
484 .ota_pki_get_new_asset = { NULL, SecXPC_OTAPKI_GetNewAsset },
485 .ota_secexperiment_get_new_asset = { NULL, SecXPC_OTASecExperiment_GetNewAsset },
486 .ota_secexperiment_get_asset = { NULL, SecXPC_OTASecExperiment_GetAsset },
487 .ota_pki_copy_trusted_ct_logs = { NULL, SecXPC_OTAPKI_CopyTrustedCTLogs },
488 .ota_pki_copy_ct_log_for_keyid = { NULL, SecXPC_OTAPKI_CopyCTLogForKeyID },
489 .networking_analytics_report = { NULL, SecXPC_Networking_AnalyticsReport },
490 .trust_store_set_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCTExceptions },
491 .trust_store_copy_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCTExceptions },
492 #if TARGET_OS_IPHONE
493 .trust_get_exception_reset_count = { NULL, SecXPCTrustGetExceptionResetCount },
494 .trust_increment_exception_reset_count = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustIncrementExceptionResetCount },
495 #endif
496 .trust_store_set_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCARevocationAdditions },
497 .trust_store_copy_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCARevocationAdditions },
498 .valid_update = { NULL, SecXPC_Valid_Update },
499 };
500
501 static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
502 xpc_type_t type = xpc_get_type(event);
503 __block CFErrorRef error = NULL;
504 xpc_object_t xpcError = NULL;
505 xpc_object_t replyMessage = NULL;
506 CFDataRef clientAuditToken = NULL;
507 CFArrayRef domains = NULL;
508 SecurityClient client = {
509 .task = NULL,
510 .accessGroups = NULL,
511 .musr = NULL,
512 .uid = xpc_connection_get_euid(connection),
513 .allowSystemKeychain = true,
514 .allowSyncBubbleKeychain = false,
515 .isNetworkExtension = false,
516 .canAccessNetworkExtensionAccessGroups = false,
517 #if TARGET_OS_IPHONE
518 .inMultiUser = false,
519 #endif
520 };
521
522 secdebug("serverxpc", "entering");
523 if (type == XPC_TYPE_DICTIONARY) {
524 replyMessage = xpc_dictionary_create_reply(event);
525
526 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
527
528 audit_token_t auditToken = {};
529 xpc_connection_get_audit_token(connection, &auditToken);
530
531 client.task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
532 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
533 client.accessGroups = SecTaskCopyAccessGroups(client.task);
534
535 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
536
537 if (operation == sec_trust_evaluate_id) {
538 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL, exceptions = NULL;
539 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
540 bool keychainsAllowed = xpc_dictionary_get_bool(event, kSecTrustKeychainsAllowedKey);
541 double verifyTime;
542 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
543 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
544 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
545 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
546 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
547 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
548 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error) &&
549 SecXPCDictionaryCopyArrayOptional(event, kSecTrustExceptionsKey, &exceptions, &error)) {
550 // If we have no error yet, capture connection and reply in block and properly retain them.
551 xpc_retain(connection);
552 CFRetainSafe(client.task);
553 CFRetainSafe(clientAuditToken);
554
555 // Clear replyMessage so we don't send a synchronous reply.
556 xpc_object_t asyncReply = replyMessage;
557 replyMessage = NULL;
558
559 SecTrustServerEvaluateBlock(SecTrustServerGetWorkloop(), clientAuditToken, certificates, anchors, anchorsOnly, keychainsAllowed, policies,
560 responses, scts, trustedLogs, verifyTime, client.accessGroups, exceptions,
561 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain,
562 CFErrorRef replyError) {
563 // Send back reply now
564 if (replyError) {
565 CFRetain(replyError);
566 } else {
567 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
568 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
569 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
570 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
571 }
572 if (replyError) {
573 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
574 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
575 if (xpcReplyError) {
576 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
577 xpc_release(xpcReplyError);
578 }
579 CFReleaseNull(replyError);
580 } else {
581 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
582 }
583
584 xpc_connection_send_message(connection, asyncReply);
585 xpc_release(asyncReply);
586 xpc_release(connection);
587 CFReleaseSafe(client.task);
588 CFReleaseSafe(clientAuditToken);
589 });
590 }
591 CFReleaseSafe(policies);
592 CFReleaseSafe(anchors);
593 CFReleaseSafe(certificates);
594 CFReleaseSafe(responses);
595 CFReleaseSafe(scts);
596 CFReleaseSafe(trustedLogs);
597 CFReleaseSafe(exceptions);
598 } else {
599 SecXPCServerOperation *server_op = NULL;
600 switch (operation) {
601 case sec_trust_store_contains_id:
602 server_op = &trustd_ops.trust_store_contains;
603 break;
604 case sec_trust_store_set_trust_settings_id:
605 server_op = &trustd_ops.trust_store_set_trust_settings;
606 break;
607 case sec_trust_store_remove_certificate_id:
608 server_op = &trustd_ops.trust_store_remove_certificate;
609 break;
610 case sec_trust_store_copy_all_id:
611 server_op = &trustd_ops.trust_store_copy_all;
612 break;
613 case sec_trust_store_copy_usage_constraints_id:
614 server_op = &trustd_ops.trust_store_copy_usage_constraints;
615 break;
616 case sec_ocsp_cache_flush_id:
617 server_op = &trustd_ops.ocsp_cache_flush;
618 break;
619 case sec_ota_pki_trust_store_version_id:
620 server_op = &trustd_ops.ota_pki_trust_store_version;
621 break;
622 case sec_ota_pki_asset_version_id:
623 server_op = &trustd_ops.ota_pki_asset_version;
624 break;
625 case kSecXPCOpOTAGetEscrowCertificates:
626 server_op = &trustd_ops.ota_pki_get_escrow_certs;
627 break;
628 case kSecXPCOpOTAPKIGetNewAsset:
629 server_op = &trustd_ops.ota_pki_get_new_asset;
630 break;
631 case kSecXPCOpOTASecExperimentGetNewAsset:
632 server_op = &trustd_ops.ota_secexperiment_get_new_asset;
633 break;
634 case kSecXPCOpOTASecExperimentGetAsset:
635 server_op = &trustd_ops.ota_secexperiment_get_asset;
636 break;
637 case kSecXPCOpOTAPKICopyTrustedCTLogs:
638 server_op = &trustd_ops.ota_pki_copy_trusted_ct_logs;
639 break;
640 case kSecXPCOpOTAPKICopyCTLogForKeyID:
641 server_op = &trustd_ops.ota_pki_copy_ct_log_for_keyid;
642 break;
643 case kSecXPCOpNetworkingAnalyticsReport:
644 server_op = &trustd_ops.networking_analytics_report;
645 break;
646 case kSecXPCOpSetCTExceptions:
647 server_op = &trustd_ops.trust_store_set_ct_exceptions;
648 break;
649 case kSecXPCOpCopyCTExceptions:
650 server_op = &trustd_ops.trust_store_copy_ct_exceptions;
651 break;
652 #if TARGET_OS_IPHONE
653 case sec_trust_get_exception_reset_count_id:
654 server_op = &trustd_ops.trust_get_exception_reset_count;
655 break;
656 case sec_trust_increment_exception_reset_count_id:
657 server_op = &trustd_ops.trust_increment_exception_reset_count;
658 break;
659 #endif
660 case kSecXPCOpSetCARevocationAdditions:
661 server_op = &trustd_ops.trust_store_set_ca_revocation_additions;
662 break;
663 case kSecXPCOpCopyCARevocationAdditions:
664 server_op = &trustd_ops.trust_store_copy_ca_revocation_additions;
665 break;
666 case kSecXPCOpValidUpdate:
667 server_op = &trustd_ops.valid_update;
668 break;
669 default:
670 break;
671 }
672 if (server_op && server_op->handler) {
673 bool entitled = true;
674 if (server_op->entitlement) {
675 entitled = EntitlementPresentAndTrue(operation, client.task, server_op->entitlement, &error);
676 }
677 if (entitled) {
678 (void)server_op->handler(&client, event, replyMessage, &error);
679 }
680 }
681 }
682
683 if (error)
684 {
685 if(SecErrorGetOSStatus(error) == errSecItemNotFound)
686 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
687 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
688 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
689 else
690 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
691
692 xpcError = SecCreateXPCObjectWithCFError(error);
693 if (replyMessage) {
694 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
695 }
696 } else if (replyMessage) {
697 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
698 }
699 } else {
700 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
701 secerror("%@: returning error: %@", client.task, error);
702 xpcError = SecCreateXPCObjectWithCFError(error);
703 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
704 }
705
706 if (replyMessage) {
707 xpc_connection_send_message(connection, replyMessage);
708 xpc_release(replyMessage);
709 }
710 if (xpcError)
711 xpc_release(xpcError);
712 CFReleaseSafe(error);
713 CFReleaseSafe(client.accessGroups);
714 CFReleaseSafe(client.musr);
715 CFReleaseSafe(client.task);
716 CFReleaseSafe(domains);
717 CFReleaseSafe(clientAuditToken);
718 }
719
720 static void trustd_xpc_init(const char *service_name)
721 {
722 secdebug("serverxpc", "start");
723 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
724 if (!listener) {
725 seccritical("security failed to register xpc listener for %s, exiting", service_name);
726 abort();
727 }
728
729 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
730 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
731 xpc_connection_set_target_queue(connection, SecTrustServerGetWorkloop());
732 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
733 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
734 trustd_xpc_dictionary_handler(connection, event);
735 }
736 });
737 xpc_connection_activate(connection);
738 }
739 });
740 xpc_connection_activate(listener);
741 }
742
743 static void trustd_sandbox(void) {
744 #if TARGET_OS_OSX
745 char buf[PATH_MAX] = "";
746
747 if (!_set_user_dir_suffix("com.apple.trustd") ||
748 confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof(buf)) == 0 ||
749 (mkdir(buf, 0700) && errno != EEXIST)) {
750 secerror("failed to initialize temporary directory (%d): %s", errno, strerror(errno));
751 exit(EXIT_FAILURE);
752 }
753
754 char *tempdir = realpath(buf, NULL);
755 if (tempdir == NULL) {
756 secerror("failed to resolve temporary directory (%d): %s", errno, strerror(errno));
757 exit(EXIT_FAILURE);
758 }
759
760 if (confstr(_CS_DARWIN_USER_CACHE_DIR, buf, sizeof(buf)) == 0 ||
761 (mkdir(buf, 0700) && errno != EEXIST)) {
762 secerror("failed to initialize cache directory (%d): %s", errno, strerror(errno));
763 exit(EXIT_FAILURE);
764 }
765
766 char *cachedir = realpath(buf, NULL);
767 if (cachedir == NULL) {
768 secerror("failed to resolve cache directory (%d): %s", errno, strerror(errno));
769 exit(EXIT_FAILURE);
770 }
771
772 const char *parameters[] = {
773 "_TMPDIR", tempdir,
774 "_DARWIN_CACHE_DIR", cachedir,
775 NULL
776 };
777
778 char *sberror = NULL;
779 if (sandbox_init_with_parameters("com.apple.trustd", SANDBOX_NAMED, parameters, &sberror) != 0) {
780 secerror("Failed to enter trustd sandbox: %{public}s", sberror);
781 exit(EXIT_FAILURE);
782 }
783
784 free(tempdir);
785 free(cachedir);
786 #else // !TARGET_OS_OSX
787 char buf[PATH_MAX] = "";
788 _set_user_dir_suffix("com.apple.trustd");
789 confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof(buf));
790 #endif // !TARGET_OS_OSX
791 }
792
793 int main(int argc, char *argv[])
794 {
795 DisableLocalization();
796
797 char *wait4debugger = getenv("WAIT4DEBUGGER");
798 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
799 seccritical("SIGSTOPing self, awaiting debugger");
800 kill(getpid(), SIGSTOP);
801 seccritical("Again, for good luck (or bad debuggers)");
802 kill(getpid(), SIGSTOP);
803 }
804
805 trustd_sandbox();
806
807 const char *serviceName = kTrustdXPCServiceName;
808 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
809 serviceName = kTrustdAgentXPCServiceName;
810 }
811
812 /* set up SQLite before some other component has a chance to create a database connection */
813 _SecDbServerSetup();
814
815 gTrustd = &trustd_spi;
816
817 /* Initialize static content */
818 SecPolicyServerInitialize(); // set up callbacks for policy checks
819 SecRevocationDbInitialize(); // set up revocation database if it doesn't already exist, or needs to be replaced
820 SecPinningDbInitialize(); // set up the pinning database
821 #if TARGET_OS_OSX
822 SecTrustLegacySourcesListenForKeychainEvents(); // set up the legacy keychain event listeners (for cache invalidation)
823 #endif
824
825 /* We're ready now. Go. */
826 trustd_xpc_init(serviceName);
827 dispatch_main();
828 }