]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server.c
Security-57337.50.23.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 = 0;
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 client.activeUser = MKBForegroundUserSessionID(&error);
501 if (client.activeUser == -1 || client.activeUser == 0) {
502 assert(0);
503 client.activeUser = 0;
504 }
505
506 /*
507 * If we are a edu mode user, and its not the active user,
508 * then the request is coming from inside the syncbubble.
509 *
510 * otherwise we are going to execute the request as the
511 * active user.
512 */
513
514 if (client.uid > 501 && (uid_t)client.activeUser != client.uid) {
515 secinfo("serverxpc", "securityd client: sync bubble user");
516 client.musr = SecMUSRCreateSyncBubbleUserUUID(client.uid);
517 client.keybag = KEYBAG_DEVICE;
518 } else {
519 secinfo("serverxpc", "securityd client: active user");
520 client.musr = SecMUSRCreateActiveUserUUID(client.activeUser);
521 client.uid = (uid_t)client.activeUser;
522 client.keybag = KEYBAG_DEVICE;
523 }
524 }
525 #endif
526
527 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
528
529 bool hasEntitlement;
530 audit_token_t auditToken = {};
531 xpc_connection_get_audit_token(connection, &auditToken);
532
533 client.task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
534 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
535 pthread_setspecific(taskThreadKey, client.task);
536 client.accessGroups = SecTaskCopyAccessGroups(client.task);
537 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
538 domains = SecTaskCopySharedWebCredentialDomains(client.task);
539 }
540 #if TARGET_OS_IPHONE
541 client.allowSystemKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateSystemKeychain);
542 client.isNetworkExtension = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateNetworkExtension);
543 #endif
544 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
545 if (client.inMultiUser) {
546 client.allowSyncBubbleKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainSyncBubble);
547 }
548 #endif
549
550 // TODO: change back to secdebug
551 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
552
553 if (true) {
554 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
555 // Refer to rdar://problem/18615626&18616300 for more details.
556 int64_t minimumDirtyInterval = (int64_t) (2 * NSEC_PER_SEC);
557 xpc_transaction_begin();
558 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, minimumDirtyInterval), dispatch_get_main_queue(), ^{
559 xpc_transaction_end();
560 });
561 }
562
563 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
564 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) ||
565 (client.task && SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle));
566
567 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
568 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
569
570 if (!hasEntitlement) {
571 CFErrorRef entitlementError = NULL;
572 SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle);
573 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError);
574 CFReleaseSafe(entitlementError);
575 }
576
577 if (true) {
578 switch (operation)
579 {
580 case sec_item_add_id:
581 {
582 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
583 if (query) {
584 CFTypeRef result = NULL;
585 if (_SecItemAdd(query, &client, &result, &error) && result) {
586 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
587 CFRelease(result);
588 }
589 CFRelease(query);
590 }
591 break;
592 }
593 case sec_item_copy_matching_id:
594 {
595 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
596 if (query) {
597 CFTypeRef result = NULL;
598 if (_SecItemCopyMatching(query, &client, &result, &error) && result) {
599 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
600 CFRelease(result);
601 }
602 CFRelease(query);
603 }
604 break;
605 }
606 case sec_item_update_id:
607 {
608 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
609 if (query) {
610 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
611 if (attributesToUpdate) {
612 bool result = _SecItemUpdate(query, attributesToUpdate, &client, &error);
613 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
614 CFRelease(attributesToUpdate);
615 }
616 CFRelease(query);
617 }
618 break;
619 }
620 case sec_item_delete_id:
621 {
622 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
623 if (query) {
624 bool result = _SecItemDelete(query, &client, &error);
625 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
626 CFRelease(query);
627 }
628 break;
629 }
630 case sec_trust_store_contains_id:
631 {
632 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
633 if (ts) {
634 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
635 if (digest) {
636 bool contains;
637 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error))
638 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains);
639 CFRelease(digest);
640 }
641 }
642 break;
643 }
644 case sec_trust_store_set_trust_settings_id:
645 {
646 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementModifyAnchorCertificates)) {
647 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
648 if (ts) {
649 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error);
650 if (certificate) {
651 CFTypeRef trustSettingsDictOrArray = NULL;
652 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) {
653 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error);
654 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
655 CFReleaseSafe(trustSettingsDictOrArray);
656 }
657 CFRelease(certificate);
658 }
659 }
660 } else {
661 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementModifyAnchorCertificates, &error);
662 }
663 break;
664 }
665 case sec_trust_store_remove_certificate_id:
666 {
667 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementModifyAnchorCertificates)) {
668 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
669 if (ts) {
670 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
671 if (digest) {
672 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error);
673 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
674 CFRelease(digest);
675 }
676 }
677 } else {
678 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementModifyAnchorCertificates, &error);
679 }
680 break;
681 }
682 case sec_delete_all_id:
683 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error));
684 break;
685 case sec_trust_evaluate_id:
686 {
687 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL;
688 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
689 double verifyTime;
690 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
691 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
692 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
693 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
694 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
695 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
696 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) {
697 // If we have no error yet, capture connection and reply in block and properly retain them.
698 xpc_retain(connection);
699 CFRetainSafe(client.task);
700 CFRetainSafe(clientAuditToken);
701
702 // Clear replyMessage so we don't send a synchronous reply.
703 xpc_object_t asyncReply = replyMessage;
704 replyMessage = NULL;
705
706 SecTrustServerEvaluateBlock(clientAuditToken,
707 certificates, anchors, anchorsOnly, policies, responses, scts, trustedLogs, verifyTime, client.accessGroups,
708 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) {
709 // Send back reply now
710 if (replyError) {
711 CFRetain(replyError);
712 } else {
713 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
714 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
715 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
716 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
717 }
718 if (replyError) {
719 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
720 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
721 if (xpcReplyError) {
722 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
723 xpc_release(xpcReplyError);
724 }
725 CFRelease(replyError);
726 } else {
727 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
728 }
729
730 xpc_connection_send_message(connection, asyncReply);
731 xpc_release(asyncReply);
732 xpc_release(connection);
733 CFReleaseSafe(client.task);
734 CFReleaseSafe(clientAuditToken);
735 });
736 }
737 CFReleaseSafe(policies);
738 CFReleaseSafe(anchors);
739 CFReleaseSafe(certificates);
740 CFReleaseSafe(responses);
741 CFReleaseSafe(scts);
742 CFReleaseSafe(trustedLogs);
743 break;
744 }
745 case sec_keychain_backup_id:
746 {
747 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
748 CFDataRef keybag = NULL, passcode = NULL;
749 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
750 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
751 CFDataRef backup = _SecServerKeychainCreateBackup(&client, keybag, passcode, &error);
752 if (backup) {
753 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
754 if (fd < 0) {
755 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
756 } else {
757 bool writeResult = SecDataWriteFileDescriptor(fd, backup);
758 if (close(fd) != 0)
759 writeResult = false;
760 if (!writeResult)
761 SecError(errSecIO, &error, CFSTR("Failed to write backup file: %d"), errno);
762 SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, writeResult, NULL);
763 }
764 CFRelease(backup);
765 }
766 CFReleaseSafe(passcode);
767 }
768 CFReleaseSafe(keybag);
769 }
770 } else {
771 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
772 }
773 break;
774 }
775 case sec_keychain_restore_id:
776 {
777 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
778 CFDataRef backup = NULL;
779 void *mem = NULL;
780 size_t size = 0;
781
782 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
783 if (fd != -1) {
784 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
785 } else {
786 backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
787 }
788 if (backup) {
789 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
790 if (keybag) {
791 CFDataRef passcode = NULL;
792 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
793 bool result = _SecServerKeychainRestore(backup, &client, keybag, passcode, &error);
794 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
795 CFReleaseSafe(passcode);
796 }
797 CFRelease(keybag);
798 }
799 CFRelease(backup);
800 }
801 if (mem) {
802 munmap(mem, size);
803 }
804 } else {
805 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
806 }
807 break;
808 }
809 case sec_keychain_sync_update_message_id:
810 {
811 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
812 if (updates) {
813 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
814 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
815 CFReleaseNull(result);
816 }
817 CFReleaseNull(updates);
818 break;
819 }
820 case sec_keychain_backup_syncable_id:
821 {
822 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
823
824 CFDictionaryRef oldbackup = NULL;
825 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
826 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
827 if (keybag) {
828 CFDataRef passcode = NULL;
829 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
830 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
831 if (newbackup) {
832 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
833 CFRelease(newbackup);
834 }
835 CFReleaseSafe(passcode);
836 }
837 CFRelease(keybag);
838 }
839 CFReleaseSafe(oldbackup);
840 }
841 } else {
842 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
843 }
844 break;
845 }
846 case sec_keychain_restore_syncable_id:
847 {
848 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
849
850 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
851 if (backup) {
852 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
853 if (keybag) {
854 CFDataRef passcode = NULL;
855 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
856 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
857 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
858 CFReleaseSafe(passcode);
859 }
860 CFRelease(keybag);
861 }
862 CFRelease(backup);
863 }
864 } else {
865 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
866 }
867 break;
868 }
869 case sec_item_backup_copy_names_id:
870 {
871 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
872 CFArrayRef names = SecServerItemBackupCopyNames(&error);
873 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
874 CFReleaseSafe(names);
875 } else {
876 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
877 }
878 break;
879 }
880 case sec_item_backup_handoff_fd_id:
881 {
882 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
883 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
884 int fd = -1;
885 if (backupName) {
886 fd = SecServerItemBackupHandoffFD(backupName, &error);
887 CFRelease(backupName);
888 }
889 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
890 if (fd != -1)
891 close(fd);
892 } else {
893 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
894 }
895 break;
896 }
897 case sec_item_backup_set_confirmed_manifest_id:
898 {
899 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
900 CFDataRef keybagDigest = NULL;
901 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
902 CFDataRef manifest = NULL;
903 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
904 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
905 if (backupName) {
906 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
907 CFRelease(backupName);
908 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
909 }
910 CFReleaseSafe(manifest);
911 }
912 CFReleaseNull(keybagDigest);
913 }
914 } else {
915 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
916 }
917 break;
918 }
919 case sec_item_backup_restore_id:
920 {
921 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
922 bool result = false;
923 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
924 if (backupName) {
925 CFStringRef peerID = NULL;
926 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
927 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
928 if (keybag) {
929 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
930 if (secret) {
931 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
932 if (backup) {
933 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
934 CFRelease(backup);
935 }
936 CFRelease(secret);
937 }
938 CFRelease(keybag);
939 }
940 CFReleaseSafe(peerID);
941 }
942 CFRelease(backupName);
943 }
944 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
945 } else {
946 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
947 }
948 break;
949 }
950 case sec_ota_pki_asset_version_id:
951 {
952 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
953 SecOTAPKIGetCurrentAssetVersion(&error));
954 break;
955 }
956 case sec_add_shared_web_credential_id:
957 {
958 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
959 if (query) {
960 CFTypeRef result = NULL;
961 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
962 if (_SecAddSharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
963 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
964 CFRelease(result);
965 }
966 CFReleaseSafe(appID);
967 CFRelease(query);
968 }
969 break;
970 }
971 case sec_copy_shared_web_credential_id:
972 {
973 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
974 if (query) {
975 CFTypeRef result = NULL;
976 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
977 if (_SecCopySharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
978 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
979 CFRelease(result);
980 }
981 CFReleaseSafe(appID);
982 CFRelease(query);
983 }
984 break;
985 }
986 case sec_get_log_settings_id:
987 {
988 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
989 if (currentList) {
990 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
991 }
992 CFReleaseSafe(currentList);
993 break;
994 }
995 case sec_set_xpc_log_settings_id:
996 {
997 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
998 if (newSettings) {
999 SecSetXPCLogSettings_Server(newSettings, &error);
1000 }
1001 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1002 CFReleaseNull(newSettings);
1003 break;
1004 }
1005 case sec_set_circle_log_settings_id:
1006 {
1007 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
1008 if (newSettings) {
1009 SecSetCircleLogSettings_Server(newSettings, &error);
1010 }
1011 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1012 CFReleaseNull(newSettings);
1013 break;
1014 }
1015 case sec_otr_session_create_remote_id:
1016 {
1017 CFDataRef publicPeerId = NULL;
1018 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
1019 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
1020 if (otrSession) {
1021 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
1022 CFRelease(otrSession);
1023 }
1024 CFReleaseSafe(publicPeerId);
1025 }
1026 break;
1027 }
1028 case sec_otr_session_process_packet_remote_id:
1029 {
1030 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
1031 bool readyForMessages = false;
1032 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
1033 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
1034 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
1035 if (result) {
1036 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
1037 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
1038 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
1039 CFRelease(outputSessionData);
1040 CFRelease(outputPacket);
1041 }
1042 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1043
1044 CFReleaseSafe(inputPacket);
1045 }
1046 CFReleaseSafe(sessionData);
1047 }
1048 break;
1049 }
1050 case kSecXPCOpTryUserCredentials:
1051 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
1052 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1053 SOSCCTryUserCredentials_Server(label, password, &error));
1054 });
1055 break;
1056 case kSecXPCOpSetUserCredentials:
1057 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
1058 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1059 SOSCCSetUserCredentials_Server(label, password, &error));
1060 });
1061 break;
1062 case kSecXPCOpSetUserCredentialsAndDSID:
1063 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
1064 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1065 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
1066 });
1067 break;
1068 case kSecXPCOpView:
1069 with_label_and_number(event, ^(CFStringRef view, uint64_t actionCode) {
1070 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1071 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
1072 });
1073 break;
1074 case kSecXPCOpViewSet:
1075 {
1076 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
1077 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
1078 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
1079 CFReleaseNull(enabledViews);
1080 CFReleaseNull(disabledViews);
1081 }
1082 break;
1083 case kSecXPCOpSecurityProperty:
1084 with_label_and_number(event, ^(CFStringRef property, uint64_t actionCode) {
1085 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1086 SOSCCSecurityProperty_Server(property, (SOSSecurityPropertyActionCode)actionCode, &error));
1087 });
1088 break;
1089 case kSecXPCOpCanAuthenticate:
1090 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1091 SOSCCCanAuthenticate_Server(&error));
1092 break;
1093 case kSecXPCOpPurgeUserCredentials:
1094 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1095 SOSCCPurgeUserCredentials_Server(&error));
1096 break;
1097 case kSecXPCOpDeviceInCircle:
1098 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1099 SOSCCThisDeviceIsInCircle_Server(&error));
1100 break;
1101 case kSecXPCOpRequestToJoin:
1102 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1103 SOSCCRequestToJoinCircle_Server(&error));
1104 break;
1105 case kSecXPCOpRequestToJoinAfterRestore:
1106 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1107 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
1108 break;
1109 case kSecXPCOpRequestEnsureFreshParameters:
1110 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1111 SOSCCRequestEnsureFreshParameters_Server(&error));
1112 break;
1113 case kSecXPCOpGetAllTheRings:
1114 {
1115 CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error);
1116 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions);
1117 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1118 xpc_release(xpc_dictionary);
1119 }
1120 break;
1121 case kSecXPCOpApplyToARing:
1122 {
1123 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1124 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error));
1125 CFReleaseNull(ringName);
1126 }
1127 break;
1128 case kSecXPCOpWithdrawlFromARing:
1129 {
1130 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1131 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error));
1132 CFReleaseNull(ringName);
1133 }
1134 break;
1135 case kSecXPCOpRingStatus:
1136 {
1137 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1138 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error));
1139 CFReleaseNull(ringName);
1140 }
1141 break;
1142 case kSecXPCOpEnableRing:
1143 {
1144 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1145 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error));
1146 CFReleaseNull(ringName);
1147 }
1148 break;
1149 case kSecXPCOpRequestDeviceID:
1150 {
1151 CFStringRef deviceID = SOSCCCopyDeviceID_Server(&error);
1152 if (deviceID) {
1153 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error);
1154 }
1155 CFReleaseNull(deviceID);
1156 }
1157 break;
1158 case kSecXPCOpSetDeviceID:
1159 {
1160 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
1161 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error));
1162 CFReleaseNull(IDS);
1163 }
1164 break;
1165 case kSecXPCOpHandleIDSMessage:
1166 {
1167 CFDictionaryRef IDS = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyIDSMessage, &error);
1168 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, SOSCCHandleIDSMessage_Server(IDS, &error));
1169 CFReleaseNull(IDS);
1170 }
1171 break;
1172
1173 case kSecXPCOpSendIDSMessage:
1174 {
1175 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1176 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSServiceRegistrationTest_Server(message, &error));
1177 CFReleaseNull(message);
1178 }
1179 break;
1180 case kSecXPCOpPingTest:
1181 {
1182 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1183 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSPingTest_Server(message, &error));
1184 CFReleaseNull(message);
1185 }
1186 break;
1187 case kSecXPCOpIDSDeviceID:
1188 {
1189 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSDeviceIDIsAvailableTest_Server(&error));
1190 }
1191 break;
1192 case kSecXPCOpAccountSetToNew:
1193 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
1194 break;
1195 case kSecXPCOpResetToOffering:
1196 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1197 SOSCCResetToOffering_Server(&error));
1198 break;
1199 case kSecXPCOpResetToEmpty:
1200 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1201 SOSCCResetToEmpty_Server(&error));
1202 break;
1203 case kSecXPCOpRemoveThisDeviceFromCircle:
1204 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1205 SOSCCRemoveThisDeviceFromCircle_Server(&error));
1206 break;
1207 case kSecXPCOpRemovePeersFromCircle:
1208 {
1209 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfos, &error);
1210 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1211 SOSCCRemovePeersFromCircle_Server(applicants, &error));
1212 CFReleaseNull(applicants);
1213 }
1214 break;
1215 case kSecXPCOpLoggedOutOfAccount:
1216 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1217 SOSCCLoggedOutOfAccount_Server(&error));
1218 break;
1219 case kSecXPCOpBailFromCircle:
1220 {
1221 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
1222 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1223 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
1224 }
1225 break;
1226 case kSecXPCOpAcceptApplicants:
1227 {
1228 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1229 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1230 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1231 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
1232 CFReleaseSafe(applicants);
1233 }
1234 break;
1235 case kSecXPCOpRejectApplicants:
1236 {
1237 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1238 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1239 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1240 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1241 CFReleaseSafe(applicants);
1242 }
1243 break;
1244 case kSecXPCOpSetNewPublicBackupKey:
1245 {
1246 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
1247 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1248 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1249 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1250 CFReleaseNull(peerInfo);
1251 if (peerInfoData) {
1252 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1253 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1254 xpc_release(xpc_object);
1255 }
1256 CFReleaseNull(peerInfoData);
1257 CFReleaseSafe(publicBackupKey);
1258
1259 } else {
1260 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
1261 }
1262 }
1263 break;
1264 case kSecXPCOpSetBagForAllSlices:
1265 {
1266 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) {
1267 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1268 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0);
1269 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1270 CFReleaseSafe(backupSlice);
1271 } else {
1272 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error);
1273 }
1274 }
1275 break;
1276 case kSecXPCOpCopyApplicantPeerInfo:
1277 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1278 SOSCCCopyApplicantPeerInfo_Server(&error),
1279 &error);
1280 break;
1281 case kSecXPCOpCopyValidPeerPeerInfo:
1282 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1283 SOSCCCopyValidPeerPeerInfo_Server(&error),
1284 &error);
1285 break;
1286 case kSecXPCOpValidateUserPublic:
1287 {
1288 bool trusted = SOSCCValidateUserPublic_Server(&error);
1289 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1290 }
1291 break;
1292 case kSecXPCOpCopyNotValidPeerPeerInfo:
1293 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1294 SOSCCCopyNotValidPeerPeerInfo_Server(&error),
1295 &error);
1296 break;
1297 case kSecXPCOpCopyGenerationPeerInfo:
1298 xpc_dictionary_set_and_consume_CFArray(replyMessage, kSecXPCKeyResult,
1299 SOSCCCopyGenerationPeerInfo_Server(&error));
1300 break;
1301 case kSecXPCOpCopyRetirementPeerInfo:
1302 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1303 SOSCCCopyRetirementPeerInfo_Server(&error),
1304 &error);
1305 break;
1306 case kSecXPCOpCopyViewUnawarePeerInfo:
1307 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1308 SOSCCCopyViewUnawarePeerInfo_Server(&error),
1309 &error);
1310 break;
1311 case kSecXPCOpCopyAccountData:
1312 {
1313 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) {
1314 xpc_object_t xpc_account_object = NULL;
1315 CFDataRef accountData = SOSCCCopyAccountState_Server(&error);
1316 if(accountData)
1317 xpc_account_object = _CFXPCCreateXPCObjectFromCFObject(accountData);
1318
1319 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_account_object);
1320 CFReleaseNull(accountData);
1321 }
1322 else {
1323 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error);
1324 }
1325 break;
1326 }
1327 case kSecXPCOpDeleteAccountData:
1328 {
1329 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) {
1330 bool status = SOSCCDeleteAccountState_Server(&error);
1331 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1332 }
1333 else {
1334 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error);
1335 }
1336
1337 break;
1338 }
1339 case kSecXPCOpCopyEngineData:
1340 {
1341 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) {
1342
1343 xpc_object_t xpc_engine_object = NULL;
1344 CFDataRef engineData = SOSCCCopyEngineData_Server(&error);
1345 if(engineData)
1346 xpc_engine_object = _CFXPCCreateXPCObjectFromCFObject(engineData);
1347
1348 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_engine_object);
1349 CFReleaseNull(engineData);
1350
1351 }
1352 else {
1353 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error);
1354 }
1355 break;
1356 }
1357 case kSecXPCOpDeleteEngineData:
1358 {
1359 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) {
1360
1361 bool status = SOSCCDeleteEngineState_Server(&error);
1362 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1363 }
1364 else {
1365 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error);
1366 }
1367 break;
1368 }
1369 case kSecXPCOpCopyEngineState:
1370 {
1371 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) {
1372
1373 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
1374 if (array) {
1375 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1376 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1377 xpc_release(xpc_array);
1378 }
1379 CFReleaseNull(array);
1380 }
1381 else {
1382 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error);
1383 }
1384 }
1385 break;
1386 case kSecXPCOpCopyPeerPeerInfo:
1387 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1388 SOSCCCopyPeerPeerInfo_Server(&error),
1389 &error);
1390 break;
1391 case kSecXPCOpCopyConcurringPeerPeerInfo:
1392 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1393 SOSCCCopyConcurringPeerPeerInfo_Server(&error),
1394 &error);
1395 break;
1396 case kSecXPCOpCopyMyPeerInfo:
1397 {
1398 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1399 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1400 CFReleaseNull(peerInfo);
1401 if (peerInfoData) {
1402 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1403 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1404 xpc_release(xpc_object);
1405 }
1406 CFReleaseNull(peerInfoData);
1407 }
1408 break;
1409 case kSecXPCOpGetLastDepartureReason:
1410 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1411 SOSCCGetLastDepartureReason_Server(&error));
1412 break;
1413 case kSecXPCOpSetLastDepartureReason:
1414 {
1415 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1416 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1417 SOSCCSetLastDepartureReason_Server(reason, &error));
1418 break;
1419 }
1420 case kSecXPCOpProcessSyncWithAllPeers:
1421 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1422 SOSCCProcessSyncWithAllPeers_Server(&error));
1423 break;
1424 case soscc_EnsurePeerRegistration_id:
1425 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1426 SOSCCProcessEnsurePeerRegistration_Server(&error));
1427 break;
1428 case kSecXPCOpCopyIncompatibilityInfo:
1429 {
1430 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
1431 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
1432 CFReleaseSafe(iis);
1433 break;
1434 }
1435 case kSecXPCOpOTAGetEscrowCertificates:
1436 {
1437 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
1438 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error);
1439 if (array) {
1440 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1441 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1442 xpc_release(xpc_array);
1443 }
1444 CFReleaseNull(array);
1445 }
1446 break;
1447 case kSecXPCOpOTAPKIGetNewAsset:
1448 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1449 SecOTAPKISignalNewAsset(&error));
1450 break;
1451 case kSecXPCOpRollKeys:
1452 {
1453 bool force = xpc_dictionary_get_bool(event, "force");
1454 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1455 _SecServerRollKeys(force, &client, &error));
1456 }
1457 break;
1458 case kSecXPCOpSetHSA2AutoAcceptInfo:
1459 {
1460 CFDataRef cfbytes = NULL;
1461 const uint8_t *bytes = NULL;
1462 size_t len = 0;
1463
1464 bytes = xpc_dictionary_get_data(event,
1465 kSecXPCKeyHSA2AutoAcceptInfo, &len);
1466 if (!bytes) {
1467 SOSCreateError(kSOSErrorBadKey,
1468 CFSTR("missing autoaccept info"), NULL, &error);
1469 break;
1470 }
1471
1472 cfbytes = CFDataCreate(NULL, bytes, len);
1473 if (!cfbytes) {
1474 SOSCreateError(kSOSErrorAllocationFailure,
1475 CFSTR("could not allocate autoaccept info"),
1476 NULL, &error);
1477 break;
1478 }
1479
1480 xpc_dictionary_set_bool(replyMessage,
1481 kSecXPCKeyResult,
1482 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes, &error));
1483 CFRelease(cfbytes);
1484 }
1485 break;
1486 case kSecXPCOpWaitForInitialSync:
1487 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1488 SOSCCWaitForInitialSync_Server(&error));
1489 break;
1490
1491 case kSecXPCOpCopyYetToSyncViews:
1492 {
1493 CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error);
1494 if (array) {
1495 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1496 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1497 xpc_release(xpc_array);
1498 }
1499 CFReleaseNull(array);
1500 }
1501 break;
1502 case kSecXPCOpSetEscrowRecord:
1503 {
1504 CFStringRef escrow_label = SecXPCDictionaryCopyString(event, kSecXPCKeyEscrowLabel, &error);
1505 uint64_t tries = xpc_dictionary_get_int64(event, kSecXPCKeyTriesLabel);
1506
1507 bool result = SOSCCSetEscrowRecord_Server(escrow_label, tries, &error);
1508 if (result) {
1509 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1510 }
1511 CFReleaseNull(escrow_label);
1512 }
1513 break;
1514 case kSecXPCOpGetEscrowRecord:
1515 {
1516 CFDictionaryRef record = SOSCCCopyEscrowRecord_Server(&error);
1517 if (record) {
1518 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record);
1519 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1520 xpc_release(xpc_dictionary);
1521 }
1522 CFReleaseNull(record);
1523 }
1524 break;
1525 case kSecXPCOpCheckPeerAvailability:
1526 {
1527 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCCheckPeerAvailability_Server(&error));
1528 }
1529 break;
1530 case kSecXPCOpWhoAmI:
1531 {
1532 if (client.musr)
1533 xpc_dictionary_set_data(replyMessage, "musr", CFDataGetBytePtr(client.musr), CFDataGetLength(client.musr));
1534 xpc_dictionary_set_bool(replyMessage, "system-keychain", client.allowSystemKeychain);
1535 xpc_dictionary_set_bool(replyMessage, "syncbubble-keychain", client.allowSyncBubbleKeychain);
1536 xpc_dictionary_set_bool(replyMessage, "network-extension", client.isNetworkExtension);
1537 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1538 }
1539 break;
1540 case kSecXPCOpTransmogrifyToSyncBubble:
1541 {
1542 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainSyncBubble)) {
1543 #if TARGET_OS_IOS
1544 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1545 CFArrayRef services = SecXPCDictionaryCopyArray(event, "services", &error);
1546 bool res = false;
1547 if (uid && services) {
1548 res = _SecServerTransmogrifyToSyncBubble(services, uid, &client, &error);
1549 }
1550 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1551 CFReleaseNull(services);
1552 #else
1553 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1554 #endif
1555
1556 } else {
1557 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainSyncBubble, &error);
1558 }
1559 }
1560 break;
1561 case kSecXPCOpTransmogrifyToSystemKeychain:
1562 {
1563 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain)) {
1564 #if TARGET_OS_IOS
1565 bool res = _SecServerTransmogrifyToSystemKeychain(&client, &error);
1566 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1567 #else
1568 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1569 #endif
1570
1571 } else {
1572 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error);
1573 }
1574 }
1575 break;
1576 case kSecXPCOpDeleteUserView:
1577 {
1578 if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain)) {
1579 bool res = false;
1580 #if TARGET_OS_IOS
1581 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1582 if (uid) {
1583 res = _SecServerDeleteMUSERViews(&client, uid, &error);
1584 }
1585 #endif
1586 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1587
1588 } else {
1589 EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error);
1590 }
1591 }
1592 break;
1593 case kSecXPCOpWrapToBackupSliceKeyBagForView:
1594 {
1595 CFStringRef viewname = SecXPCDictionaryCopyString(event, kSecXPCKeyViewName, &error);
1596 if(viewname) {
1597 CFDataRef plaintext = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
1598 if (plaintext) {
1599 CFDataRef ciphertext = NULL;
1600 CFDataRef bskbEncoded = NULL;
1601
1602 bool result = SOSWrapToBackupSliceKeyBagForView_Server(viewname, plaintext, &ciphertext, &bskbEncoded, &error);
1603 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1604
1605 if(error) {
1606 xpc_dictionary_set_data(replyMessage, kSecXPCData, NULL, 0);
1607 xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, NULL, 0);
1608 } else if(!result) {
1609 xpc_dictionary_set_data(replyMessage, kSecXPCData, NULL, 0);
1610 xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, NULL, 0);
1611 } else {
1612 if(ciphertext) {
1613 xpc_dictionary_set_data(replyMessage, kSecXPCData, CFDataGetBytePtr(ciphertext), CFDataGetLength(ciphertext));
1614 }
1615 if(bskbEncoded) {
1616 xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, CFDataGetBytePtr(bskbEncoded), CFDataGetLength(bskbEncoded));
1617 }
1618 }
1619 }
1620 CFReleaseSafe(plaintext);
1621 }
1622 CFReleaseNull(viewname);
1623 }
1624 break;
1625 default:
1626 break;
1627 }
1628
1629 }
1630
1631 if (error)
1632 {
1633 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
1634 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1635 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
1636 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1637 else
1638 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1639
1640 xpcError = SecCreateXPCObjectWithCFError(error);
1641 if (replyMessage) {
1642 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1643 }
1644 } else if (replyMessage) {
1645 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
1646 }
1647 } else {
1648 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
1649 secerror("%@: returning error: %@", client.task, error);
1650 xpcError = SecCreateXPCObjectWithCFError(error);
1651 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
1652 }
1653
1654 if (replyMessage) {
1655 xpc_connection_send_message(connection, replyMessage);
1656 xpc_release(replyMessage);
1657 }
1658 if (xpcError)
1659 xpc_release(xpcError);
1660 pthread_setspecific(taskThreadKey, NULL);
1661 CFReleaseSafe(error);
1662 CFReleaseSafe(client.accessGroups);
1663 CFReleaseSafe(client.musr);
1664 CFReleaseSafe(client.task);
1665 CFReleaseSafe(domains);
1666 CFReleaseSafe(clientAuditToken);
1667 }
1668
1669 static void securityd_xpc_init(const char *service_name)
1670 {
1671 pthread_key_create(&taskThreadKey, NULL);
1672 SecTaskDiagnoseEntitlements = secTaskDiagnoseEntitlements;
1673
1674 secdebug("serverxpc", "start");
1675 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1676 if (!listener) {
1677 seccritical("security failed to register xpc listener for %s, exiting", service_name);
1678 abort();
1679 }
1680
1681 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1682 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1683 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1684 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
1685 xpc_retain(connection);
1686 xpc_retain(event);
1687 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1688 securityd_xpc_dictionary_handler(connection, event);
1689 xpc_release(event);
1690 xpc_release(connection);
1691 });
1692 }
1693 });
1694 xpc_connection_resume(connection);
1695 }
1696 });
1697 xpc_connection_resume(listener);
1698 }
1699
1700
1701 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1702
1703 #if TARGET_OS_EMBEDDED
1704 static void securityd_soscc_lock_hack() {
1705 dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
1706 int soscc_tok;
1707
1708 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1709 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1710 // this code will need to be generalized / migrated away from just this specific purpose.
1711 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) {
1712 char *event_description = xpc_copy_description(object);
1713 secnotice("events", "%s", event_description);
1714 free(event_description);
1715 });
1716
1717 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1718 notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) {
1719 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1720 CFErrorRef error = NULL;
1721
1722 uint64_t one_minute = 60ull;
1723 if(SecAKSLockUserKeybag(one_minute, &error)){
1724 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1725 xpc_transaction_begin();
1726
1727 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, one_minute*NSEC_PER_SEC), soscc_lock_queue, ^{
1728 CFErrorRef localError = NULL;
1729 if(!SecAKSUnLockUserKeybag(&localError))
1730 secerror("failed to unlock: %@", localError);
1731 CFReleaseNull(localError);
1732 xpc_transaction_end();
1733 });
1734 } else {
1735 secerror("Failed to take device lock assertion: %@", error);
1736 }
1737 CFReleaseSafe(error);
1738 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1739 });
1740 }
1741 #endif
1742
1743 int main(int argc, char *argv[])
1744 {
1745 char *wait4debugger = getenv("WAIT4DEBUGGER");
1746 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1747 seccritical("SIGSTOPing self, awaiting debugger");
1748 kill(getpid(), SIGSTOP);
1749 asl_log(NULL, NULL, ASL_LEVEL_CRIT,
1750 "Again, for good luck (or bad debuggers)");
1751 kill(getpid(), SIGSTOP);
1752 }
1753
1754 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
1755 {
1756 CFDictionaryRef deviceMode = MKBUserTypeDeviceMode(NULL, NULL);
1757 CFTypeRef value = NULL;
1758
1759 if (deviceMode && CFDictionaryGetValueIfPresent(deviceMode, kMKBDeviceModeKey, &value) && CFEqual(value, kMKBDeviceModeMultiUser)) {
1760 inMultiUser = 1;
1761 }
1762 CFReleaseNull(deviceMode);
1763 }
1764 #endif
1765
1766
1767 const char *serviceName = kSecuritydXPCServiceName;
1768 #if TRUSTD_SERVER
1769 serviceName = kTrustdXPCServiceName;
1770 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
1771 serviceName = kTrustdAgentXPCServiceName;
1772 }
1773 #endif
1774 securityd_init_server();
1775 securityd_xpc_init(serviceName);
1776
1777
1778 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1779 #if TARGET_OS_EMBEDDED
1780 securityd_soscc_lock_hack();
1781 #endif
1782
1783 dispatch_main();
1784
1785 return 0;
1786 }
1787
1788 /* vi:set ts=4 sw=4 et: */