]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSCloudCircle.m
Security-59306.41.2.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 cfstring_to_error_request(enum SecXPCOperation op, CFStringRef string, CFErrorRef* error)
146 {
147 __block bool result = false;
148
149 secdebug("sosops","enter - operation: %d", op);
150 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
151 xpc_object_t xString = _CFXPCCreateXPCObjectFromCFObject(string);
152 bool success = false;
153 if (xString){
154 xpc_dictionary_set_value(message, kSecXPCKeyString, xString);
155 success = true;
156 xString = nil;
157 }
158 return success;
159 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
160 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
161 return result;
162 });
163 return result;
164 }
165
166 static SOSRingStatus cfstring_to_uint64_request(enum SecXPCOperation op, CFStringRef string, CFErrorRef* error)
167 {
168 __block bool result = false;
169
170 secdebug("sosops","enter - operation: %d", op);
171 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
172 xpc_object_t xString = _CFXPCCreateXPCObjectFromCFObject(string);
173 bool success = false;
174 if (xString){
175 xpc_dictionary_set_value(message, kSecXPCKeyString, xString);
176 success = true;
177 xString = nil;
178 }
179 return success;
180 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
181 result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
182 return result;
183 });
184 return result;
185 }
186
187 static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error)
188 {
189 __block CFStringRef result = NULL;
190
191 secdebug("sosops","enter - operation: %d", op);
192 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
193 const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult);
194
195 if (c_string) {
196 result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false);
197 }
198
199 return c_string != NULL;
200 });
201 return result;
202 }
203
204 static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
205 {
206 __block bool result = false;
207
208 secdebug("sosops","enter - operation: %d", op);
209 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
210 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
211 return result;
212 });
213 return result;
214 }
215
216 static bool SecXPCDictionarySetPeerInfoData(xpc_object_t message, const char *key, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
217 bool success = false;
218 CFDataRef peerData = SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, error);
219 if (peerData) {
220 success = SecXPCDictionarySetData(message, key, peerData, error);
221 }
222 CFReleaseNull(peerData);
223 return success;
224 }
225
226 static bool peer_info_to_bool_error_request(enum SecXPCOperation op, SOSPeerInfoRef peerInfo, CFErrorRef* error)
227 {
228 __block bool result = false;
229
230 secdebug("sosops","enter - operation: %d", op);
231 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
232 return SecXPCDictionarySetPeerInfoData(message, kSecXPCKeyPeerInfo, peerInfo, error);
233 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
234 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
235 return result;
236 });
237 return result;
238 }
239
240 static CFBooleanRef cfarray_to_cfboolean_error_request(enum SecXPCOperation op, CFArrayRef views, CFErrorRef* error)
241 {
242 __block bool result = false;
243
244 secdebug("sosops","enter - operation: %d", op);
245 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
246 return SecXPCDictionarySetPList(message, kSecXPCKeyArray, views, error);
247 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
248 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
249 return true;
250 });
251 return noError ? (result ? kCFBooleanTrue : kCFBooleanFalse) : NULL;
252 }
253
254
255 static CFSetRef cfset_cfset_to_cfset_error_request(enum SecXPCOperation op, CFSetRef set1, CFSetRef set2, CFErrorRef* error)
256 {
257 __block CFSetRef result = NULL;
258
259 secdebug("sosops","enter - operation: %d", op);
260 bool noError = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
261 return SecXPCDictionarySetPList(message, kSecXPCKeySet, set1, error) && SecXPCDictionarySetPList(message, kSecXPCKeySet2, set2, error);
262 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
263 result = SecXPCDictionaryCopySet(response, kSecXPCKeyResult, error);
264 return result;
265 });
266
267 if (!noError) {
268 CFReleaseNull(result);
269 }
270 return result;
271 }
272
273
274 static bool escrow_to_bool_error_request(enum SecXPCOperation op, CFStringRef escrow_label, uint64_t tries, CFErrorRef* error)
275 {
276 __block bool result = false;
277
278 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
279
280 bool success = false;
281 xpc_object_t xEscrowLabel = _CFXPCCreateXPCObjectFromCFObject(escrow_label);
282 if (xEscrowLabel){
283 xpc_dictionary_set_value(message, kSecXPCKeyEscrowLabel, xEscrowLabel);
284 success = true;
285 xEscrowLabel = nil;
286 }
287 if(tries){
288 xpc_dictionary_set_int64(message, kSecXPCKeyTriesLabel, tries);
289 success = true;
290 }
291
292 return success;
293 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
294 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
295 return result;
296 });
297 return result;
298 }
299
300 static CF_RETURNS_RETAINED CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
301 {
302 __block CFArrayRef result = NULL;
303
304 secdebug("sosops","enter - operation: %d", op);
305 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
306 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
307 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
308 return result != NULL;
309 })) {
310 if (!isArray(result)) {
311 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
312 CFReleaseNull(result);
313 }
314 }
315 return result;
316 }
317
318 static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
319 {
320 __block CFArrayRef result = NULL;
321
322 secdebug("sosops","enter - operation: %d", op);
323 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
324 size_t length = 0;
325 const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length);
326 der_decode_plist(kCFAllocatorDefault, 0, (CFPropertyListRef*) &result, error, bytes, bytes + length);
327
328 return result != NULL;
329 })) {
330 if (!isArray(result)) {
331 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
332 CFReleaseNull(result);
333 }
334 }
335 return result;
336 }
337
338 static CFDictionaryRef strings_to_dictionary_error_request(enum SecXPCOperation op, CFErrorRef* error)
339 {
340 __block CFDictionaryRef result = NULL;
341
342 secdebug("sosops","enter - operation: %d", op);
343
344 if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
345 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
346 if(temp_result)
347 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
348 return result != NULL;
349 })){
350
351 if (!isDictionary(result)) {
352 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected dictionary, got: %@"), result);
353 CFReleaseNull(result);
354 }
355
356 }
357 return result;
358 }
359
360 static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
361 {
362 __block int result = 0;
363
364 secdebug("sosops","enter - operation: %d", op);
365 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
366 int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
367 if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) {
368 result = (int)temp_result;
369 }
370 return result;
371 });
372 return result;
373 }
374
375 static CF_RETURNS_RETAINED SOSPeerInfoRef peer_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
376 {
377 SOSPeerInfoRef result = NULL;
378 __block CFDataRef data = NULL;
379
380 secdebug("sosops","enter - operation: %d", op);
381 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
382 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
383 if (response && (NULL != temp_result)) {
384 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
385 }
386 return data != NULL;
387 });
388
389 if (isData(data)) {
390 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
391 } else {
392 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
393 }
394
395 CFReleaseNull(data);
396 return result;
397 }
398
399 static CFDataRef flags_to_data_error_request(enum SecXPCOperation op, uint32_t flags, CFErrorRef *error)
400 {
401 __block CFDataRef result = NULL;
402
403 secdebug("sosops", "enter -- operation: %d", op);
404 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
405 xpc_dictionary_set_uint64(message, kSecXPCKeyFlags, flags);
406 return true;
407 }, ^bool(xpc_object_t response, CFErrorRef *error) {
408 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
409 if (response && (NULL != temp_result)) {
410 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
411 }
412 return result != NULL;
413 });
414
415 if (!isData(result)) {
416 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
417 return NULL;
418 }
419
420 return result;
421 }
422
423
424 static CFDataRef data_to_error_request(enum SecXPCOperation op, CFErrorRef *error)
425 {
426 __block CFDataRef result = NULL;
427
428 secdebug("sosops", "enter -- operation: %d", op);
429 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
430 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
431 if (response && (NULL != temp_result)) {
432 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
433 }
434 return result != NULL;
435 });
436
437 if (!isData(result)) {
438 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
439 return NULL;
440 }
441
442 return result;
443 }
444
445 static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
446 {
447 __block CFArrayRef result = NULL;
448
449 secdebug("sosops","enter - operation: %d", op);
450 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
451 xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult);
452 if (response && (NULL != encoded_array)) {
453 result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error);
454 }
455 return result != NULL;
456 });
457
458 if (!isArray(result)) {
459 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected array, got: %@"), result);
460 CFReleaseNull(result);
461 }
462 return result;
463 }
464
465 static CF_RETURNS_RETAINED SOSPeerInfoRef data_to_peer_info_error_request(enum SecXPCOperation op, CFDataRef secret, CFErrorRef* error)
466 {
467 __block SOSPeerInfoRef result = false;
468 __block CFDataRef data = NULL;
469
470 secdebug("sosops", "enter - operation: %d", op);
471 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
472 xpc_object_t xsecretData = _CFXPCCreateXPCObjectFromCFObject(secret);
473 bool success = false;
474 if (xsecretData){
475 xpc_dictionary_set_value(message, kSecXPCKeyNewPublicBackupKey, xsecretData);
476 success = true;
477 xsecretData = nil;
478 }
479 return success;
480 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
481 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
482 if (response && (NULL != temp_result)) {
483 data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
484 }
485 return data != NULL;
486 });
487
488 if (isData(data)) {
489 result = SOSPeerInfoCreateFromData(kCFAllocatorDefault, error, data);
490 } else {
491 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), data);
492 }
493
494 CFReleaseNull(data);
495 return result;
496 }
497
498 static bool keybag_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, bool include, CFErrorRef* error)
499 {
500 secdebug("sosops", "enter - operation: %d", op);
501 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
502 xpc_object_t xData = _CFXPCCreateXPCObjectFromCFObject(data);
503 bool success = false;
504 if (xData){
505 xpc_dictionary_set_value(message, kSecXPCKeyKeybag, xData);
506 xData = nil;
507 success = true;
508 }
509 xpc_dictionary_set_bool(message, kSecXPCKeyIncludeV0, include);
510 return success;
511 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
512 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
513 });
514 }
515
516 static bool recovery_and_bool_to_bool_error_request(enum SecXPCOperation op, CFDataRef data, CFErrorRef* error)
517 {
518 secdebug("sosops", "enter - operation: %d", op);
519 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
520 xpc_object_t xData = NULL;
521 if(data) {
522 xData = _CFXPCCreateXPCObjectFromCFObject(data);
523 } else {
524 uint8_t zero = 0;
525 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1);
526 xData = _CFXPCCreateXPCObjectFromCFObject(nullData);
527 CFReleaseNull(nullData);
528 }
529 bool success = false;
530 if (xData){
531 xpc_dictionary_set_value(message, kSecXPCKeyRecoveryPublicKey, xData);
532 xData = nil;
533 success = true;
534 }
535 return success;
536 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
537 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
538 });
539 }
540
541 static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
542 {
543 __block bool result = false;
544
545 secdebug("sosops", "enter - operation: %d", op);
546 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
547 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
548 if (encoded_peers)
549 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
550 return encoded_peers != NULL;
551 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
552 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
553 return result;
554 });
555 return result;
556 }
557
558 static bool info_array_data_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFDataRef parentEvent, CFErrorRef* error)
559 {
560 __block bool result = false;
561
562 secdebug("sosops", "enter - operation: %d", op);
563 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
564 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
565 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
566 if (encoded_peers)
567 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers);
568 return encoded_peers != NULL;
569 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
570 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
571 return result;
572 });
573 return result;
574 }
575
576 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
577 uint64_t number,
578 CFErrorRef* error)
579 {
580 __block bool result = false;
581
582 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
583 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
584 return true;
585 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
586 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
587 return result;
588 });
589
590 return result;
591 }
592
593 static bool cfstring_and_cfdata_to_cfdata_cfdata_error_request(enum SecXPCOperation op, CFStringRef viewName, CFDataRef input, CFDataRef* data, CFDataRef* data2, CFErrorRef* error) {
594 secdebug("sosops", "enter - operation: %d", op);
595 __block bool result = false;
596 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
597 xpc_object_t xviewname = _CFXPCCreateXPCObjectFromCFObject(viewName);
598 xpc_object_t xinput = _CFXPCCreateXPCObjectFromCFObject(input);
599 bool success = false;
600 if (xviewname && xinput){
601 xpc_dictionary_set_value(message, kSecXPCKeyViewName, xviewname);
602 xpc_dictionary_set_value(message, kSecXPCData, xinput);
603 success = true;
604 xviewname = nil;
605 xinput = nil;
606 }
607 return success;
608 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
609 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
610
611 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCData);
612 if ((NULL != temp_result) && data) {
613 *data = _CFXPCCreateCFObjectFromXPCObject(temp_result);
614 }
615 temp_result = xpc_dictionary_get_value(response, kSecXPCKeyKeybag);
616 if ((NULL != temp_result) && data2) {
617 *data2 = _CFXPCCreateCFObjectFromXPCObject(temp_result);
618 }
619
620 return result;
621 });
622
623 if (data &&!isData(*data)) {
624 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data);
625 }
626 if (data2 &&!isData(*data2)) {
627 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data2);
628 }
629
630 return result;
631 }
632
633 static bool cfdata_and_int_error_request_returns_bool(enum SecXPCOperation op, CFDataRef thedata,
634 PiggyBackProtocolVersion version, CFErrorRef *error) {
635 __block bool result = false;
636
637 sec_trace_enter_api(NULL);
638 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
639 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
640 bool success = false;
641 if (xdata) {
642 xpc_dictionary_set_value(message, kSecXPCData, xdata);
643 xpc_dictionary_set_uint64(message, kSecXPCVersion, version);
644 success = true;
645 xdata = nil;
646 }
647
648 return success;
649 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
650 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
651 return (bool)true;
652 });
653
654 return result;
655 }
656
657 static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CFDataRef thedata, CFErrorRef *error) {
658 __block CFDataRef result = NULL;
659
660 sec_trace_enter_api(NULL);
661 securityd_send_sync_and_do(op, error, ^(xpc_object_t message, CFErrorRef *error) {
662 xpc_object_t xdata = _CFXPCCreateXPCObjectFromCFObject(thedata);
663 bool success = false;
664 if (xdata) {
665 xpc_dictionary_set_value(message, kSecXPCData, xdata);
666 success = true;
667 xdata = nil;
668 }
669 return success;
670 }, ^(xpc_object_t response, __unused CFErrorRef *error) {
671 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
672 if (response && (NULL != temp_result)) {
673 CFTypeRef object = _CFXPCCreateCFObjectFromXPCObject(temp_result);
674 result = copyIfData(object, error);
675 CFReleaseNull(object);
676 }
677 return (bool) (result != NULL);
678 });
679
680 return result;
681 }
682
683 bool SOSCCRequestToJoinCircle(CFErrorRef* error)
684 {
685 sec_trace_enter_api(NULL);
686 sec_trace_return_bool_api(^{
687 do_if_registered(soscc_RequestToJoinCircle, error);
688
689 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
690 }, NULL)
691 }
692
693 bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
694 {
695 sec_trace_enter_api(NULL);
696 sec_trace_return_bool_api(^{
697 do_if_registered(soscc_RequestToJoinCircleWithAnalytics, parentEvent, error);
698
699 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinWithAnalytics, parentEvent, error);
700 }, NULL)
701 }
702
703 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
704 {
705 sec_trace_enter_api(NULL);
706 sec_trace_return_bool_api(^{
707 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
708
709 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
710 }, NULL)
711 }
712
713 bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
714 {
715 sec_trace_enter_api(NULL);
716 sec_trace_return_bool_api(^{
717 do_if_registered(soscc_RequestToJoinCircleAfterRestoreWithAnalytics, parentEvent, error);
718
719 return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, parentEvent, error);
720 }, NULL)
721 }
722
723 bool SOSCCAccountHasPublicKey(CFErrorRef *error)
724 {
725 sec_trace_enter_api(NULL);
726 sec_trace_return_bool_api(^{
727 do_if_registered(soscc_AccountHasPublicKey, error);
728
729 return simple_bool_error_request(kSecXPCOpAccountHasPublicKey, error);
730 }, NULL)
731
732 }
733
734 bool SOSCCAccountIsNew(CFErrorRef *error)
735 {
736 sec_trace_enter_api(NULL);
737 sec_trace_return_bool_api(^{
738 do_if_registered(soscc_AccountIsNew, error);
739
740 return simple_bool_error_request(kSecXPCOpAccountIsNew, error);
741 }, NULL)
742 }
743
744 bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
745 {
746 sec_trace_enter_api(NULL);
747 sec_trace_return_bool_api(^{
748 do_if_registered(soscc_WaitForInitialSyncWithAnalytics, parentEvent, error);
749
750 return sfsigninanalytics_bool_error_request(kSecXPCOpWaitForInitialSyncWithAnalytics, parentEvent, error);
751 }, NULL)
752 }
753
754 bool SOSCCWaitForInitialSync(CFErrorRef* error)
755 {
756 sec_trace_enter_api(NULL);
757 sec_trace_return_bool_api(^{
758 do_if_registered(soscc_WaitForInitialSync, error);
759
760 return simple_bool_error_request(kSecXPCOpWaitForInitialSync, error);
761 }, NULL)
762 }
763
764 CFArrayRef SOSCCCopyYetToSyncViewsList(CFErrorRef* error)
765 {
766 sec_trace_enter_api(NULL);
767 sec_trace_return_api(CFArrayRef, ^{
768 do_if_registered(soscc_CopyYetToSyncViewsList, error);
769
770 return simple_array_error_request(kSecXPCOpCopyYetToSyncViews, error);
771 }, NULL)
772 }
773
774 bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error)
775 {
776 sec_trace_enter_api(NULL);
777 sec_trace_return_bool_api(^{
778 do_if_registered(soscc_RequestEnsureFreshParameters, error);
779
780 return simple_bool_error_request(kSecXPCOpRequestEnsureFreshParameters, error);
781 }, NULL)
782 }
783
784 CFStringRef SOSCCGetAllTheRings(CFErrorRef *error){
785 sec_trace_enter_api(NULL);
786 sec_trace_return_api(CFStringRef, ^{
787 do_if_registered(soscc_GetAllTheRings, error);
788
789
790 return simple_cfstring_error_request(kSecXPCOpGetAllTheRings, error);
791 }, NULL)
792 }
793 bool SOSCCApplyToARing(CFStringRef ringName, CFErrorRef* error)
794 {
795 sec_trace_enter_api(NULL);
796 sec_trace_return_bool_api(^{
797 do_if_registered(soscc_ApplyToARing, ringName, error);
798
799 return cfstring_to_error_request(kSecXPCOpApplyToARing, ringName, error);
800 }, NULL)
801 }
802
803 bool SOSCCWithdrawlFromARing(CFStringRef ringName, CFErrorRef* error)
804 {
805 sec_trace_enter_api(NULL);
806 sec_trace_return_bool_api(^{
807 do_if_registered(soscc_WithdrawlFromARing, ringName, error);
808
809 return cfstring_to_error_request(kSecXPCOpWithdrawlFromARing, ringName, error);
810 }, NULL)
811 }
812
813 SOSRingStatus SOSCCRingStatus(CFStringRef ringName, CFErrorRef* error)
814 {
815 sec_trace_enter_api(NULL);
816 sec_trace_return_api(SOSRingStatus, ^{
817 do_if_registered(soscc_RingStatus, ringName, error);
818
819 return cfstring_to_uint64_request(kSecXPCOpRingStatus, ringName, error);
820 }, CFSTR("SOSCCStatus=%d"))
821 }
822
823 bool SOSCCEnableRing(CFStringRef ringName, CFErrorRef* error)
824 {
825 sec_trace_enter_api(NULL);
826 sec_trace_return_bool_api(^{
827 do_if_registered(soscc_EnableRing, ringName, error);
828
829 return cfstring_to_error_request(kSecXPCOpEnableRing, ringName, error);
830 }, NULL)
831 }
832
833 bool SOSCCAccountSetToNew(CFErrorRef *error)
834 {
835 secwarning("SOSCCAccountSetToNew called");
836 sec_trace_enter_api(NULL);
837 sec_trace_return_bool_api(^{
838 do_if_registered(soscc_SetToNew, error);
839 return simple_bool_error_request(kSecXPCOpAccountSetToNew, error);
840 }, NULL)
841 }
842
843 bool SOSCCResetToOffering(CFErrorRef* error)
844 {
845 secwarning("SOSCCResetToOffering called");
846 sec_trace_enter_api(NULL);
847 sec_trace_return_bool_api(^{
848 do_if_registered(soscc_ResetToOffering, error);
849
850 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
851 }, NULL)
852 }
853
854 bool SOSCCResetToEmpty(CFErrorRef* error)
855 {
856 secwarning("SOSCCResetToEmpty called");
857 sec_trace_enter_api(NULL);
858 sec_trace_return_bool_api(^{
859 do_if_registered(soscc_ResetToEmpty, error);
860
861 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
862 }, NULL)
863 }
864
865 bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
866 {
867 secwarning("SOSCCResetToEmptyWithAnalytics called");
868 sec_trace_enter_api(NULL);
869 sec_trace_return_bool_api(^{
870 do_if_registered(soscc_ResetToEmptyWithAnalytics, parentEvent, error);
871
872 return sfsigninanalytics_bool_error_request(kSecXPCOpResetToEmptyWithAnalytics, parentEvent, error);
873 }, NULL)
874 }
875 bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error)
876 {
877 sec_trace_enter_api(NULL);
878 sec_trace_return_bool_api(^{
879 do_if_registered(soscc_RemovePeersFromCircle, peers, error);
880
881 return info_array_to_bool_error_request(kSecXPCOpRemovePeersFromCircle, peers, error);
882 }, NULL)
883 }
884
885 bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error)
886 {
887 sec_trace_enter_api(NULL);
888 sec_trace_return_bool_api(^{
889 do_if_registered(soscc_RemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
890
891 return info_array_data_to_bool_error_request(kSecXPCOpRemovePeersFromCircleWithAnalytics, peers, parentEvent, error);
892 }, NULL)
893 }
894
895 bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error)
896 {
897 sec_trace_enter_api(NULL);
898 sec_trace_return_bool_api(^{
899 do_if_registered(soscc_RemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
900
901 return sfsigninanalytics_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, parentEvent, error);
902 }, NULL)
903 }
904
905 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
906 {
907 sec_trace_enter_api(NULL);
908 sec_trace_return_bool_api(^{
909 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
910
911 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
912 }, NULL)
913 }
914
915 bool SOSCCLoggedOutOfAccount(CFErrorRef* error)
916 {
917 sec_trace_enter_api(NULL);
918 sec_trace_return_bool_api(^{
919 do_if_registered(soscc_LoggedOutOfAccount, error);
920
921 return simple_bool_error_request(kSecXPCOpLoggedOutOfAccount, error);
922 }, NULL)
923 }
924
925 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
926 {
927 sec_trace_enter_api(NULL);
928 sec_trace_return_bool_api(^{
929 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
930
931 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
932 }, NULL)
933 }
934
935 bool SOSCCSignedOut(bool immediate, CFErrorRef* error)
936 {
937 uint64_t limit = strtoul(optarg, NULL, 10);
938
939 if(immediate)
940 return SOSCCRemoveThisDeviceFromCircle(error);
941 else
942 return SOSCCBailFromCircle_BestEffort(limit, error);
943
944 }
945
946 CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
947 {
948 sec_trace_enter_api(NULL);
949 sec_trace_return_api(CFArrayRef, ^{
950 do_if_registered(soscc_CopyPeerInfo, error);
951
952 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
953 }, CFSTR("return=%@"));
954 }
955
956 CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
957 {
958 sec_trace_enter_api(NULL);
959 sec_trace_return_api(CFArrayRef, ^{
960 do_if_registered(soscc_CopyConcurringPeerInfo, error);
961
962 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
963 }, CFSTR("return=%@"));
964 }
965
966 CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error)
967 {
968 sec_trace_enter_api(NULL);
969 sec_trace_return_api(CFArrayRef, ^{
970 do_if_registered(soscc_CopyGenerationPeerInfo, error);
971
972 return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error);
973 }, CFSTR("return=%@"));
974 }
975
976 CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
977 {
978 sec_trace_enter_api(NULL);
979 sec_trace_return_api(CFArrayRef, ^{
980 do_if_registered(soscc_CopyApplicantPeerInfo, error);
981
982 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
983 }, CFSTR("return=%@"));
984 }
985
986 bool SOSCCValidateUserPublic(CFErrorRef* error){
987 sec_trace_enter_api(NULL);
988 sec_trace_return_api(bool, ^{
989 do_if_registered(soscc_ValidateUserPublic, error);
990
991 return simple_bool_error_request(kSecXPCOpValidateUserPublic, error);
992 }, NULL);
993 }
994
995 CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error)
996 {
997 sec_trace_enter_api(NULL);
998 sec_trace_return_api(CFArrayRef, ^{
999 do_if_registered(soscc_CopyValidPeerPeerInfo, error);
1000
1001 return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error);
1002 }, CFSTR("return=%@"));
1003 }
1004
1005 CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error)
1006 {
1007 sec_trace_enter_api(NULL);
1008 sec_trace_return_api(CFArrayRef, ^{
1009 do_if_registered(soscc_CopyNotValidPeerPeerInfo, error);
1010
1011 return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error);
1012 }, CFSTR("return=%@"));
1013 }
1014
1015 CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error)
1016 {
1017 sec_trace_enter_api(NULL);
1018 sec_trace_return_api(CFArrayRef, ^{
1019 do_if_registered(soscc_CopyRetirementPeerInfo, error);
1020
1021 return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error);
1022 }, CFSTR("return=%@"));
1023 }
1024
1025 CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error)
1026 {
1027 sec_trace_enter_api(NULL);
1028 sec_trace_return_api(CFArrayRef, ^{
1029 do_if_registered(soscc_CopyViewUnawarePeerInfo, error);
1030
1031 return array_of_info_error_request(kSecXPCOpCopyViewUnawarePeerInfo, error);
1032 }, CFSTR("return=%@"));
1033 }
1034
1035 CFDataRef SOSCCCopyAccountState(CFErrorRef* error)
1036 {
1037 sec_trace_enter_api(NULL);
1038 sec_trace_return_api(CFDataRef, ^{
1039 do_if_registered(soscc_CopyAccountState, error);
1040
1041 return data_to_error_request(kSecXPCOpCopyAccountData, error);
1042 }, CFSTR("return=%@"));
1043 }
1044
1045 bool SOSCCDeleteAccountState(CFErrorRef *error)
1046 {
1047 sec_trace_enter_api(NULL);
1048 sec_trace_return_api(bool, ^{
1049 do_if_registered(soscc_DeleteAccountState, error);
1050 return simple_bool_error_request(kSecXPCOpDeleteAccountData, error);
1051 }, NULL);
1052 }
1053 CFDataRef SOSCCCopyEngineData(CFErrorRef* error)
1054 {
1055 sec_trace_enter_api(NULL);
1056 sec_trace_return_api(CFDataRef, ^{
1057 do_if_registered(soscc_CopyEngineData, error);
1058
1059 return data_to_error_request(kSecXPCOpCopyEngineData, error);
1060 }, CFSTR("return=%@"));
1061 }
1062
1063 bool SOSCCDeleteEngineState(CFErrorRef *error)
1064 {
1065 sec_trace_enter_api(NULL);
1066 sec_trace_return_api(bool, ^{
1067 do_if_registered(soscc_DeleteEngineState, error);
1068 return simple_bool_error_request(kSecXPCOpDeleteEngineData, error);
1069 }, NULL);
1070 }
1071
1072 SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error)
1073 {
1074 sec_trace_enter_api(NULL);
1075 sec_trace_return_api(SOSPeerInfoRef, ^{
1076 do_if_registered(soscc_CopyMyPeerInfo, error);
1077
1078 return peer_info_error_request(kSecXPCOpCopyMyPeerInfo, error);
1079 }, CFSTR("return=%@"));
1080 }
1081
1082 static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error)
1083 {
1084 sec_trace_enter_api(NULL);
1085 sec_trace_return_api(CFArrayRef, ^{
1086 do_if_registered(soscc_CopyEngineState, error);
1087
1088 return der_array_error_request(kSecXPCOpCopyEngineState, error);
1089 }, CFSTR("return=%@"));
1090 }
1091
1092 CFStringRef kSOSCCEngineStatePeerIDKey = CFSTR("PeerID");
1093 CFStringRef kSOSCCEngineStateManifestCountKey = CFSTR("ManifestCount");
1094 CFStringRef kSOSCCEngineStateSyncSetKey = CFSTR("SyncSet");
1095 CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump");
1096 CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash");
1097
1098 void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) {
1099
1100 CFArrayForEach(states, ^(const void *value) {
1101 CFDictionaryRef dict = asDictionary(value, NULL);
1102 if (dict) {
1103 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
1104
1105 CFStringRef id = asString(CFDictionaryGetValue(dict, kSOSCCEngineStatePeerIDKey), NULL);
1106
1107 if (id) {
1108 CFStringAppendFormat(description, NULL, CFSTR("remote %@ "), id);
1109 } else {
1110 CFStringAppendFormat(description, NULL, CFSTR("local "));
1111 }
1112
1113 CFSetRef viewSet = asSet(CFDictionaryGetValue(dict, kSOSCCEngineStateSyncSetKey), NULL);
1114 if (viewSet) {
1115 CFStringSetPerformWithDescription(viewSet, ^(CFStringRef setDescription) {
1116 CFStringAppend(description, setDescription);
1117 });
1118 } else {
1119 CFStringAppendFormat(description, NULL, CFSTR("<Missing view set!>"));
1120 }
1121
1122 CFStringAppendFormat(description, NULL, CFSTR(" [%@]"),
1123 CFDictionaryGetValue(dict, kSOSCCEngineStateManifestCountKey));
1124
1125 CFDataRef mainfestHash = asData(CFDictionaryGetValue(dict, kSOSCCEngineStateManifestHashKey), NULL);
1126
1127 if (mainfestHash) {
1128 CFDataPerformWithHexString(mainfestHash, ^(CFStringRef dataString) {
1129 CFStringAppendFormat(description, NULL, CFSTR(" %@"), dataString);
1130 });
1131 }
1132
1133 CFStringRef coderDescription = asString(CFDictionaryGetValue(dict, kSOSCCEngineStateCoderKey), NULL);
1134 if (coderDescription) {
1135 CFStringAppendFormat(description, NULL, CFSTR(" %@"), coderDescription);
1136 }
1137
1138 block(description);
1139
1140 CFReleaseNull(description);
1141 }
1142 });
1143 }
1144
1145 bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) {
1146 CFArrayRef states = SOSCCCopyEngineState(error);
1147 if (states == NULL)
1148 return false;
1149
1150 SOSCCForEachEngineStateAsStringFromArray(states, block);
1151
1152 CFReleaseNull(states);
1153
1154 return true;
1155 }
1156
1157
1158 bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
1159 {
1160 sec_trace_enter_api(NULL);
1161 sec_trace_return_bool_api(^{
1162 do_if_registered(soscc_AcceptApplicants, applicants, error);
1163
1164 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
1165 }, NULL)
1166 }
1167
1168 bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
1169 {
1170 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
1171 sec_trace_return_bool_api(^{
1172 do_if_registered(soscc_RejectApplicants, applicants, error);
1173
1174 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
1175 }, NULL)
1176 }
1177
1178 static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pubKey, CFErrorRef *error)
1179 {
1180 sec_trace_enter_api(NULL);
1181 sec_trace_return_api(SOSPeerInfoRef, ^{
1182 do_if_registered(soscc_SetNewPublicBackupKey, pubKey, error);
1183
1184 return data_to_peer_info_error_request(kSecXPCOpSetNewPublicBackupKey, pubKey, error);
1185 }, CFSTR("return=%@"));
1186 }
1187
1188 SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){
1189 secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()");
1190 CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error);
1191 secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData);
1192 SOSPeerInfoRef copiedPeer = publicKeyData ? SOSSetNewPublicBackupKey(publicKeyData, error) : NULL;
1193 secnotice("devRecovery", "SOSSetNewPublicBackupKey (%@)", copiedPeer);
1194 CFReleaseNull(publicKeyData);
1195 return copiedPeer;
1196 }
1197
1198 bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){
1199 sec_trace_enter_api(NULL);
1200 sec_trace_return_bool_api(^{
1201 do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error);
1202 return keybag_and_bool_to_bool_error_request(kSecXPCOpSetBagForAllSlices, aks_bag, forV0Only, error);
1203 }, NULL);
1204 }
1205
1206
1207 bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){
1208 sec_trace_enter_api(NULL);
1209 sec_trace_return_bool_api(^{
1210 bool retval = false;
1211 do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error);
1212 // NULL recovery_key is handled in recovery_and_bool_to_bool_error_request now.
1213 retval = recovery_and_bool_to_bool_error_request(kSecXPCOpRegisterRecoveryPublicKey, recovery_key, error);
1214 return retval;
1215 }, NULL);
1216 }
1217
1218 CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){
1219 sec_trace_enter_api(NULL);
1220 sec_trace_return_api(CFDataRef, ^{
1221 do_if_registered(soscc_CopyRecoveryPublicKey, error);
1222 return data_to_error_request(kSecXPCOpGetRecoveryPublicKey, error);
1223 }, CFSTR("return=%@"));
1224 }
1225 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
1226 CFStringRef user_label, CFDataRef user_password,
1227 CFErrorRef* error)
1228 {
1229 __block bool result = false;
1230
1231 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1232 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
1233 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
1234 });
1235 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
1236 return true;
1237 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1238 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1239 return result;
1240 });
1241
1242 return result;
1243 }
1244
1245 static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op,
1246 CFStringRef user_label, CFDataRef user_password,
1247 CFStringRef dsid, CFDataRef parentEvent, CFErrorRef* error)
1248 {
1249 __block bool result = false;
1250
1251 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1252 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
1253 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
1254 });
1255 CFStringPerformWithCString(dsid, ^(const char *utr8StrDSID) {
1256 xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID);
1257 });
1258 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
1259 if(parentEvent){
1260 SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
1261 }
1262 return true;
1263 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1264 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1265 return result;
1266 });
1267
1268 return result;
1269 }
1270
1271 bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1272 {
1273 secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label);
1274 return SOSCCSetUserCredentials(user_label, user_password, error);
1275 }
1276
1277 bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
1278 {
1279 secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label);
1280 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1281 sec_trace_return_bool_api(^{
1282 do_if_registered(soscc_SetUserCredentials, user_label, user_password, error);
1283
1284 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
1285 }, NULL)
1286 }
1287
1288 bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1289 {
1290 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label);
1291 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1292 sec_trace_return_bool_api(^{
1293 do_if_registered(soscc_SetUserCredentialsAndDSID, user_label, user_password, dsid, error);
1294
1295 bool result = false;
1296 __block CFStringRef account_dsid = dsid;
1297
1298 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1299 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1300
1301 if(account_dsid == NULL){
1302 account_dsid = CFSTR("");
1303 }
1304 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, nil, error);
1305 out:
1306 return result;
1307
1308 }, NULL)
1309 }
1310
1311 bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error)
1312 {
1313 secnotice("circleOps", "SOSCCSetUserCredentialsAndDSIDWithAnalytics for %@\n", user_label);
1314 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
1315 sec_trace_return_bool_api(^{
1316 do_if_registered(soscc_SetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, dsid, parentEvent, error);
1317
1318 bool result = false;
1319 __block CFStringRef account_dsid = dsid;
1320
1321 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1322 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1323
1324 if(account_dsid == NULL){
1325 account_dsid = CFSTR("");
1326 }
1327 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, account_dsid, parentEvent, error);
1328 out:
1329 return result;
1330
1331 }, NULL)
1332 }
1333
1334 static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) {
1335 sec_trace_return_bool_api(^{
1336 do_if_registered(soscc_TryUserCredentials, user_label, user_password, dsid, error);
1337
1338 bool result = false;
1339 __block CFStringRef account_dsid = dsid;
1340
1341 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1342 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1343
1344 if(account_dsid == NULL){
1345 account_dsid = CFSTR("");
1346 }
1347
1348 return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, nil, error);
1349 out:
1350 return result;
1351
1352 }, NULL)
1353
1354 }
1355
1356 bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
1357 {
1358 secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label);
1359 require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil")));
1360 require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil")));
1361 CFStringRef account_dsid = (dsid != NULL) ? dsid: CFSTR("");
1362 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, account_dsid, error);
1363 out:
1364 return false;
1365 }
1366
1367 bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) {
1368 return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error);
1369 }
1370
1371
1372 bool SOSCCCanAuthenticate(CFErrorRef* error) {
1373 sec_trace_enter_api(NULL);
1374 sec_trace_return_bool_api(^{
1375 do_if_registered(soscc_CanAuthenticate, error);
1376
1377 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
1378 }, NULL)
1379 }
1380
1381 bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
1382 sec_trace_enter_api(NULL);
1383 sec_trace_return_bool_api(^{
1384 do_if_registered(soscc_PurgeUserCredentials, error);
1385
1386 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
1387 }, NULL)
1388 }
1389
1390 enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) {
1391 sec_trace_enter_api(NULL);
1392 sec_trace_return_api(enum DepartureReason, ^{
1393 do_if_registered(soscc_GetLastDepartureReason, error);
1394
1395 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
1396 }, NULL)
1397 }
1398
1399 bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) {
1400 sec_trace_enter_api(NULL);
1401 sec_trace_return_api(bool, ^{
1402 do_if_registered(soscc_SetLastDepartureReason, reason, error);
1403 return securityd_send_sync_and_do(kSecXPCOpSetLastDepartureReason, error,
1404 ^bool(xpc_object_t message, CFErrorRef *error) {
1405 xpc_dictionary_set_int64(message, kSecXPCKeyReason, reason);
1406 return true;
1407 },
1408 ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1409 return xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1410 }
1411 );
1412 }, NULL)
1413 }
1414
1415 CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) {
1416 sec_trace_enter_api(NULL);
1417 sec_trace_return_api(CFStringRef, ^{
1418 do_if_registered(soscc_CopyIncompatibilityInfo, error);
1419
1420 return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error);
1421 }, NULL)
1422 }
1423
1424 bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){
1425 secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration");
1426 sec_trace_enter_api(NULL);
1427 sec_trace_return_bool_api(^{
1428 do_if_registered(soscc_EnsurePeerRegistration, error);
1429
1430 return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error);
1431 }, NULL)
1432 }
1433
1434
1435 CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error)
1436 {
1437 sec_trace_enter_api(NULL);
1438 sec_trace_return_api(CFSetRef, ^{
1439 do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error);
1440
1441 return cfset_cfset_to_cfset_error_request(kSecXPCOpProcessSyncWithPeers, peers, backupPeers, error);
1442 }, NULL)
1443 }
1444
1445
1446 SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
1447 {
1448 sec_trace_enter_api(NULL);
1449 sec_trace_return_api(SyncWithAllPeersReason, ^{
1450 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
1451
1452 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
1453 }, NULL)
1454 }
1455
1456 CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
1457 {
1458 switch (status) {
1459 case kSOSCCInCircle:
1460 return CFSTR("InCircle");
1461 case kSOSCCNotInCircle:
1462 return CFSTR("NotInCircle");
1463 case kSOSCCRequestPending:
1464 return CFSTR("RequestPending");
1465 case kSOSCCCircleAbsent:
1466 return CFSTR("CircleAbsent");
1467 case kSOSCCError:
1468 return CFSTR("InternalError");
1469 default:
1470 return CFSTR("Unknown Status");
1471 };
1472 }
1473
1474
1475 CFStringRef SOSCCGetViewResultDescription(SOSViewResultCode vrc)
1476 {
1477 switch (vrc) {
1478 case kSOSCCGeneralViewError:
1479 return CFSTR("GeneralViewError");
1480 case kSOSCCViewMember:
1481 return CFSTR("ViewMember");
1482 case kSOSCCViewNotMember:
1483 return CFSTR("ViewNotMember");
1484 case kSOSCCViewNotQualified:
1485 return CFSTR("ViewNotQualified");
1486 case kSOSCCNoSuchView:
1487 return CFSTR("ViewUndefined");
1488 default:
1489 return CFSTR("Unknown View Status");
1490 };
1491 }
1492
1493
1494 static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t error_result,
1495 CFStringRef name, uint64_t action, CFErrorRef *error) {
1496 __block int64_t result = error_result;
1497
1498 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1499 CFStringPerformWithCString(name, ^(const char *utf8Str) {
1500 xpc_dictionary_set_string(message, kSecXPCKeyViewName, utf8Str);
1501 });
1502 xpc_dictionary_set_int64(message, kSecXPCKeyViewActionCode, action);
1503 return true;
1504 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1505 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
1506 result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
1507 }
1508 return result != error_result;
1509 });
1510
1511 return result;
1512 }
1513
1514 SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) {
1515 if(actionCode == kSOSCCViewQuery) {
1516 uint64_t circleStat = SOSGetCachedCircleBitmask();
1517 if(circleStat & CC_STATISVALID) {
1518 SOSViewResultCode retval = kSOSCCViewNotMember;
1519 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1520 if(enabledViews) {
1521 if(CFSetContainsValue(enabledViews, view)) {
1522 retval = kSOSCCViewMember;
1523 } else {
1524 retval = kSOSCCViewNotMember;
1525 }
1526 CFReleaseNull(enabledViews);
1527 }
1528 return retval;
1529 }
1530 }
1531 sec_trace_enter_api(NULL);
1532 sec_trace_return_api(SOSViewResultCode, ^{
1533 do_if_registered(soscc_View, view, actionCode, error);
1534
1535 return (SOSViewResultCode) name_action_to_code_request(kSecXPCOpView, kSOSCCGeneralViewError, view, actionCode, error);
1536 }, CFSTR("SOSViewResultCode=%d"))
1537 }
1538
1539
1540 bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) {
1541 CFErrorRef *error = NULL;
1542 __block bool result = false;
1543
1544 sec_trace_enter_api(NULL);
1545 sec_trace_return_bool_api(^{
1546 do_if_registered(soscc_ViewSet, enabledViews, disabledViews);
1547 return securityd_send_sync_and_do(kSecXPCOpViewSet, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1548 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1549 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1550 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1551 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1552 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1553 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1554 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1555 return result;
1556 });
1557 }, NULL)
1558 }
1559
1560 bool SOSCCViewSetWithAnalytics(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) {
1561 CFErrorRef *error = NULL;
1562 __block bool result = false;
1563
1564 sec_trace_enter_api(NULL);
1565 sec_trace_return_bool_api(^{
1566 do_if_registered(soscc_ViewSetWithAnalytics, enabledViews, disabledViews, parentEvent);
1567 return securityd_send_sync_and_do(kSecXPCOpViewSetWithAnalytics, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1568 xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error);
1569 xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error);
1570 if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc);
1571 if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc);
1572 if(parentEvent) SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error);
1573 return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ;
1574 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
1575 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
1576 return result;
1577 });
1578 }, NULL)
1579 }
1580
1581 static CFStringRef copyViewNames(size_t n, CFStringRef *views) {
1582 CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0);
1583 CFStringAppend(retval, CFSTR("|"));
1584 for(size_t i = 0; i < n; i++) {
1585 CFStringAppend(retval, views[i]);
1586 CFStringAppend(retval, CFSTR("|"));
1587 }
1588 return retval;
1589 }
1590
1591 static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) {
1592 __block bool retval = true;
1593 CFErrorRef error = NULL;
1594
1595 if(n == 0 || views == NULL) return false;
1596 CFStringRef viewString = copyViewNames(n, views);
1597
1598 SOSCCStatus cstatus = SOSCCThisDeviceIsInCircle(&error);
1599 if(cstatus != kSOSCCInCircle) {
1600 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) Error: (%@)", viewString, SOSCCGetStatusDescription(cstatus), error);
1601 retval = false;
1602 }
1603
1604 if(retval == true) {
1605 // use cached values if valid
1606 uint64_t circleStat = SOSGetCachedCircleBitmask();
1607 if(circleStat & CC_STATISVALID) {
1608 CFSetRef enabledViews = SOSCreateCachedViewStatus();
1609 if(enabledViews) {
1610 for(size_t i = 0; i < n; i++) {
1611 if(!CFSetContainsValue(enabledViews, views[i])) {
1612 retval = false;
1613 }
1614 }
1615 CFReleaseNull(enabledViews);
1616 CFReleaseNull(viewString);
1617 return retval;
1618 }
1619 }
1620
1621 // make the individual calls otherwise.
1622 for(size_t i = 0; i < n; i++) {
1623 SOSViewResultCode vstatus = SOSCCView(views[i], kSOSCCViewQuery, &error);
1624 if(vstatus != kSOSCCViewMember) {
1625 secnotice("viewCheck", "Checking view / circle status for %@: SOSCCStatus: (%@) SOSViewResultCode(%@) Error: (%@)", views[i],
1626 SOSCCGetStatusDescription(cstatus), SOSCCGetViewResultDescription(vstatus), error);
1627 retval = false;
1628 }
1629 }
1630 }
1631
1632 if(retval == true) {
1633 secnotice("viewCheck", "Checking view / circle status for %@: ENABLED", viewString);
1634 }
1635 CFReleaseNull(error);
1636 CFReleaseNull(viewString);
1637 return retval;
1638 }
1639
1640 bool SOSCCIsIcloudKeychainSyncing(void) {
1641 CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable };
1642 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1643 }
1644
1645 bool SOSCCIsSafariSyncing(void) {
1646 CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards };
1647 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1648 }
1649
1650 bool SOSCCIsAppleTVSyncing(void) {
1651 CFStringRef views[] = { kSOSViewAppleTV };
1652 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1653 }
1654
1655 bool SOSCCIsHomeKitSyncing(void) {
1656 CFStringRef views[] = { kSOSViewHomeKit };
1657 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1658 }
1659
1660 bool SOSCCIsWiFiSyncing(void) {
1661 CFStringRef views[] = { kSOSViewWiFi };
1662 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1663 }
1664
1665 bool SOSCCIsContinuityUnlockSyncing(void) {
1666 CFStringRef views[] = { kSOSViewContinuityUnlock };
1667 return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views);
1668 }
1669
1670
1671 bool SOSCCSetEscrowRecord(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error ){
1672 secnotice("escrow", "enter SOSCCSetEscrowRecord");
1673 sec_trace_enter_api(NULL);
1674 sec_trace_return_bool_api(^{
1675 do_if_registered(soscc_SetEscrowRecords, escrow_label, tries, error);
1676
1677 return escrow_to_bool_error_request(kSecXPCOpSetEscrowRecord, escrow_label, tries, error);
1678 }, NULL)
1679 }
1680
1681 CFDictionaryRef SOSCCCopyEscrowRecord(CFErrorRef *error){
1682 secnotice("escrow", "enter SOSCCCopyEscrowRecord");
1683 sec_trace_enter_api(NULL);
1684 sec_trace_return_api(CFDictionaryRef, ^{
1685 do_if_registered(soscc_CopyEscrowRecords, error);
1686
1687 return strings_to_dictionary_error_request(kSecXPCOpGetEscrowRecord, error);
1688 }, CFSTR("return=%@"))
1689
1690 }
1691
1692 CFDictionaryRef SOSCCCopyBackupInformation(CFErrorRef *error) {
1693 secnotice("escrow", "enter SOSCCCopyBackupInformation");
1694 sec_trace_enter_api(NULL);
1695 sec_trace_return_api(CFDictionaryRef, ^{
1696 do_if_registered(soscc_CopyBackupInformation, error);
1697 return strings_to_dictionary_error_request(kSecXPCOpCopyBackupInformation, error);
1698 }, CFSTR("return=%@"))
1699 }
1700
1701 bool SOSWrapToBackupSliceKeyBagForView(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error) {
1702 sec_trace_enter_api(NULL);
1703 sec_trace_return_bool_api(^{
1704 do_if_registered(sosbskb_WrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error);
1705
1706 return cfstring_and_cfdata_to_cfdata_cfdata_error_request(kSecXPCOpWrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error);
1707 }, NULL)
1708 }
1709
1710
1711 SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) {
1712 secnotice("hsa2PB", "enter SOSCCCopyApplication applicant");
1713 sec_trace_enter_api(NULL);
1714
1715 sec_trace_return_api(SOSPeerInfoRef, ^{
1716 do_if_registered(soscc_CopyApplicant, error);
1717 return peer_info_error_request(kSecXPCOpCopyApplication, error);
1718 }, CFSTR("return=%@"));
1719 }
1720
1721 bool SOSCCCleanupKVSKeys(CFErrorRef *error) {
1722 secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys");
1723 sec_trace_enter_api(NULL);
1724 sec_trace_return_bool_api(^{
1725 do_if_registered(soscc_SOSCCCleanupKVSKeys, error);
1726
1727 return simple_bool_error_request(kSecXPCOpKVSKeyCleanup, error);
1728 }, NULL)
1729
1730 return false;
1731 }
1732
1733 bool SOSCCTestPopulateKVSWithBadKeys(CFErrorRef *error) {
1734 secnotice("cleanup-keys", "enter SOSCCPopulateKVSWithBadKeys");
1735 sec_trace_enter_api(NULL);
1736 sec_trace_return_bool_api(^{
1737 do_if_registered(soscc_SOSCCTestPopulateKVSWithBadKeys, error);
1738
1739 return simple_bool_error_request(kSecXPCOpPopulateKVS, error);
1740 }, NULL)
1741
1742 return false;
1743 }
1744
1745 CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) {
1746 secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver");
1747 sec_trace_enter_api(NULL);
1748
1749 sec_trace_return_api(CFDataRef, ^{
1750 CFDataRef result = NULL;
1751 do_if_registered(soscc_CopyCircleJoiningBlob, applicant, error);
1752 CFDataRef piData = SOSPeerInfoCopyEncodedData(applicant, kCFAllocatorDefault, error);
1753 result = cfdata_error_request_returns_cfdata(kSecXPCOpCopyCircleJoiningBlob, piData, error);
1754 CFReleaseNull(piData);
1755 return result;
1756 }, CFSTR("return=%@"));
1757 }
1758
1759 CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) {
1760 secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver");
1761 sec_trace_enter_api(NULL);
1762
1763 sec_trace_return_api(CFDataRef, ^{
1764 do_if_registered(soscc_CopyInitialSyncData, flags, error);
1765 return flags_to_data_error_request(kSecXPCOpCopyInitialSyncBlob, flags, error);
1766 }, CFSTR("return=%@"));
1767 }
1768
1769 bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) {
1770 secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant");
1771 sec_trace_enter_api(NULL);
1772 sec_trace_return_bool_api(^{
1773 do_if_registered(soscc_JoinWithCircleJoiningBlob, joiningBlob, version, error);
1774
1775 return cfdata_and_int_error_request_returns_bool(kSecXPCOpJoinWithCircleJoiningBlob, joiningBlob, version, error);
1776 }, NULL)
1777 }
1778
1779 bool SOSCCIsThisDeviceLastBackup(CFErrorRef *error) {
1780 secnotice("peer", "enter SOSCCIsThisDeviceLastBackup");
1781 sec_trace_enter_api(NULL);
1782 sec_trace_return_bool_api(^{
1783 do_if_registered(soscc_IsThisDeviceLastBackup, error);
1784
1785 return simple_bool_error_request(kSecXPCOpIsThisDeviceLastBackup, error);
1786 }, NULL)
1787 }
1788
1789 CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) {
1790 secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled");
1791 sec_trace_enter_api(NULL);
1792 sec_trace_return_api(CFBooleanRef, ^{
1793 do_if_registered(soscc_SOSCCPeersHaveViewsEnabled, viewNames, error);
1794
1795 return cfarray_to_cfboolean_error_request(kSecXPCOpPeersHaveViewsEnabled, viewNames, error);
1796 }, CFSTR("return=%@"))
1797 }
1798
1799 bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1800 secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending");
1801
1802 sec_trace_return_bool_api(^{
1803 do_if_registered(soscc_SOSCCMessageFromPeerIsPending, peer, error);
1804
1805 return peer_info_to_bool_error_request(kSecXPCOpMessageFromPeerIsPending, peer, error);
1806 }, NULL)
1807
1808 }
1809
1810 bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) {
1811 sec_trace_return_bool_api(^{
1812 do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error);
1813
1814 return peer_info_to_bool_error_request(kSecXPCOpSendToPeerIsPending, peer, error);
1815 }, NULL)
1816 }
1817
1818 /*
1819 * SecSOSStatus interfaces
1820 */
1821
1822 @interface SecSOSStatus : NSObject {
1823 NSXPCConnection* _connection;
1824 }
1825 @property NSXPCConnection *connection;
1826 @end
1827
1828 @implementation SecSOSStatus
1829 @synthesize connection = _connection;
1830
1831 - (instancetype) init
1832 {
1833 if ((self = [super init]) == NULL)
1834 return NULL;
1835
1836 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
1837 _SOSControlSetupInterface(interface);
1838
1839 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0];
1840 if (self.connection == NULL){
1841 return NULL;
1842 }
1843 self.connection.remoteObjectInterface = interface;
1844
1845 [self.connection resume];
1846
1847 return self;
1848 }
1849
1850 @end
1851
1852 static id<SOSControlProtocol>
1853 SOSCCGetStatusObject(CFErrorRef *error)
1854 {
1855 if (gSecurityd && gSecurityd->soscc_status)
1856 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1857
1858 static SecSOSStatus *control;
1859 static dispatch_once_t onceToken;
1860 dispatch_once(&onceToken, ^{
1861 control = [[SecSOSStatus alloc] init];
1862 });
1863 return control.connection.remoteObjectProxy;
1864 }
1865
1866
1867 static id<SOSControlProtocol>
1868 SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) {
1869 if (gSecurityd && gSecurityd->soscc_status)
1870 return (__bridge id<SOSControlProtocol>)gSecurityd->soscc_status();
1871
1872 static SecSOSStatus *control;
1873 static dispatch_once_t onceToken;
1874 dispatch_once(&onceToken, ^{
1875 control = [[SecSOSStatus alloc] init];
1876 });
1877
1878 __block NSError *localError = nil;
1879 id <SOSControlProtocol> synchronousRemoteObject = [control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
1880 secnotice("ghostbust", "An error occurred on the xpc connection to setup the background session: %@", error );
1881 if(error) {
1882 localError = error;
1883 }
1884 }];
1885 if(cferror && localError) {
1886 *cferror = (__bridge CFErrorRef)(localError);
1887 }
1888 return synchronousRemoteObject;
1889 }
1890
1891
1892
1893 void
1894 SOSCCAccountGetPublicKey(void (^reply)(BOOL trusted, NSData *data, NSError *error))
1895 {
1896 CFErrorRef error = NULL;
1897 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1898 if (status == NULL) {
1899 reply(false, NULL, (__bridge NSError *)error);
1900 CFReleaseNull(error);
1901 return;
1902 }
1903
1904 [status userPublicKey:reply];
1905 }
1906
1907 void
1908 SOSCCAccountGetAccountPrivateCredential(void (^complete)(NSData *data, NSError *error))
1909 {
1910 CFErrorRef error = NULL;
1911 id<SOSControlProtocol> status = SOSCCGetStatusObject(&error);
1912 if (status == NULL) {
1913 complete(NULL, (__bridge NSError *)error);
1914 CFReleaseNull(error);
1915 return;
1916 }
1917
1918 [status validatedStashedAccountCredential:complete];
1919 }
1920
1921 void
1922 SOSCCAccountGetKeyCircleGeneration(void (^reply)(NSData *data, NSError *error))
1923 {
1924 SOSCCAccountGetPublicKey(^(BOOL __unused trusted, NSData *data, NSError *error){
1925 if (data == NULL) {
1926 reply(data, error);
1927 } else {
1928 NSMutableData *digest = [NSMutableData dataWithLength:CCSHA256_OUTPUT_SIZE];
1929 ccdigest(ccsha256_di(), [data length], [data bytes], [digest mutableBytes]);
1930 reply(digest, error);
1931 }
1932 });
1933 }
1934
1935 NSString *
1936 SOSCCCircleHash(NSError **error)
1937 {
1938 CFErrorRef cferror = NULL;
1939 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&cferror);
1940 if (status == NULL) {
1941 if (error) {
1942 *error = (__bridge NSError *)cferror;
1943 }
1944 CFReleaseNull(cferror);
1945 return NULL;
1946 }
1947 __block NSString *hash = NULL;
1948 [status circleHash:^(NSString *circleHash, NSError *error) {
1949 hash = circleHash;
1950 }];
1951 return hash;
1952 }
1953
1954
1955
1956 void
1957 SOSCCGhostBust(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1958 CFErrorRef error = NULL;
1959 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1960 if (status == NULL) {
1961 complete(false, (__bridge NSError *)error);
1962 CFReleaseNull(error);
1963 return;
1964 }
1965 secnotice("ghostbust", "API Called");
1966 [status ghostBust:options complete:^(bool ghostBusted, NSError *error) {
1967 secnotice("ghostbust", "API returned: %d", ghostBusted);
1968 complete(ghostBusted, error);
1969 }];
1970 }
1971
1972 void SOSCCGhostBustTriggerTimed(SOSAccountGhostBustingOptions options, void (^complete)(bool ghostsBusted, NSError *error)) {
1973 CFErrorRef error = NULL;
1974 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1975 if (status == NULL) {
1976 complete(false, (__bridge NSError *)error);
1977 CFReleaseNull(error);
1978 return;
1979 }
1980 secnotice("ghostbust", "API Trigger Timed Called");
1981 [status ghostBustTriggerTimed:options complete:^(bool ghostBusted, NSError *error) {
1982 secnotice("ghostbust", "API Trigger Timed returned: %d", ghostBusted);
1983 complete(ghostBusted, error);
1984 }];
1985 }
1986
1987 void SOSCCGhostBustInfo(void (^complete)(NSData *json, NSError *error)) {
1988 CFErrorRef error = NULL;
1989 id<SOSControlProtocol> status = SOSCCGetSynchronousStatusObject(&error);
1990 if (status == NULL) {
1991 complete(false, (__bridge NSError *)error);
1992 CFReleaseNull(error);
1993 return;
1994 }
1995 secnotice("ghostbust", "API Info Called");
1996 [status ghostBustInfo:^(NSData *json, NSError *error) {
1997 secnotice("ghostbust", "API Info returned");
1998 complete(json, error);
1999 }];
2000 }
2001
2002