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