]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server.c
Security-57740.1.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
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 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
616 domains = SecTaskCopySharedWebCredentialDomains(client.task);
617 }
618 #if TARGET_OS_IPHONE
619 client.allowSystemKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateSystemKeychain);
620 client.isNetworkExtension = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateNetworkExtension);
621 #endif
622 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
623 if (client.inMultiUser) {
624 client.allowSyncBubbleKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainSyncBubble);
625 }
626 #endif
627 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
628
629 if (true) {
630 switch (operation)
631 {
632 #if !TRUSTD_SERVER
633 case sec_item_add_id:
634 {
635 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
636 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
637 if (query) {
638 CFTypeRef result = NULL;
639 if (_SecItemAdd(query, &client, &result, &error) && result) {
640 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
641 CFReleaseNull(result);
642 }
643 CFReleaseNull(query);
644 }
645 break;
646 }
647 }
648 case sec_item_copy_matching_id:
649 {
650 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
651 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
652 if (query) {
653 CFTypeRef result = NULL;
654 if (_SecItemCopyMatching(query, &client, &result, &error) && result) {
655 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
656 CFReleaseNull(result);
657 }
658 CFReleaseNull(query);
659 }
660 break;
661 }
662 }
663 case sec_item_update_id:
664 {
665 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
666 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
667 if (query) {
668 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
669 if (attributesToUpdate) {
670 bool result = _SecItemUpdate(query, attributesToUpdate, &client, &error);
671 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
672 CFReleaseNull(attributesToUpdate);
673 }
674 CFReleaseNull(query);
675 }
676 }
677 break;
678 }
679 case sec_item_delete_id:
680 {
681 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
682 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
683 if (query) {
684 bool result = _SecItemDelete(query, &client, &error);
685 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
686 CFReleaseNull(query);
687 }
688 }
689 break;
690 }
691 case sec_item_update_token_items_id:
692 {
693 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
694 CFStringRef tokenID = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
695 CFArrayRef attributes = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error);
696 if (tokenID) {
697 bool result = _SecItemUpdateTokenItems(tokenID, attributes, &client, &error);
698 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
699 }
700 CFReleaseNull(tokenID);
701 CFReleaseNull(attributes);
702 }
703 break;
704 }
705 case sec_trust_store_contains_id:
706 {
707 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
708 if (ts) {
709 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
710 if (digest) {
711 bool contains;
712 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error))
713 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains);
714 CFReleaseNull(digest);
715 }
716 }
717 break;
718 }
719 case sec_trust_store_set_trust_settings_id:
720 {
721 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementModifyAnchorCertificates, &error)) {
722 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
723 if (ts) {
724 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error);
725 if (certificate) {
726 CFTypeRef trustSettingsDictOrArray = NULL;
727 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) {
728 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error);
729 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
730 CFReleaseSafe(trustSettingsDictOrArray);
731 }
732 CFReleaseNull(certificate);
733 }
734 }
735 }
736 break;
737 }
738 case sec_trust_store_remove_certificate_id:
739 {
740 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementModifyAnchorCertificates, &error)) {
741 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
742 if (ts) {
743 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
744 if (digest) {
745 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error);
746 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
747 CFReleaseNull(digest);
748 }
749 }
750 }
751 break;
752 }
753 case sec_trust_store_copy_all_id:
754 {
755 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementModifyAnchorCertificates, &error)) {
756 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
757 if (ts) {
758 CFArrayRef trustStoreContents = NULL;
759 if(_SecTrustStoreCopyAll(ts, &trustStoreContents, &error) && trustStoreContents) {
760 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, trustStoreContents, &error);
761 CFReleaseNull(trustStoreContents);
762 }
763 }
764 }
765 break;
766 }
767 case sec_trust_store_copy_usage_constraints_id:
768 {
769 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementModifyAnchorCertificates, &error)) {
770 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
771 if (ts) {
772 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
773 if (digest) {
774 CFArrayRef usageConstraints = NULL;
775 if(_SecTrustStoreCopyUsageConstraints(ts, digest, &usageConstraints, &error) && usageConstraints) {
776 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, usageConstraints, &error);
777 CFReleaseNull(usageConstraints);
778 }
779 CFReleaseNull(digest);
780 }
781 }
782 }
783 break;
784 }
785 case sec_delete_all_id:
786 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error));
787 break;
788 #endif /* !TRUSTD_SERVER */
789 case sec_trust_evaluate_id:
790 {
791 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL;
792 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
793 bool keychainsAllowed = xpc_dictionary_get_bool(event, kSecTrustKeychainsAllowedKey);
794 double verifyTime;
795 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
796 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
797 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
798 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
799 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
800 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
801 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) {
802 // If we have no error yet, capture connection and reply in block and properly retain them.
803 xpc_retain(connection);
804 CFRetainSafe(client.task);
805 CFRetainSafe(clientAuditToken);
806
807 // Clear replyMessage so we don't send a synchronous reply.
808 xpc_object_t asyncReply = replyMessage;
809 replyMessage = NULL;
810
811 SecTrustServerEvaluateBlock(clientAuditToken,
812 certificates, anchors, anchorsOnly, keychainsAllowed, policies, responses, scts, trustedLogs, verifyTime, client.accessGroups,
813 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) {
814 // Send back reply now
815 if (replyError) {
816 CFRetain(replyError);
817 } else {
818 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
819 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
820 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
821 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
822 }
823 if (replyError) {
824 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
825 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
826 if (xpcReplyError) {
827 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
828 xpc_release(xpcReplyError);
829 }
830 CFReleaseNull(replyError);
831 } else {
832 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
833 }
834
835 xpc_connection_send_message(connection, asyncReply);
836 xpc_release(asyncReply);
837 xpc_release(connection);
838 CFReleaseSafe(client.task);
839 CFReleaseSafe(clientAuditToken);
840 });
841 }
842 CFReleaseSafe(policies);
843 CFReleaseSafe(anchors);
844 CFReleaseSafe(certificates);
845 CFReleaseSafe(responses);
846 CFReleaseSafe(scts);
847 CFReleaseSafe(trustedLogs);
848 break;
849 }
850 #if !TRUSTD_SERVER
851 case sec_keychain_backup_id:
852 {
853 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
854 CFDataRef keybag = NULL, passcode = NULL;
855 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
856 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
857 CFDataRef backup = _SecServerKeychainCreateBackup(&client, keybag, passcode, &error);
858 if (backup) {
859 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
860 if (fd < 0) {
861 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
862 } else {
863 bool writeResult = SecDataWriteFileDescriptor(fd, backup);
864 if (close(fd) != 0)
865 writeResult = false;
866 if (!writeResult)
867 SecError(errSecIO, &error, CFSTR("Failed to write backup file: %d"), errno);
868 SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, writeResult, NULL);
869 }
870 CFRelease(backup);
871 }
872 CFReleaseSafe(passcode);
873 }
874 CFReleaseSafe(keybag);
875 }
876 }
877 break;
878 }
879 case sec_keychain_restore_id:
880 {
881 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
882 CFDataRef backup = NULL;
883 void *mem = NULL;
884 size_t size = 0;
885
886 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
887 if (fd != -1) {
888 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
889 } else {
890 backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
891 }
892 if (backup) {
893 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
894 if (keybag) {
895 CFDataRef passcode = NULL;
896 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
897 bool result = _SecServerKeychainRestore(backup, &client, keybag, passcode, &error);
898 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
899 CFReleaseSafe(passcode);
900 }
901 }
902 CFReleaseNull(keybag);
903 }
904 CFReleaseNull(backup);
905 if (fd != -1)
906 close(fd);
907 if (mem) {
908 munmap(mem, size);
909 }
910 }
911 break;
912 }
913 case sec_keychain_backup_keybag_uuid_id:
914 {
915 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
916 CFDataRef backup = NULL;
917 CFStringRef uuid = NULL;
918 void *mem = NULL;
919 size_t size = 0;
920
921 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
922 if (fd != -1) {
923 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
924 if (backup)
925 uuid = _SecServerBackupCopyUUID(backup, &error);
926 }
927 if (uuid)
928 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, uuid, &error);
929
930 CFReleaseNull(backup);
931 if (fd != -1)
932 close(fd);
933 if (mem) {
934 munmap(mem, size);
935 }
936 CFReleaseNull(uuid);
937 }
938 break;
939 }
940 case sec_keychain_sync_update_message_id:
941 {
942 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
943 if (updates) {
944 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
945 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
946 CFReleaseNull(result);
947 }
948 CFReleaseNull(updates);
949 break;
950 }
951 case sec_keychain_backup_syncable_id:
952 {
953 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
954 CFDictionaryRef oldbackup = NULL;
955 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
956 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
957 if (keybag) {
958 CFDataRef passcode = NULL;
959 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
960 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
961 if (newbackup) {
962 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
963 CFRelease(newbackup);
964 }
965 CFReleaseSafe(passcode);
966 }
967 CFReleaseNull(keybag);
968 }
969 CFReleaseSafe(oldbackup);
970 }
971 }
972 break;
973 }
974 case sec_keychain_restore_syncable_id:
975 {
976 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
977 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
978 if (backup) {
979 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
980 if (keybag) {
981 CFDataRef passcode = NULL;
982 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
983 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
984 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
985 CFReleaseSafe(passcode);
986 }
987 CFReleaseNull(keybag);
988 }
989 CFReleaseNull(backup);
990 }
991 }
992 break;
993 }
994 case sec_item_backup_copy_names_id:
995 {
996 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
997 CFArrayRef names = SecServerItemBackupCopyNames(&error);
998 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
999 CFReleaseSafe(names);
1000 }
1001 break;
1002 }
1003 case sec_item_backup_handoff_fd_id:
1004 {
1005 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1006 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
1007 int fd = -1;
1008 if (backupName) {
1009 fd = SecServerItemBackupHandoffFD(backupName, &error);
1010 CFRelease(backupName);
1011 }
1012 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
1013 if (fd != -1)
1014 close(fd);
1015 }
1016 break;
1017 }
1018 case sec_item_backup_set_confirmed_manifest_id:
1019 {
1020 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1021 CFDataRef keybagDigest = NULL;
1022 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
1023 CFDataRef manifest = NULL;
1024 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
1025 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
1026 if (backupName) {
1027 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
1028 CFRelease(backupName);
1029 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1030 }
1031 CFReleaseSafe(manifest);
1032 }
1033 }
1034 CFReleaseNull(keybagDigest);
1035 }
1036 break;
1037 }
1038 case sec_item_backup_restore_id:
1039 {
1040 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1041 bool result = false;
1042 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
1043 if (backupName) {
1044 CFStringRef peerID = NULL;
1045 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
1046 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1047 if (keybag) {
1048 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
1049 if (secret) {
1050 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
1051 if (backup) {
1052 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
1053 CFRelease(backup);
1054 }
1055 CFRelease(secret);
1056 }
1057 CFRelease(keybag);
1058 }
1059 CFReleaseSafe(peerID);
1060 }
1061 CFRelease(backupName);
1062 }
1063 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1064 }
1065 break;
1066 }
1067 case sec_ota_pki_asset_version_id:
1068 {
1069 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1070 SecOTAPKIGetCurrentAssetVersion(&error));
1071 break;
1072 }
1073 case sec_add_shared_web_credential_id:
1074 {
1075 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
1076 if (query) {
1077 CFTypeRef result = NULL;
1078 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
1079 if (_SecAddSharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
1080 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
1081 CFReleaseNull(result);
1082 }
1083 CFReleaseSafe(appID);
1084 CFReleaseNull(query);
1085 }
1086 break;
1087 }
1088 case sec_copy_shared_web_credential_id:
1089 {
1090 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
1091 if (query) {
1092 CFTypeRef result = NULL;
1093 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
1094 if (_SecCopySharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
1095 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
1096 CFReleaseNull(result);
1097 }
1098 CFReleaseSafe(appID);
1099 CFReleaseNull(query);
1100 }
1101 break;
1102 }
1103 case sec_get_log_settings_id:
1104 {
1105 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
1106 if (currentList) {
1107 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
1108 }
1109 CFReleaseSafe(currentList);
1110 break;
1111 }
1112 case sec_set_xpc_log_settings_id:
1113 {
1114 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
1115 if (newSettings) {
1116 SecSetXPCLogSettings_Server(newSettings, &error);
1117 }
1118 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1119 CFReleaseNull(newSettings);
1120 break;
1121 }
1122 case sec_set_circle_log_settings_id:
1123 {
1124 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
1125 if (newSettings) {
1126 SecSetCircleLogSettings_Server(newSettings, &error);
1127 }
1128 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1129 CFReleaseNull(newSettings);
1130 break;
1131 }
1132 case sec_otr_session_create_remote_id:
1133 {
1134 CFDataRef publicPeerId = NULL;
1135 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
1136 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
1137 if (otrSession) {
1138 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
1139 CFReleaseNull(otrSession);
1140 }
1141 CFReleaseSafe(publicPeerId);
1142 }
1143 break;
1144 }
1145 case sec_otr_session_process_packet_remote_id:
1146 {
1147 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
1148 bool readyForMessages = false;
1149 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
1150 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
1151 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
1152 if (result) {
1153 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
1154 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
1155 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
1156 CFReleaseNull(outputSessionData);
1157 CFReleaseNull(outputPacket);
1158 }
1159 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1160
1161 CFReleaseSafe(inputPacket);
1162 }
1163 CFReleaseSafe(sessionData);
1164 }
1165 break;
1166 }
1167 case kSecXPCOpTryUserCredentials:
1168 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1169 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
1170 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1171 SOSCCTryUserCredentials_Server(label, password, &error));
1172 });
1173 }
1174 break;
1175 case kSecXPCOpSetUserCredentials:
1176 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1177 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
1178 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1179 SOSCCSetUserCredentials_Server(label, password, &error));
1180 });
1181 }
1182 break;
1183 case kSecXPCOpSetUserCredentialsAndDSID:
1184 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1185 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
1186 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1187 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
1188 });
1189 }
1190 break;
1191 case kSecXPCOpView:
1192 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1193 with_label_and_number(event, ^(CFStringRef view, uint64_t actionCode) {
1194 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1195 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
1196 });
1197 }
1198 break;
1199 case kSecXPCOpViewSet:
1200 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1201 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
1202 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
1203 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
1204 CFReleaseNull(enabledViews);
1205 CFReleaseNull(disabledViews);
1206 }
1207 break;
1208 case kSecXPCOpSecurityProperty:
1209 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1210 with_label_and_number(event, ^(CFStringRef property, uint64_t actionCode) {
1211 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1212 SOSCCSecurityProperty_Server(property, (SOSSecurityPropertyActionCode)actionCode, &error));
1213 });
1214 }
1215 break;
1216 case kSecXPCOpCanAuthenticate:
1217 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1218 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1219 SOSCCCanAuthenticate_Server(&error));
1220 }
1221 break;
1222 case kSecXPCOpPurgeUserCredentials:
1223 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1224 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1225 SOSCCPurgeUserCredentials_Server(&error));
1226 }
1227 break;
1228 case kSecXPCOpDeviceInCircle:
1229 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1230 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1231 SOSCCThisDeviceIsInCircle_Server(&error));
1232 }
1233 break;
1234 case kSecXPCOpRequestToJoin:
1235 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1236 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1237 SOSCCRequestToJoinCircle_Server(&error));
1238 }
1239 break;
1240 case kSecXPCOpAccountHasPublicKey:
1241 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1242 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1243 SOSCCAccountHasPublicKey_Server(&error));
1244 }
1245 break;
1246 case kSecXPCOpAccountIsNew:
1247 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1248 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1249 SOSCCAccountIsNew_Server(&error));
1250 }
1251 break;
1252 case kSecXPCOpRequestToJoinAfterRestore:
1253 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1254 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1255 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
1256 }
1257 break;
1258 case kSecXPCOpRequestEnsureFreshParameters:
1259 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1260 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1261 SOSCCRequestEnsureFreshParameters_Server(&error));
1262 }
1263 break;
1264 case kSecXPCOpGetAllTheRings:
1265 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1266 CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error);
1267 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions);
1268 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1269 xpc_release(xpc_dictionary);
1270 }
1271 break;
1272 case kSecXPCOpApplyToARing:
1273 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1274 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1275 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error));
1276 CFReleaseNull(ringName);
1277 }
1278 break;
1279 case kSecXPCOpWithdrawlFromARing:
1280 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1281 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1282 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error));
1283 CFReleaseNull(ringName);
1284 }
1285 break;
1286 case kSecXPCOpRingStatus:
1287 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1288 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1289 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error));
1290 CFReleaseNull(ringName);
1291 }
1292 break;
1293 case kSecXPCOpEnableRing:
1294 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1295 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
1296 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error));
1297 CFReleaseNull(ringName);
1298 }
1299 break;
1300 case kSecXPCOpRequestDeviceID:
1301 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1302 CFStringRef deviceID = SOSCCCopyDeviceID_Server(&error);
1303 if (deviceID) {
1304 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error);
1305 }
1306 CFReleaseNull(deviceID);
1307 }
1308 break;
1309 case kSecXPCOpSetDeviceID:
1310 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1311 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
1312 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error));
1313 CFReleaseNull(IDS);
1314 }
1315 break;
1316 case kSecXPCOpHandleIDSMessage:
1317 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1318 CFDictionaryRef IDS = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyIDSMessage, &error);
1319 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, SOSCCHandleIDSMessage_Server(IDS, &error));
1320 CFReleaseNull(IDS);
1321 }
1322 break;
1323
1324 case kSecXPCOpSendIDSMessage:
1325 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1326 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1327 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSServiceRegistrationTest_Server(message, &error));
1328 CFReleaseNull(message);
1329 }
1330 break;
1331 case kSecXPCOpSyncWithKVSPeer:
1332 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1333 CFStringRef peerID = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
1334 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestSyncWithPeerOverKVS(peerID, &error));
1335 CFReleaseNull(peerID);
1336 }
1337 break;
1338 case kSecXPCOpSyncWithIDSPeer:
1339 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1340 CFStringRef deviceID = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
1341 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestSyncWithPeerOverIDS(deviceID, &error));
1342 CFReleaseNull(deviceID);
1343 }
1344 break;
1345 case kSecXPCOpPingTest:
1346 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1347 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
1348 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSPingTest_Server(message, &error));
1349 CFReleaseNull(message);
1350 }
1351 break;
1352 case kSecXPCOpIDSDeviceID:
1353 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1354 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSDeviceIDIsAvailableTest_Server(&error));
1355 }
1356 break;
1357 case kSecXPCOpAccountSetToNew:
1358 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1359 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
1360 }
1361 break;
1362 case kSecXPCOpResetToOffering:
1363 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1364 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1365 SOSCCResetToOffering_Server(&error));
1366 }
1367 break;
1368 case kSecXPCOpResetToEmpty:
1369 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1370 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1371 SOSCCResetToEmpty_Server(&error));
1372 }
1373 break;
1374 case kSecXPCOpRemoveThisDeviceFromCircle:
1375 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1376 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1377 SOSCCRemoveThisDeviceFromCircle_Server(&error));
1378 }
1379 break;
1380 case kSecXPCOpRemovePeersFromCircle:
1381 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1382 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfos, &error);
1383 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1384 SOSCCRemovePeersFromCircle_Server(applicants, &error));
1385 CFReleaseNull(applicants);
1386 }
1387 break;
1388 case kSecXPCOpLoggedOutOfAccount:
1389 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1390 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1391 SOSCCLoggedOutOfAccount_Server(&error));
1392 }
1393 break;
1394 case kSecXPCOpBailFromCircle:
1395 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1396 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
1397 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1398 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
1399 }
1400 break;
1401 case kSecXPCOpAcceptApplicants:
1402 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1403 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1404 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1405 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1406 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
1407 CFReleaseSafe(applicants);
1408 }
1409 break;
1410 case kSecXPCOpRejectApplicants:
1411 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1412 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
1413 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1414 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1415 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1416 CFReleaseSafe(applicants);
1417 }
1418 break;
1419 case kSecXPCOpSetNewPublicBackupKey:
1420 {
1421 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1422 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1423 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1424 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1425 CFReleaseNull(peerInfo);
1426 if (peerInfoData) {
1427 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1428 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1429 xpc_release(xpc_object);
1430 }
1431 CFReleaseNull(peerInfoData);
1432 CFReleaseSafe(publicBackupKey);
1433
1434 }
1435 }
1436 break;
1437 case kSecXPCOpSetBagForAllSlices:
1438 {
1439 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1440 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1441 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0);
1442 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1443 CFReleaseSafe(backupSlice);
1444 }
1445 }
1446 break;
1447 case kSecXPCOpCopyApplicantPeerInfo:
1448 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1449 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1450 SOSCCCopyApplicantPeerInfo_Server(&error),
1451 &error);
1452 }
1453 break;
1454 case kSecXPCOpCopyValidPeerPeerInfo:
1455 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1456 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1457 SOSCCCopyValidPeerPeerInfo_Server(&error),
1458 &error);
1459 }
1460 break;
1461 case kSecXPCOpValidateUserPublic:
1462 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1463 bool trusted = SOSCCValidateUserPublic_Server(&error);
1464 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1465 }
1466 break;
1467 case kSecXPCOpCopyNotValidPeerPeerInfo:
1468 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1469 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1470 SOSCCCopyNotValidPeerPeerInfo_Server(&error),
1471 &error);
1472 }
1473 break;
1474 case kSecXPCOpCopyGenerationPeerInfo:
1475 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1476 xpc_dictionary_set_and_consume_CFArray(replyMessage, kSecXPCKeyResult,
1477 SOSCCCopyGenerationPeerInfo_Server(&error));
1478 }
1479 break;
1480 case kSecXPCOpCopyRetirementPeerInfo:
1481 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1482 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1483 SOSCCCopyRetirementPeerInfo_Server(&error),
1484 &error);
1485 }
1486 break;
1487 case kSecXPCOpCopyViewUnawarePeerInfo:
1488 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1489 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1490 SOSCCCopyViewUnawarePeerInfo_Server(&error),
1491 &error);
1492 }
1493 break;
1494 case kSecXPCOpCopyAccountData:
1495 {
1496 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1497 xpc_object_t xpc_account_object = NULL;
1498 CFDataRef accountData = SOSCCCopyAccountState_Server(&error);
1499 if(accountData)
1500 xpc_account_object = _CFXPCCreateXPCObjectFromCFObject(accountData);
1501
1502 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_account_object);
1503 CFReleaseNull(accountData);
1504 }
1505 break;
1506 }
1507 case kSecXPCOpDeleteAccountData:
1508 {
1509 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1510 bool status = SOSCCDeleteAccountState_Server(&error);
1511 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1512 }
1513 break;
1514 }
1515 case kSecXPCOpCopyEngineData:
1516 {
1517 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1518
1519 xpc_object_t xpc_engine_object = NULL;
1520 CFDataRef engineData = SOSCCCopyEngineData_Server(&error);
1521 if(engineData)
1522 xpc_engine_object = _CFXPCCreateXPCObjectFromCFObject(engineData);
1523
1524 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_engine_object);
1525 CFReleaseNull(engineData);
1526
1527 }
1528 break;
1529 }
1530 case kSecXPCOpDeleteEngineData:
1531 {
1532 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1533 bool status = SOSCCDeleteEngineState_Server(&error);
1534 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1535 }
1536 break;
1537 }
1538 case kSecXPCOpCopyEngineState:
1539 {
1540 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1541 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
1542 if (array) {
1543 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1544 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1545 xpc_release(xpc_array);
1546 }
1547 CFReleaseNull(array);
1548 }
1549 }
1550 break;
1551 case kSecXPCOpCopyPeerPeerInfo:
1552 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1553 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1554 SOSCCCopyPeerPeerInfo_Server(&error),
1555 &error);
1556 }
1557 break;
1558 case kSecXPCOpCopyConcurringPeerPeerInfo:
1559 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1560 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1561 SOSCCCopyConcurringPeerPeerInfo_Server(&error),
1562 &error);
1563 }
1564 break;
1565 case kSecXPCOpCopyMyPeerInfo:
1566 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1567 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1568 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1569 CFReleaseNull(peerInfo);
1570 if (peerInfoData) {
1571 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1572 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1573 xpc_release(xpc_object);
1574 }
1575 CFReleaseNull(peerInfoData);
1576 }
1577 break;
1578 case kSecXPCOpGetLastDepartureReason:
1579 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1580 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1581 SOSCCGetLastDepartureReason_Server(&error));
1582 }
1583 break;
1584 case kSecXPCOpSetLastDepartureReason:
1585 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1586 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1587 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1588 SOSCCSetLastDepartureReason_Server(reason, &error));
1589 break;
1590 }
1591 case kSecXPCOpProcessSyncWithAllPeers:
1592 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1593 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1594 SOSCCProcessSyncWithAllPeers_Server(&error));
1595 }
1596 break;
1597 case soscc_EnsurePeerRegistration_id:
1598 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1599 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1600 SOSCCProcessEnsurePeerRegistration_Server(&error));
1601 }
1602 break;
1603 case kSecXPCOpCopyIncompatibilityInfo:
1604 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1605 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
1606 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
1607 CFReleaseSafe(iis);
1608 break;
1609 }
1610 case kSecXPCOpOTAGetEscrowCertificates:
1611 {
1612 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
1613 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error);
1614 if (array) {
1615 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1616 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1617 xpc_release(xpc_array);
1618 }
1619 CFReleaseNull(array);
1620 }
1621 break;
1622 case kSecXPCOpOTAPKIGetNewAsset:
1623 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1624 SecOTAPKISignalNewAsset(&error));
1625 break;
1626 case kSecXPCOpRollKeys:
1627 {
1628 bool force = xpc_dictionary_get_bool(event, "force");
1629 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1630 _SecServerRollKeys(force, &client, &error));
1631 }
1632 break;
1633 case kSecXPCOpSetHSA2AutoAcceptInfo:
1634 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1635 CFDataRef cfbytes = NULL;
1636 const uint8_t *bytes = NULL;
1637 size_t len = 0;
1638
1639 bytes = xpc_dictionary_get_data(event,
1640 kSecXPCKeyHSA2AutoAcceptInfo, &len);
1641 if (!bytes) {
1642 SOSCreateError(kSOSErrorBadKey,
1643 CFSTR("missing autoaccept info"), NULL, &error);
1644 break;
1645 }
1646
1647 cfbytes = CFDataCreate(NULL, bytes, len);
1648 if (!cfbytes) {
1649 SOSCreateError(kSOSErrorAllocationFailure,
1650 CFSTR("could not allocate autoaccept info"),
1651 NULL, &error);
1652 break;
1653 }
1654
1655 xpc_dictionary_set_bool(replyMessage,
1656 kSecXPCKeyResult,
1657 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes, &error));
1658 CFReleaseNull(cfbytes);
1659 }
1660 break;
1661 case kSecXPCOpWaitForInitialSync:
1662 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1663 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1664 SOSCCWaitForInitialSync_Server(&error));
1665 }
1666 break;
1667
1668 case kSecXPCOpCopyYetToSyncViews:
1669 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1670 CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error);
1671 if (array) {
1672 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1673 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1674 xpc_release(xpc_array);
1675 }
1676 CFReleaseNull(array);
1677 }
1678 break;
1679 case kSecXPCOpSetEscrowRecord:
1680 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1681 CFStringRef escrow_label = SecXPCDictionaryCopyString(event, kSecXPCKeyEscrowLabel, &error);
1682 uint64_t tries = xpc_dictionary_get_int64(event, kSecXPCKeyTriesLabel);
1683
1684 bool result = SOSCCSetEscrowRecord_Server(escrow_label, tries, &error);
1685 if (result) {
1686 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1687 }
1688 CFReleaseNull(escrow_label);
1689 }
1690 break;
1691 case kSecXPCOpGetEscrowRecord:
1692 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1693 CFDictionaryRef record = SOSCCCopyEscrowRecord_Server(&error);
1694 if (record) {
1695 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record);
1696 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1697 xpc_release(xpc_dictionary);
1698 }
1699 CFReleaseNull(record);
1700 }
1701 break;
1702 case kSecXPCOpCheckPeerAvailability:
1703 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1704 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCCheckPeerAvailability_Server(&error));
1705 }
1706 break;
1707
1708
1709 case kSecXPCOpIsThisDeviceLastBackup:
1710 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1711 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error));
1712 }
1713 break;
1714 case kSecXPCOpPeersHaveViewsEnabled:
1715 {
1716 CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error);
1717 if (viewSet) {
1718 CFBooleanRef result = SOSCCPeersHaveViewsEnabled_Server(viewSet, &error);
1719 if (result) {
1720 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result != kCFBooleanFalse);
1721 }
1722 }
1723 CFReleaseNull(viewSet);
1724 }
1725 break;
1726
1727 case kSecXPCOpWhoAmI:
1728 {
1729 if (client.musr)
1730 xpc_dictionary_set_data(replyMessage, "musr", CFDataGetBytePtr(client.musr), CFDataGetLength(client.musr));
1731 xpc_dictionary_set_bool(replyMessage, "system-keychain", client.allowSystemKeychain);
1732 xpc_dictionary_set_bool(replyMessage, "syncbubble-keychain", client.allowSyncBubbleKeychain);
1733 xpc_dictionary_set_bool(replyMessage, "network-extension", client.isNetworkExtension);
1734 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1735 }
1736 break;
1737 case kSecXPCOpTransmogrifyToSyncBubble:
1738 {
1739 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainSyncBubble, &error)) {
1740 #if TARGET_OS_IOS
1741 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1742 CFArrayRef services = SecXPCDictionaryCopyArray(event, "services", &error);
1743 bool res = false;
1744 if (uid && services) {
1745 res = _SecServerTransmogrifyToSyncBubble(services, uid, &client, &error);
1746 }
1747 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1748 CFReleaseNull(services);
1749 #else
1750 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1751 #endif
1752 }
1753 }
1754 break;
1755 case kSecXPCOpTransmogrifyToSystemKeychain:
1756 {
1757 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
1758 #if TARGET_OS_IOS
1759 bool res = _SecServerTransmogrifyToSystemKeychain(&client, &error);
1760 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1761 #else
1762 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1763 #endif
1764
1765 }
1766 }
1767 break;
1768 case kSecXPCOpDeleteUserView:
1769 {
1770 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
1771 bool res = false;
1772 #if TARGET_OS_IOS
1773 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1774 if (uid) {
1775 res = _SecServerDeleteMUSERViews(&client, uid, &error);
1776 }
1777 #endif
1778 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1779
1780 }
1781 }
1782 break;
1783 case kSecXPCOpWrapToBackupSliceKeyBagForView:
1784 {
1785 CFStringRef viewname = SecXPCDictionaryCopyString(event, kSecXPCKeyViewName, &error);
1786 if(viewname) {
1787 CFDataRef plaintext = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
1788 if (plaintext) {
1789 CFDataRef ciphertext = NULL;
1790 CFDataRef bskbEncoded = NULL;
1791
1792 bool result = SOSWrapToBackupSliceKeyBagForView_Server(viewname, plaintext, &ciphertext, &bskbEncoded, &error);
1793 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1794
1795 if(!error && result) {
1796 if(ciphertext) {
1797 xpc_dictionary_set_data(replyMessage, kSecXPCData, CFDataGetBytePtr(ciphertext), CFDataGetLength(ciphertext));
1798 }
1799 if(bskbEncoded) {
1800 xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, CFDataGetBytePtr(bskbEncoded), CFDataGetLength(bskbEncoded));
1801 }
1802 }
1803 CFReleaseSafe(ciphertext);
1804 CFReleaseSafe(bskbEncoded);
1805 }
1806 CFReleaseSafe(plaintext);
1807 }
1808 CFReleaseNull(viewname);
1809 }
1810 break;
1811 case kSecXPCOpCopyApplication:
1812 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1813 SOSPeerInfoRef peerInfo = SOSCCCopyApplication_Server(&error);
1814 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1815 CFReleaseNull(peerInfo);
1816 if (peerInfoData) {
1817 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1818 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1819 xpc_release(xpc_object);
1820 }
1821 CFReleaseNull(peerInfoData);
1822 }
1823 break;
1824 case kSecXPCOpCopyCircleJoiningBlob:
1825 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1826 CFDataRef appBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error);
1827 SOSPeerInfoRef applicant = SOSPeerInfoCreateFromData(kCFAllocatorDefault, &error, appBlob);
1828 CFDataRef pbblob = SOSCCCopyCircleJoiningBlob_Server(applicant, &error);
1829 if (pbblob) {
1830 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(pbblob);
1831 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1832 xpc_release(xpc_object);
1833 }
1834 CFReleaseNull(pbblob);
1835 CFReleaseNull(applicant);
1836 CFReleaseNull(appBlob);
1837 }
1838 break;
1839 case kSecXPCOpJoinWithCircleJoiningBlob:
1840 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1841 CFDataRef joiningBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error);
1842
1843 bool retval = SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob, &error);
1844 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1845 CFReleaseNull(joiningBlob);
1846 }
1847 break;
1848 case sec_delete_items_with_access_groups_id:
1849 {
1850 bool retval = false;
1851 #if TARGET_OS_IPHONE
1852 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateUninstallDeletion, &error)) {
1853 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1854
1855 if (accessGroups) {
1856 retval = _SecItemServerDeleteAllWithAccessGroups(accessGroups, &client, &error);
1857 }
1858 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1859 CFReleaseNull(accessGroups);
1860 }
1861 #endif
1862 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1863 }
1864 break;
1865 #endif /* !TRUSTD_SERVER */
1866 default:
1867 break;
1868 }
1869
1870 }
1871
1872 if (error)
1873 {
1874 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
1875 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1876 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
1877 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1878 else
1879 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1880
1881 xpcError = SecCreateXPCObjectWithCFError(error);
1882 if (replyMessage) {
1883 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1884 }
1885 } else if (replyMessage) {
1886 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
1887 }
1888 } else {
1889 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
1890 secerror("%@: returning error: %@", client.task, error);
1891 xpcError = SecCreateXPCObjectWithCFError(error);
1892 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
1893 }
1894
1895 if (replyMessage) {
1896 xpc_connection_send_message(connection, replyMessage);
1897 xpc_release(replyMessage);
1898 }
1899 if (xpcError)
1900 xpc_release(xpcError);
1901 #if TARGET_OS_IPHONE
1902 pthread_setspecific(taskThreadKey, NULL);
1903 #endif
1904 CFReleaseSafe(error);
1905 CFReleaseSafe(client.accessGroups);
1906 CFReleaseSafe(client.musr);
1907 CFReleaseSafe(client.task);
1908 CFReleaseSafe(domains);
1909 CFReleaseSafe(clientAuditToken);
1910 }
1911
1912 static void securityd_xpc_init(const char *service_name)
1913 {
1914 #if TARGET_OS_IPHONE
1915 pthread_key_create(&taskThreadKey, NULL);
1916 SecTaskDiagnoseEntitlements = secTaskDiagnoseEntitlements;
1917 #endif
1918
1919 secdebug("serverxpc", "start");
1920 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1921 if (!listener) {
1922 seccritical("security failed to register xpc listener for %s, exiting", service_name);
1923 abort();
1924 }
1925
1926 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1927 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1928 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1929 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
1930 xpc_retain(connection);
1931 xpc_retain(event);
1932 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1933 securityd_xpc_dictionary_handler(connection, event);
1934 xpc_release(event);
1935 xpc_release(connection);
1936 });
1937 }
1938 });
1939 xpc_connection_resume(connection);
1940 }
1941 });
1942 xpc_connection_resume(listener);
1943 }
1944
1945
1946 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1947
1948 #if TARGET_OS_EMBEDDED
1949 static void securityd_soscc_lock_hack() {
1950 dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
1951 int soscc_tok;
1952
1953 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1954 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1955 // this code will need to be generalized / migrated away from just this specific purpose.
1956 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) {
1957 char *event_description = xpc_copy_description(object);
1958 secnotice("events", "%s", event_description);
1959 free(event_description);
1960 });
1961
1962 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1963 notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) {
1964 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1965 CFErrorRef error = NULL;
1966
1967 uint64_t one_minute = 60ull;
1968 if(SecAKSLockUserKeybag(one_minute, &error)){
1969 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1970 xpc_transaction_begin();
1971
1972 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, one_minute*NSEC_PER_SEC), soscc_lock_queue, ^{
1973 CFErrorRef localError = NULL;
1974 if(!SecAKSUnLockUserKeybag(&localError))
1975 secerror("failed to unlock: %@", localError);
1976 CFReleaseNull(localError);
1977 xpc_transaction_end();
1978 });
1979 } else {
1980 secerror("Failed to take device lock assertion: %@", error);
1981 }
1982 CFReleaseNull(error);
1983 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1984 });
1985 }
1986 #endif
1987
1988 #if TRUSTD_SERVER
1989 #include <trustd/SecTrustOSXEntryPoints.h>
1990 static void trustd_init_server(void) {
1991 SecTrustLegacySourcesEventRunloopCreate();
1992 }
1993 #endif
1994
1995 int main(int argc, char *argv[])
1996 {
1997 char *wait4debugger = getenv("WAIT4DEBUGGER");
1998 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1999 seccritical("SIGSTOPing self, awaiting debugger");
2000 kill(getpid(), SIGSTOP);
2001 seccritical("Again, for good luck (or bad debuggers)");
2002 kill(getpid(), SIGSTOP);
2003 }
2004
2005 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
2006 {
2007 CFDictionaryRef deviceMode = MKBUserTypeDeviceMode(NULL, NULL);
2008 CFTypeRef value = NULL;
2009
2010 if (deviceMode && CFDictionaryGetValueIfPresent(deviceMode, kMKBDeviceModeKey, &value) && CFEqual(value, kMKBDeviceModeMultiUser)) {
2011 inMultiUser = 1;
2012 }
2013 CFReleaseNull(deviceMode);
2014 }
2015 #endif
2016
2017 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
2018 Secd doesn't realize DB connections get invalidated when network home directory users logout
2019 and their home gets unmounted. Exit secd, start fresh when user logs back in.
2020 */
2021 #if !TARGET_OS_IPHONE
2022 int sessionstatechanged_tok;
2023 notify_register_dispatch(kSA_SessionStateChangedNotification, &sessionstatechanged_tok, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token __unused) {
2024 // we could be a process running as root.
2025 // However, since root never logs out this isn't an issue.
2026 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn) {
2027 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
2028 xpc_transaction_exit_clean();
2029 });
2030 }
2031 });
2032 #endif
2033
2034 const char *serviceName = kSecuritydXPCServiceName;
2035 #if TRUSTD_SERVER
2036 serviceName = kTrustdXPCServiceName;
2037 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
2038 serviceName = kTrustdAgentXPCServiceName;
2039 }
2040 #endif
2041 /* setup SQDLite before some other component have a chance to create a database connection */
2042 _SecServerDatabaseSetup();
2043
2044 securityd_init_server();
2045 #if TRUSTD_SERVER
2046 trustd_init_server();
2047 #endif
2048 securityd_xpc_init(serviceName);
2049
2050 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
2051 #if TARGET_OS_EMBEDDED
2052 securityd_soscc_lock_hack();
2053 #endif
2054
2055 dispatch_main();
2056
2057 return 0;
2058 }
2059
2060 /* vi:set ts=4 sw=4 et: */