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