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