]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server.c
d12b66e9e1719c74ade45fab66ebb620c2def4c9
[apple/security.git] / OSX / sec / ipc / server.c
1 /*
2 * Copyright (c) 2007-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 <Security/SecureObjectSync/SOSPeerInfoDER.h>
25 #include <Security/SecureObjectSync/SOSCloudCircle.h>
26 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27 #include <Security/SecureObjectSync/SOSInternal.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecEntitlements.h>
32 #include <Security/SecInternal.h>
33 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
34 #include <Security/SecPolicyInternal.h>
35 #include <Security/SecTask.h>
36 #include <Security/SecuritydXPC.h>
37 #include <securityd/OTATrustUtilities.h>
38 #include <securityd/SOSCloudCircleServer.h>
39 #include <securityd/SecItemBackupServer.h>
40 #include <securityd/SecItemServer.h>
41 #include <securityd/SecLogSettingsServer.h>
42 #include <securityd/SecOTRRemote.h>
43 #include <securityd/SecTrustServer.h>
44 #include <securityd/SecTrustStoreServer.h>
45 #include <securityd/iCloudTrace.h>
46 #include <securityd/spi.h>
47 #include <utilities/SecCFError.h>
48 #include <utilities/SecCFWrappers.h>
49 #include <utilities/SecDb.h>
50 #include <utilities/SecIOFormat.h>
51 #include <utilities/SecXPCError.h>
52 #include <utilities/debugging.h>
53
54 #include <AssertMacros.h>
55 #include <CoreFoundation/CFXPCBridge.h>
56 #include <CoreFoundation/CoreFoundation.h>
57 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
58 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
59 #include <MobileKeyBag/MobileKeyBag.h>
60 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
61 #include <asl.h>
62 #include <bsm/libbsm.h>
63 #include <ipc/securityd_client.h>
64 #include <libkern/OSAtomic.h>
65 #include <mach/mach.h>
66 #include <mach/message.h>
67 #include <notify.h>
68 #include <stdlib.h>
69 #include <sys/queue.h>
70 #include <sys/sysctl.h>
71 #include <syslog.h>
72 #include <xpc/private.h>
73 #include <xpc/xpc.h>
74
75 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
76 #include <Security/SecTaskPriv.h>
77 #endif
78
79 static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
80 CFStringRef entitlement)
81 {
82 CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task,
83 entitlement, NULL);
84 if (value && CFGetTypeID(value) != CFStringGetTypeID()) {
85 CFRelease(value);
86 value = NULL;
87 }
88
89 return value;
90 }
91
92 static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task,
93 CFStringRef entitlement)
94 {
95 CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task,
96 entitlement, NULL);
97 if (value) {
98 if (CFGetTypeID(value) == CFArrayGetTypeID()) {
99 CFIndex ix, count = CFArrayGetCount(value);
100 for (ix = 0; ix < count; ++ix) {
101 CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix);
102 if (CFGetTypeID(string) != CFStringGetTypeID()) {
103 CFRelease(value);
104 value = NULL;
105 break;
106 }
107 }
108 } else {
109 CFRelease(value);
110 value = NULL;
111 }
112 }
113
114 return value;
115 }
116
117 static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) {
118 return SecTaskCopyStringForEntitlement(task,
119 kSecEntitlementApplicationIdentifier);
120 }
121
122 static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) {
123 return SecTaskCopyArrayOfStringsForEntitlement(task,
124 kSecEntitlementAssociatedDomains);
125 }
126
127 static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) {
128 CFMutableArrayRef groups = NULL;
129 CFArrayRef keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
130 kSecEntitlementKeychainAccessGroups);
131 CFArrayRef appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
132 kSecEntitlementAppleSecurityApplicationGroups);
133 CFStringRef appID = SecTaskCopyApplicationIdentifier(task);
134 CFIndex kagLen = keychainAccessGroups ? CFArrayGetCount(keychainAccessGroups) : 0;
135 CFIndex asagLen = appleSecurityApplicationGroups ? CFArrayGetCount(appleSecurityApplicationGroups) : 0;
136 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
137 if ((appID || asagLen) && !SecTaskEntitlementsValidated(task)) {
138 CFReleaseNull(appID);
139 asagLen = 0;
140 }
141 #endif
142 CFIndex len = kagLen + asagLen + (appID ? 1 : 0);
143 if (len) {
144 groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks);
145 if (kagLen)
146 CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, kagLen));
147 if (appID)
148 CFArrayAppendValue(groups, appID);
149 if (asagLen)
150 CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, asagLen));
151 #if TARGET_IPHONE_SIMULATOR
152 } else {
153 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
154 groups = (CFMutableArrayRef)CFRetainSafe(SecAccessGroupsGetCurrent());
155 #endif
156 }
157
158 CFReleaseSafe(appID);
159 CFReleaseSafe(keychainAccessGroups);
160 CFReleaseSafe(appleSecurityApplicationGroups);
161 return groups;
162 }
163
164 static pthread_key_t taskThreadKey;
165 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups) {
166 SecTaskRef taskRef = pthread_getspecific(taskThreadKey);
167 if (taskRef == NULL) {
168 secerror("MISSING keychain entitlements: no stored taskRef found");
169 return;
170 }
171
172 CFErrorRef error = NULL;
173 CFArrayRef entitlementNames = CFArrayCreateForCFTypes(NULL,
174 kSecEntitlementApplicationIdentifier,
175 kSecEntitlementKeychainAccessGroups,
176 kSecEntitlementAppleSecurityApplicationGroups,
177 NULL);
178 CFDictionaryRef rawEntitlements = SecTaskCopyValuesForEntitlements(taskRef, entitlementNames, &error);
179 CFRelease(entitlementNames);
180
181 if (rawEntitlements == NULL) {
182 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error);
183 CFReleaseSafe(error);
184 __security_simulatecrash(CFSTR("failed to read keychain client entitlement(s)"), __sec_exception_code_MissingEntitlements);
185 return;
186 }
187
188 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements);
189 secerror("MISSING keychain entitlements: original ag: %@", accessGroups);
190 CFArrayRef newAccessGroups = SecTaskCopyAccessGroups(taskRef);
191 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups);
192
193 __security_simulatecrash(CFSTR("keychain entitlement(s) missing"), __sec_exception_code_MissingEntitlements);
194
195 CFReleaseSafe(newAccessGroups);
196 CFReleaseSafe(rawEntitlements);
197 }
198
199 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task,
200 CFStringRef entitlement) {
201 CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task,
202 entitlement, NULL);
203 if (!canModify)
204 return false;
205 CFTypeID canModifyType = CFGetTypeID(canModify);
206 bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify);
207 CFRelease(canModify);
208 return ok;
209 }
210
211 static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) {
212 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
213
214 if (label_utf8) { // Anything we would do here requires a user label
215 size_t password_length = 0;
216 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
217
218 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
219 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
220
221 action(user_label, user_password);
222
223 CFReleaseNull(user_password);
224 CFReleaseNull(user_label);
225 }
226 }
227
228 static void with_label_and_password_and_dsid(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password, CFStringRef dsid)) {
229 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
230
231 if (label_utf8) { // Anything we would do here requires a user label
232 size_t password_length = 0;
233 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
234 const char *xdsid = xpc_dictionary_get_string(message, kSecXPCKeyDSID);
235
236 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
237 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
238 CFStringRef dsid = CFStringCreateWithCString(kCFAllocatorDefault, xdsid, kCFStringEncodingUTF8);
239
240 action(user_label, user_password, dsid);
241
242 CFReleaseNull(dsid);
243 CFReleaseNull(user_password);
244 CFReleaseNull(user_label);
245 }
246 }
247
248 static void with_label_and_number(xpc_object_t message, void (^action)(CFStringRef label, uint64_t number)) {
249 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyViewName);
250 const int64_t number = xpc_dictionary_get_int64(message, kSecXPCKeyViewActionCode);
251 secnotice("views", "Action Code Raw is %d", (int) number);
252 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
253
254 action(user_label, number);
255 CFReleaseNull(user_label);
256 }
257
258 static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) {
259 if (!path)
260 return true;
261 xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error);
262 if (!xpc_chain)
263 return false;
264
265 xpc_dictionary_set_value(message, key, xpc_chain);
266 xpc_release(xpc_chain);
267 return true;
268 }
269
270 static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) {
271 size_t length = 0;
272 const void *bytes = xpc_dictionary_get_data(message, key, &length);
273 if (bytes) {
274 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length);
275 if (certificate)
276 return certificate;
277 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key);
278 } else {
279 SecError(errSecParam, error, CFSTR("object for key %s missing"), key);
280 }
281 return NULL;
282 }
283
284 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
285 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
286 if (!xpc_certificates)
287 return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key);
288 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
289 return *certificates;
290 }
291
292 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
293 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
294 if (!xpc_certificates) {
295 *certificates = NULL;
296 return true;
297 }
298 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
299 return *certificates;
300 }
301
302 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) {
303 xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key);
304 if (!xpc_policies) {
305 if (policies)
306 *policies = NULL;
307 return true;
308 }
309 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error);
310 return *policies != NULL;
311 }
312
313 static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) {
314 SecTrustStoreRef ts = NULL;
315 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error);
316 if (domain) {
317 ts = SecTrustStoreForDomainName(domain, error);
318 CFRelease(domain);
319 }
320 return ts;
321 }
322
323 static bool SecXPCDictionaryGetDouble(xpc_object_t message, const char *key, double *pvalue, CFErrorRef *error) {
324 *pvalue = xpc_dictionary_get_double(message, key);
325 if (*pvalue == NAN) {
326 return SecError(errSecParam, error, CFSTR("object for key %s bad double"), key);
327 }
328 return true;
329 }
330
331 static CFArrayRef SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary, const char *key, CFErrorRef *error) {
332 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary, key), error);
333 }
334
335 static CFDataRef CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array, size_t index, CFErrorRef *error) {
336 CFDataRef data = NULL;
337 size_t length = 0;
338 const uint8_t *bytes = xpc_array_get_data(xpc_data_array, index, &length);
339 if (bytes) {
340 data = CFDataCreate(kCFAllocatorDefault, bytes, length);
341 }
342 if (!data)
343 SecError(errSecParam, error, CFSTR("data_array[%zu] failed to decode"), index);
344
345 return data;
346 }
347
348 static CFArrayRef CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array, CFErrorRef *error) {
349 CFMutableArrayRef data_array = NULL;
350 require_action_quiet(xpc_get_type(xpc_data_array) == XPC_TYPE_ARRAY, exit,
351 SecError(errSecParam, error, CFSTR("data_array xpc value is not an array")));
352 size_t count = xpc_array_get_count(xpc_data_array);
353 require_action_quiet(data_array = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit,
354 SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count));
355
356 size_t ix;
357 for (ix = 0; ix < count; ++ix) {
358 CFDataRef data = CFDataCreateWithXPCArrayAtIndex(xpc_data_array, ix, error);
359 if (!data) {
360 CFRelease(data_array);
361 return NULL;
362 }
363 CFArraySetValueAtIndex(data_array, ix, data);
364 CFRelease(data);
365 }
366
367 exit:
368 return data_array;
369 }
370
371 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message, const char *key, CFArrayRef *data_array, CFErrorRef *error) {
372 xpc_object_t xpc_data_array = xpc_dictionary_get_value(message, key);
373 if (!xpc_data_array) {
374 if (data_array)
375 *data_array = NULL;
376 return true;
377 }
378 *data_array = CFDataXPCArrayCopyArray(xpc_data_array, error);
379 return *data_array != NULL;
380 }
381
382 static CFSetRef SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event, const char *key) {
383 CFErrorRef error = NULL;
384 xpc_object_t object = xpc_dictionary_get_value(event, key);
385 CFSetRef retval = NULL;
386 if(object) retval = CreateCFSetRefFromXPCObject(object, &error);
387 CFReleaseNull(error);
388 return retval;
389 }
390
391 static inline
392 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array) {
393 if (cf_array) {
394 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(cf_array);
395 xpc_dictionary_set_value(xdict, key, xpc_array);
396 xpc_release(xpc_array);
397 }
398 CFReleaseNull(cf_array);
399 }
400
401 static inline
402 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array, CFErrorRef *error) {
403 bool success = true;
404 if (cf_array) {
405 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(cf_array, error);
406 if (xpc_array) {
407 xpc_dictionary_set_value(xdict, key, xpc_array);
408 xpc_release(xpc_array);
409 } else {
410 success = false;
411 }
412 }
413 CFReleaseNull(cf_array);
414 return success;
415 }
416
417
418 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
419 xpc_type_t type = xpc_get_type(event);
420 __block CFErrorRef error = NULL;
421 xpc_object_t xpcError = NULL;
422 xpc_object_t replyMessage = NULL;
423 SecTaskRef clientTask = NULL;
424 CFDataRef clientAuditToken = NULL;
425 CFArrayRef accessGroups = NULL;
426 CFArrayRef domains = NULL;
427
428 secdebug("serverxpc", "entering");
429 if (type == XPC_TYPE_DICTIONARY) {
430 // TODO: Find out what we're dispatching.
431 replyMessage = xpc_dictionary_create_reply(event);
432
433 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
434
435 bool hasEntitlement;
436 audit_token_t auditToken = {};
437 xpc_connection_get_audit_token(connection, &auditToken);
438
439 clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
440 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
441 pthread_setspecific(taskThreadKey, clientTask);
442 accessGroups = SecTaskCopyAccessGroups(clientTask);
443 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
444 domains = SecTaskCopySharedWebCredentialDomains(clientTask);
445 }
446
447 // TODO: change back to secdebug
448 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
449
450 if (true) {
451 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
452 // Refer to rdar://problem/18615626&18616300 for more details.
453 int64_t minimumDirtyInterval = (int64_t) (2 * NSEC_PER_SEC);
454 xpc_transaction_begin();
455 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, minimumDirtyInterval), dispatch_get_main_queue(), ^{
456 xpc_transaction_end();
457 });
458 }
459
460 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
461 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) ||
462 (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle));
463
464 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
465 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
466
467 if (!hasEntitlement) {
468 CFErrorRef entitlementError = NULL;
469 SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle);
470 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError);
471 CFReleaseSafe(entitlementError);
472 }
473
474 if (true) {
475 switch (operation)
476 {
477 case sec_item_add_id:
478 {
479 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
480 if (query) {
481 CFTypeRef result = NULL;
482 if (_SecItemAdd(query, accessGroups, &result, &error) && result) {
483 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
484 CFRelease(result);
485 }
486 CFRelease(query);
487 }
488 break;
489 }
490 case sec_item_copy_matching_id:
491 {
492 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
493 if (query) {
494 CFTypeRef result = NULL;
495 if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) {
496 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
497 CFRelease(result);
498 }
499 CFRelease(query);
500 }
501 break;
502 }
503 case sec_item_update_id:
504 {
505 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
506 if (query) {
507 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
508 if (attributesToUpdate) {
509 bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error);
510 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
511 CFRelease(attributesToUpdate);
512 }
513 CFRelease(query);
514 }
515 break;
516 }
517 case sec_item_delete_id:
518 {
519 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
520 if (query) {
521 bool result = _SecItemDelete(query, accessGroups, &error);
522 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
523 CFRelease(query);
524 }
525 break;
526 }
527 case sec_trust_store_contains_id:
528 {
529 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
530 if (ts) {
531 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
532 if (digest) {
533 bool contains;
534 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error))
535 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains);
536 CFRelease(digest);
537 }
538 }
539 break;
540 }
541 case sec_trust_store_set_trust_settings_id:
542 {
543 if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) {
544 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
545 if (ts) {
546 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error);
547 if (certificate) {
548 CFTypeRef trustSettingsDictOrArray = NULL;
549 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) {
550 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error);
551 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
552 CFReleaseSafe(trustSettingsDictOrArray);
553 }
554 CFRelease(certificate);
555 }
556 }
557 } else {
558 SecError(errSecMissingEntitlement, &error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates);
559 }
560 break;
561 }
562 case sec_trust_store_remove_certificate_id:
563 {
564 if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) {
565 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
566 if (ts) {
567 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
568 if (digest) {
569 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error);
570 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
571 CFRelease(digest);
572 }
573 }
574 } else {
575 SecError(errSecMissingEntitlement, &error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates);
576 }
577 break;
578 }
579 case sec_delete_all_id:
580 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error));
581 break;
582 case sec_trust_evaluate_id:
583 {
584 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL;
585 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
586 double verifyTime;
587 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
588 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
589 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
590 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
591 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
592 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
593 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) {
594 // If we have no error yet, capture connection and reply in block and properly retain them.
595 xpc_retain(connection);
596 CFRetainSafe(clientTask);
597 CFRetainSafe(clientAuditToken);
598
599 // Clear replyMessage so we don't send a synchronous reply.
600 xpc_object_t asyncReply = replyMessage;
601 replyMessage = NULL;
602
603 SecTrustServerEvaluateBlock(clientAuditToken,
604 certificates, anchors, anchorsOnly, policies, responses, scts, trustedLogs, verifyTime, accessGroups,
605 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) {
606 // Send back reply now
607 if (replyError) {
608 CFRetain(replyError);
609 } else {
610 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
611 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
612 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
613 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
614 }
615 if (replyError) {
616 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
617 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
618 if (xpcReplyError) {
619 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
620 xpc_release(xpcReplyError);
621 }
622 CFRelease(replyError);
623 } else {
624 secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
625 }
626
627 xpc_connection_send_message(connection, asyncReply);
628 xpc_release(asyncReply);
629 xpc_release(connection);
630 CFReleaseSafe(clientTask);
631 CFReleaseSafe(clientAuditToken);
632 });
633 }
634 CFReleaseSafe(policies);
635 CFReleaseSafe(anchors);
636 CFReleaseSafe(certificates);
637 CFReleaseSafe(responses);
638 CFReleaseSafe(scts);
639 CFReleaseSafe(trustedLogs);
640 break;
641 }
642 case sec_keychain_backup_id:
643 {
644 CFDataRef keybag = NULL, passcode = NULL;
645 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
646 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
647 CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error);
648 if (backup) {
649 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
650 CFRelease(backup);
651 }
652 CFReleaseSafe(passcode);
653 }
654 CFReleaseSafe(keybag);
655 }
656 break;
657 }
658 case sec_keychain_restore_id:
659 {
660 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
661 if (backup) {
662 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
663 if (keybag) {
664 CFDataRef passcode = NULL;
665 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
666 bool result = _SecServerKeychainRestore(backup, keybag, passcode, &error);
667 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
668 CFReleaseSafe(passcode);
669 }
670 CFRelease(keybag);
671 }
672 CFRelease(backup);
673 }
674 break;
675 }
676 case sec_keychain_sync_update_message_id:
677 {
678 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
679 if (updates) {
680 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
681 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
682 CFReleaseNull(result);
683 }
684 CFReleaseNull(updates);
685 break;
686 }
687 case sec_keychain_backup_syncable_id:
688 {
689 CFDictionaryRef oldbackup = NULL;
690 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
691 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
692 if (keybag) {
693 CFDataRef passcode = NULL;
694 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
695 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
696 if (newbackup) {
697 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
698 CFRelease(newbackup);
699 }
700 CFReleaseSafe(passcode);
701 }
702 CFRelease(keybag);
703 }
704 CFReleaseSafe(oldbackup);
705 }
706 break;
707 }
708 case sec_keychain_restore_syncable_id:
709 {
710 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
711 if (backup) {
712 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
713 if (keybag) {
714 CFDataRef passcode = NULL;
715 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
716 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
717 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
718 CFReleaseSafe(passcode);
719 }
720 CFRelease(keybag);
721 }
722 CFRelease(backup);
723 }
724 break;
725 }
726 case sec_item_backup_copy_names_id:
727 {
728 CFArrayRef names = SecServerItemBackupCopyNames(&error);
729 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
730 CFReleaseSafe(names);
731 break;
732 }
733 case sec_item_backup_handoff_fd_id:
734 {
735 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
736 int fd = -1;
737 if (backupName) {
738 fd = SecServerItemBackupHandoffFD(backupName, &error);
739 CFRelease(backupName);
740 }
741 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
742 if (fd != -1)
743 close(fd);
744 break;
745 }
746 case sec_item_backup_set_confirmed_manifest_id:
747 {
748 CFDataRef keybagDigest = NULL;
749 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
750 CFDataRef manifest = NULL;
751 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
752 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
753 if (backupName) {
754 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
755 CFRelease(backupName);
756 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
757 }
758 CFReleaseSafe(manifest);
759 }
760 CFRelease(keybagDigest);
761 }
762 break;
763 }
764 case sec_item_backup_restore_id:
765 {
766 bool result = false;
767 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
768 if (backupName) {
769 CFStringRef peerID = NULL;
770 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
771 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
772 if (keybag) {
773 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
774 if (secret) {
775 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
776 if (backup) {
777 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
778 CFRelease(backup);
779 }
780 CFRelease(secret);
781 }
782 CFRelease(keybag);
783 }
784 CFReleaseSafe(peerID);
785 }
786 CFRelease(backupName);
787 }
788 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
789 break;
790 }
791 case sec_ota_pki_asset_version_id:
792 {
793 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
794 SecOTAPKIGetCurrentAssetVersion(&error));
795 break;
796 }
797 case sec_add_shared_web_credential_id:
798 {
799 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
800 if (query) {
801 CFTypeRef result = NULL;
802 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
803 if (_SecAddSharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
804 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
805 CFRelease(result);
806 }
807 CFReleaseSafe(appID);
808 CFRelease(query);
809 }
810 break;
811 }
812 case sec_copy_shared_web_credential_id:
813 {
814 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
815 if (query) {
816 CFTypeRef result = NULL;
817 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
818 if (_SecCopySharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
819 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
820 CFRelease(result);
821 }
822 CFReleaseSafe(appID);
823 CFRelease(query);
824 }
825 break;
826 }
827 case sec_get_log_settings_id:
828 {
829 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
830 if (currentList) {
831 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
832 }
833 CFReleaseSafe(currentList);
834 break;
835 }
836 case sec_set_xpc_log_settings_id:
837 {
838 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
839 if (newSettings) {
840 SecSetXPCLogSettings_Server(newSettings, &error);
841 }
842 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
843 CFReleaseNull(newSettings);
844 break;
845 }
846 case sec_set_circle_log_settings_id:
847 {
848 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
849 if (newSettings) {
850 SecSetCircleLogSettings_Server(newSettings, &error);
851 }
852 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
853 CFReleaseNull(newSettings);
854 break;
855 }
856 case sec_otr_session_create_remote_id:
857 {
858 CFDataRef publicPeerId = NULL;
859 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
860 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
861 if (otrSession) {
862 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
863 CFRelease(otrSession);
864 }
865 CFReleaseSafe(publicPeerId);
866 }
867 break;
868 }
869 case sec_otr_session_process_packet_remote_id:
870 {
871 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
872 bool readyForMessages = false;
873 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
874 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
875 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
876 if (result) {
877 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
878 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
879 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
880 CFRelease(outputSessionData);
881 CFRelease(outputPacket);
882 }
883 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
884
885 CFReleaseSafe(inputPacket);
886 }
887 CFReleaseSafe(sessionData);
888 }
889 break;
890 }
891 case kSecXPCOpTryUserCredentials:
892 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
893 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
894 SOSCCTryUserCredentials_Server(label, password, &error));
895 });
896 break;
897 case kSecXPCOpSetUserCredentials:
898 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
899 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
900 SOSCCSetUserCredentials_Server(label, password, &error));
901 });
902 break;
903 case kSecXPCOpSetUserCredentialsAndDSID:
904 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
905 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
906 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
907 });
908 break;
909 case kSecXPCOpView:
910 with_label_and_number(event, ^(CFStringRef view, uint64_t actionCode) {
911 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
912 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
913 });
914 break;
915 case kSecXPCOpViewSet:
916 {
917 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
918 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
919 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
920 CFReleaseNull(enabledViews);
921 CFReleaseNull(disabledViews);
922 }
923 break;
924 case kSecXPCOpSecurityProperty:
925 with_label_and_number(event, ^(CFStringRef property, uint64_t actionCode) {
926 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
927 SOSCCSecurityProperty_Server(property, (SOSSecurityPropertyActionCode)actionCode, &error));
928 });
929 break;
930 case kSecXPCOpCanAuthenticate:
931 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
932 SOSCCCanAuthenticate_Server(&error));
933 break;
934 case kSecXPCOpPurgeUserCredentials:
935 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
936 SOSCCPurgeUserCredentials_Server(&error));
937 break;
938 case kSecXPCOpDeviceInCircle:
939 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
940 SOSCCThisDeviceIsInCircle_Server(&error));
941 break;
942 case kSecXPCOpRequestToJoin:
943 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
944 SOSCCRequestToJoinCircle_Server(&error));
945 break;
946 case kSecXPCOpRequestToJoinAfterRestore:
947 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
948 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
949 break;
950 case kSecXPCOpRequestEnsureFreshParameters:
951 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
952 SOSCCRequestEnsureFreshParameters_Server(&error));
953 break;
954 case kSecXPCOpGetAllTheRings:
955 {
956 CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error);
957 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions);
958 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
959 xpc_release(xpc_dictionary);
960 }
961 break;
962 case kSecXPCOpApplyToARing:
963 {
964 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
965 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error));
966 CFReleaseNull(ringName);
967 }
968 break;
969 case kSecXPCOpWithdrawlFromARing:
970 {
971 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
972 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error));
973 CFReleaseNull(ringName);
974 }
975 break;
976 case kSecXPCOpRingStatus:
977 {
978 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
979 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error));
980 CFReleaseNull(ringName);
981 }
982 break;
983 case kSecXPCOpEnableRing:
984 {
985 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
986 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error));
987 CFReleaseNull(ringName);
988 }
989 break;
990 case kSecXPCOpRequestDeviceID:
991 {
992 CFStringRef deviceID = SOSCCCopyDeviceID_Server(&error);
993 if (deviceID) {
994 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error);
995 }
996 CFReleaseNull(deviceID);
997 }
998 break;
999 case kSecXPCOpSetDeviceID:
1000 {
1001 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
1002 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error));
1003 CFReleaseNull(IDS);
1004 }
1005 break;
1006 case kSecXPCOpHandleIDSMessage:
1007 {
1008 CFDictionaryRef IDS = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyIDSMessage, &error);
1009 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, SOSCCHandleIDSMessage_Server(IDS, &error));
1010 CFReleaseNull(IDS);
1011 }
1012 break;
1013
1014 case kSecXPCOpSendIDSMessage:
1015 {
1016 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1017 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSServiceRegistrationTest_Server(message, &error));
1018 CFReleaseNull(message);
1019 }
1020 break;
1021 case kSecXPCOpPingTest:
1022 {
1023 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1024 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSPingTest_Server(message, &error));
1025 CFReleaseNull(message);
1026 }
1027 break;
1028 case kSecXPCOpIDSDeviceID:
1029 {
1030 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSDeviceIDIsAvailableTest_Server(&error));
1031 }
1032 break;
1033 case kSecXPCOpAccountSetToNew:
1034 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
1035 break;
1036 case kSecXPCOpResetToOffering:
1037 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1038 SOSCCResetToOffering_Server(&error));
1039 break;
1040 case kSecXPCOpResetToEmpty:
1041 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1042 SOSCCResetToEmpty_Server(&error));
1043 break;
1044 case kSecXPCOpRemoveThisDeviceFromCircle:
1045 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1046 SOSCCRemoveThisDeviceFromCircle_Server(&error));
1047 break;
1048 case kSecXPCOpRemovePeersFromCircle:
1049 {
1050 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfos, &error);
1051 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1052 SOSCCRemovePeersFromCircle_Server(applicants, &error));
1053 CFReleaseNull(applicants);
1054 }
1055 break;
1056 case kSecXPCOpLoggedOutOfAccount:
1057 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1058 SOSCCLoggedOutOfAccount_Server(&error));
1059 break;
1060 case kSecXPCOpBailFromCircle:
1061 {
1062 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
1063 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1064 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
1065 }
1066 break;
1067 case kSecXPCOpAcceptApplicants:
1068 {
1069 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1070 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1071 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1072 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
1073 CFReleaseSafe(applicants);
1074 }
1075 break;
1076 case kSecXPCOpRejectApplicants:
1077 {
1078 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1079 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1080 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1081 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1082 CFReleaseSafe(applicants);
1083 }
1084 break;
1085 case kSecXPCOpSetNewPublicBackupKey:
1086 {
1087 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1088 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1089 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1090 CFReleaseNull(peerInfo);
1091 if (peerInfoData) {
1092 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1093 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1094 xpc_release(xpc_object);
1095 }
1096 CFReleaseNull(peerInfoData);
1097 CFReleaseSafe(publicBackupKey);
1098
1099 }
1100 break;
1101 case kSecXPCOpSetBagForAllSlices:
1102 {
1103 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1104 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0);
1105 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1106 CFReleaseSafe(backupSlice);
1107 }
1108 break;
1109 case kSecXPCOpCopyApplicantPeerInfo:
1110 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1111 SOSCCCopyApplicantPeerInfo_Server(&error),
1112 &error);
1113 break;
1114 case kSecXPCOpCopyValidPeerPeerInfo:
1115 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1116 SOSCCCopyValidPeerPeerInfo_Server(&error),
1117 &error);
1118 break;
1119 case kSecXPCOpValidateUserPublic:
1120 {
1121 bool trusted = SOSCCValidateUserPublic_Server(&error);
1122 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1123 }
1124 break;
1125 case kSecXPCOpCopyNotValidPeerPeerInfo:
1126 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1127 SOSCCCopyNotValidPeerPeerInfo_Server(&error),
1128 &error);
1129 break;
1130 case kSecXPCOpCopyGenerationPeerInfo:
1131 xpc_dictionary_set_and_consume_CFArray(replyMessage, kSecXPCKeyResult,
1132 SOSCCCopyGenerationPeerInfo_Server(&error));
1133 break;
1134 case kSecXPCOpCopyRetirementPeerInfo:
1135 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1136 SOSCCCopyRetirementPeerInfo_Server(&error),
1137 &error);
1138 break;
1139 case kSecXPCOpCopyViewUnawarePeerInfo:
1140 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1141 SOSCCCopyViewUnawarePeerInfo_Server(&error),
1142 &error);
1143 break;
1144 case kSecXPCOpCopyEngineState:
1145 {
1146 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
1147 if (array) {
1148 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1149 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1150 xpc_release(xpc_array);
1151 }
1152 CFReleaseNull(array);
1153 }
1154 break;
1155 case kSecXPCOpCopyPeerPeerInfo:
1156 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1157 SOSCCCopyPeerPeerInfo_Server(&error),
1158 &error);
1159 break;
1160 case kSecXPCOpCopyConcurringPeerPeerInfo:
1161 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1162 SOSCCCopyConcurringPeerPeerInfo_Server(&error),
1163 &error);
1164 break;
1165 case kSecXPCOpCopyMyPeerInfo:
1166 {
1167 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1168 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1169 CFReleaseNull(peerInfo);
1170 if (peerInfoData) {
1171 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1172 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1173 xpc_release(xpc_object);
1174 }
1175 CFReleaseNull(peerInfoData);
1176 }
1177 break;
1178 case kSecXPCOpGetLastDepartureReason:
1179 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1180 SOSCCGetLastDepartureReason_Server(&error));
1181 break;
1182 case kSecXPCOpSetLastDepartureReason:
1183 {
1184 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1185 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1186 SOSCCSetLastDepartureReason_Server(reason, &error));
1187 break;
1188 }
1189 case kSecXPCOpProcessSyncWithAllPeers:
1190 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1191 SOSCCProcessSyncWithAllPeers_Server(&error));
1192 break;
1193 case soscc_EnsurePeerRegistration_id:
1194 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1195 SOSCCProcessEnsurePeerRegistration_Server(&error));
1196 break;
1197 case kSecXPCOpCopyIncompatibilityInfo:
1198 {
1199 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
1200 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
1201 CFReleaseSafe(iis);
1202 break;
1203 }
1204 case kSecXPCOpOTAGetEscrowCertificates:
1205 {
1206 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
1207 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error);
1208 if (array) {
1209 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1210 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1211 xpc_release(xpc_array);
1212 }
1213 CFReleaseNull(array);
1214 }
1215 break;
1216 case kSecXPCOpOTAPKIGetNewAsset:
1217 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1218 SecOTAPKISignalNewAsset(&error));
1219 break;
1220 case kSecXPCOpRollKeys:
1221 {
1222 bool force = xpc_dictionary_get_bool(event, "force");
1223 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1224 _SecServerRollKeys(force, &error));
1225 }
1226 break;
1227 case kSecXPCOpSetHSA2AutoAcceptInfo:
1228 {
1229 CFDataRef cfbytes = NULL;
1230 const uint8_t *bytes = NULL;
1231 size_t len = 0;
1232
1233 bytes = xpc_dictionary_get_data(event,
1234 kSecXPCKeyHSA2AutoAcceptInfo, &len);
1235 if (!bytes) {
1236 SOSCreateError(kSOSErrorBadKey,
1237 CFSTR("missing autoaccept info"), NULL, &error);
1238 break;
1239 }
1240
1241 cfbytes = CFDataCreate(NULL, bytes, len);
1242 if (!cfbytes) {
1243 SOSCreateError(kSOSErrorAllocationFailure,
1244 CFSTR("could not allocate autoaccept info"),
1245 NULL, &error);
1246 break;
1247 }
1248
1249 xpc_dictionary_set_bool(replyMessage,
1250 kSecXPCKeyResult,
1251 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes, &error));
1252 CFRelease(cfbytes);
1253 }
1254 break;
1255 case kSecXPCOpWaitForInitialSync:
1256 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1257 SOSCCWaitForInitialSync_Server(&error));
1258 break;
1259
1260 case kSecXPCOpCopyYetToSyncViews:
1261 {
1262 CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error);
1263 if (array) {
1264 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1265 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1266 xpc_release(xpc_array);
1267 }
1268 CFReleaseNull(array);
1269 }
1270 break;
1271 case kSecXPCOpSetEscrowRecord:
1272 {
1273 CFStringRef escrow_label = SecXPCDictionaryCopyString(event, kSecXPCKeyEscrowLabel, &error);
1274 uint64_t tries = xpc_dictionary_get_int64(event, kSecXPCKeyTriesLabel);
1275
1276 bool result = SOSCCSetEscrowRecord_Server(escrow_label, tries, &error);
1277 if (result) {
1278 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1279 }
1280 CFReleaseNull(escrow_label);
1281 }
1282 break;
1283 case kSecXPCOpGetEscrowRecord:
1284 {
1285 CFDictionaryRef record = SOSCCCopyEscrowRecord_Server(&error);
1286 if (record) {
1287 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record);
1288 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1289 xpc_release(xpc_dictionary);
1290 }
1291 CFReleaseNull(record);
1292 }
1293 break;
1294 case kSecXPCOpCheckPeerAvailability:
1295 {
1296 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCCheckPeerAvailability_Server(&error));
1297 }
1298 break;
1299 default:
1300 break;
1301 }
1302
1303 }
1304
1305 if (error)
1306 {
1307 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
1308 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1309 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
1310 secwarning("Authentication is needed %@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1311 else
1312 secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1313
1314 xpcError = SecCreateXPCObjectWithCFError(error);
1315 if (replyMessage) {
1316 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1317 }
1318 } else if (replyMessage) {
1319 secdebug("ipc", "%@ %@ responding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
1320 }
1321 } else {
1322 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
1323 secerror("%@: returning error: %@", clientTask, error);
1324 xpcError = SecCreateXPCObjectWithCFError(error);
1325 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
1326 }
1327
1328 if (replyMessage) {
1329 xpc_connection_send_message(connection, replyMessage);
1330 xpc_release(replyMessage);
1331 }
1332 if (xpcError)
1333 xpc_release(xpcError);
1334 CFReleaseSafe(error);
1335 CFReleaseSafe(accessGroups);
1336 CFReleaseSafe(domains);
1337 pthread_setspecific(taskThreadKey, NULL);
1338 CFReleaseSafe(clientTask);
1339 CFReleaseSafe(clientAuditToken);
1340 }
1341
1342 static void securityd_xpc_init(const char *service_name)
1343 {
1344 pthread_key_create(&taskThreadKey, NULL);
1345 SecTaskDiagnoseEntitlements = secTaskDiagnoseEntitlements;
1346
1347 secdebug("serverxpc", "start");
1348 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1349 if (!listener) {
1350 seccritical("security failed to register xpc listener for %s, exiting", service_name);
1351 abort();
1352 }
1353
1354 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1355 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1356 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1357 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
1358 xpc_retain(connection);
1359 xpc_retain(event);
1360 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1361 securityd_xpc_dictionary_handler(connection, event);
1362 xpc_release(event);
1363 xpc_release(connection);
1364 });
1365 }
1366 });
1367 xpc_connection_resume(connection);
1368 }
1369 });
1370 xpc_connection_resume(listener);
1371 }
1372
1373
1374 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1375
1376 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1377 static void securityd_soscc_lock_hack() {
1378 dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
1379 int soscc_tok;
1380 __block MKBAssertionRef lockAssertion = NULL;
1381 uint32_t rc;
1382
1383 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1384 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1385 // this code will need to be generalized / migrated away from just this specific purpose.
1386 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) {
1387 char *event_description = xpc_copy_description(object);
1388 secnotice("events", "%s", event_description);
1389 free(event_description);
1390 });
1391
1392 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1393 rc = notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) {
1394 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: already holding lock %d", (int) (lockAssertion != NULL));
1395
1396 // Release previously held assertion (if present)
1397 CFReleaseSafe(lockAssertion);
1398
1399 // New lock assertion
1400 int k300 = 300;
1401 CFNumberRef cfn300 = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &k300);
1402 const void *keys[] = {kMKBAssertionTypeKey , kMKBAssertionTimeoutKey};
1403 const void *vals[] = {kMKBAssertionTypeProfile, cfn300};
1404 CFDictionaryRef lockOptions = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2,
1405 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1406 CFErrorRef err = NULL;
1407
1408 lockAssertion = MKBDeviceLockAssertion(lockOptions, &err);
1409 if (lockAssertion) {
1410 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1411 xpc_transaction_begin();
1412
1413 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, k300*NSEC_PER_SEC), soscc_lock_queue, ^{
1414 xpc_transaction_end();
1415 });
1416 } else {
1417 secerror("Failed to take device lock assertion: %@", err);
1418 }
1419 CFReleaseSafe(err);
1420 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1421
1422 CFReleaseSafe(cfn300);
1423 CFReleaseSafe(lockOptions);
1424 });
1425 }
1426 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1427
1428 int main(int argc, char *argv[])
1429 {
1430 char *wait4debugger = getenv("WAIT4DEBUGGER");
1431 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1432 seccritical("SIGSTOPing self, awaiting debugger");
1433 kill(getpid(), SIGSTOP);
1434 asl_log(NULL, NULL, ASL_LEVEL_CRIT,
1435 "Again, for good luck (or bad debuggers)");
1436 kill(getpid(), SIGSTOP);
1437 }
1438
1439 const char *serviceName = kSecuritydXPCServiceName;
1440 #if TRUSTD_SERVER
1441 serviceName = kTrustdXPCServiceName;
1442 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
1443 serviceName = kTrustdAgentXPCServiceName;
1444 }
1445 #endif
1446 securityd_init_server();
1447 securityd_xpc_init(serviceName);
1448
1449 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1450 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1451 securityd_soscc_lock_hack();
1452 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1453
1454 dispatch_main();
1455
1456 return 0;
1457 }
1458
1459 /* vi:set ts=4 sw=4 et: */