]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server.c
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / ipc / server.c
1 /*
2 * Copyright (c) 2007-2017 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 #if TARGET_DARWINOS
25 #undef OCTAGON
26 #undef SECUREOBJECTSYNC
27 #undef SHAREDWEBCREDENTIALS
28 #endif
29
30 #include <os/transaction_private.h>
31 #include <os/variant_private.h>
32
33 #include <corecrypto/ccec.h>
34 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
35 #include <Security/SecureObjectSync/SOSCloudCircle.h>
36 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
37 #include "keychain/SecureObjectSync/SOSInternal.h"
38 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
39 #include "keychain/SecureObjectSync/SOSControlServer.h"
40 #include <Security/SecBase.h>
41 #include <Security/SecBasePriv.h>
42 #include <Security/SecCertificatePriv.h>
43 #include <Security/SecEntitlements.h>
44 #include <Security/SecInternal.h>
45 #include <Security/SecItem.h>
46 #include <Security/SecItemPriv.h>
47 #include <Security/SecPolicy.h>
48 #include <Security/SecPolicyInternal.h>
49 #include <Security/SecTask.h>
50 #include <Security/SecTrustInternal.h>
51 #include <Security/SecuritydXPC.h>
52 #include "trust/trustd/OTATrustUtilities.h"
53 #include "keychain/securityd/SOSCloudCircleServer.h"
54 #include "keychain/securityd/SecItemBackupServer.h"
55 #include "keychain/securityd/SecItemServer.h"
56 #include "keychain/securityd/SecLogSettingsServer.h"
57 #include "keychain/securityd/SecOTRRemote.h"
58 #include "trust/trustd/SecTrustServer.h"
59 #include "trust/trustd/SecTrustStoreServer.h"
60 #include "keychain/securityd/iCloudTrace.h"
61 #include "keychain/securityd/spi.h"
62 #include <utilities/SecAKSWrappers.h>
63 #include <utilities/SecCFError.h>
64 #include <utilities/SecCFWrappers.h>
65 #include <utilities/SecDb.h>
66 #include <utilities/SecIOFormat.h>
67 #include <utilities/SecXPCError.h>
68 #include <utilities/debugging.h>
69 #include <utilities/SecInternalReleasePriv.h>
70 #include <utilities/der_plist_internal.h>
71 #include <utilities/der_plist.h>
72 #include "trust/trustd/personalization.h"
73 #include "trust/trustd/SecPinningDb.h"
74 #include "keychain/securityd/SFKeychainControlManager.h"
75
76 #include <keychain/ckks/CKKS.h>
77 #include <keychain/ckks/CKKSControlServer.h>
78 #include "keychain/ot/OctagonControlServer.h"
79
80 #include "keychain/securityd/SFKeychainServer.h"
81 #if !TARGET_OS_BRIDGE
82 #include "keychain/securityd/PolicyReporter.h"
83 #endif
84
85 #include <AssertMacros.h>
86 #include <CoreFoundation/CFXPCBridge.h>
87 #include <CoreFoundation/CoreFoundation.h>
88 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
89
90 #if TARGET_OS_OSX
91 #include <Security/SecTaskPriv.h>
92 #include <login/SessionAgentStatusCom.h>
93 #endif
94 #include <asl.h>
95 #include <bsm/libbsm.h>
96 #include <ipc/securityd_client.h>
97 #include <libkern/OSAtomic.h>
98 #include <mach/mach.h>
99 #include <mach/message.h>
100 #include <notify.h>
101 #include <stdlib.h>
102 #include <sys/queue.h>
103 #include <sys/sysctl.h>
104 #include <syslog.h>
105 #include <xpc/private.h>
106 #include <xpc/xpc.h>
107
108 #include <ipc/server_security_helpers.h>
109 #include <ipc/server_entitlement_helpers.h>
110
111 #include "keychain/ot/OT.h"
112 #include "keychain/escrowrequest/EscrowRequestXPCServer.h"
113 #include "keychain/escrowrequest/EscrowRequestServerHelpers.h"
114
115 #if TARGET_OS_OSX
116 #include <sandbox.h>
117 #include <pwd.h>
118 #include <err.h>
119 #endif
120
121 #include "util.h"
122
123 static void refresh_prng(void)
124 {
125 aks_ref_key_t ref = NULL;
126
127 int fd = open("/dev/random", O_WRONLY);
128 if (fd == -1) {
129 secerror("failed to open /dev/random (%d)", errno);
130 goto out;
131 }
132
133 /* create class F ref-key, and use its public key as an entropy source */
134 int err = aks_ref_key_create(bad_keybag_handle, key_class_f, key_type_asym_ec_p256, NULL, 0, &ref);
135 if (err != kAKSReturnSuccess) {
136 secerror("failed to create refkey (%d)", err);
137 goto out;
138 }
139
140 size_t pub_key_len = 0;
141 const uint8_t *pub_key = aks_ref_key_get_public_key(ref, &pub_key_len);
142 if (pub_key_len > ccec_export_pub_size_cp(ccec_cp_256())) {
143 secerror("invalid pub key (%zu)", pub_key_len);
144 goto out;
145 }
146
147 while (pub_key_len > 0) {
148 ssize_t n = write(fd, pub_key, pub_key_len);
149 if (n == -1) {
150 secerror("failed to write /dev/random (%d)", errno);
151 goto out;
152 }
153
154 pub_key += n;
155 pub_key_len -= n;
156 }
157
158 out:
159 if (ref) {
160 aks_ref_key_free(&ref);
161 }
162
163 if (fd >= 0) {
164 close(fd);
165 }
166 }
167
168 #if SECUREOBJECTSYNC
169
170 CF_RETURNS_RETAINED
171 static CFStringRef
172 _xpc_dictionary_copy_CFString(xpc_object_t xdict, const char *key)
173 {
174 CFStringRef result = NULL;
175 const char *str = xpc_dictionary_get_string(xdict, key);
176 if (str != NULL) {
177 result = CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8);
178 }
179 return result;
180 }
181
182 CF_RETURNS_RETAINED
183 static CFDataRef
184 _xpc_dictionary_copy_CFDataNoCopy(xpc_object_t xdict, const char *key)
185 {
186 CFDataRef result = NULL;
187 size_t len = 0;
188 const void *ptr = xpc_dictionary_get_data(xdict, key, &len);
189 if (ptr != NULL) {
190 result = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ptr, len, kCFAllocatorNull);
191 }
192 return result;
193 }
194
195 static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) {
196 CFStringRef user_label = _xpc_dictionary_copy_CFString(message, kSecXPCKeyUserLabel);
197 CFDataRef user_password = _xpc_dictionary_copy_CFDataNoCopy(message, kSecXPCKeyUserPassword);
198
199 if (user_label != NULL && user_password != NULL) {
200 action(user_label, user_password);
201 }
202
203 CFReleaseNull(user_label);
204 CFReleaseNull(user_password);
205 }
206
207 static void with_label_and_password_and_dsid(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password, CFStringRef dsid)) {
208 CFStringRef user_label = _xpc_dictionary_copy_CFString(message, kSecXPCKeyUserLabel);
209 CFDataRef user_password = _xpc_dictionary_copy_CFDataNoCopy(message, kSecXPCKeyUserPassword);
210 CFStringRef dsid = _xpc_dictionary_copy_CFString(message, kSecXPCKeyDSID);
211
212 /* dsid is optional */
213 if (user_label != NULL && user_password != NULL) {
214 action(user_label, user_password, dsid);
215 }
216
217 CFReleaseNull(user_label);
218 CFReleaseNull(user_password);
219 CFReleaseNull(dsid);
220 }
221
222 static void with_view_and_action(xpc_object_t message, void (^action)(CFStringRef view_name, uint64_t view_action_code)) {
223 CFStringRef view = _xpc_dictionary_copy_CFString(message, kSecXPCKeyViewName);
224 const int64_t number = xpc_dictionary_get_int64(message, kSecXPCKeyViewActionCode);
225
226 if (view != NULL) {
227 action(view, number);
228 }
229
230 CFReleaseNull(view);
231 }
232
233 static CFArrayRef SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary, const char *key, CFErrorRef *error) {
234 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary, key), error);
235 }
236
237 static CFDataRef SecXPCDictionaryCopyCFDataRef(xpc_object_t message, const char *key, CFErrorRef *error) {
238 CFDataRef retval = NULL;
239 const uint8_t *bytes = NULL;
240 size_t len = 0;
241
242 bytes = xpc_dictionary_get_data(message, key, &len);
243 require_action_quiet(bytes, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("missing CFDataRef info"), NULL, error));
244 retval = CFDataCreate(NULL, bytes, len);
245 require_action_quiet(retval, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("could not allocate CFDataRef info"), NULL, error));
246 errOut:
247 return retval;
248 }
249
250 static CFSetRef CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER, CFErrorRef* error) {
251 CFSetRef retval = NULL;
252 require_action_quiet(xpcSetDER, errOut, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Set to decode")));
253
254 require_action_quiet(xpc_get_type(xpcSetDER) == XPC_TYPE_DATA, errOut, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("xpcSetDER not data, got %@"), xpcSetDER));
255
256 const uint8_t* der = xpc_data_get_bytes_ptr(xpcSetDER);
257 const uint8_t* der_end = der + xpc_data_get_length(xpcSetDER);
258 der = der_decode_set(kCFAllocatorDefault, &retval, error, der, der_end);
259 if (der != der_end) {
260 SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data"));
261 goto errOut;
262 }
263 return retval;
264 errOut:
265 CFReleaseNull(retval);
266 return NULL;
267 }
268
269 static SOSPeerInfoRef SecXPCDictionaryCopyPeerInfo(xpc_object_t message, const char *key, CFErrorRef *error) {
270 size_t length = 0;
271 const uint8_t *der = xpc_dictionary_get_data(message, key, &length);
272
273 return SecRequirementError(der != NULL, error, CFSTR("No data for key %s"), key) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault, error, &der, der + length) : NULL;
274 }
275
276 static CFSetRef SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event, const char *key) {
277 CFErrorRef error = NULL;
278 xpc_object_t object = xpc_dictionary_get_value(event, key);
279 CFSetRef retval = NULL;
280 if(object) retval = CreateCFSetRefFromXPCObject(object, &error);
281 CFReleaseNull(error);
282 return retval;
283 }
284
285 static inline
286 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array) {
287 if (cf_array) {
288 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(cf_array);
289 xpc_dictionary_set_value(xdict, key, xpc_array);
290 xpc_release(xpc_array);
291 }
292 CFReleaseNull(cf_array);
293 }
294
295 static inline
296 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array, CFErrorRef *error) {
297 bool success = true;
298 if (cf_array) {
299 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(cf_array, error);
300 if (xpc_array) {
301 xpc_dictionary_set_value(xdict, key, xpc_array);
302 xpc_release(xpc_array);
303 } else {
304 success = false;
305 }
306 }
307 CFReleaseNull(cf_array);
308 return success;
309 }
310
311 #endif /* SECUREOBJECTSYNC */
312
313 static CFDataRef
314 SecDataCopyMmapFileDescriptor(int fd, void **mem, size_t *size, CFErrorRef *error)
315 {
316 struct stat sb;
317 if (fstat(fd, &sb) < 0) {
318 return NULL;
319 }
320
321 *size = (size_t)sb.st_size;
322 if ((off_t)*size != sb.st_size) {
323 return NULL;
324 }
325
326 *mem = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0);
327 if (*mem == MAP_FAILED) {
328 return NULL;
329 }
330
331 return CFDataCreateWithBytesNoCopy(NULL, *mem, *size, kCFAllocatorNull);
332 }
333
334 static bool
335 SecDataWriteFileDescriptor(int fd, CFDataRef data)
336 {
337 CFIndex count = CFDataGetLength(data);
338 const uint8_t *ptr = CFDataGetBytePtr(data);
339 bool writeResult = false;
340
341 while (count) {
342 ssize_t ret = write(fd, ptr, count);
343 if (ret <= 0)
344 break;
345 count -= ret;
346 ptr += ret;
347 }
348 if (count == 0)
349 writeResult = true;
350
351 return writeResult;
352 }
353
354 // Returns error if entitlement isn't present.
355 static bool
356 EntitlementPresentAndTrue(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
357 {
358 if (!SecTaskGetBooleanValueForEntitlement(clientTask, entitlement)) {
359 SecError(errSecMissingEntitlement, error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)op), clientTask, entitlement);
360 return false;
361 }
362 return true;
363 }
364
365 static bool
366 EntitlementAbsentOrFalse(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
367 {
368 if (SecTaskGetBooleanValueForEntitlement(clientTask, entitlement)) {
369 SecError(errSecNotAvailable, error, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation) op), clientTask, entitlement);
370 return false;
371 }
372 return true;
373 }
374
375 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
376 xpc_type_t type = xpc_get_type(event);
377 __block CFErrorRef error = NULL;
378 xpc_object_t xpcError = NULL;
379 xpc_object_t replyMessage = NULL;
380 CFDataRef clientAuditToken = NULL;
381 CFArrayRef domains = NULL;
382 SecurityClient client = {
383 .task = NULL,
384 .accessGroups = NULL,
385 .musr = NULL,
386 .uid = xpc_connection_get_euid(connection),
387 .allowSystemKeychain = false,
388 .allowSyncBubbleKeychain = false,
389 .isNetworkExtension = false,
390 .canAccessNetworkExtensionAccessGroups = false,
391 .applicationIdentifier = NULL,
392 .isAppClip = false,
393 };
394
395 secdebug("serverxpc", "entering");
396 if (type == XPC_TYPE_DICTIONARY) {
397 // TODO: Find out what we're dispatching.
398 replyMessage = xpc_dictionary_create_reply(event);
399
400 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
401
402 audit_token_t auditToken = {};
403 xpc_connection_get_audit_token(connection, &auditToken);
404 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
405
406 if (!fill_security_client(&client, xpc_connection_get_euid(connection), auditToken)) {
407 CFReleaseNull(clientAuditToken);
408 xpc_connection_send_message(connection, replyMessage);
409 xpc_release(replyMessage);
410 return;
411 }
412
413 #if TARGET_OS_IOS
414 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
415 domains = SecTaskCopySharedWebCredentialDomains(client.task);
416 }
417 #endif
418 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
419
420 switch (operation)
421 {
422 case sec_item_add_id:
423 {
424 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
425 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
426 if (query) {
427 // Check for any entitlement-required attributes
428 bool entitlementsCorrect = true;
429 if(CFDictionaryGetValue(query, kSecAttrDeriveSyncIDFromItemAttributes) ||
430 CFDictionaryGetValue(query, kSecAttrPCSPlaintextServiceIdentifier) ||
431 CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicKey) ||
432 CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicIdentity)) {
433 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error);
434 }
435 if(entitlementsCorrect &&
436 (CFDictionaryGetValue(query, kSecDataInetExtraNotes) ||
437 CFDictionaryGetValue(query, kSecDataInetExtraHistory) ||
438 CFDictionaryGetValue(query, kSecDataInetExtraClientDefined0) ||
439 CFDictionaryGetValue(query, kSecDataInetExtraClientDefined1) ||
440 CFDictionaryGetValue(query, kSecDataInetExtraClientDefined2) ||
441 CFDictionaryGetValue(query, kSecDataInetExtraClientDefined3))) {
442 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error);
443 }
444
445 if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) {
446 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateSysBound, &error);
447 }
448
449 CFTypeRef result = NULL;
450 if(entitlementsCorrect) {
451 if (_SecItemAdd(query, &client, &result, &error) && result) {
452 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
453 CFReleaseNull(result);
454 }
455 }
456 CFReleaseNull(query);
457 }
458 break;
459 }
460 }
461 case sec_item_copy_matching_id:
462 {
463 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
464 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
465 if (query) {
466 CFTypeRef result = NULL;
467 if (_SecItemCopyMatching(query, &client, &result, &error) && result) {
468 SecXPCDictionarySetPListWithRepair(replyMessage, kSecXPCKeyResult, result, true, &error);
469 CFReleaseNull(result);
470 }
471 CFReleaseNull(query);
472 }
473 break;
474 }
475 }
476 case sec_item_update_id:
477 {
478 if (EntitlementAbsentOrFalse(sec_item_update_id, client.task, kSecEntitlementKeychainDeny, &error)) {
479 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
480 if (query) {
481 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
482 if (attributesToUpdate) {
483 // Check for any entitlement-required attributes
484 bool entitlementsCorrect = true;
485 if(CFDictionaryGetValue(query, kSecAttrDeriveSyncIDFromItemAttributes) ||
486 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextServiceIdentifier) ||
487 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicKey) ||
488 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicIdentity)) {
489 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error);
490 }
491 if(entitlementsCorrect &&
492 (CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraNotes) ||
493 CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraHistory) ||
494 CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined0) ||
495 CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined1) ||
496 CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined2) ||
497 CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined3))) {
498 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error);
499 }
500 if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) {
501 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateSysBound, &error);
502 }
503
504 if(entitlementsCorrect) {
505 bool result = _SecItemUpdate(query, attributesToUpdate, &client, &error);
506 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
507 }
508 CFReleaseNull(attributesToUpdate);
509 }
510 CFReleaseNull(query);
511 }
512 }
513 break;
514 }
515 case sec_item_delete_id:
516 {
517 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
518 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
519 if (query) {
520 bool result = _SecItemDelete(query, &client, &error);
521 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
522 CFReleaseNull(query);
523 }
524 }
525 break;
526 }
527 case sec_item_update_token_items_for_access_groups_id:
528 {
529 if (EntitlementAbsentOrFalse(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementKeychainDeny, &error) &&
530 EntitlementPresentAndTrue(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementUpdateTokenItems, &error)) {
531 CFStringRef tokenID = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
532 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error);
533 CFArrayRef tokenItems = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error);
534 if (tokenID) {
535 bool result = _SecItemUpdateTokenItemsForAccessGroups(tokenID, accessGroups, tokenItems, &client, &error);
536 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
537 }
538 CFReleaseNull(tokenID);
539 CFReleaseNull(accessGroups);
540 CFReleaseNull(tokenItems);
541 }
542 break;
543 }
544 case sec_delete_all_id:
545 {
546 bool retval = false;
547 #if TARGET_OS_IPHONE
548 /* buddy is temporary allowed to do this */
549 CFStringRef applicationIdentifier = SecTaskCopyApplicationIdentifier(client.task);
550 bool isBuddy = applicationIdentifier &&
551 CFEqual(applicationIdentifier, CFSTR("com.apple.purplebuddy"));
552 CFReleaseNull(applicationIdentifier);
553
554 if (isBuddy || EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateDeleteAll, &error))
555 {
556 retval = _SecItemDeleteAll(&error);
557 }
558 #endif
559 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
560 break;
561 }
562 case sec_keychain_backup_id:
563 {
564 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
565 CFDataRef keybag = NULL, passcode = NULL;
566 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
567 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
568 bool emcs = SecXPCDictionaryGetBool(event, kSecXPCKeyEMCSBackup, NULL);
569 CFDataRef backup = _SecServerKeychainCreateBackup(&client, keybag, passcode, emcs, &error);
570 if (backup) {
571 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
572 if (fd < 0) {
573 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
574 } else {
575 bool writeResult = SecDataWriteFileDescriptor(fd, backup);
576 if (close(fd) != 0)
577 writeResult = false;
578 if (!writeResult)
579 SecError(errSecIO, &error, CFSTR("Failed to write backup file: %d"), errno);
580 SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, writeResult, NULL);
581 }
582 CFRelease(backup);
583 }
584 CFReleaseSafe(passcode);
585 }
586 CFReleaseSafe(keybag);
587 }
588 }
589 break;
590 }
591 case sec_keychain_restore_id:
592 {
593 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
594 CFDataRef backup = NULL;
595 void *mem = NULL;
596 size_t size = 0;
597
598 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
599 if (fd != -1) {
600 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
601 } else {
602 backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
603 }
604 if (backup) {
605 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
606 if (keybag) {
607 CFDataRef passcode = NULL;
608 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
609 bool result = _SecServerKeychainRestore(backup, &client, keybag, passcode, &error);
610 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
611 CFReleaseSafe(passcode);
612 }
613 }
614 CFReleaseNull(keybag);
615 }
616 CFReleaseNull(backup);
617 if (fd != -1)
618 close(fd);
619 if (mem) {
620 munmap(mem, size);
621 }
622 }
623 break;
624 }
625 case sec_keychain_backup_keybag_uuid_id:
626 {
627 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
628 CFDataRef backup = NULL;
629 CFStringRef uuid = NULL;
630 void *mem = NULL;
631 size_t size = 0;
632
633 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
634 if (fd != -1) {
635 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
636 if (backup)
637 uuid = _SecServerBackupCopyUUID(backup, &error);
638 }
639 if (uuid)
640 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, uuid, &error);
641
642 CFReleaseNull(backup);
643 if (fd != -1)
644 close(fd);
645 if (mem) {
646 munmap(mem, size);
647 }
648 CFReleaseNull(uuid);
649 }
650 break;
651 }
652 #if SECUREOBJECTSYNC
653 case sec_keychain_sync_update_message_id:
654 {
655 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
656 if (updates) {
657 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
658 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
659 CFReleaseNull(result);
660 }
661 CFReleaseNull(updates);
662 break;
663 }
664 case sec_keychain_backup_syncable_id:
665 {
666 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
667 CFDictionaryRef oldbackup = NULL;
668 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
669 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
670 if (keybag) {
671 CFDataRef passcode = NULL;
672 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
673 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
674 if (newbackup) {
675 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
676 CFRelease(newbackup);
677 }
678 CFReleaseSafe(passcode);
679 }
680 CFReleaseNull(keybag);
681 }
682 CFReleaseSafe(oldbackup);
683 }
684 }
685 break;
686 }
687 case sec_keychain_restore_syncable_id:
688 {
689 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
690 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
691 if (backup) {
692 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
693 if (keybag) {
694 CFDataRef passcode = NULL;
695 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
696 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
697 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
698 CFReleaseSafe(passcode);
699 }
700 CFReleaseNull(keybag);
701 }
702 CFReleaseNull(backup);
703 }
704 }
705 break;
706 }
707 case sec_item_backup_copy_names_id:
708 {
709 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
710 CFArrayRef names = SecServerItemBackupCopyNames(&error);
711 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
712 CFReleaseSafe(names);
713 }
714 break;
715 }
716 case sec_item_backup_ensure_copy_view_id:
717 {
718 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
719 CFStringRef viewName = NULL;
720 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyString, &viewName, &error)) {
721 CFStringRef name = SecServerItemBackupEnsureCopyView(viewName, &error);
722 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, name, &error);
723 CFReleaseNull(name);
724 }
725 }
726 break;
727 }
728 case sec_item_backup_handoff_fd_id:
729 {
730 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
731 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
732 int fd = -1;
733 if (backupName) {
734 fd = SecServerItemBackupHandoffFD(backupName, &error);
735 CFRelease(backupName);
736 }
737 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
738 if (fd != -1)
739 close(fd);
740 }
741 break;
742 }
743 case sec_item_backup_set_confirmed_manifest_id:
744 {
745 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
746 CFDataRef keybagDigest = NULL;
747 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
748 CFDataRef manifest = NULL;
749 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
750 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
751 if (backupName) {
752 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
753 CFRelease(backupName);
754 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
755 }
756 CFReleaseSafe(manifest);
757 }
758 }
759 CFReleaseNull(keybagDigest);
760 }
761 break;
762 }
763 case sec_item_backup_restore_id:
764 {
765 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
766 bool result = false;
767 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
768 if (backupName) {
769 CFStringRef peerID = NULL;
770 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
771 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
772 if (keybag) {
773 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
774 if (secret) {
775 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
776 if (backup) {
777 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
778 CFRelease(backup);
779 }
780 CFRelease(secret);
781 }
782 CFRelease(keybag);
783 }
784 CFReleaseSafe(peerID);
785 }
786 CFRelease(backupName);
787 }
788 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
789 }
790 break;
791 }
792 case sec_add_shared_web_credential_id:
793 {
794 #if SHAREDWEBCREDENTIALS
795 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
796 if (query) {
797 CFTypeRef result = NULL;
798
799 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
800 if (_SecAddSharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
801 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
802 CFReleaseNull(result);
803 }
804 CFReleaseSafe(appID);
805 CFReleaseNull(query);
806 }
807 #else
808 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, kCFBooleanFalse, &error);
809 #endif
810 break;
811 }
812 case sec_copy_shared_web_credential_id:
813 {
814 #if SHAREDWEBCREDENTIALS
815 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
816 if (query) {
817 CFTypeRef result = NULL;
818 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
819 if (_SecCopySharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
820 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
821 CFReleaseNull(result);
822 }
823 CFReleaseSafe(appID);
824 CFReleaseNull(query);
825 }
826 #else
827 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, kCFBooleanFalse, &error);
828 #endif
829 break;
830 }
831 case sec_get_log_settings_id:
832 {
833 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
834 if (currentList) {
835 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
836 }
837 CFReleaseSafe(currentList);
838 break;
839 }
840 case sec_set_xpc_log_settings_id:
841 {
842 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
843 if (newSettings) {
844 SecSetXPCLogSettings_Server(newSettings, &error);
845 }
846 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
847 CFReleaseNull(newSettings);
848 break;
849 }
850 case sec_set_circle_log_settings_id:
851 {
852 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
853 if (newSettings) {
854 SecSetCircleLogSettings_Server(newSettings, &error);
855 }
856 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
857 CFReleaseNull(newSettings);
858 break;
859 }
860 case sec_otr_session_create_remote_id:
861 {
862 CFDataRef publicPeerId = NULL;
863 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
864 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
865 if (otrSession) {
866 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
867 CFReleaseNull(otrSession);
868 }
869 CFReleaseSafe(publicPeerId);
870 }
871 break;
872 }
873 case sec_otr_session_process_packet_remote_id:
874 {
875 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
876 bool readyForMessages = false;
877 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
878 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
879 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
880 if (result) {
881 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
882 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
883 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
884 CFReleaseNull(outputSessionData);
885 CFReleaseNull(outputPacket);
886 }
887 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
888
889 CFReleaseSafe(inputPacket);
890 }
891 CFReleaseSafe(sessionData);
892 }
893 break;
894 }
895 case kSecXPCOpTryUserCredentials:
896 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
897 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
898 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
899 SOSCCTryUserCredentials_Server(label, password, dsid, &error));
900 });
901 }
902 break;
903 case kSecXPCOpSetUserCredentials:
904 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
905 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
906 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
907 SOSCCSetUserCredentials_Server(label, password, &error));
908 });
909 }
910 break;
911 case kSecXPCOpSetUserCredentialsAndDSID:
912 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
913 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
914 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
915 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
916 });
917 }
918 break;
919 case kSecXPCOpView:
920 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
921 with_view_and_action(event, ^(CFStringRef view, uint64_t actionCode) {
922 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
923 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
924 });
925 }
926 break;
927 case kSecXPCOpViewSet:
928 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
929 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
930 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
931 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
932 CFReleaseNull(enabledViews);
933 CFReleaseNull(disabledViews);
934 }
935 break;
936 case kSecXPCOpCanAuthenticate:
937 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
938 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
939 SOSCCCanAuthenticate_Server(&error));
940 }
941 break;
942 case kSecXPCOpPurgeUserCredentials:
943 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
944 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
945 SOSCCPurgeUserCredentials_Server(&error));
946 }
947 break;
948 case kSecXPCOpDeviceInCircle:
949 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
950 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
951 SOSCCThisDeviceIsInCircle_Server(&error));
952 }
953 break;
954 case kSecXPCOpRequestToJoin:
955 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
956 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
957 SOSCCRequestToJoinCircle_Server(&error));
958 }
959 break;
960 case kSecXPCOpAccountHasPublicKey:
961 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
962 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
963 SOSCCAccountHasPublicKey_Server(&error));
964 }
965 break;
966
967 case kSecXPCOpRequestToJoinAfterRestore:
968 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
969 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
970 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
971 }
972 break;
973 case kSecXPCOpRequestDeviceID:
974 case kSecXPCOpSetDeviceID:
975 case kSecXPCOpHandleIDSMessage:
976 case kSecXPCOpSyncWithIDSPeer:
977 case kSecXPCOpSendIDSMessage:
978 case kSecXPCOpPingTest:
979 case kSecXPCOpIDSDeviceID:
980 case kSecXPCOpSyncWithKVSPeerIDOnly:{
981 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyError, errSecUnimplemented);
982 }
983 break;
984 case kSecXPCOpAccountSetToNew:
985 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
986 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
987 }
988 break;
989 case kSecXPCOpResetToOffering:
990 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
991 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
992 SOSCCResetToOffering_Server(&error));
993 }
994 break;
995 case kSecXPCOpResetToEmpty:
996 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
997 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
998 SOSCCResetToEmpty_Server(&error));
999 }
1000 break;
1001 case kSecXPCOpRemoveThisDeviceFromCircle:
1002 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1003 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1004 SOSCCRemoveThisDeviceFromCircle_Server(&error));
1005 }
1006 break;
1007 case kSecXPCOpRemovePeersFromCircle:
1008 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1009 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error);
1010 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1011 SOSCCRemovePeersFromCircle_Server(applicants, &error));
1012 CFReleaseNull(applicants);
1013 }
1014 break;
1015 case kSecXPCOpLoggedIntoAccount:
1016 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1017 SOSCCNotifyLoggedIntoAccount_Server();
1018 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1019 true);
1020 }
1021 break;
1022 case kSecXPCOpLoggedOutOfAccount:
1023 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1024 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1025 SOSCCLoggedOutOfAccount_Server(&error));
1026 }
1027 break;
1028 case kSecXPCOpAcceptApplicants:
1029 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1030 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfoArray);
1031 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1032 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1033 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1034 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
1035 CFReleaseSafe(applicants);
1036 }
1037 break;
1038 case kSecXPCOpRejectApplicants:
1039 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1040 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfoArray);
1041 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1042 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1043 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1044 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1045 CFReleaseSafe(applicants);
1046 }
1047 break;
1048 case kSecXPCOpSetNewPublicBackupKey:
1049 {
1050 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1051 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1052 if (publicBackupKey != NULL) {
1053 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1054 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1055 CFReleaseNull(peerInfo);
1056 if (peerInfoData) {
1057 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1058 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1059 xpc_release(xpc_object);
1060 }
1061 CFReleaseNull(peerInfoData);
1062 CFReleaseSafe(publicBackupKey);
1063 }
1064 }
1065 }
1066 break;
1067 case kSecXPCOpRegisterRecoveryPublicKey:
1068 {
1069 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1070 CFDataRef recovery_key = SecXPCDictionaryCopyData(event, kSecXPCKeyRecoveryPublicKey, &error);
1071 if (recovery_key != NULL) {
1072 uint8_t zero = 0;
1073 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1); // token we send if we really wanted to send NULL
1074 if(CFEqual(recovery_key, nullData)) {
1075 CFReleaseNull(recovery_key);
1076 }
1077 CFReleaseNull(nullData);
1078 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRegisterRecoveryPublicKey_Server(recovery_key, &error));
1079 CFReleaseNull(recovery_key);
1080 }
1081 }
1082 }
1083 break;
1084 case kSecXPCOpGetRecoveryPublicKey:
1085 {
1086 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1087 xpc_object_t xpc_recovery_object = NULL;
1088 CFDataRef recovery = SOSCCCopyRecoveryPublicKey(&error);
1089 if(recovery)
1090 xpc_recovery_object = _CFXPCCreateXPCObjectFromCFObject(recovery);
1091
1092 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_recovery_object);
1093 CFReleaseNull(recovery);
1094 }
1095 }
1096 break;
1097 case kSecXPCOpSetBagForAllSlices:
1098 {
1099 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1100 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); // NULL checked below
1101 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0); // false is ok, so it's safe for this paramter to be unset or incorrect type
1102 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1103 CFReleaseSafe(backupSlice);
1104 }
1105 }
1106 break;
1107 case kSecXPCOpCopyApplicantPeerInfo:
1108 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1109 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1110 SOSCCCopyApplicantPeerInfo_Server(&error),
1111 &error);
1112 }
1113 break;
1114 case kSecXPCOpCopyValidPeerPeerInfo:
1115 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1116 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1117 SOSCCCopyValidPeerPeerInfo_Server(&error),
1118 &error);
1119 }
1120 break;
1121 case kSecXPCOpValidateUserPublic:
1122 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1123 bool trusted = SOSCCValidateUserPublic_Server(&error);
1124 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1125 }
1126 break;
1127 case kSecXPCOpCopyNotValidPeerPeerInfo:
1128 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1129 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1130 SOSCCCopyNotValidPeerPeerInfo_Server(&error),
1131 &error);
1132 }
1133 break;
1134 case kSecXPCOpCopyGenerationPeerInfo:
1135 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1136 xpc_dictionary_set_and_consume_CFArray(replyMessage, kSecXPCKeyResult,
1137 SOSCCCopyGenerationPeerInfo_Server(&error));
1138 }
1139 break;
1140 case kSecXPCOpCopyRetirementPeerInfo:
1141 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1142 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1143 SOSCCCopyRetirementPeerInfo_Server(&error),
1144 &error);
1145 }
1146 break;
1147 case kSecXPCOpCopyViewUnawarePeerInfo:
1148 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1149 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1150 SOSCCCopyViewUnawarePeerInfo_Server(&error),
1151 &error);
1152 }
1153 break;
1154 case kSecXPCOpCopyEngineState:
1155 {
1156 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1157 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
1158 CFDataRef derData = NULL;
1159
1160 require_quiet(array, done);
1161 derData = CFPropertyListCreateDERData(kCFAllocatorDefault, array, &error);
1162
1163 require_quiet(derData, done);
1164 xpc_dictionary_set_data(replyMessage, kSecXPCKeyResult, CFDataGetBytePtr(derData),CFDataGetLength(derData));
1165 done:
1166 CFReleaseNull(derData);
1167 CFReleaseNull(array);
1168 }
1169 }
1170 break;
1171 case kSecXPCOpCopyPeerPeerInfo:
1172 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1173 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1174 SOSCCCopyPeerPeerInfo_Server(&error),
1175 &error);
1176 }
1177 break;
1178 case kSecXPCOpCopyConcurringPeerPeerInfo:
1179 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1180 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1181 SOSCCCopyConcurringPeerPeerInfo_Server(&error),
1182 &error);
1183 }
1184 break;
1185 case kSecXPCOpCopyMyPeerInfo:
1186 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1187 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1188 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1189 CFReleaseNull(peerInfo);
1190 if (peerInfoData) {
1191 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1192 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1193 xpc_release(xpc_object);
1194 }
1195 CFReleaseNull(peerInfoData);
1196 }
1197 break;
1198 case kSecXPCOpGetLastDepartureReason:
1199 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1200 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1201 SOSCCGetLastDepartureReason_Server(&error));
1202 }
1203 break;
1204 case kSecXPCOpSetLastDepartureReason:
1205 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1206 // 0 is a legitimate reason (kSOSDepartureReasonError), so it's safe for this parameter to be unset or incorrect type
1207 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1208 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1209 SOSCCSetLastDepartureReason_Server(reason, &error));
1210 }
1211 break;
1212 case kSecXPCOpProcessSyncWithPeers:
1213 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
1214 CFSetRef peers = SecXPCDictionaryCopySet(event, kSecXPCKeySet, &error);
1215 CFSetRef backupPeers = SecXPCDictionaryCopySet(event, kSecXPCKeySet2, &error);
1216 if (peers && backupPeers) {
1217 CFSetRef result = SOSCCProcessSyncWithPeers_Server(peers, backupPeers, &error);
1218 if (result) {
1219 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
1220 }
1221 CFReleaseNull(result);
1222 }
1223 CFReleaseNull(peers);
1224 CFReleaseNull(backupPeers);
1225 }
1226 break;
1227 case kSecXPCOpProcessSyncWithAllPeers:
1228 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
1229 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1230 SOSCCProcessSyncWithAllPeers_Server(&error));
1231 }
1232 break;
1233 case soscc_EnsurePeerRegistration_id:
1234 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
1235 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1236 SOSCCProcessEnsurePeerRegistration_Server(&error));
1237 }
1238 break;
1239 case kSecXPCOpRollKeys:
1240 {
1241 // false is valid, so it's safe for this parameter to be unset or incorrect type
1242 bool force = xpc_dictionary_get_bool(event, "force");
1243 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1244 _SecServerRollKeys(force, &client, &error));
1245 }
1246 break;
1247 case kSecXPCOpWaitForInitialSync:
1248 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1249 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1250 SOSCCWaitForInitialSync_Server(&error));
1251 }
1252 break;
1253 case kSecXPCOpPeersHaveViewsEnabled:
1254 {
1255 CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error);
1256 if (viewSet) {
1257 CFBooleanRef result = SOSCCPeersHaveViewsEnabled_Server(viewSet, &error);
1258 if (result != NULL) {
1259 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result != kCFBooleanFalse);
1260 }
1261 }
1262 CFReleaseNull(viewSet);
1263 }
1264 break;
1265
1266 case kSecXPCOpWhoAmI:
1267 {
1268 if (client.musr)
1269 xpc_dictionary_set_data(replyMessage, "musr", CFDataGetBytePtr(client.musr), CFDataGetLength(client.musr));
1270 xpc_dictionary_set_bool(replyMessage, "system-keychain", client.allowSystemKeychain);
1271 xpc_dictionary_set_bool(replyMessage, "syncbubble-keychain", client.allowSyncBubbleKeychain);
1272 xpc_dictionary_set_bool(replyMessage, "network-extension", client.isNetworkExtension);
1273 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1274 }
1275 break;
1276 case kSecXPCOpTransmogrifyToSyncBubble:
1277 {
1278 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainSyncBubble, &error)) {
1279 #if TARGET_OS_IOS
1280 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1281 CFArrayRef services = SecXPCDictionaryCopyArray(event, "services", &error);
1282 bool res = false;
1283 if (uid && services) {
1284 res = _SecServerTransmogrifyToSyncBubble(services, uid, &client, &error);
1285 }
1286 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1287 CFReleaseNull(services);
1288 #else
1289 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1290 #endif
1291 }
1292 }
1293 break;
1294 case kSecXPCOpTransmogrifyToSystemKeychain:
1295 {
1296 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
1297 #if TARGET_OS_IOS
1298 bool res = _SecServerTransmogrifyToSystemKeychain(&client, &error);
1299 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1300 #else
1301 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1302 #endif
1303
1304 }
1305 }
1306 break;
1307 case kSecXPCOpDeleteUserView:
1308 {
1309 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
1310 bool res = false;
1311 #if TARGET_OS_IOS
1312 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1313 if (uid) {
1314 res = _SecServerDeleteMUSERViews(&client, uid, &error);
1315 }
1316 #endif
1317 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1318
1319 }
1320 }
1321 break;
1322 case kSecXPCOpCopyApplication:
1323 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1324 SOSPeerInfoRef peerInfo = SOSCCCopyApplication_Server(&error);
1325 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1326 CFReleaseNull(peerInfo);
1327 if (peerInfoData) {
1328 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1329 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1330 xpc_release(xpc_object);
1331 }
1332 CFReleaseNull(peerInfoData);
1333 }
1334 break;
1335 case kSecXPCOpCopyCircleJoiningBlob:
1336 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1337 CFDataRef appBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error);
1338 if (appBlob != NULL) {
1339 SOSPeerInfoRef applicant = SOSPeerInfoCreateFromData(kCFAllocatorDefault, &error, appBlob);
1340 if (applicant != NULL) {
1341 CFDataRef pbblob = SOSCCCopyCircleJoiningBlob_Server(applicant, &error);
1342 if (pbblob) {
1343 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(pbblob);
1344 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1345 xpc_release(xpc_object);
1346 }
1347 CFReleaseNull(pbblob);
1348 CFReleaseNull(applicant);
1349 }
1350 CFReleaseNull(appBlob);
1351 }
1352 }
1353 break;
1354 case kSecXPCOpCopyInitialSyncBlob:
1355 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1356 uint64_t flags = xpc_dictionary_get_uint64(event, kSecXPCKeyFlags); // 0 is a valid flags, so no error checking
1357 CFDataRef initialblob = SOSCCCopyInitialSyncData_Server((uint32_t)flags, &error);
1358 if (initialblob) {
1359 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(initialblob);
1360 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1361 xpc_release(xpc_object);
1362 }
1363 CFReleaseNull(initialblob);
1364 }
1365 break;
1366 case kSecXPCOpJoinWithCircleJoiningBlob:
1367 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1368 CFDataRef joiningBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error); // NULL checked below
1369 uint64_t version = xpc_dictionary_get_uint64(event, kSecXPCVersion); // 0 is valid, so this parameter can be unset or incorrect type
1370 if (joiningBlob != NULL) {
1371 bool retval = SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob, (PiggyBackProtocolVersion) version, &error);
1372 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1373 CFReleaseNull(joiningBlob);
1374 }
1375 }
1376 break;
1377 case kSecXPCOpKVSKeyCleanup:
1378 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1379 bool retval = SOSCCCleanupKVSKeys_Server(&error);
1380 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1381 }
1382 break;
1383 case kSecXPCOpMessageFromPeerIsPending:
1384 {
1385 SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error);
1386 if (peer) {
1387 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1388 SOSCCMessageFromPeerIsPending_Server(peer, &error));
1389 }
1390 CFReleaseNull(peer);
1391 break;
1392 }
1393 case kSecXPCOpSendToPeerIsPending:
1394 {
1395 SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error);
1396 if (peer) {
1397 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1398 SOSCCSendToPeerIsPending(peer, &error));
1399 }
1400 CFReleaseNull(peer);
1401 break;
1402 }
1403 #endif /* !SECUREOBJECTSYNC */
1404 case sec_delete_items_with_access_groups_id:
1405 {
1406 bool retval = false;
1407 #if TARGET_OS_IPHONE
1408 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateUninstallDeletion, &error)) {
1409 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1410
1411 if (accessGroups) {
1412 retval = _SecItemServerDeleteAllWithAccessGroups(accessGroups, &client, &error);
1413 }
1414 CFReleaseNull(accessGroups);
1415 }
1416 #endif
1417 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1418 }
1419 break;
1420 case kSecXPCOpBackupKeybagAdd: {
1421 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementBackupTableOperations, &error)) {
1422 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1423 }
1424 break;
1425 }
1426 case kSecXPCOpBackupKeybagDelete: {
1427 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementBackupTableOperations, &error)) {
1428 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1429 }
1430 break;
1431 }
1432 case kSecXPCOpKeychainControlEndpoint: {
1433 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainControl, &error)) {
1434 xpc_endpoint_t endpoint = SecServerCreateKeychainControlEndpoint();
1435 if (endpoint) {
1436 xpc_dictionary_set_value(replyMessage, kSecXPCKeyEndpoint, endpoint);
1437 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1438 xpc_release(endpoint);
1439 } else {
1440 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1441 }
1442 }
1443 break;
1444 }
1445 case sec_item_copy_parent_certificates_id: {
1446 CFArrayRef results = NULL;
1447 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateCertificateAllAccess, &error)) {
1448 CFDataRef issuer = SecXPCDictionaryCopyData(event, kSecXPCKeyNormalizedIssuer, &error);
1449 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1450 if (issuer && accessGroups) {
1451 results = _SecItemCopyParentCertificates(issuer, accessGroups, &error);
1452 }
1453 CFReleaseNull(issuer);
1454 CFReleaseNull(accessGroups);
1455 }
1456 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, results, &error);
1457 CFReleaseNull(results);
1458 break;
1459 }
1460 case sec_item_certificate_exists_id: {
1461 bool result = false;
1462 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateCertificateAllAccess, &error)) {
1463 CFDataRef issuer = SecXPCDictionaryCopyData(event, kSecXPCKeyNormalizedIssuer, &error);
1464 CFDataRef serialNum = SecXPCDictionaryCopyData(event, kSecXPCKeySerialNumber, &error);
1465 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1466 if (issuer && serialNum && accessGroups) {
1467 result = _SecItemCertificateExists(issuer, serialNum, accessGroups, &error);
1468 }
1469 CFReleaseNull(issuer);
1470 CFReleaseNull(serialNum);
1471 CFReleaseNull(accessGroups);
1472 }
1473 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1474 break;
1475 }
1476 default:
1477 break;
1478 }
1479
1480 if (error)
1481 {
1482 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
1483 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1484 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
1485 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1486 else
1487 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1488
1489 xpcError = SecCreateXPCObjectWithCFError(error);
1490 if (replyMessage) {
1491 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1492 }
1493 } else if (replyMessage) {
1494 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
1495 }
1496 } else {
1497 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
1498 secerror("%@: returning error: %@", client.task, error);
1499 xpcError = SecCreateXPCObjectWithCFError(error);
1500 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
1501 }
1502
1503 if (replyMessage) {
1504 xpc_connection_send_message(connection, replyMessage);
1505 xpc_release(replyMessage);
1506 }
1507 if (xpcError) {
1508 xpc_release(xpcError);
1509 }
1510 CFReleaseSafe(error);
1511 CFReleaseSafe(client.accessGroups);
1512 CFReleaseSafe(client.musr);
1513 CFReleaseSafe(client.task);
1514 CFReleaseNull(client.applicationIdentifier);
1515 CFReleaseSafe(domains);
1516 CFReleaseSafe(clientAuditToken);
1517 }
1518
1519 static void securityd_xpc_init(const char *service_name)
1520 {
1521 secdebug("serverxpc", "start");
1522 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1523 if (!listener) {
1524 seccritical("security failed to register xpc listener for %s, exiting", service_name);
1525 abort();
1526 }
1527
1528 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1529 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1530 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1531 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
1532 // Synchronous. The client has a connection pool so they can be somewhat re-entrant if they need.
1533 securityd_xpc_dictionary_handler(connection, event);
1534 }
1535 });
1536 xpc_connection_resume(connection);
1537 }
1538 });
1539 xpc_connection_resume(listener);
1540
1541 #if OCTAGON
1542 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) {
1543 xpc_activity_state_t activityState = xpc_activity_get_state(activity);
1544 if (activityState == XPC_ACTIVITY_STATE_RUN) {
1545 SecCKKS24hrNotification();
1546 SecOctagon24hrNotification();
1547 }
1548 });
1549 #endif
1550
1551 xpc_activity_register("com.apple.securityd.prng", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) {
1552 xpc_activity_state_t state = xpc_activity_get_state(activity);
1553 if (state == XPC_ACTIVITY_STATE_RUN) {
1554 refresh_prng();
1555 }
1556 });
1557
1558 #if OCTAGON && !TARGET_OS_BRIDGE
1559 // Kick off reporting tasks.
1560 if (os_variant_has_internal_diagnostics("com.apple.security") && !os_variant_is_recovery("securityd")) {
1561 InitPolicyReporter();
1562 }
1563 #endif
1564 }
1565
1566
1567 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1568
1569 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE
1570 static void securityd_soscc_lock_hack() {
1571 dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
1572 int soscc_tok;
1573
1574 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1575 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1576 // this code will need to be generalized / migrated away from just this specific purpose.
1577 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) {
1578 char *event_description = xpc_copy_description(object);
1579 secnotice("events", "%s", event_description);
1580 free(event_description);
1581 });
1582
1583 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1584 notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) {
1585 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1586 CFErrorRef error = NULL;
1587
1588 uint64_t one_minute = 60ull;
1589 if(SecAKSUserKeybagHoldLockAssertion(one_minute, &error)){
1590 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1591 os_transaction_t transaction = os_transaction_create("securityd-LockAssertedingHolder");
1592
1593 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, one_minute*NSEC_PER_SEC), soscc_lock_queue, ^{
1594 CFErrorRef localError = NULL;
1595 if(!SecAKSUserKeybagDropLockAssertion(&localError))
1596 secerror("failed to unlock: %@", localError);
1597 CFReleaseNull(localError);
1598 os_release(transaction);
1599 });
1600 } else {
1601 secerror("Failed to take device lock assertion: %@", error);
1602 }
1603 CFReleaseNull(error);
1604 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1605 });
1606 }
1607 #endif
1608
1609 #if TARGET_OS_OSX
1610
1611 static char *
1612 homedirPath(void)
1613 {
1614 static char homeDir[PATH_MAX] = {};
1615
1616 if (homeDir[0] == '\0') {
1617 struct passwd* pwd = getpwuid(getuid());
1618 if (pwd == NULL)
1619 return NULL;
1620
1621 if (realpath(pwd->pw_dir, homeDir) == NULL) {
1622 strlcpy(homeDir, pwd->pw_dir, sizeof(homeDir));
1623 }
1624 }
1625 return homeDir;
1626 }
1627 #endif
1628
1629
1630 int main(int argc, char *argv[])
1631 {
1632 DisableLocalization();
1633
1634 char *wait4debugger = getenv("WAIT4DEBUGGER");
1635 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1636 seccritical("SIGSTOPing self, awaiting debugger");
1637 kill(getpid(), SIGSTOP);
1638 seccritical("Again, for good luck (or bad debuggers)");
1639 kill(getpid(), SIGSTOP);
1640 }
1641
1642 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1643 Secd doesn't realize DB connections get invalidated when network home directory users logout
1644 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1645 */
1646 #if TARGET_OS_OSX
1647 int sessionstatechanged_tok;
1648 notify_register_dispatch(kSA_SessionStateChangedNotification, &sessionstatechanged_tok, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token __unused) {
1649 // we could be a process running as root.
1650 // However, since root never logs out this isn't an issue.
1651 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn) {
1652 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1653 xpc_transaction_exit_clean();
1654 });
1655 }
1656 });
1657 #endif
1658
1659 signal(SIGTERM, SIG_IGN);
1660 static dispatch_source_t termSource;
1661 termSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0));
1662 dispatch_source_set_event_handler(termSource, ^{
1663 secnotice("signal", "SIGTERM, exiting when clean ✌️");
1664 xpc_transaction_exit_clean();
1665 });
1666 dispatch_activate(termSource);
1667
1668 #if TARGET_OS_OSX
1669 #define SECD_PROFILE_NAME "com.apple.secd"
1670 const char *homedir = homedirPath();
1671 if (homedir == NULL) {
1672 errx(1, "failed to get home directory for secd");
1673 }
1674
1675 char *errorbuf = NULL;
1676 const char *sandbox_params[] = {"_HOME", homedir, NULL};
1677 int32_t rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf);
1678 if (rc) {
1679 errx(1, "Failed to instantiate sandbox: %d %s", rc, errorbuf);
1680 /* errx will quit the process */
1681 }
1682 #endif /* TARGET_OS_OSX */
1683
1684 const char *serviceName = kSecuritydXPCServiceName;
1685
1686 // Mark our interest in running some features (before we bring the DB layer up)
1687 #if OCTAGON
1688 EscrowRequestServerSetEnabled(true);
1689 OctagonSetShouldPerformInitialization(true);
1690 SecCKKSEnable();
1691 #endif
1692
1693 /* setup SQDLite before some other component have a chance to create a database connection */
1694 _SecDbServerSetup();
1695
1696 securityd_init_server();
1697 securityd_xpc_init(serviceName);
1698 SecCreateSecuritydXPCServer();
1699
1700 #if SECUREOBJECTSYNC
1701 SOSControlServerInitialize();
1702 #endif
1703
1704 #if OCTAGON
1705 CKKSControlServerInitialize();
1706 OctagonControlServerInitialize();
1707 EscrowRequestXPCServerInitialize();
1708 #endif
1709
1710 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1711 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE
1712 securityd_soscc_lock_hack();
1713 #endif
1714
1715 CFRunLoopRun();
1716 }
1717
1718 /* vi:set ts=4 sw=4 et: */