]> git.saurik.com Git - apple/security.git/blob - trust/trustd/trustd.c
Security-59306.41.2.tar.gz
[apple/security.git] / trust / trustd / trustd.c
1 /*
2 * Copyright (c) 2017-2018 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 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 #if TARGET_OS_IPHONE
385 static bool SecXPCTrustGetExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) {
386 uint64_t exceptionResetCount = SecTrustServerGetExceptionResetCount(error);
387 if (error && *error) {
388 return false;
389 }
390
391 xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, exceptionResetCount);
392 return true;
393 }
394
395 static bool SecXPCTrustIncrementExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) {
396 OSStatus status = errSecInternal;
397 bool result = SecTrustServerIncrementExceptionResetCount(error);
398 if (result && (!error || (error && !*error))) {
399 status = errSecSuccess;
400 }
401
402 xpc_dictionary_set_bool(reply, kSecXPCKeyResult, status);
403 return result;
404 }
405 #endif
406
407 typedef bool(*SecXPCOperationHandler)(SecurityClient *client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error);
408
409 typedef struct {
410 CFStringRef entitlement;
411 SecXPCOperationHandler handler;
412 } SecXPCServerOperation;
413
414 struct trustd_operations {
415 SecXPCServerOperation trust_store_contains;
416 SecXPCServerOperation trust_store_set_trust_settings;
417 SecXPCServerOperation trust_store_remove_certificate;
418 SecXPCServerOperation trust_store_copy_all;
419 SecXPCServerOperation trust_store_copy_usage_constraints;
420 SecXPCServerOperation ocsp_cache_flush;
421 SecXPCServerOperation ota_pki_trust_store_version;
422 SecXPCServerOperation ota_pki_asset_version;
423 SecXPCServerOperation ota_pki_get_escrow_certs;
424 SecXPCServerOperation ota_pki_get_new_asset;
425 SecXPCServerOperation ota_pki_copy_trusted_ct_logs;
426 SecXPCServerOperation ota_pki_copy_ct_log_for_keyid;
427 SecXPCServerOperation networking_analytics_report;
428 SecXPCServerOperation trust_store_set_ct_exceptions;
429 SecXPCServerOperation trust_store_copy_ct_exceptions;
430 SecXPCServerOperation ota_secexperiment_get_asset;
431 SecXPCServerOperation ota_secexperiment_get_new_asset;
432 #if TARGET_OS_IPHONE
433 SecXPCServerOperation trust_get_exception_reset_count;
434 SecXPCServerOperation trust_increment_exception_reset_count;
435 #endif
436 };
437
438 static struct trustd_operations trustd_ops = {
439 .trust_store_contains = { NULL, SecXPCTrustStoreContains },
440 .trust_store_set_trust_settings = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetTrustSettings },
441 .trust_store_remove_certificate = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreRemoveCertificate },
442 .trust_store_copy_all = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyAll },
443 .trust_store_copy_usage_constraints = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyUsageConstraints },
444 .ocsp_cache_flush = { NULL, SecXPC_OCSPCacheFlush },
445 .ota_pki_trust_store_version = { NULL, SecXPC_OTAPKI_GetCurrentTrustStoreVersion },
446 .ota_pki_asset_version = { NULL, SecXPC_OTAPKI_GetCurrentAssetVersion },
447 .ota_pki_get_escrow_certs = { NULL, SecXPC_OTAPKI_GetEscrowCertificates },
448 .ota_pki_get_new_asset = { NULL, SecXPC_OTAPKI_GetNewAsset },
449 .ota_secexperiment_get_new_asset = { NULL, SecXPC_OTASecExperiment_GetNewAsset },
450 .ota_secexperiment_get_asset = { NULL, SecXPC_OTASecExperiment_GetAsset },
451 .ota_pki_copy_trusted_ct_logs = { NULL, SecXPC_OTAPKI_CopyTrustedCTLogs },
452 .ota_pki_copy_ct_log_for_keyid = { NULL, SecXPC_OTAPKI_CopyCTLogForKeyID },
453 .networking_analytics_report = { NULL, SecXPC_Networking_AnalyticsReport },
454 .trust_store_set_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCTExceptions },
455 .trust_store_copy_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCTExceptions },
456 #if TARGET_OS_IPHONE
457 .trust_get_exception_reset_count = { NULL, SecXPCTrustGetExceptionResetCount },
458 .trust_increment_exception_reset_count = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustIncrementExceptionResetCount },
459 #endif
460 };
461
462 static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
463 xpc_type_t type = xpc_get_type(event);
464 __block CFErrorRef error = NULL;
465 xpc_object_t xpcError = NULL;
466 xpc_object_t replyMessage = NULL;
467 CFDataRef clientAuditToken = NULL;
468 CFArrayRef domains = NULL;
469 SecurityClient client = {
470 .task = NULL,
471 .accessGroups = NULL,
472 .musr = NULL,
473 .uid = xpc_connection_get_euid(connection),
474 .allowSystemKeychain = true,
475 .allowSyncBubbleKeychain = false,
476 .isNetworkExtension = false,
477 .canAccessNetworkExtensionAccessGroups = false,
478 #if TARGET_OS_IPHONE
479 .inMultiUser = false,
480 #endif
481 };
482
483 secdebug("serverxpc", "entering");
484 if (type == XPC_TYPE_DICTIONARY) {
485 replyMessage = xpc_dictionary_create_reply(event);
486
487 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
488
489 audit_token_t auditToken = {};
490 xpc_connection_get_audit_token(connection, &auditToken);
491
492 client.task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
493 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
494 client.accessGroups = SecTaskCopyAccessGroups(client.task);
495
496 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
497
498 if (operation == sec_trust_evaluate_id) {
499 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL, exceptions = NULL;
500 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
501 bool keychainsAllowed = xpc_dictionary_get_bool(event, kSecTrustKeychainsAllowedKey);
502 double verifyTime;
503 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
504 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
505 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
506 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
507 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
508 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
509 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error) &&
510 SecXPCDictionaryCopyArrayOptional(event, kSecTrustExceptionsKey, &exceptions, &error)) {
511 // If we have no error yet, capture connection and reply in block and properly retain them.
512 xpc_retain(connection);
513 CFRetainSafe(client.task);
514 CFRetainSafe(clientAuditToken);
515
516 // Clear replyMessage so we don't send a synchronous reply.
517 xpc_object_t asyncReply = replyMessage;
518 replyMessage = NULL;
519
520 SecTrustServerEvaluateBlock(SecTrustServerGetWorkloop(), clientAuditToken, certificates, anchors, anchorsOnly, keychainsAllowed, policies,
521 responses, scts, trustedLogs, verifyTime, client.accessGroups, exceptions,
522 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain,
523 CFErrorRef replyError) {
524 // Send back reply now
525 if (replyError) {
526 CFRetain(replyError);
527 } else {
528 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
529 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
530 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
531 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
532 }
533 if (replyError) {
534 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
535 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
536 if (xpcReplyError) {
537 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
538 xpc_release(xpcReplyError);
539 }
540 CFReleaseNull(replyError);
541 } else {
542 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
543 }
544
545 xpc_connection_send_message(connection, asyncReply);
546 xpc_release(asyncReply);
547 xpc_release(connection);
548 CFReleaseSafe(client.task);
549 CFReleaseSafe(clientAuditToken);
550 });
551 }
552 CFReleaseSafe(policies);
553 CFReleaseSafe(anchors);
554 CFReleaseSafe(certificates);
555 CFReleaseSafe(responses);
556 CFReleaseSafe(scts);
557 CFReleaseSafe(trustedLogs);
558 CFReleaseSafe(exceptions);
559 } else {
560 SecXPCServerOperation *server_op = NULL;
561 switch (operation) {
562 case sec_trust_store_contains_id:
563 server_op = &trustd_ops.trust_store_contains;
564 break;
565 case sec_trust_store_set_trust_settings_id:
566 server_op = &trustd_ops.trust_store_set_trust_settings;
567 break;
568 case sec_trust_store_remove_certificate_id:
569 server_op = &trustd_ops.trust_store_remove_certificate;
570 break;
571 case sec_trust_store_copy_all_id:
572 server_op = &trustd_ops.trust_store_copy_all;
573 break;
574 case sec_trust_store_copy_usage_constraints_id:
575 server_op = &trustd_ops.trust_store_copy_usage_constraints;
576 break;
577 case sec_ocsp_cache_flush_id:
578 server_op = &trustd_ops.ocsp_cache_flush;
579 break;
580 case sec_ota_pki_trust_store_version_id:
581 server_op = &trustd_ops.ota_pki_trust_store_version;
582 break;
583 case sec_ota_pki_asset_version_id:
584 server_op = &trustd_ops.ota_pki_asset_version;
585 break;
586 case kSecXPCOpOTAGetEscrowCertificates:
587 server_op = &trustd_ops.ota_pki_get_escrow_certs;
588 break;
589 case kSecXPCOpOTAPKIGetNewAsset:
590 server_op = &trustd_ops.ota_pki_get_new_asset;
591 break;
592 case kSecXPCOpOTASecExperimentGetNewAsset:
593 server_op = &trustd_ops.ota_secexperiment_get_new_asset;
594 break;
595 case kSecXPCOpOTASecExperimentGetAsset:
596 server_op = &trustd_ops.ota_secexperiment_get_asset;
597 break;
598 case kSecXPCOpOTAPKICopyTrustedCTLogs:
599 server_op = &trustd_ops.ota_pki_copy_trusted_ct_logs;
600 break;
601 case kSecXPCOpOTAPKICopyCTLogForKeyID:
602 server_op = &trustd_ops.ota_pki_copy_ct_log_for_keyid;
603 break;
604 case kSecXPCOpNetworkingAnalyticsReport:
605 server_op = &trustd_ops.networking_analytics_report;
606 break;
607 case kSecXPCOpSetCTExceptions:
608 server_op = &trustd_ops.trust_store_set_ct_exceptions;
609 break;
610 case kSecXPCOpCopyCTExceptions:
611 server_op = &trustd_ops.trust_store_copy_ct_exceptions;
612 break;
613 #if TARGET_OS_IPHONE
614 case sec_trust_get_exception_reset_count_id:
615 server_op = &trustd_ops.trust_get_exception_reset_count;
616 break;
617 case sec_trust_increment_exception_reset_count_id:
618 server_op = &trustd_ops.trust_increment_exception_reset_count;
619 break;
620 #endif
621 default:
622 break;
623 }
624 if (server_op && server_op->handler) {
625 bool entitled = true;
626 if (server_op->entitlement) {
627 entitled = EntitlementPresentAndTrue(operation, client.task, server_op->entitlement, &error);
628 }
629 if (entitled) {
630 (void)server_op->handler(&client, event, replyMessage, &error);
631 }
632 }
633 }
634
635 if (error)
636 {
637 if(SecErrorGetOSStatus(error) == errSecItemNotFound)
638 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
639 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
640 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
641 else
642 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
643
644 xpcError = SecCreateXPCObjectWithCFError(error);
645 if (replyMessage) {
646 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
647 }
648 } else if (replyMessage) {
649 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
650 }
651 } else {
652 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
653 secerror("%@: returning error: %@", client.task, error);
654 xpcError = SecCreateXPCObjectWithCFError(error);
655 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
656 }
657
658 if (replyMessage) {
659 xpc_connection_send_message(connection, replyMessage);
660 xpc_release(replyMessage);
661 }
662 if (xpcError)
663 xpc_release(xpcError);
664 CFReleaseSafe(error);
665 CFReleaseSafe(client.accessGroups);
666 CFReleaseSafe(client.musr);
667 CFReleaseSafe(client.task);
668 CFReleaseSafe(domains);
669 CFReleaseSafe(clientAuditToken);
670 }
671
672 static void trustd_xpc_init(const char *service_name)
673 {
674 secdebug("serverxpc", "start");
675 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
676 if (!listener) {
677 seccritical("security failed to register xpc listener for %s, exiting", service_name);
678 abort();
679 }
680
681 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
682 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
683 xpc_connection_set_target_queue(connection, SecTrustServerGetWorkloop());
684 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
685 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
686 trustd_xpc_dictionary_handler(connection, event);
687 }
688 });
689 xpc_connection_activate(connection);
690 }
691 });
692 xpc_connection_activate(listener);
693 }
694
695 static void trustd_sandbox(void) {
696 #if TARGET_OS_OSX
697 char buf[PATH_MAX] = "";
698
699 if (!_set_user_dir_suffix("com.apple.trustd") ||
700 confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof(buf)) == 0 ||
701 (mkdir(buf, 0700) && errno != EEXIST)) {
702 secerror("failed to initialize temporary directory (%d): %s", errno, strerror(errno));
703 exit(EXIT_FAILURE);
704 }
705
706 char *tempdir = realpath(buf, NULL);
707 if (tempdir == NULL) {
708 secerror("failed to resolve temporary directory (%d): %s", errno, strerror(errno));
709 exit(EXIT_FAILURE);
710 }
711
712 if (confstr(_CS_DARWIN_USER_CACHE_DIR, buf, sizeof(buf)) == 0 ||
713 (mkdir(buf, 0700) && errno != EEXIST)) {
714 secerror("failed to initialize cache directory (%d): %s", errno, strerror(errno));
715 exit(EXIT_FAILURE);
716 }
717
718 char *cachedir = realpath(buf, NULL);
719 if (cachedir == NULL) {
720 secerror("failed to resolve cache directory (%d): %s", errno, strerror(errno));
721 exit(EXIT_FAILURE);
722 }
723
724 const char *parameters[] = {
725 "_TMPDIR", tempdir,
726 "_DARWIN_CACHE_DIR", cachedir,
727 NULL
728 };
729
730 char *sberror = NULL;
731 if (sandbox_init_with_parameters("com.apple.trustd", SANDBOX_NAMED, parameters, &sberror) != 0) {
732 secerror("Failed to enter trustd sandbox: %{public}s", sberror);
733 exit(EXIT_FAILURE);
734 }
735
736 free(tempdir);
737 free(cachedir);
738 #else // !TARGET_OS_OSX
739 char buf[PATH_MAX] = "";
740 _set_user_dir_suffix("com.apple.trustd");
741 confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof(buf));
742 #endif // !TARGET_OS_OSX
743 }
744
745 int main(int argc, char *argv[])
746 {
747 DisableLocalization();
748
749 char *wait4debugger = getenv("WAIT4DEBUGGER");
750 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
751 seccritical("SIGSTOPing self, awaiting debugger");
752 kill(getpid(), SIGSTOP);
753 seccritical("Again, for good luck (or bad debuggers)");
754 kill(getpid(), SIGSTOP);
755 }
756
757 trustd_sandbox();
758
759 const char *serviceName = kTrustdXPCServiceName;
760 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
761 serviceName = kTrustdAgentXPCServiceName;
762 }
763
764 /* set up SQLite before some other component has a chance to create a database connection */
765 _SecDbServerSetup();
766
767 gTrustd = &trustd_spi;
768
769 /* Initialize static content */
770 SecPolicyServerInitialize(); // set up callbacks for policy checks
771 SecRevocationDbInitialize(); // set up revocation database if it doesn't already exist, or needs to be replaced
772 SecPinningDbInitialize(); // set up the pinning database
773 #if TARGET_OS_OSX
774 SecTrustLegacySourcesListenForKeychainEvents(); // set up the legacy keychain event listeners (for cache invalidation)
775 #endif
776
777 /* We're ready now. Go. */
778 trustd_xpc_init(serviceName);
779 dispatch_main();
780 }