]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c
Security-58286.31.2.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / CKBridge / SOSCloudKeychainClient.c
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 SOSCloudTransport.c - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle
26 These are the exported functions from CloudKeychainProxy
27 */
28
29 /*
30 This XPC service is essentially just a proxy to iCloud KVS, which exists since
31 at one time the main security code could not link against Foundation.
32
33 See sendTSARequestWithXPC in tsaSupport.c for how to call the service
34
35 The client of an XPC service does not get connection events, nor does it
36 need to deal with transactions.
37 */
38
39 #include <AssertMacros.h>
40
41 #include <xpc/xpc.h>
42 #include <CoreFoundation/CoreFoundation.h>
43 #include <CoreFoundation/CFXPCBridge.h>
44 #include <sysexits.h>
45 #include <syslog.h>
46 #include <os/activity.h>
47 #include <CoreFoundation/CFUserNotification.h>
48 #include <Security/SecureObjectSync/SOSInternal.h>
49 #include <notify.h>
50
51 #include <utilities/debugging.h>
52 #include <utilities/SecCFWrappers.h>
53 #include <utilities/SecXPCError.h>
54
55 #include "SOSCloudKeychainConstants.h"
56 #include "SOSCloudKeychainClient.h"
57 #include "SOSUserKeygen.h"
58 #include "SecOTRSession.h"
59
60 #include <os/activity.h>
61 #include <os/state_private.h>
62
63
64 static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error");
65
66 #define SOSCKCSCOPE "sync"
67
68 // MARK: ---------- SOSCloudTransport ----------
69
70 /* SOSCloudTransport, a statically initialized transport singleton. */
71 static SOSCloudTransportRef sTransport = NULL;
72
73 static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void);
74
75 void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport) {
76 sTransport = transport;
77 }
78
79 void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock);
80
81
82
83 /* Return the singleton cloud transport instance. */
84 CFDictionaryRef SOSCloudCopyKVSState(void) {
85 __block CFDictionaryRef retval = NULL;
86
87 static dispatch_queue_t processQueue = NULL;
88 static dispatch_once_t onceToken;
89 dispatch_once(&onceToken, ^{
90 processQueue = dispatch_queue_create("KVSStateCapture", DISPATCH_QUEUE_SERIAL);
91 });
92
93 if (processQueue == NULL)
94 return NULL;
95
96 dispatch_semaphore_t waitSemaphore = NULL;
97
98 waitSemaphore = dispatch_semaphore_create(0);
99
100 CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error) {
101 retval = returnedValues;
102 if (retval) CFRetain(retval);
103 dispatch_semaphore_signal(waitSemaphore);
104 };
105
106 SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
107
108 dispatch_semaphore_wait(waitSemaphore, DISPATCH_TIME_FOREVER);
109 dispatch_release(waitSemaphore);
110
111 return retval;
112 }
113
114
115 os_state_block_t kvsStateBlock = ^os_state_data_t(os_state_hints_t hints) {
116 os_state_data_t retval = NULL;
117 __block CFDictionaryRef kvsdict = NULL;
118 CFDataRef serializedKVS = NULL;
119
120 require_quiet(hints->osh_api == 3, errOut); // only grab on sysdiagnose or command lin
121
122 kvsdict = SOSCloudCopyKVSState();
123
124 require_quiet(kvsdict, errOut);
125 serializedKVS = CFPropertyListCreateData(kCFAllocatorDefault, kvsdict, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
126 size_t statelen = CFDataGetLength(serializedKVS);
127 retval = (os_state_data_t)calloc(1, OS_STATE_DATA_SIZE_NEEDED(statelen));
128 require_quiet(retval, errOut);
129
130 retval->osd_type = OS_STATE_DATA_SERIALIZED_NSCF_OBJECT;
131 memcpy(retval->osd_data, CFDataGetBytePtr(serializedKVS), statelen);
132 retval->osd_size = statelen;
133 strcpy(retval->osd_title, "CloudCircle KVS Object");
134 errOut:
135 CFReleaseNull(kvsdict);
136 CFReleaseNull(serializedKVS);
137 return retval;
138 };
139
140
141 static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void)
142 {
143 static dispatch_once_t sTransportOnce;
144 dispatch_once(&sTransportOnce, ^{
145 if (!sTransport)
146 SOSCloudKeychainSetTransport(SOSCloudTransportCreateXPCTransport());
147 // provide state handler to sysdiagnose and logging
148 os_state_add_handler(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), kvsStateBlock);
149 });
150 return sTransport;
151 }
152
153
154 // MARK: ----- utilities -----
155
156 static CFErrorRef makeError(CFIndex which)
157 {
158 CFDictionaryRef userInfo = NULL;
159 return CFErrorCreate(kCFAllocatorDefault, sErrorDomain, which, userInfo);
160 }
161
162 // MARK: ----- DEBUG Utilities -----
163
164 //------------------------------------------------------------------------------------------------
165 // DEBUG only
166 //------------------------------------------------------------------------------------------------
167
168 static void describeXPCObject(char *prefix, xpc_object_t object)
169 {
170 //#ifndef NDEBUG
171 // This is useful for debugging.
172 if (object)
173 {
174 char *desc = xpc_copy_description(object);
175 secdebug(SOSCKCSCOPE, "%s%s\n", prefix, desc);
176 free(desc);
177 }
178 else
179 secdebug(SOSCKCSCOPE, "%s<NULL>\n", prefix);
180 //#endif
181 }
182
183 static void describeXPCType(char *prefix, xpc_type_t xtype)
184 {
185 // Add others as necessary, e.g. XPC_TYPE_DOUBLE
186 #ifndef NDEBUG
187 // This is useful for debugging.
188 char msg[256]={0,};
189 if (XPC_TYPE_CONNECTION == xtype)
190 strcpy(msg, "XPC_TYPE_CONNECTION");
191 else if (XPC_TYPE_ERROR == xtype)
192 strcpy(msg, "XPC_TYPE_ERROR");
193 else if (XPC_TYPE_DICTIONARY == xtype)
194 strcpy(msg, "XPC_TYPE_DICTIONARY");
195 else
196 strcpy(msg, "<unknown>");
197
198 secdebug(SOSCKCSCOPE, "%s type:%s\n", prefix, msg);
199 #endif
200 }
201
202 // MARK: ---------- SOSXPCCloudTransport ----------
203
204 typedef struct SOSXPCCloudTransport *SOSXPCCloudTransportRef;
205 struct SOSXPCCloudTransport
206 {
207 struct SOSCloudTransport transport;
208 xpc_connection_t serviceConnection;
209 xpc_connection_t idsProxyServiceConnection;
210 dispatch_queue_t xpc_queue;
211 };
212
213 static bool xpc_event_filter(const xpc_connection_t peer, xpc_object_t event, CFErrorRef *error)
214 {
215 // return true if the type is XPC_TYPE_DICTIONARY (and therefore something more to process)
216 secdebug(SOSCKCSCOPE, "handle_connection_event\n");
217 xpc_type_t xtype = xpc_get_type(event);
218 describeXPCType("handle_xpc_event", xtype);
219 if (XPC_TYPE_CONNECTION == xtype)
220 {
221 secdebug(SOSCKCSCOPE, "handle_xpc_event: XPC_TYPE_CONNECTION (unexpected)");
222 // The client of an XPC service does not get connection events
223 // For now, we log this and keep going
224 describeXPCObject("handle_xpc_event: XPC_TYPE_CONNECTION, obj : ", event);
225 #if 0
226 if (error)
227 *error = makeError(kSOSOUnexpectedConnectionEvent); // FIX
228 assert(true);
229 #endif
230 }
231 else
232 if (XPC_TYPE_ERROR == xtype)
233 {
234 #ifndef NDEBUG
235 const char *estr = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
236 #endif
237 secdebug(SOSCKCSCOPE, "default: xpc error: %s\n", estr);
238 #if 0 // just log for now
239 CFStringRef errStr = CFStringCreateWithCString(kCFAllocatorDefault, estr, kCFStringEncodingUTF8);
240 CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
241 if (errStr)
242 CFDictionaryAddValue(userInfo, kCFErrorLocalizedDescriptionKey, errStr);
243 if (error)
244 *error = CFErrorCreate(kCFAllocatorDefault, sErrorDomain, kSOSOXPCErrorEvent, userInfo);
245 CFReleaseSafe(errStr);
246 CFReleaseSafe(userInfo);
247 #endif
248 }
249 else
250 if (XPC_TYPE_DICTIONARY == xtype)
251 {
252 secdebug(SOSCKCSCOPE, "received dictionary event %p\n", event);
253 return true;
254 }
255 else
256 {
257 secdebug(SOSCKCSCOPE, "default: unexpected connection event %p\n", event);
258 describeXPCObject("handle_xpc_event: obj : ", event);
259 if (error)
260 *error = makeError(kSOSOUnexpectedXPCEvent);
261 }
262 return false;
263 }
264
265 static void setupIDSProxyServiceConnection(SOSXPCCloudTransportRef transport)
266 {
267 secnotice(SOSCKCSCOPE, "IDS Transport: setting up xpc connection");
268 transport->idsProxyServiceConnection = xpc_connection_create_mach_service(xpcIDSServiceName, transport->xpc_queue, 0);
269
270 secdebug(SOSCKCSCOPE, "ids service connection: %p\n", transport->idsProxyServiceConnection);
271
272 xpc_connection_set_event_handler(transport->idsProxyServiceConnection, ^(xpc_object_t event) {
273 secdebug(SOSCKCSCOPE, "IDS Transport, xpc_connection_set_event_handler\n");
274 if(event == XPC_ERROR_CONNECTION_INVALID){
275 secnotice(SOSCKCSCOPE, "IDS Transport: xpc connection invalid. Oh well.");
276 }
277 });
278
279 xpc_connection_activate(transport->idsProxyServiceConnection);
280 xpc_retain(transport->idsProxyServiceConnection);
281 }
282
283 static void teardownIDSProxyServiceConnection(SOSXPCCloudTransportRef transport)
284 {
285 secnotice(SOSCKCSCOPE, "IDS Transport: tearing down xpc connection");
286 xpc_release(transport->idsProxyServiceConnection);
287 transport->idsProxyServiceConnection = NULL;
288 }
289
290 static void setupServiceConnection(SOSXPCCloudTransportRef transport)
291 {
292 secnotice(SOSCKCSCOPE, "CKP Transport: setting up xpc connection");
293 transport->serviceConnection = xpc_connection_create_mach_service(xpcServiceName, transport->xpc_queue, 0);
294
295 secdebug(SOSCKCSCOPE, "serviceConnection: %p\n", transport->serviceConnection);
296
297 xpc_connection_set_event_handler(transport->serviceConnection, ^(xpc_object_t event) {
298 secdebug(SOSCKCSCOPE, "CKP Transport, xpc_connection_set_event_handler\n");
299 if(event == XPC_ERROR_CONNECTION_INVALID){
300 secnotice(SOSCKCSCOPE, "CKP Transport: xpc connection invalid. Oh well.");
301 }
302 });
303
304 xpc_connection_activate(transport->serviceConnection);
305 xpc_retain(transport->serviceConnection);
306 }
307
308 static void teardownServiceConnection(SOSXPCCloudTransportRef transport)
309 {
310 secnotice(SOSCKCSCOPE, "CKP Transport: tearing down xpc connection");
311 xpc_release(transport->serviceConnection);
312 transport->serviceConnection = NULL;
313 }
314
315 static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport)
316 {
317 secdebug(SOSCKCSCOPE, "initXPCConnection\n");
318
319 transport->xpc_queue = dispatch_queue_create(xpcServiceName, DISPATCH_QUEUE_SERIAL);
320
321 setupServiceConnection(transport);
322 setupIDSProxyServiceConnection(transport);
323
324 // Any time a new session starts, reestablish the XPC connections.
325 int token;
326 notify_register_dispatch("com.apple.system.loginwindow.desktopUp", &token, transport->xpc_queue, ^(int token2) {
327 secnotice(SOSCKCSCOPE, "CKP/IDS Transport: desktopUp happened, reestablishing xpc connections");
328 teardownServiceConnection(transport);
329 setupServiceConnection(transport);
330 teardownIDSProxyServiceConnection(transport);
331 setupIDSProxyServiceConnection(transport);
332 });
333 }
334
335 static void talkWithIDS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
336 {
337 CFErrorRef connectionError = NULL;
338
339 os_activity_t trace_activity = os_activity_start("talkWithIDS", OS_ACTIVITY_FLAG_DEFAULT);
340 require_action(transport->idsProxyServiceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen));
341 require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError));
342 dispatch_retain(processQueue);
343
344 xpc_connection_send_message_with_reply(transport->idsProxyServiceConnection, message, transport->xpc_queue, ^(xpc_object_t reply)
345 {
346 CFErrorRef serverError = NULL;
347 CFTypeRef object = NULL;
348 if (xpc_event_filter(transport->idsProxyServiceConnection, reply, &serverError) && reply)
349 {
350 describeXPCObject("IDS Proxy: reply : ", reply);
351 if (serverError)
352 secerror("Error from xpc_event_filter: %@", serverError);
353 xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue);
354 if (xrv)
355 {
356 describeXPCObject("talkwithIDS: xrv: ", xrv);
357 /*
358 * The given XPC object must be one that was previously returned by
359 * _CFXPCCreateXPCMessageWithCFObject().
360 */
361 object = _CFXPCCreateCFObjectFromXPCObject(xrv); // CF object is retained; release in callback
362 secnotice("talkwithIDS", "converted CF object: %@", object);
363 }
364 else
365 secerror("missing value reply");
366
367 xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError);
368 if (xerror)
369 serverError = SecCreateCFErrorWithXPCObject(xerror); // use SecCFCreateErrorWithFormat?
370 }
371 dispatch_async(processQueue, ^{
372 if (replyBlock)
373 replyBlock(object, serverError);
374 CFReleaseSafe(object);
375 if (serverError)
376 {
377 secerror("talkwithIDS callback error: %@", serverError);
378 CFReleaseSafe(serverError);
379 }
380 dispatch_release(processQueue);
381 });
382 });
383 return;
384
385 xit:
386 secerror("talkWithIDS error: %@", connectionError);
387 dispatch_async(processQueue, ^{
388 if (replyBlock)
389 replyBlock(NULL, connectionError);
390 CFReleaseSafe(connectionError);
391 dispatch_release(processQueue);
392 });
393
394 os_activity_end(trace_activity);
395 }
396
397 typedef void (^ProxyReplyBlock)(xpc_object_t reply);
398
399 static bool messageToProxy(SOSXPCCloudTransportRef transport, xpc_object_t message, CFErrorRef *error, dispatch_queue_t processQueue, ProxyReplyBlock replyBlock) {
400 CFErrorRef connectionError = NULL;
401
402 require_action(transport->serviceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen));
403 require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError));
404
405 xpc_connection_send_message_with_reply(transport->serviceConnection, message, processQueue, replyBlock);
406 xit:
407 return CFErrorPropagate(connectionError, error);
408 }
409
410 static void talkWithKVS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
411 {
412 CFErrorRef messagingError = NULL;
413 dispatch_retain(processQueue);
414 bool messaged = messageToProxy(transport, message, &messagingError, transport->xpc_queue, ^(xpc_object_t reply)
415 {
416 CFErrorRef serverError = NULL;
417 CFTypeRef object = NULL;
418 if (xpc_event_filter(transport->serviceConnection, reply, &serverError) && reply)
419 {
420 describeXPCObject("getValuesFromKVS: reply : ", reply);
421 if (serverError)
422 secerror("Error from xpc_event_filter: %@", serverError);
423 xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue);
424 if (xrv)
425 {
426 describeXPCObject("talkWithKVS: xrv: ", xrv);
427 /*
428 * The given XPC object must be one that was previously returned by
429 * _CFXPCCreateXPCMessageWithCFObject().
430 */
431 object = _CFXPCCreateCFObjectFromXPCObject(xrv); // CF object is retained; release in callback
432 secnotice("talkwithkvs", "converted CF object: %@", object);
433 }
434 else
435 secerror("missing value reply");
436
437 xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError);
438 if (xerror)
439 serverError = SecCreateCFErrorWithXPCObject(xerror); // use SecCFCreateErrorWithFormat?
440 }
441 dispatch_async(processQueue, ^{
442 if (replyBlock)
443 replyBlock(object, serverError);
444 CFReleaseSafe(object);
445 if (serverError)
446 {
447 secerror("callback error: %@", serverError);
448 CFReleaseSafe(serverError);
449 }
450 dispatch_release(processQueue);
451 });
452 });
453
454 if (!messaged) {
455 secerror("talkWithKVS error: %@", messagingError);
456 dispatch_async(processQueue, ^{
457 if (replyBlock)
458 replyBlock(NULL, messagingError);
459 CFReleaseSafe(messagingError);
460 dispatch_release(processQueue);
461 });
462 }
463 }
464
465 // MARK: ---------- SOSXPCCloudTransport Client Calls ----------
466
467 /* Concrete function backend implementations. */
468 static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport,
469 CloudItemsChangedBlock itemsChangedBlock) {
470 if (transport->itemsChangedBlock != itemsChangedBlock)
471 {
472 secnotice(SOSCKCSCOPE, "Changing itemsChangedBlock");
473 if (transport->itemsChangedBlock)
474 Block_release(transport->itemsChangedBlock);
475 transport->itemsChangedBlock = Block_copy(itemsChangedBlock);
476 }
477 }
478
479 /* Virtual function backend implementations. */
480 static void SOSCloudTransportPut(SOSCloudTransportRef transport, CFDictionaryRef values, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
481 {
482 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
483 secdebug(SOSCKCSCOPE, "%@", values);
484 CFErrorRef error = NULL;
485 xpc_object_t message = NULL;
486 xpc_object_t xobject = NULL;
487 require_action(values, xit, error = makeError(kSOSObjectNotFoundError));
488
489 message = xpc_dictionary_create(NULL, NULL, 0);
490 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
491 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationPUTDictionary);
492
493 xobject = _CFXPCCreateXPCObjectFromCFObject(values);
494 require_action(xobject, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject));
495 xpc_dictionary_set_value(message, kMessageKeyValue, xobject);
496 xpc_release(xobject);
497
498 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
499 xpc_release(message);
500 return;
501
502 xit:
503 if (replyBlock)
504 replyBlock(NULL, error);
505 CFReleaseSafe(error);
506 }
507
508 /* Get from KVS */
509 void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
510 {
511 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
512 secdebug(SOSCKCSCOPE, "%@", keysToGet);
513 CFErrorRef error = NULL;
514 xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
515 xpc_object_t xkeysToGet = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create();
516
517 require_action(xkeysToGet, xit, error = makeError(kSOSObjectNotFoundError));
518
519 if (keysToGet) // don't add if nulll; will call getall
520 xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToGet);
521
522 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
523 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
524 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGETv2);
525 xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
526
527 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
528 xpc_release(xkeysToGet);
529 xpc_release(xkeysOfInterest);
530 xpc_release(message);
531 return;
532
533 xit:
534 if(xkeysOfInterest)
535 xpc_release(xkeysOfInterest);
536 if(xkeysToGet)
537 xpc_release(xkeysToGet);
538 if (replyBlock)
539 replyBlock(NULL, error);
540 CFReleaseSafe(error);
541 }
542
543 //
544 // Handles NULL by seting xpc_null.
545 static void SecXPCDictionarySetCFObject(xpc_object_t xdict, const char *key, CFTypeRef object)
546 {
547 xpc_object_t xpc_obj = object ? _CFXPCCreateXPCObjectFromCFObject(object) : xpc_null_create();
548 xpc_dictionary_set_value(xdict, key, xpc_obj);
549 xpc_release(xpc_obj);
550 }
551
552 static void SOSCloudTransportGetIDSDeviceID(SOSCloudTransportRef transport, CloudKeychainReplyBlock replyBlock)
553 {
554 dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
555
556 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
557
558 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
559 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
560 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGetDeviceID);
561
562 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
563 xpc_release(message);
564 }
565
566 static void SOSCloudTransportGetPerformanceStats(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
567 {
568 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
569
570 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
571 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
572 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGetIDSPerfCounters);
573
574 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
575 xpc_release(message);
576 }
577
578 static void SOSCloudTransportSendFragmentedIDSMessage(SOSCloudTransportRef transport, CFDictionaryRef messageData, CFStringRef deviceName, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock){
579
580 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
581 xpc_object_t xmessageData = _CFXPCCreateXPCObjectFromCFObject(messageData);
582
583 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
584 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
585 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSendFragmentedIDSMessage);
586
587 xpc_dictionary_set_value(message, kMessageKeyValue, xmessageData);
588 SecXPCDictionarySetCFObject(message, kMessageKeyDeviceName, deviceName);
589 SecXPCDictionarySetCFObject(message, kMessageKeyPeerID, peerID);
590 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
591
592 xpc_release(xmessageData);
593 xpc_release(message);
594 }
595
596 static void SOSCloudTransportRetrievePendingMessagesInFlight(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock){
597
598 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
599
600 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
601 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
602 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGetPendingMesages);
603
604 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
605
606 xpc_release(message);
607 }
608
609 static void SOSCloudTransportCheckIDSDeviceIDAvailability(SOSCloudTransportRef transport, CFArrayRef ids, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
610 {
611 secdebug(SOSCKCSCOPE, "start");
612 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
613
614 xpc_object_t xIDSArray = _CFXPCCreateXPCObjectFromCFObject(ids);
615
616 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
617 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
618 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSendDeviceList);
619
620 SecXPCDictionarySetCFObject(message, kMessageKeyPeerID, peerID);
621 xpc_dictionary_set_value(message, kMessageKeyValue, xIDSArray);
622
623 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
624
625 xpc_release(xIDSArray);
626 xpc_release(message);
627
628 }
629
630 static void SOSCloudTransportSendIDSMessage(SOSCloudTransportRef transport, CFDictionaryRef messageData, CFStringRef deviceName, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock){
631
632 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
633 xpc_object_t xmessageData = _CFXPCCreateXPCObjectFromCFObject(messageData);
634
635 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
636 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
637 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSendIDSMessage);
638
639 xpc_dictionary_set_value(message, kMessageKeyValue, xmessageData);
640 SecXPCDictionarySetCFObject(message, kMessageKeyDeviceName, deviceName);
641 SecXPCDictionarySetCFObject(message, kMessageKeyPeerID, peerID);
642 talkWithIDS(xpcTransport, message, processQueue, replyBlock);
643
644 xpc_release(xmessageData);
645 xpc_release(message);
646 }
647
648 static void SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport,
649 CFDictionaryRef keys,
650 CFStringRef accountUUID,
651 dispatch_queue_t processQueue,
652 CloudKeychainReplyBlock replyBlock)
653 {
654 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
655
656 xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
657 SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageAllKeys, keys);
658
659 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
660 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
661 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeys);
662 xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
663 SecXPCDictionarySetCFObject(message, kMessageKeyAccountUUID, accountUUID);
664
665 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
666 xpc_release(message);
667 xpc_release(xkeysOfInterest);
668 }
669
670 static void SOSCloudTransportRemoveKeys(SOSCloudTransportRef transport,
671 CFArrayRef keys,
672 CFStringRef accountUUID,
673 dispatch_queue_t processQueue,
674 CloudKeychainReplyBlock replyBlock)
675 {
676 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
677
678 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
679 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
680
681 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRemoveKeys);
682 SecXPCDictionarySetCFObject(message, kMessageKeyAccountUUID, accountUUID);
683 SecXPCDictionarySetCFObject(message, kMessageKeyValue, keys);
684
685 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
686 xpc_release(message);
687 }
688
689 static void SOSCloudTransportGetAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
690 {
691 secdebug(SOSCKCSCOPE, "start");
692 SOSCloudTransportGet(transport, NULL, processQueue, replyBlock);
693 }
694
695 static void SOSCloudTransportSync(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
696 {
697 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
698 secdebug(SOSCKCSCOPE, "start");
699 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
700 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
701 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronize);
702 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
703 xpc_release(message);
704 }
705
706 static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
707 {
708 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
709 secnotice(SOSCKCSCOPE, "%s XPC request to CKD: %s", kWAIT2MINID, kOperationSynchronizeAndWait);
710
711 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
712 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
713 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronizeAndWait);
714
715 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
716 xpc_release(message);
717 }
718
719 static void SOSCloudTransportClearAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
720 {
721 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
722 secdebug(SOSCKCSCOPE, "start");
723 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
724 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
725 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationClearStore);
726 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
727 xpc_release(message);
728 }
729
730 static void SOSCloudTransportRequestSyncWithPeers(SOSCloudTransportRef transport, CFArrayRef /* CFStringRef */ peers, CFArrayRef /* CFStringRef */ backupPeers, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
731 {
732 secdebug(SOSCKCSCOPE, "start");
733 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
734
735 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
736
737 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
738 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestSyncWithPeers);
739
740 SecXPCDictionarySetCFObject(xpcmessage, kMessageKeyPeerIDList, peers);
741 SecXPCDictionarySetCFObject(xpcmessage, kMesssgeKeyBackupPeerIDList, backupPeers);
742
743 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
744
745 xpc_release(xpcmessage);
746 }
747
748
749 static bool SOSCloudTransportHasPeerSyncPending(SOSCloudTransportRef transport, CFStringRef peerID, CFErrorRef* error)
750 {
751 secdebug(SOSCKCSCOPE, "start");
752 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
753
754 __block bool isSyncing = false;
755
756 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
757
758 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
759 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationHasPendingSyncWithPeer);
760
761 SecXPCDictionarySetCFObject(xpcmessage, kMessageKeyPeerID, peerID);
762
763 dispatch_semaphore_t wait = dispatch_semaphore_create(0);
764 bool sent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(xpc_object_t reply) {
765 isSyncing = xpc_dictionary_get_bool(reply, kMessageKeyValue);
766 dispatch_semaphore_signal(wait);
767 });
768
769 if (sent) {
770 dispatch_semaphore_wait(wait, DISPATCH_TIME_FOREVER);
771 }
772
773 dispatch_release(wait);
774
775 return sent && isSyncing;
776 }
777
778
779 static bool SOSCloudTransportHasPendingKey(SOSCloudTransportRef transport, CFStringRef keyName, CFErrorRef* error)
780 {
781 secdebug(SOSCKCSCOPE, "start");
782 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
783
784 __block bool kvsHasMessage = false;
785
786 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
787
788 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
789 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationHasPendingKey);
790
791 SecXPCDictionarySetCFObject(xpcmessage, kMessageKeyKey, keyName);
792
793 dispatch_semaphore_t kvsWait = dispatch_semaphore_create(0);
794 bool kvsSent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(xpc_object_t reply) {
795 kvsHasMessage = xpc_dictionary_get_bool(reply, kMessageKeyValue);
796 dispatch_semaphore_signal(kvsWait);
797 });
798
799 if (kvsSent) {
800 dispatch_semaphore_wait(kvsWait, DISPATCH_TIME_FOREVER);
801 }
802
803 dispatch_release(kvsWait);
804
805 return kvsSent && kvsHasMessage;
806 }
807
808
809 static void SOSCloudTransportRequestEnsurePeerRegistration(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
810 {
811 secdebug(SOSCKCSCOPE, "start");
812 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
813
814 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
815 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
816 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestEnsurePeerRegistration);
817
818 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
819
820 xpc_release(xpcmessage);
821 }
822
823 static void SOSCloudTransportRequestPerfCounters(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
824 {
825 secdebug(SOSCKCSCOPE, "start");
826 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
827
828 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
829 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
830 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationPerfCounters);
831
832 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
833
834 xpc_release(xpcmessage);
835 }
836
837
838 static void SOSCloudTransportFlush(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
839 {
840 secdebug(SOSCKCSCOPE, "start");
841 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
842
843 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
844 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
845 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationFlush);
846
847 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
848
849 xpc_release(xpcmessage);
850 }
851
852 static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void)
853 {
854 SOSXPCCloudTransportRef st;
855 st = calloc(1, sizeof(*st));
856 st->transport.put = SOSCloudTransportPut;
857 st->transport.updateKeys = SOSCloudTransportUpdateKeys;
858 st->transport.sendIDSMessage = SOSCloudTransportSendIDSMessage;
859 st->transport.sendFragmentedIDSMessage = SOSCloudTransportSendFragmentedIDSMessage;
860 st->transport.retrieveMessages = SOSCloudTransportRetrievePendingMessagesInFlight;
861
862 st->transport.getDeviceID = SOSCloudTransportGetIDSDeviceID;
863 st->transport.get = SOSCloudTransportGet;
864 st->transport.getAll = SOSCloudTransportGetAll;
865 st->transport.synchronize = SOSCloudTransportSync;
866 st->transport.synchronizeAndWait = SOSCloudTransportSyncAndWait;
867 st->transport.clearAll = SOSCloudTransportClearAll;
868 st->transport.requestSyncWithPeers = SOSCloudTransportRequestSyncWithPeers;
869 st->transport.hasPeerSyncPending = SOSCloudTransportHasPeerSyncPending;
870 st->transport.hasPendingKey = SOSCloudTransportHasPendingKey;
871 st->transport.requestEnsurePeerRegistration = SOSCloudTransportRequestEnsurePeerRegistration;
872 st->transport.requestPerfCounters = SOSCloudTransportRequestPerfCounters;
873 st->transport.getIDSDeviceAvailability = SOSCloudTransportCheckIDSDeviceIDAvailability;
874 st->transport.flush = SOSCloudTransportFlush;
875 st->transport.removeKeys = SOSCloudTransportRemoveKeys;
876 st->transport.counters = SOSCloudTransportGetPerformanceStats;
877 st->transport.itemsChangedBlock = Block_copy(^CFArrayRef(CFDictionaryRef changes) {
878 secerror("Calling default itemsChangedBlock - fatal: %@", changes);
879 assert(false);
880 return NULL;
881 });
882 SOSXPCCloudTransportInit(st);
883 return &st->transport;
884 }
885
886 // MARK: ---------- SOSCloudKeychain concrete client APIs ----------
887 void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock)
888 {
889 secdebug(SOSCKCSCOPE, "start");
890 SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(),
891 itemsChangedBlock);
892 }
893
894 // MARK: ---------- SOSCloudKeychain virtual client APIs ----------
895
896 void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
897 {
898 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
899 if (cTransportRef)
900 cTransportRef->put(cTransportRef, objects, processQueue, replyBlock);
901 }
902
903 void SOSCloudKeychainUpdateKeys(CFDictionaryRef keys, CFStringRef accountUUID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
904 {
905 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
906 if (cTransportRef)
907 cTransportRef->updateKeys(cTransportRef, keys, accountUUID, processQueue, replyBlock);
908 }
909
910
911 void SOSCloudKeychainRemoveKeys(CFArrayRef keys, CFStringRef accountUUID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
912 {
913 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
914 if (cTransportRef)
915 cTransportRef->removeKeys(cTransportRef, keys, accountUUID, processQueue, replyBlock);
916 }
917
918 void SOSCloudKeychainSendIDSMessage(CFDictionaryRef message, CFStringRef deviceName, CFStringRef peerID, dispatch_queue_t processQueue, CFBooleanRef fragmentation, CloudKeychainReplyBlock replyBlock)
919 {
920 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
921
922 if(cTransportRef && fragmentation == kCFBooleanTrue)
923 cTransportRef->sendFragmentedIDSMessage(cTransportRef, message, deviceName, peerID, processQueue, replyBlock);
924 else if(cTransportRef)
925 cTransportRef->sendIDSMessage(cTransportRef, message, deviceName, peerID, processQueue, replyBlock);
926
927 }
928
929 void SOSCloudKeychainRetrievePendingMessageFromProxy(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
930 {
931 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
932
933 if(cTransportRef)
934 cTransportRef->retrieveMessages(cTransportRef, processQueue, replyBlock);
935
936 }
937 void SOSCloudKeychainRetrieveCountersFromIDSProxy(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
938 {
939 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
940
941 if(cTransportRef)
942 cTransportRef->counters(cTransportRef, processQueue, replyBlock);
943
944 }
945 void SOSCloudKeychainGetIDSDeviceID(CloudKeychainReplyBlock replyBlock)
946 {
947 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
948 if (cTransportRef)
949 cTransportRef->getDeviceID(cTransportRef, replyBlock);
950
951 }
952 void SOSCloudKeychainGetIDSDeviceAvailability(CFArrayRef ids, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock){
953
954 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
955
956 if (cTransportRef)
957 cTransportRef->getIDSDeviceAvailability(cTransportRef, ids, peerID, processQueue, replyBlock);
958 }
959 CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates)
960 {
961 CFArrayRef result = NULL;
962 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
963 if (cTransportRef->itemsChangedBlock)
964 result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates);
965 return result;
966 }
967
968 void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
969 {
970 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
971 if (cTransportRef)
972 cTransportRef->get(cTransportRef, keysToGet, processQueue, replyBlock);
973 }
974
975 void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
976 {
977 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
978 if (cTransportRef)
979 cTransportRef->getAll(cTransportRef, processQueue, replyBlock);
980 }
981
982 void SOSCloudKeychainSynchronizeAndWait(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
983 {
984 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
985 if (cTransportRef)
986 cTransportRef->synchronizeAndWait(cTransportRef, processQueue, replyBlock);
987 }
988
989 //DEBUG ONLY
990 void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
991 {
992 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
993 if (cTransportRef)
994 cTransportRef->synchronize(cTransportRef, processQueue, replyBlock);
995 }
996
997 //DEBUG ONLY
998 void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
999 {
1000 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1001 if (cTransportRef)
1002 cTransportRef->clearAll(cTransportRef, processQueue, replyBlock);
1003 }
1004
1005 void SOSCloudKeychainRequestSyncWithPeers(CFArrayRef /* CFStringRef */ peers, CFArrayRef /* CFStringRef */ backupPeers, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
1006 {
1007 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1008 if (cTransportRef)
1009 cTransportRef->requestSyncWithPeers(cTransportRef, peers, backupPeers, processQueue, replyBlock);
1010 }
1011
1012 bool SOSCloudKeychainHasPendingKey(CFStringRef keyName, CFErrorRef* error) {
1013 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1014
1015 return cTransportRef && cTransportRef->hasPendingKey(cTransportRef, keyName, error);
1016 }
1017
1018 bool SOSCloudKeychainHasPendingSyncWithPeer(CFStringRef peerID, CFErrorRef* error) {
1019 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1020
1021 return cTransportRef && cTransportRef->hasPeerSyncPending(cTransportRef, peerID, error);
1022 }
1023
1024 void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
1025 {
1026 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1027 if (cTransportRef)
1028 cTransportRef->requestEnsurePeerRegistration(cTransportRef, processQueue, replyBlock);
1029 }
1030
1031 void SOSCloudKeychainRequestPerfCounters(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
1032 {
1033 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1034 if (cTransportRef)
1035 cTransportRef->requestPerfCounters(cTransportRef, processQueue, replyBlock);
1036 }
1037
1038
1039 void SOSCloudKeychainFlush(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
1040 {
1041 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
1042 if (cTransportRef)
1043 cTransportRef->flush(cTransportRef, processQueue, replyBlock);
1044 }