]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSCloudCircle.m
Security-59306.101.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSCloudCircle.m
1 /*
2 * Copyright (c) 2012-2014 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 //
25 // SOSCloudCircle.m
26 //
27
28 #import <Foundation/Foundation.h>
29 #import <Foundation/NSXPCConnection_Private.h>
30
31 #include <stdio.h>
32 #include <AssertMacros.h>
33 #include "keychain/SecureObjectSync/SOSCloudCircle.h"
34 #include "keychain/SecureObjectSync/SOSCloudCircleInternal.h"
35 #include "keychain/SecureObjectSync/SOSCircle.h"
36 #include "keychain/SecureObjectSync/SOSAccount.h"
37 #include "keychain/SecureObjectSync/SOSFullPeerInfo.h"
38 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
39 #include "keychain/SecureObjectSync/SOSInternal.h"
40 #include "keychain/SecureObjectSync/SOSRing.h"
41 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
42 #include <Security/SecureObjectSync/SOSViews.h>
43 #include "keychain/SecureObjectSync/SOSControlHelper.h"
44 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
45
46 #include <Security/SecKeyPriv.h>
47 #include <Security/SecFramework.h>
48 #include <CoreFoundation/CFXPCBridge.h>
49
50 #include "keychain/securityd/SecItemServer.h"
51
52 #include <utilities/SecDispatchRelease.h>
53 #include <utilities/SecCFRelease.h>
54 #include <utilities/SecCFWrappers.h>
55 #include <utilities/SecXPCError.h>
56
57 #include <corecrypto/ccsha2.h>
58
59 #include <utilities/debugging.h>
60
61 #include <CoreFoundation/CoreFoundation.h>
62
63 #include <xpc/xpc.h>
64 #define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
65 #include <ipc/securityd_client.h>
66 #include "keychain/securityd/spi.h"
67
68 #include <Security/SecuritydXPC.h>
69
70 const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged";
71 const char * kSOSCCViewMembershipChangedNotification = "com.apple.security.secureobjectsync.viewschanged";
72 const char * kSOSCCInitialSyncChangedNotification = "com.apple.security.secureobjectsync.initialsyncchanged";
73 const char * kSOSCCHoldLockForInitialSync = "com.apple.security.secureobjectsync.holdlock";
74 const char * kSOSCCPeerAvailable = "com.apple.security.secureobjectsync.peeravailable";
75 const char * kSOSCCRecoveryKeyChanged = "com.apple.security.secureobjectsync.recoverykeychanged";
76 const char * kSOSCCCircleOctagonKeysChangedNotification = "com.apple.security.sosoctagonbitschanged";
77
78 #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
79
80 static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
81 {
82 xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
83
84 return value && (xpc_get_type(value) == type);
85 }
86
87 SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error)
88 {
89 SOSCCStatus retval = SOSGetCachedCircleStatus(error);
90 if(retval != kSOSNoCachedValue) {
91 secdebug("circleOps", "Retrieved cached circle value %d", retval);
92 return retval;
93 }
94 return SOSCCThisDeviceIsInCircleNonCached(error);
95 }
96
97
98 SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error)
99 {
100 sec_trace_enter_api(NULL);
101 sec_trace_return_api(SOSCCStatus, ^{
102 SOSCCStatus result = kSOSCCError;
103
104 do_if_registered(soscc_ThisDeviceIsInCircle, error);
105
106 xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error);
107 if (message) {
108 xpc_object_t response = securityd_message_with_reply_sync(message, error);
109
110 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
111 result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
112 } else {
113 result = kSOSCCError;
114 }
115
116 if (result < 0) {
117 if (response && securityd_message_no_error(response, error))
118 {
119 char *desc = xpc_copy_description(response);
120 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc);
121 free((void *)desc);
122 }
123 }
124 }
125 secnotice("circleOps", "Retrieved non-cached circle value %d", result);
126
127 return result;
128 }, CFSTR("SOSCCStatus=%d"))
129 }
130
131 static bool sfsigninanalytics_bool_error_request(enum SecXPCOperation op, CFDataRef parentEvent, CFErrorRef* error)
132 {
133 __block bool result = false;
134
135 secdebug("sosops","enter - operation: %d", op);
136 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
137 return SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
138 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
139 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
140 return result;
141 });
142 return result;
143 }
144
145 static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
146 {
147 __block bool result = false;
148
149 secdebug("sosops","enter - operation: %d", op);
150 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
151 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
152 return result;
153 });
154 return result;
155 }
156
157 static bool SecXPCDictionarySetPeerInfoData(xpc_object_t message, const char *key, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
158 bool success = false;
159 CFDataRef peerData = SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, error);
160 if (peerData) {
161 success = SecXPCDictionarySetData(message, key, peerData, error);
162 }
163 CFReleaseNull(peerData);
164 return success;
165 }
166
167 static bool peer_info_to_bool_error_request(enum SecXPCOperation op, SOSPeerInfoRef peerInfo, CFErrorRef* error)
168 {
169 __block bool result = false;
170
171 secdebug("sosops","enter - operation: %d", op);
172 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
173 return SecXPCDictionarySetPeerInfoData(message, kSecXPCKeyPeerInfo, peerInfo, error);
174 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
175 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
176 return result;
177 });
178 return result;
179 }
180
181 static CFBooleanRef cfarray_to_cfboolean_error_request(enum SecXPCOperation op, CFArrayRef views, CFErrorRef* error)
182 {
183 __block bool result = false;
184
185 secdebug("sosops","enter - operation: %d", op);
186 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
187 return SecXPCDictionarySetPList(message, kSecXPCKeyArray, views, error);
188 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
189 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
190 return true;
191 });
192 return noError ? (result ? kCFBooleanTrue : kCFBooleanFalse) : NULL;
193 }
194
195
196 static CFSetRef cfset_cfset_to_cfset_error_request(enum SecXPCOperation op, CFSetRef set1, CFSetRef set2, CFErrorRef* error)
197 {
198 __block CFSetRef result = NULL;
199
200 secdebug("sosops","enter - operation: %d", op);
201 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
202 return SecXPCDictionarySetPList(message, kSecXPCKeySet, set1, error) && SecXPCDictionarySetPList(message, kSecXPCKeySet2, set2, error);
203 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
204 result = SecXPCDictionaryCopySet(response, kSecXPCKeyResult, error);
205 return result;
206 });
207
208 if (!noError) {
209 CFReleaseNull(result);
210 }
211 return result;
212 }
213
214 static CF_RETURNS_RETAINED CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
215 {
216 __block CFArrayRef result = NULL;
217
218 secdebug("sosops","enter - operation: %d", op);
219 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
220 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
221 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
222 return result != NULL;
223 })) {
224 if (!isArray(result)) {
225 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
226 CFReleaseNull(result);
227 }
228 }
229 return result;
230 }
231
232 static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
233 {
234 __block CFArrayRef result = NULL;
235
236 secdebug("sosops","enter - operation: %d", op);
237 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
238 size_t length = 0;
239 const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length);
240 der_decode_plist(kCFAllocatorDefault, 0, (CFPropertyListRef*) &result, error, bytes, bytes + length);
241
242 return result != NULL;
243 })) {
244 if (!isArray(result)) {
245 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
246 CFReleaseNull(result);
247 }
248 }
249 return result;
250 }
251
252 static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
253 {
254 __block int result = 0;
255
256 secdebug("sosops","enter - operation: %d", op);
257 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
258 int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
259 if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) {
260 result = (int)temp_result;
261 }
262 return result;
263 });
264 return result;
265 }
266
267 static CF_RETURNS_RETAINED SOSPeerInfoRef peer_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
268 {
269 SOSPeerInfoRef result = NULL;
270 __block CFDataRef data = NULL;
271
272 secdebug("sosops","enter - operation: %d", op);
273 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
274 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
275 if (response && (NULL != temp_result)) {
276 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
277 }
278 return data != NULL;
279 });
280
281 if (isData(data)) {
282 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
283 } else {
284 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
285 }
286
287 CFReleaseNull(data);
288 return result;
289 }
290
291 static CFDataRef flags_to_data_error_request(enum SecXPCOperation op, uint32_t flags, CFErrorRef *error)
292 {
293 __block CFDataRef result = NULL;
294
295 secdebug("sosops", "enter -- operation: %d", op);
296 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
297 xpc_dictionary_set_uint64(message, kSecXPCKeyFlags, flags);
298 return true;
299 }, ^bool(xpc_object_t response, CFErrorRef *error) {
300 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
301 if (response && (NULL != temp_result)) {
302 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
303 }
304 return result != NULL;
305 });
306
307 if (!isData(result)) {
308 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
309 return NULL;
310 }
311
312 return result;
313 }
314
315
316 static CFDataRef data_to_error_request(enum SecXPCOperation op, CFErrorRef *error)
317 {
318 __block CFDataRef result = NULL;
319
320 secdebug("sosops", "enter -- operation: %d", op);
321 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
322 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
323 if (response && (NULL != temp_result)) {
324 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
325 }
326 return result != NULL;
327 });
328
329 if (!isData(result)) {
330 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
331 return NULL;
332 }
333
334 return result;
335 }
336
337 static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
338 {
339 __block CFArrayRef result = NULL;
340
341 secdebug("sosops","enter - operation: %d", op);
342 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
343 xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult);
344 if (response && (NULL != encoded_array)) {
345 result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error);
346 }
347 return result != NULL;
348 });
349
350 if (!isArray(result)) {
351 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
352 CFReleaseNull(result);
353 }
354 return result;
355 }
356
357 static CF_RETURNS_RETAINED SOSPeerInfoRef data_to_peer_info_error_request(enum SecXPCOperation op, CFDataRef secret, CFErrorRef* error)
358 {
359 __block SOSPeerInfoRef result = false;
360 __block CFDataRef data = NULL;
361
362 secdebug("sosops", "enter - operation: %d", op);
363 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
364 xpc_object_t xsecretData = _CFXPCCreateXPCObjectFromCFObject(secret);
365 bool success = false;
366 if (xsecretData){
367 xpc_dictionary_set_value(message, kSecXPCKeyNewPublicBackupKey, xsecretData);
368 success = true;
369 xsecretData = nil;
370 }
371 return success;
372 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
373 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
374 if (response && (NULL != temp_result)) {
375 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
376 }
377 return data != NULL;
378 });
379
380 if (isData(data)) {
381 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
382 } else {
383 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
384 }
385
386 CFReleaseNull(data);
387 return result;
388 }
389
390 static bool keybag_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, bool include, CFErrorRef* error)
391 {
392 secdebug("sosops", "enter - operation: %d", op);
393 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
394 xpc_object_t xData = _CFXPCCreateXPCObjectFromCFObject(data);
395 bool success = false;
396 if (xData){
397 xpc_dictionary_set_value(message, kSecXPCKeyKeybag, xData);
398 xData = nil;
399 success = true;
400 }
401 xpc_dictionary_set_bool(message, kSecXPCKeyIncludeV0, include);
402 return success;
403 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
404 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
405 });
406 }
407
408 static bool recovery_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, CFErrorRef* error)
409 {
410 secdebug("sosops", "enter - operation: %d", op);
411 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
412 xpc_object_t xData = NULL;
413 if(data) {
414 xData = _CFXPCCreateXPCObjectFromCFObject(data);
415 } else {
416 uint8_t zero = 0;
417 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1);
418 xData = _CFXPCCreateXPCObjectFromCFObject(nullData);
419 CFReleaseNull(nullData);
420 }
421 bool success = false;
422 if (xData){
423 xpc_dictionary_set_value(message, kSecXPCKeyRecoveryPublicKey, xData);
424 xData = nil;
425 success = true;
426 }
427 return success;
428 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
429 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
430 });
431 }
432
433 static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
434 {
435 __block bool result = false;
436
437 secdebug("sosops", "enter - operation: %d", op);
438 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
439 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
440 if (encoded_peers)
441 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
442 return encoded_peers != NULL;
443 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
444 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
445 return result;
446 });
447 return result;
448 }
449
450 static bool info_array_data_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFDataRef parentEvent, CFErrorRef* error)
451 {
452 __block bool result = false;
453
454 secdebug("sosops", "enter - operation: %d", op);
455 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
456 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
457 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
458 if (encoded_peers)
459 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
460 return encoded_peers != NULL;
461 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
462 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
463 return result;
464 });
465 return result;
466 }
467
468 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
469 uint64_t number,
470 CFErrorRef* error)
471 {
472 __block bool result = false;
473
474 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
475 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
476 return true;
477 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
478 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
479 return result;
480 });
481
482 return result;
483 }
484
485 static bool cfdata_and_int_error_request_returns_bool(enum SecXPCOperation op, CFDataRef thedata,
486 PiggyBackProtocolVersion version, CFErrorRef *error) {
487 __block bool result = false;
488
489 sec_trace_enter_api(NULL);
490 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
491 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
492 bool success = false;
493 if (xdata) {
494 xpc_dictionary_set_value(message, kSecXPCData, xdata);
495 xpc_dictionary_set_uint64(message, kSecXPCVersion, version);
496 success = true;
497 xdata = nil;
498 }
499
500 return success;
501 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
502 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
503 return (bool)true;
504 });
505
506 return result;
507 }
508
509 static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CFDataRef thedata, CFErrorRef *error) {
510 __block CFDataRef result = NULL;
511
512 sec_trace_enter_api(NULL);
513 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
514 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
515 bool success = false;
516 if (xdata) {
517 xpc_dictionary_set_value(message, kSecXPCData, xdata);
518 success = true;
519 xdata = nil;
520 }
521 return success;
522 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
523 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
524 if (response && (NULL != temp_result)) {
525 CFTypeRef object = _CFXPCCreateCFObjectFromXPCObject(temp_result);
526 result = copyIfData(object, error);
527 CFReleaseNull(object);
528 }
529 return (bool) (result != NULL);
530 });
531
532 return result;
533 }
534
535 bool SOSCCRequestToJoinCircle(CFErrorRef* error)
536 {
537 sec_trace_enter_api(NULL);
538 sec_trace_return_bool_api(^{
539 do_if_registered(soscc_RequestToJoinCircle, error);
540
541 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
542 }, NULL)
543 }
544
545 bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
546 {
547 sec_trace_enter_api(NULL);
548 sec_trace_return_bool_api(^{
549 do_if_registered(soscc_RequestToJoinCircleWithAnalytics, parentEvent, error);
550
551 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinWithAnalytics, parentEvent, error);
552 }, NULL)
553 }
554
555 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
556 {
557 sec_trace_enter_api(NULL);
558 sec_trace_return_bool_api(^{
559 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
560
561 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
562 }, NULL)
563 }
564
565 bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
566 {
567 sec_trace_enter_api(NULL);
568 sec_trace_return_bool_api(^{
569 do_if_registered(soscc_RequestToJoinCircleAfterRestoreWithAnalytics, parentEvent, error);
570
571 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, parentEvent, error);
572 }, NULL)
573 }
574
575 bool SOSCCAccountHasPublicKey(CFErrorRef *error)
576 {
577 sec_trace_enter_api(NULL);
578 sec_trace_return_bool_api(^{
579 do_if_registered(soscc_AccountHasPublicKey, error);
580
581 return simple_bool_error_request(kSecXPCOpAccountHasPublicKey, error);
582 }, NULL)
583
584 }
585
586 bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
587 {
588 sec_trace_enter_api(NULL);
589 sec_trace_return_bool_api(^{
590 do_if_registered(soscc_WaitForInitialSyncWithAnalytics, parentEvent, error);
591
592 return sfsigninanalytics_bool_error_request(kSecXPCOpWaitForInitialSyncWithAnalytics, parentEvent, error);
593 }, NULL)
594 }
595
596 bool SOSCCWaitForInitialSync(CFErrorRef* error)
597 {
598 sec_trace_enter_api(NULL);
599 sec_trace_return_bool_api(^{
600 do_if_registered(soscc_WaitForInitialSync, error);
601
602 return simple_bool_error_request(kSecXPCOpWaitForInitialSync, error);
603 }, NULL)
604 }
605
606 bool SOSCCAccountSetToNew(CFErrorRef *error)
607 {
608 secwarning("SOSCCAccountSetToNew called");
609 sec_trace_enter_api(NULL);
610 sec_trace_return_bool_api(^{
611 do_if_registered(soscc_SetToNew, error);
612 return simple_bool_error_request(kSecXPCOpAccountSetToNew, error);
613 }, NULL)
614 }
615
616 bool SOSCCResetToOffering(CFErrorRef* error)
617 {
618 secwarning("SOSCCResetToOffering called");
619 sec_trace_enter_api(NULL);
620 sec_trace_return_bool_api(^{
621 do_if_registered(soscc_ResetToOffering, error);
622
623 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
624 }, NULL)
625 }
626
627 bool SOSCCResetToEmpty(CFErrorRef* error)
628 {
629 secwarning("SOSCCResetToEmpty called");
630 sec_trace_enter_api(NULL);
631 sec_trace_return_bool_api(^{
632 do_if_registered(soscc_ResetToEmpty, error);
633
634 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
635 }, NULL)
636 }
637
638 bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
639 {
640 secwarning("SOSCCResetToEmptyWithAnalytics called");
641 sec_trace_enter_api(NULL);
642 sec_trace_return_bool_api(^{
643 do_if_registered(soscc_ResetToEmptyWithAnalytics, parentEvent, error);
644
645 return sfsigninanalytics_bool_error_request(kSecXPCOpResetToEmptyWithAnalytics, parentEvent, error);
646 }, NULL)
647 }
648 bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error)
649 {
650 sec_trace_enter_api(NULL);
651 sec_trace_return_bool_api(^{
652 do_if_registered(soscc_RemovePeersFromCircle, peers, error);
653
654 return info_array_to_bool_error_request(kSecXPCOpRemovePeersFromCircle, peers, error);
655 }, NULL)
656 }
657
658 bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error)
659 {
660 sec_trace_enter_api(NULL);
661 sec_trace_return_bool_api(^{
662 do_if_registered(soscc_RemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
663
664 return info_array_data_to_bool_error_request(kSecXPCOpRemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
665 }, NULL)
666 }
667
668 bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
669 {
670 sec_trace_enter_api(NULL);
671 sec_trace_return_bool_api(^{
672 do_if_registered(soscc_RemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
673
674 return sfsigninanalytics_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
675 }, NULL)
676 }
677
678 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
679 {
680 sec_trace_enter_api(NULL);
681 sec_trace_return_bool_api(^{
682 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
683
684 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
685 }, NULL)
686 }
687
688 bool SOSCCLoggedOutOfAccount(CFErrorRef* error)
689 {
690 sec_trace_enter_api(NULL);
691 sec_trace_return_bool_api(^{
692 do_if_registered(soscc_LoggedOutOfAccount, error);
693
694 return simple_bool_error_request(kSecXPCOpLoggedOutOfAccount, error);
695 }, NULL)
696 }
697
698 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
699 {
700 sec_trace_enter_api(NULL);
701 sec_trace_return_bool_api(^{
702 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
703
704 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
705 }, NULL)
706 }
707
708 CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
709 {
710 sec_trace_enter_api(NULL);
711 sec_trace_return_api(CFArrayRef, ^{
712 do_if_registered(soscc_CopyPeerInfo, error);
713
714 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
715 }, CFSTR("return=%@"));
716 }
717
718 CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
719 {
720 sec_trace_enter_api(NULL);
721 sec_trace_return_api(CFArrayRef, ^{
722 do_if_registered(soscc_CopyConcurringPeerInfo, error);
723
724 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
725 }, CFSTR("return=%@"));
726 }
727
728 CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error)
729 {
730 sec_trace_enter_api(NULL);
731 sec_trace_return_api(CFArrayRef, ^{
732 do_if_registered(soscc_CopyGenerationPeerInfo, error);
733
734 return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error);
735 }, CFSTR("return=%@"));
736 }
737
738 CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
739 {
740 sec_trace_enter_api(NULL);
741 sec_trace_return_api(CFArrayRef, ^{
742 do_if_registered(soscc_CopyApplicantPeerInfo, error);
743
744 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
745 }, CFSTR("return=%@"));
746 }
747
748 bool SOSCCValidateUserPublic(CFErrorRef* error){
749 sec_trace_enter_api(NULL);
750 sec_trace_return_api(bool, ^{
751 do_if_registered(soscc_ValidateUserPublic, error);
752
753 return simple_bool_error_request(kSecXPCOpValidateUserPublic, error);
754 }, NULL);
755 }
756
757 CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error)
758 {
759 sec_trace_enter_api(NULL);
760 sec_trace_return_api(CFArrayRef, ^{
761 do_if_registered(soscc_CopyValidPeerPeerInfo, error);
762
763 return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error);
764 }, CFSTR("return=%@"));
765 }
766
767 CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error)
768 {
769 sec_trace_enter_api(NULL);
770 sec_trace_return_api(CFArrayRef, ^{
771 do_if_registered(soscc_CopyNotValidPeerPeerInfo, error);
772
773 return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error);
774 }, CFSTR("return=%@"));
775 }
776
777 CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error)
778 {
779 sec_trace_enter_api(NULL);
780 sec_trace_return_api(CFArrayRef, ^{
781 do_if_registered(soscc_CopyRetirementPeerInfo, error);
782
783 return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error);
784 }, CFSTR("return=%@"));
785 }
786
787 CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error)
788 {
789 sec_trace_enter_api(NULL);
790 sec_trace_return_api(CFArrayRef, ^{
791 do_if_registered(soscc_CopyViewUnawarePeerInfo, error);
792
793 return array_of_info_error_request(kSecXPCOpCopyViewUnawarePeerInfo, error);
794 }, CFSTR("return=%@"));
795 }
796
797 SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error)
798 {
799 sec_trace_enter_api(NULL);
800 sec_trace_return_api(SOSPeerInfoRef, ^{
801 do_if_registered(soscc_CopyMyPeerInfo, error);
802
803 return peer_info_error_request(kSecXPCOpCopyMyPeerInfo, error);
804 }, CFSTR("return=%@"));
805 }
806
807 static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error)
808 {
809 sec_trace_enter_api(NULL);
810 sec_trace_return_api(CFArrayRef, ^{
811 do_if_registered(soscc_CopyEngineState, error);
812
813 return der_array_error_request(kSecXPCOpCopyEngineState, error);
814 }, CFSTR("return=%@"));
815 }
816
817 CFStringRef kSOSCCEngineStatePeerIDKey = CFSTR("PeerID");
818 CFStringRef kSOSCCEngineStateManifestCountKey = CFSTR("ManifestCount");
819 CFStringRef kSOSCCEngineStateSyncSetKey = CFSTR("SyncSet");
820 CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump");
821 CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash");
822
823 void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) {
824
825 CFArrayForEach(states, ^(const void *value) {
826 CFDictionaryRef dict = asDictionary(value, NULL);
827 if (dict) {
828 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
829
830 CFStringRef id = asString(CFDictionaryGetValue(dict, kSOSCCEngineStatePeerIDKey), NULL);
831
832 if (id) {
833 CFStringAppendFormat(description, NULL, CFSTR("remote %@ "), id);
834 } else {
835 CFStringAppendFormat(description, NULL, CFSTR("local "));
836 }
837
838 CFSetRef viewSet = asSet(CFDictionaryGetValue(dict, kSOSCCEngineStateSyncSetKey), NULL);
839 if (viewSet) {
840 CFStringSetPerformWithDescription(viewSet, ^(CFStringRef setDescription) {
841 CFStringAppend(description, setDescription);
842 });
843 } else {
844 CFStringAppendFormat(description, NULL, CFSTR("<Missing view set!>"));
845 }
846
847 CFStringAppendFormat(description, NULL, CFSTR(" [%@]"),
848 CFDictionaryGetValue(dict, kSOSCCEngineStateManifestCountKey));
849
850 CFDataRef mainfestHash = asData(CFDictionaryGetValue(dict, kSOSCCEngineStateManifestHashKey), NULL);
851
852 if (mainfestHash) {
853 CFDataPerformWithHexString(mainfestHash, ^(CFStringRef dataString) {
854 CFStringAppendFormat(description, NULL, CFSTR(" %@"), dataString);
855 });
856 }
857
858 CFStringRef coderDescription = asString(CFDictionaryGetValue(dict, kSOSCCEngineStateCoderKey), NULL);
859 if (coderDescription) {
860 CFStringAppendFormat(description, NULL, CFSTR(" %@"), coderDescription);
861 }
862
863 block(description);
864
865 CFReleaseNull(description);
866 }
867 });
868 }
869
870 bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) {
871 CFArrayRef states = SOSCCCopyEngineState(error);
872 if (states == NULL)
873 return false;
874
875 SOSCCForEachEngineStateAsStringFromArray(states, block);
876
877 CFReleaseNull(states);
878
879 return true;
880 }
881
882
883 bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
884 {
885 sec_trace_enter_api(NULL);
886 sec_trace_return_bool_api(^{
887 do_if_registered(soscc_AcceptApplicants, applicants, error);
888
889 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
890 }, NULL)
891 }
892
893 bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
894 {
895 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
896 sec_trace_return_bool_api(^{
897 do_if_registered(soscc_RejectApplicants, applicants, error);
898
899 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
900 }, NULL)
901 }
902
903 static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pubKey, CFErrorRef *error)
904 {
905 sec_trace_enter_api(NULL);
906 sec_trace_return_api(SOSPeerInfoRef, ^{
907 do_if_registered(soscc_SetNewPublicBackupKey, pubKey, error);
908
909 return data_to_peer_info_error_request(kSecXPCOpSetNewPublicBackupKey, pubKey, error);
910 }, CFSTR("return=%@"));
911 }
912
913 SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){
914 secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()");
915 CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error);
916 secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData);
917 SOSPeerInfoRef copiedPeer = publicKeyData ? SOSSetNewPublicBackupKey(publicKeyData, error) : NULL;
918 secnotice("devRecovery", "SOSSetNewPublicBackupKey (%@)", copiedPeer);
919 CFReleaseNull(publicKeyData);
920 return copiedPeer;
921 }
922
923 bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){
924 sec_trace_enter_api(NULL);
925 sec_trace_return_bool_api(^{
926 do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error);
927 return keybag_and_bool_to_bool_error_request(kSecXPCOpSetBagForAllSlices, aks_bag, forV0Only, error);
928 }, NULL);
929 }
930
931
932 bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){
933 sec_trace_enter_api(NULL);
934 sec_trace_return_bool_api(^{
935 bool retval = false;
936 do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error);
937 // NULL recovery_key is handled in recovery_and_bool_to_bool_error_request now.
938 retval = recovery_and_bool_to_bool_error_request(kSecXPCOpRegisterRecoveryPublicKey, recovery_key, error);
939 return retval;
940 }, NULL);
941 }
942
943 CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){
944 sec_trace_enter_api(NULL);
945 sec_trace_return_api(CFDataRef, ^{
946 do_if_registered(soscc_CopyRecoveryPublicKey, error);
947 return data_to_error_request(kSecXPCOpGetRecoveryPublicKey, error);
948 }, CFSTR("return=%@"));
949 }
950 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
951 CFStringRef user_label, CFDataRef user_password,
952 CFErrorRef* error)
953 {
954 __block bool result = false;
955
956 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
957 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
958 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
959 });
960 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
961 return true;
962 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
963 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
964 return result;
965 });
966
967 return result;
968 }
969
970 static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op,
971 CFStringRef user_label, CFDataRef user_password,
972 CFStringRef dsid, CFDataRef parentEvent, CFErrorRef* error)
973 {
974 __block bool result = false;
975
976 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
977 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
978 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
979 });
980 CFStringPerformWithCString(dsid, ^(const char *utr8StrDSID) {
981 xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID);
982 });
983 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
984 if(parentEvent){
985 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
986 }
987 return true;
988 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
989 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
990 return result;
991 });
992
993 return result;
994 }
995
996 bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
997 {
998 secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label);
999 return SOSCCSetUserCredentials(user_label, user_password, error);
1000 }
1001
1002 bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1003 {
1004 secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label);
1005 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1006 sec_trace_return_bool_api(^{
1007 do_if_registered(soscc_SetUserCredentials, user_label, user_password, error);
1008
1009 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
1010 }, NULL)
1011 }
1012
1013 bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1014 {
1015 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label);
1016 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1017 sec_trace_return_bool_api(^{
1018 do_if_registered(soscc_SetUserCredentialsAndDSID, user_label, user_password, dsid, error);
1019
1020 bool result = false;
1021 __block CFStringRef account_dsid = dsid;
1022
1023 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1024 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1025
1026 if(account_dsid == NULL){
1027 account_dsid = CFSTR("");
1028 }
1029 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, nil, error);
1030 out:
1031 return result;
1032
1033 }, NULL)
1034 }
1035
1036 bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error)
1037 {
1038 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSIDWithAnalytics for %@\n", user_label);
1039 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1040 sec_trace_return_bool_api(^{
1041 do_if_registered(soscc_SetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, dsid, parentEvent, error);
1042
1043 bool result = false;
1044 __block CFStringRef account_dsid = dsid;
1045
1046 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1047 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1048
1049 if(account_dsid == NULL){
1050 account_dsid = CFSTR("");
1051 }
1052 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, account_dsid, parentEvent, error);
1053 out:
1054 return result;
1055
1056 }, NULL)
1057 }
1058
1059 static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) {
1060 sec_trace_return_bool_api(^{
1061 do_if_registered(soscc_TryUserCredentials, user_label, user_password, dsid, error);
1062
1063 bool result = false;
1064 __block CFStringRef account_dsid = dsid;
1065
1066 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1067 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1068
1069 if(account_dsid == NULL){
1070 account_dsid = CFSTR("");
1071 }
1072
1073 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, nil, error);
1074 out:
1075 return result;
1076
1077 }, NULL)
1078
1079 }
1080
1081 bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1082 {
1083 secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label);
1084 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1085 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1086 CFStringRef account_dsid = (dsid != NULL) ? dsid: CFSTR("");
1087 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, account_dsid, error);
1088 out:
1089 return false;
1090 }
1091
1092 bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) {
1093 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error);
1094 }
1095
1096
1097 bool SOSCCCanAuthenticate(CFErrorRef* error) {
1098 sec_trace_enter_api(NULL);
1099 sec_trace_return_bool_api(^{
1100 do_if_registered(soscc_CanAuthenticate, error);
1101
1102 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
1103 }, NULL)
1104 }
1105
1106 bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
1107 sec_trace_enter_api(NULL);
1108 sec_trace_return_bool_api(^{
1109 do_if_registered(soscc_PurgeUserCredentials, error);
1110
1111 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
1112 }, NULL)
1113 }
1114
1115 enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) {
1116 sec_trace_enter_api(NULL);
1117 sec_trace_return_api(enum DepartureReason, ^{
1118 do_if_registered(soscc_GetLastDepartureReason, error);
1119
1120 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
1121 }, NULL)
1122 }
1123
1124 bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) {
1125 sec_trace_enter_api(NULL);
1126 sec_trace_return_api(bool, ^{
1127 do_if_registered(soscc_SetLastDepartureReason, reason, error);
1128 return securityd_send_sync_and_do(kSecXPCOpSetLastDepartureReason, error,
1129 ^bool(xpc_object_t message, CFErrorRef *error) {
1130 xpc_dictionary_set_int64(message, kSecXPCKeyReason, reason);
1131 return true;
1132 },
1133 ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1134 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1135 }
1136 );
1137 }, NULL)
1138 }
1139
1140 bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){
1141 secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration");
1142 sec_trace_enter_api(NULL);
1143 sec_trace_return_bool_api(^{
1144 do_if_registered(soscc_EnsurePeerRegistration, error);
1145
1146 return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error);
1147 }, NULL)
1148 }
1149
1150
1151 CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error)
1152 {
1153 sec_trace_enter_api(NULL);
1154 sec_trace_return_api(CFSetRef, ^{
1155 do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error);
1156
1157 return cfset_cfset_to_cfset_error_request(kSecXPCOpProcessSyncWithPeers, peers, backupPeers, error);
1158 }, NULL)
1159 }
1160
1161
1162 SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
1163 {
1164 sec_trace_enter_api(NULL);
1165 sec_trace_return_api(SyncWithAllPeersReason, ^{
1166 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
1167
1168 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
1169 }, NULL)
1170 }
1171
1172 CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
1173 {
1174 switch (status) {
1175 case kSOSCCInCircle:
1176 return CFSTR("InCircle");
1177 case kSOSCCNotInCircle:
1178 return CFSTR("NotInCircle");
1179 case kSOSCCRequestPending:
1180 return CFSTR("RequestPending");
1181 case kSOSCCCircleAbsent:
1182 return CFSTR("CircleAbsent");
1183 case kSOSCCError:
1184 return CFSTR("InternalError");
1185 default:
1186 return CFSTR("Unknown Status");
1187 };
1188 }
1189
1190
1191 CFStringRef SOSCCGetViewResultDescription(SOSViewResultCode vrc)
1192 {
1193 switch (vrc) {
1194 case kSOSCCGeneralViewError:
1195 return CFSTR("GeneralViewError");
1196 case kSOSCCViewMember:
1197 return CFSTR("ViewMember");
1198 case kSOSCCViewNotMember:
1199 return CFSTR("ViewNotMember");
1200 case kSOSCCViewNotQualified:
1201 return CFSTR("ViewNotQualified");
1202 case kSOSCCNoSuchView:
1203 return CFSTR("ViewUndefined");
1204 default:
1205 return CFSTR("Unknown View Status");
1206 };
1207 }
1208
1209
1210 static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t error_result,
1211 CFStringRef name, uint64_t action, CFErrorRef *error) {
1212 __block int64_t result = error_result;
1213
1214 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1215 CFStringPerformWithCString(name, ^(const char *utf8Str) {
1216 xpc_dictionary_set_string(message, kSecXPCKeyViewName, utf8Str);
1217 });
1218 xpc_dictionary_set_int64(message, kSecXPCKeyViewActionCode, action);
1219 return true;
1220 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1221 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
1222 result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
1223 }
1224 return result != error_result;
1225 });
1226
1227 return result;
1228 }
1229
1230 SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) {
1231 if(actionCode == kSOSCCViewQuery) {
1232 uint64_t circleStat = SOSGetCachedCircleBitmask();
1233 if(circleStat & CC_STATISVALID) {
1234 SOSViewResultCode retval = kSOSCCViewNotMember;
1235 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1236 if(enabledViews) {
1237 if(CFSetContainsValue(enabledViews, view)) {
1238 retval = kSOSCCViewMember;
1239 } else {
1240 retval = kSOSCCViewNotMember;
1241 }
1242 CFReleaseNull(enabledViews);
1243 }
1244 return retval;
1245 }
1246 }
1247 sec_trace_enter_api(NULL);
1248 sec_trace_return_api(SOSViewResultCode, ^{
1249 do_if_registered(soscc_View, view, actionCode, error);
1250
1251 return (SOSViewResultCode) name_action_to_code_request(kSecXPCOpView, kSOSCCGeneralViewError, view, actionCode, error);
1252 }, CFSTR("SOSViewResultCode=%d"))
1253 }
1254
1255
1256 bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) {
1257 CFErrorRef *error = NULL;
1258 __block bool result = false;
1259
1260 sec_trace_enter_api(NULL);
1261 sec_trace_return_bool_api(^{
1262 do_if_registered(soscc_ViewSet, enabledViews, disabledViews);
1263 return securityd_send_sync_and_do(kSecXPCOpViewSet, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1264 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1265 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1266 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1267 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1268 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1269 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1270 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1271 return result;
1272 });
1273 }, NULL)
1274 }
1275
1276 bool SOSCCViewSetWithAnalytics(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) {
1277 CFErrorRef *error = NULL;
1278 __block bool result = false;
1279
1280 sec_trace_enter_api(NULL);
1281 sec_trace_return_bool_api(^{
1282 do_if_registered(soscc_ViewSetWithAnalytics, enabledViews, disabledViews, parentEvent);
1283 return securityd_send_sync_and_do(kSecXPCOpViewSetWithAnalytics, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1284 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1285 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1286 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1287 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1288 if(parentEvent) SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
1289 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1290 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1291 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1292 return result;
1293 });
1294 }, NULL)
1295 }
1296
1297 static CFStringRef copyViewNames(size_t n, CFStringRef *views) {
1298 CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0);
1299 CFStringAppend(retval, CFSTR("|"));
1300 for(size_t i = 0; i < n; i++) {
1301 CFStringAppend(retval, views[i]);
1302 CFStringAppend(retval, CFSTR("|"));
1303 }
1304 return retval;
1305 }
1306
1307 static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) {
1308 __block bool retval = true;
1309 CFErrorRef error = NULL;
1310
1311 if(n == 0 || views == NULL) return false;
1312 CFStringRef viewString = copyViewNames(n, views);
1313
1314 SOSCCStatus cstatus = SOSCCThisDeviceIsInCircle(&error);
1315 if(cstatus != kSOSCCInCircle) {
1316 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) Error: (%@)", viewString, SOSCCGetStatusDescription(cstatus), error);
1317 retval = false;
1318 }
1319
1320 if(retval == true) {
1321 // use cached values if valid
1322 uint64_t circleStat = SOSGetCachedCircleBitmask();
1323 if(circleStat & CC_STATISVALID) {
1324 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1325 if(enabledViews) {
1326 for(size_t i = 0; i < n; i++) {
1327 if(!CFSetContainsValue(enabledViews, views[i])) {
1328 retval = false;
1329 }
1330 }
1331 CFReleaseNull(enabledViews);
1332 CFReleaseNull(viewString);
1333 return retval;
1334 }
1335 }
1336
1337 // make the individual calls otherwise.
1338 for(size_t i = 0; i < n; i++) {
1339 SOSViewResultCode vstatus = SOSCCView(views[i], kSOSCCViewQuery, &error);
1340 if(vstatus != kSOSCCViewMember) {
1341 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) SOSViewResultCode(%@) Error: (%@)", views[i],
1342 SOSCCGetStatusDescription(cstatus), SOSCCGetViewResultDescription(vstatus), error);
1343 retval = false;
1344 }
1345 }
1346 }
1347
1348 if(retval == true) {
1349 secnotice("viewCheck", "Checking view / circle status for %@: ENABLED", viewString);
1350 }
1351 CFReleaseNull(error);
1352 CFReleaseNull(viewString);
1353 return retval;
1354 }
1355
1356 bool SOSCCIsIcloudKeychainSyncing(void) {
1357 CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable };
1358 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1359 }
1360
1361 bool SOSCCIsSafariSyncing(void) {
1362 CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards };
1363 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1364 }
1365
1366 bool SOSCCIsAppleTVSyncing(void) {
1367 CFStringRef views[] = { kSOSViewAppleTV };
1368 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1369 }
1370
1371 bool SOSCCIsHomeKitSyncing(void) {
1372 CFStringRef views[] = { kSOSViewHomeKit };
1373 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1374 }
1375
1376 bool SOSCCIsWiFiSyncing(void) {
1377 CFStringRef views[] = { kSOSViewWiFi };
1378 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1379 }
1380
1381 bool SOSCCIsContinuityUnlockSyncing(void) {
1382 CFStringRef views[] = { kSOSViewContinuityUnlock };
1383 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1384 }
1385
1386 SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) {
1387 secnotice("hsa2PB", "enter SOSCCCopyApplication applicant");
1388 sec_trace_enter_api(NULL);
1389
1390 sec_trace_return_api(SOSPeerInfoRef, ^{
1391 do_if_registered(soscc_CopyApplicant, error);
1392 return peer_info_error_request(kSecXPCOpCopyApplication, error);
1393 }, CFSTR("return=%@"));
1394 }
1395
1396 bool SOSCCCleanupKVSKeys(CFErrorRef *error) {
1397 secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys");
1398 sec_trace_enter_api(NULL);
1399 sec_trace_return_bool_api(^{
1400 do_if_registered(soscc_SOSCCCleanupKVSKeys, error);
1401
1402 return simple_bool_error_request(kSecXPCOpKVSKeyCleanup, error);
1403 }, NULL)
1404
1405 return false;
1406 }
1407
1408 CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) {
1409 secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver");
1410 sec_trace_enter_api(NULL);
1411
1412 sec_trace_return_api(CFDataRef, ^{
1413 CFDataRef result = NULL;
1414 do_if_registered(soscc_CopyCircleJoiningBlob, applicant, error);
1415 CFDataRef piData = SOSPeerInfoCopyEncodedData(applicant, kCFAllocatorDefault, error);
1416 result = cfdata_error_request_returns_cfdata(kSecXPCOpCopyCircleJoiningBlob, piData, error);
1417 CFReleaseNull(piData);
1418 return result;
1419 }, CFSTR("return=%@"));
1420 }
1421
1422 CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) {
1423 secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver");
1424 sec_trace_enter_api(NULL);
1425
1426 sec_trace_return_api(CFDataRef, ^{
1427 do_if_registered(soscc_CopyInitialSyncData, flags, error);
1428 return flags_to_data_error_request(kSecXPCOpCopyInitialSyncBlob, flags, error);
1429 }, CFSTR("return=%@"));
1430 }
1431
1432 bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) {
1433 secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant");
1434 sec_trace_enter_api(NULL);
1435 sec_trace_return_bool_api(^{
1436 do_if_registered(soscc_JoinWithCircleJoiningBlob, joiningBlob, version, error);
1437
1438 return cfdata_and_int_error_request_returns_bool(kSecXPCOpJoinWithCircleJoiningBlob, joiningBlob, version, error);
1439 }, NULL)
1440 }
1441
1442 CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) {
1443 secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled");
1444 sec_trace_enter_api(NULL);
1445 sec_trace_return_api(CFBooleanRef, ^{
1446 do_if_registered(soscc_SOSCCPeersHaveViewsEnabled, viewNames, error);
1447
1448 return cfarray_to_cfboolean_error_request(kSecXPCOpPeersHaveViewsEnabled, viewNames, error);
1449 }, CFSTR("return=%@"))
1450 }
1451
1452 bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1453 secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending");
1454
1455 sec_trace_return_bool_api(^{
1456 do_if_registered(soscc_SOSCCMessageFromPeerIsPending, peer, error);
1457
1458 return peer_info_to_bool_error_request(kSecXPCOpMessageFromPeerIsPending, peer, error);
1459 }, NULL)
1460
1461 }
1462
1463 bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1464 sec_trace_return_bool_api(^{
1465 do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error);
1466
1467 return peer_info_to_bool_error_request(kSecXPCOpSendToPeerIsPending, peer, error);
1468 }, NULL)
1469 }
1470
1471 /*
1472 * SecSOSStatus interfaces
1473 */
1474
1475 @interface SecSOSStatus : NSObject {
1476 NSXPCConnection* _connection;
1477 }
1478 @property NSXPCConnection *connection;
1479 @end
1480
1481 @implementation SecSOSStatus
1482 @synthesize connection = _connection;
1483
1484 - (instancetype) init
1485 {
1486 if ((self = [super init]) == NULL)
1487 return NULL;
1488
1489 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
1490 _SOSControlSetupInterface(interface);
1491
1492 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0];
1493 if (self.connection == NULL){
1494 return NULL;
1495 }
1496 self.connection.remoteObjectInterface = interface;
1497
1498 [self.connection resume];
1499
1500 return self;
1501 }
1502
1503 @end
1504
1505 static id<SOSControlProtocol>
1506 SOSCCGetStatusObject(CFErrorRef *error)
1507 {
1508 if (gSecurityd && gSecurityd->soscc_status)
1509 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1510
1511 static SecSOSStatus *control;
1512 static dispatch_once_t onceToken;
1513 dispatch_once(&onceToken, ^{
1514 control = [[SecSOSStatus alloc] init];
1515 });
1516 return control.connection.remoteObjectProxy;
1517 }
1518
1519
1520 static id<SOSControlProtocol>
1521 SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) {
1522 if (gSecurityd && gSecurityd->soscc_status)
1523 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1524
1525 static SecSOSStatus *control;
1526 static dispatch_once_t onceToken;
1527 dispatch_once(&onceToken, ^{
1528 control = [[SecSOSStatus alloc] init];
1529 });
1530
1531 __block NSError *localError = nil;
1532 id <SOSControlProtocol> synchronousRemoteObject = [control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
1533 secnotice("ghostbust", "An error occurred on the xpc connection to setup the background session: %@", error );
1534 if(error) {
1535 localError = error;
1536 }
1537 }];
1538 if(cferror && localError) {
1539 *cferror = (__bridge CFErrorRef)(localError);
1540 }
1541 return synchronousRemoteObject;
1542 }
1543
1544
1545
1546 void
1547 SOSCCAccountGetPublicKey(void (^reply)(BOOL trusted, NSData *data, NSError *error))
1548 {
1549 CFErrorRef error = NULL;
1550 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1551 if (status == NULL) {
1552 reply(false, NULL, (__bridge NSError *)error);
1553 CFReleaseNull(error);
1554 return;
1555 }
1556
1557 [status userPublicKey:reply];
1558 }
1559
1560 void
1561 SOSCCAccountGetAccountPrivateCredential(void (^complete)(NSData *data, NSError *error))
1562 {
1563 CFErrorRef error = NULL;
1564 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1565 if (status == NULL) {
1566 complete(NULL, (__bridge NSError *)error);
1567 CFReleaseNull(error);
1568 return;
1569 }
1570
1571 [status validatedStashedAccountCredential:complete];
1572 }
1573
1574 void
1575 SOSCCAccountGetKeyCircleGeneration(void (^reply)(NSData *data, NSError *error))
1576 {
1577 SOSCCAccountGetPublicKey(^(BOOL __unused trusted, NSData *data, NSError *error){
1578 if (data == NULL) {
1579 reply(data, error);
1580 } else {
1581 NSMutableData *digest = [NSMutableData dataWithLength:CCSHA256_OUTPUT_SIZE];
1582 ccdigest(ccsha256_di(), [data length], [data bytes], [digest mutableBytes]);
1583 reply(digest, error);
1584 }
1585 });
1586 }
1587
1588 NSString *
1589 SOSCCCircleHash(NSError **error)
1590 {
1591 CFErrorRef cferror = NULL;
1592 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&cferror);
1593 if (status == NULL) {
1594 if (error) {
1595 *error = (__bridge NSError *)cferror;
1596 }
1597 CFReleaseNull(cferror);
1598 return NULL;
1599 }
1600 __block NSString *hash = NULL;
1601 [status circleHash:^(NSString *circleHash, NSError *error) {
1602 hash = circleHash;
1603 }];
1604 return hash;
1605 }
1606
1607
1608
1609 void
1610 SOSCCGhostBust(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1611 CFErrorRef error = NULL;
1612 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1613 if (status == NULL) {
1614 complete(false, (__bridge NSError *)error);
1615 CFReleaseNull(error);
1616 return;
1617 }
1618 secnotice("ghostbust", "API Called");
1619 [status ghostBust:options complete:^(bool ghostBusted, NSError *error) {
1620 secnotice("ghostbust", "API returned: %d", ghostBusted);
1621 complete(ghostBusted, error);
1622 }];
1623 }
1624
1625 void SOSCCGhostBustTriggerTimed(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1626 CFErrorRef error = NULL;
1627 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1628 if (status == NULL) {
1629 complete(false, (__bridge NSError *)error);
1630 CFReleaseNull(error);
1631 return;
1632 }
1633 secnotice("ghostbust", "API Trigger Timed Called");
1634 [status ghostBustTriggerTimed:options complete:^(bool ghostBusted, NSError *error) {
1635 secnotice("ghostbust", "API Trigger Timed returned: %d", ghostBusted);
1636 complete(ghostBusted, error);
1637 }];
1638 }
1639
1640 void SOSCCGhostBustInfo(void (^complete)(NSData *json, NSError *error)) {
1641 CFErrorRef error = NULL;
1642 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1643 if (status == NULL) {
1644 complete(false, (__bridge NSError *)error);
1645 CFReleaseNull(error);
1646 return;
1647 }
1648 secnotice("ghostbust", "API Info Called");
1649 [status ghostBustInfo:^(NSData *json, NSError *error) {
1650 secnotice("ghostbust", "API Info returned");
1651 complete(json, error);
1652 }];
1653 }
1654
1655