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