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