2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 SOSCloudTransport.c - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle
26 These are the exported functions from CloudKeychainProxy
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.
33 See sendTSARequestWithXPC in tsaSupport.c for how to call the service
35 The client of an XPC service does not get connection events, nor does it
36 need to deal with transactions.
39 #include <AssertMacros.h>
42 #include <CoreFoundation/CoreFoundation.h>
43 #include <CoreFoundation/CFXPCBridge.h>
46 #include <os/activity.h>
47 #include <CoreFoundation/CFUserNotification.h>
48 #include "keychain/SecureObjectSync/SOSInternal.h"
51 #include <utilities/debugging.h>
52 #include <utilities/SecCFWrappers.h>
53 #include <utilities/SecXPCError.h>
55 #include "SOSCloudKeychainConstants.h"
56 #include "SOSCloudKeychainClient.h"
57 #include "SOSUserKeygen.h"
58 #include "SecOTRSession.h"
60 #include <os/activity.h>
61 #include <os/state_private.h>
64 static CFStringRef sErrorDomain
= CFSTR("com.apple.security.sos.transport.error");
66 #define SOSCKCSCOPE "sync"
68 // MARK: ---------- SOSCloudTransport ----------
70 static SOSCloudTransportRef
SOSCloudTransportCreateXPCTransport(void);
72 void SOSCloudTransportGet(SOSCloudTransportRef transport
, CFArrayRef keysToGet
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
);
76 /* Return the singleton cloud transport instance. */
77 CFDictionaryRef
SOSCloudCopyKVSState(void) {
78 __block CFDictionaryRef retval
= NULL
;
80 static dispatch_queue_t processQueue
= NULL
;
81 static dispatch_once_t onceToken
;
82 dispatch_once(&onceToken
, ^{
83 processQueue
= dispatch_queue_create("KVSStateCapture", DISPATCH_QUEUE_SERIAL
);
86 if (processQueue
== NULL
)
89 dispatch_semaphore_t waitSemaphore
= NULL
;
91 waitSemaphore
= dispatch_semaphore_create(0);
93 CloudKeychainReplyBlock replyBlock
= ^ (CFDictionaryRef returnedValues
, CFErrorRef error
) {
94 retval
= returnedValues
;
95 if (retval
) CFRetain(retval
);
96 dispatch_semaphore_signal(waitSemaphore
);
99 SOSCloudKeychainGetAllObjectsFromCloud(processQueue
, replyBlock
);
101 dispatch_semaphore_wait(waitSemaphore
, DISPATCH_TIME_FOREVER
);
102 dispatch_release(waitSemaphore
);
108 os_state_block_t kvsStateBlock
= ^os_state_data_t(os_state_hints_t hints
) {
109 os_state_data_t retval
= NULL
;
110 __block CFDictionaryRef kvsdict
= NULL
;
111 CFDataRef serializedKVS
= NULL
;
113 require_quiet(hints
->osh_api
== 3, errOut
); // only grab on sysdiagnose or command lin
115 kvsdict
= SOSCloudCopyKVSState();
117 require_quiet(kvsdict
, errOut
);
118 serializedKVS
= CFPropertyListCreateData(kCFAllocatorDefault
, kvsdict
, kCFPropertyListBinaryFormat_v1_0
, 0, NULL
);
119 size_t statelen
= CFDataGetLength(serializedKVS
);
120 retval
= (os_state_data_t
)calloc(1, OS_STATE_DATA_SIZE_NEEDED(statelen
));
121 require_quiet(retval
, errOut
);
123 retval
->osd_type
= OS_STATE_DATA_SERIALIZED_NSCF_OBJECT
;
124 memcpy(retval
->osd_data
, CFDataGetBytePtr(serializedKVS
), statelen
);
125 retval
->osd_size
= statelen
;
126 strcpy(retval
->osd_title
, "CloudCircle KVS Object");
128 CFReleaseNull(kvsdict
);
129 CFReleaseNull(serializedKVS
);
133 static SOSCloudTransportRef defaultTransport
= NULL
;
136 SOSCloudTransportSetDefaultTransport(SOSCloudTransportRef transport
)
138 defaultTransport
= transport
;
141 static SOSCloudTransportRef
SOSCloudTransportDefaultTransport(void)
143 static dispatch_once_t sTransportOnce
;
144 dispatch_once(&sTransportOnce
, ^{
145 if (defaultTransport
== NULL
) {
146 defaultTransport
= SOSCloudTransportCreateXPCTransport();
147 // provide state handler to sysdiagnose and logging
148 os_state_add_handler(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY
, 0), kvsStateBlock
);
151 return defaultTransport
;
155 // MARK: ----- utilities -----
157 static CFErrorRef
makeError(CFIndex which
)
159 CFDictionaryRef userInfo
= NULL
;
160 return CFErrorCreate(kCFAllocatorDefault
, sErrorDomain
, which
, userInfo
);
163 // MARK: ---------- SOSXPCCloudTransport ----------
165 typedef struct SOSXPCCloudTransport
*SOSXPCCloudTransportRef
;
166 struct SOSXPCCloudTransport
168 struct SOSCloudTransport transport
;
169 xpc_connection_t serviceConnection
;
170 dispatch_queue_t xpc_queue
;
173 static void teardownServiceConnection(SOSXPCCloudTransportRef transport
)
175 secnotice(SOSCKCSCOPE
, "CKP Transport: tearing down xpc connection");
176 dispatch_assert_queue(transport
->xpc_queue
);
177 if (transport
->serviceConnection
) {
178 xpc_release(transport
->serviceConnection
);
179 transport
->serviceConnection
= NULL
;
183 static void setupServiceConnection(SOSXPCCloudTransportRef transport
)
185 secnotice(SOSCKCSCOPE
, "CKP Transport: setting up xpc connection");
186 dispatch_assert_queue(transport
->xpc_queue
);
188 transport
->serviceConnection
= xpc_connection_create_mach_service(kCKPServiceName
, transport
->xpc_queue
, 0);
190 secdebug(SOSCKCSCOPE
, "serviceConnection: %@", transport
->serviceConnection
);
192 xpc_connection_set_event_handler(transport
->serviceConnection
, ^(xpc_object_t event
) {
193 secdebug(SOSCKCSCOPE
, "CKP Transport, xpc_connection_set_event_handler");
194 if(event
== XPC_ERROR_CONNECTION_INVALID
){
195 secnotice(SOSCKCSCOPE
, "CKP Transport: xpc connection invalid. Will tear down connection.");
196 dispatch_async(transport
->xpc_queue
, ^{
197 teardownServiceConnection(transport
);
202 xpc_connection_activate(transport
->serviceConnection
);
205 static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport
)
207 secdebug(SOSCKCSCOPE
, "initXPCConnection");
209 transport
->xpc_queue
= dispatch_queue_create(kCKPServiceName
, DISPATCH_QUEUE_SERIAL
);
211 dispatch_sync(transport
->xpc_queue
, ^{
212 setupServiceConnection(transport
);
215 // Any time a new session starts, reestablish the XPC connections.
217 notify_register_dispatch("com.apple.system.loginwindow.desktopUp", &token
, transport
->xpc_queue
, ^(int token2
) {
218 secnotice(SOSCKCSCOPE
, "CKP Transport: desktopUp happened, reestablishing xpc connections");
219 teardownServiceConnection(transport
);
223 typedef void (^ProxyReplyBlock
)(xpc_object_t reply
);
225 static bool messageToProxy(SOSXPCCloudTransportRef transport
, xpc_object_t message
, CFErrorRef
*error
, dispatch_queue_t processQueue
, ProxyReplyBlock replyBlock
) {
226 __block CFErrorRef connectionError
= NULL
;
228 dispatch_sync(transport
->xpc_queue
, ^{
229 if (transport
->serviceConnection
== NULL
) {
230 setupServiceConnection(transport
);
233 if (transport
->serviceConnection
&& message
) {
234 xpc_connection_send_message_with_reply(transport
->serviceConnection
, message
, processQueue
, replyBlock
);
236 connectionError
= makeError(kSOSConnectionNotOpen
);
239 return CFErrorPropagate(connectionError
, error
);
242 static void talkWithKVS(SOSXPCCloudTransportRef transport
, xpc_object_t message
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
244 CFErrorRef messagingError
= NULL
;
245 dispatch_retain(processQueue
);
246 bool messaged
= messageToProxy(transport
, message
, &messagingError
, transport
->xpc_queue
, ^(xpc_object_t reply
) {
247 CFErrorRef serverError
= NULL
;
248 CFTypeRef object
= NULL
;
250 if (xpc_get_type(reply
) == XPC_TYPE_DICTIONARY
) {
251 xpc_object_t xrv
= xpc_dictionary_get_value(reply
, kMessageKeyValue
);
253 object
= _CFXPCCreateCFObjectFromXPCObject(xrv
);
255 secerror("missing value reply");
258 xpc_object_t xerror
= xpc_dictionary_get_value(reply
, kMessageKeyError
);
260 serverError
= SecCreateCFErrorWithXPCObject(xerror
);
263 serverError
= makeError(kSOSMessageInvalid
);
264 secerror("Odd reply from CloudKeychainProxy: %@: %@", reply
, serverError
);
266 dispatch_async(processQueue
, ^{
268 replyBlock(object
, serverError
);
270 CFReleaseSafe(object
);
272 secerror("callback error: %@", serverError
);
273 CFReleaseSafe(serverError
);
275 dispatch_release(processQueue
);
280 secerror("talkWithKVS error: %@", messagingError
);
281 dispatch_async(processQueue
, ^{
283 replyBlock(NULL
, messagingError
);
284 CFReleaseSafe(messagingError
);
285 dispatch_release(processQueue
);
290 // MARK: ---------- SOSXPCCloudTransport Client Calls ----------
292 /* Concrete function backend implementations. */
293 static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport
,
294 CloudItemsChangedBlock itemsChangedBlock
) {
295 if (transport
->itemsChangedBlock
!= itemsChangedBlock
)
297 secnotice(SOSCKCSCOPE
, "Changing itemsChangedBlock");
298 if (transport
->itemsChangedBlock
)
299 Block_release(transport
->itemsChangedBlock
);
300 transport
->itemsChangedBlock
= Block_copy(itemsChangedBlock
);
304 /* Virtual function backend implementations. */
305 static void SOSCloudTransportPut(SOSCloudTransportRef transport
, CFDictionaryRef values
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
307 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
308 secdebug(SOSCKCSCOPE
, "%@", values
);
309 CFErrorRef error
= NULL
;
310 xpc_object_t message
= NULL
;
311 xpc_object_t xobject
= NULL
;
312 require_action(values
, xit
, error
= makeError(kSOSObjectNotFoundError
));
314 message
= xpc_dictionary_create(NULL
, NULL
, 0);
315 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
316 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationPUTDictionary
);
318 xobject
= _CFXPCCreateXPCObjectFromCFObject(values
);
319 require_action(xobject
, xit
, error
= makeError(kSOSObjectCantBeConvertedToXPCObject
));
320 xpc_dictionary_set_value(message
, kMessageKeyValue
, xobject
);
321 xpc_release(xobject
);
323 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
324 xpc_release(message
);
329 replyBlock(NULL
, error
);
330 CFReleaseSafe(error
);
334 void SOSCloudTransportGet(SOSCloudTransportRef transport
, CFArrayRef keysToGet
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
336 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
337 secdebug(SOSCKCSCOPE
, "%@", keysToGet
);
338 CFErrorRef error
= NULL
;
339 xpc_object_t xkeysOfInterest
= xpc_dictionary_create(NULL
, NULL
, 0);
340 xpc_object_t xkeysToGet
= keysToGet
? _CFXPCCreateXPCObjectFromCFObject(keysToGet
) : xpc_null_create();
342 require_action(xkeysToGet
, xit
, error
= makeError(kSOSObjectNotFoundError
));
344 if (keysToGet
) // don't add if nulll; will call getall
345 xpc_dictionary_set_value(xkeysOfInterest
, kMessageKeyKeysToGet
, xkeysToGet
);
347 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
348 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
349 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationGETv2
);
350 xpc_dictionary_set_value(message
, kMessageKeyValue
, xkeysOfInterest
);
352 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
353 xpc_release(xkeysToGet
);
354 xpc_release(xkeysOfInterest
);
355 xpc_release(message
);
360 xpc_release(xkeysOfInterest
);
362 xpc_release(xkeysToGet
);
364 replyBlock(NULL
, error
);
365 CFReleaseSafe(error
);
369 // Handles NULL by seting xpc_null.
370 static void SecXPCDictionarySetCFObject(xpc_object_t xdict
, const char *key
, CFTypeRef object
)
372 xpc_object_t xpc_obj
= object
? _CFXPCCreateXPCObjectFromCFObject(object
) : xpc_null_create();
373 xpc_dictionary_set_value(xdict
, key
, xpc_obj
);
374 xpc_release(xpc_obj
);
377 static void SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport
,
378 CFDictionaryRef keys
,
379 CFStringRef accountUUID
,
380 dispatch_queue_t processQueue
,
381 CloudKeychainReplyBlock replyBlock
)
383 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
385 xpc_object_t xkeysOfInterest
= xpc_dictionary_create(NULL
, NULL
, 0);
386 SecXPCDictionarySetCFObject(xkeysOfInterest
, kMessageAllKeys
, keys
);
388 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
389 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
390 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationRegisterKeys
);
391 xpc_dictionary_set_value(message
, kMessageKeyValue
, xkeysOfInterest
);
392 SecXPCDictionarySetCFObject(message
, kMessageKeyAccountUUID
, accountUUID
);
394 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
395 xpc_release(message
);
396 xpc_release(xkeysOfInterest
);
399 static void SOSCloudTransportRemoveKeys(SOSCloudTransportRef transport
,
401 CFStringRef accountUUID
,
402 dispatch_queue_t processQueue
,
403 CloudKeychainReplyBlock replyBlock
)
405 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
407 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
408 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
410 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationRemoveKeys
);
411 SecXPCDictionarySetCFObject(message
, kMessageKeyAccountUUID
, accountUUID
);
412 SecXPCDictionarySetCFObject(message
, kMessageKeyValue
, keys
);
414 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
415 xpc_release(message
);
418 static void SOSCloudTransportGetAll(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
420 secdebug(SOSCKCSCOPE
, "start");
421 SOSCloudTransportGet(transport
, NULL
, processQueue
, replyBlock
);
424 static void SOSCloudTransportSync(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
426 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
427 secdebug(SOSCKCSCOPE
, "start");
428 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
429 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
430 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationSynchronize
);
431 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
432 xpc_release(message
);
435 static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
437 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
438 secnotice(SOSCKCSCOPE
, "%s XPC request to CKD: %s", kWAIT2MINID
, kOperationSynchronizeAndWait
);
440 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
441 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
442 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationSynchronizeAndWait
);
444 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
445 xpc_release(message
);
448 static void SOSCloudTransportClearAll(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
450 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
451 secdebug(SOSCKCSCOPE
, "start");
452 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
453 xpc_dictionary_set_uint64(message
, kMessageKeyVersion
, kCKDXPCVersion
);
454 xpc_dictionary_set_string(message
, kMessageKeyOperation
, kOperationClearStore
);
455 talkWithKVS(xpcTransport
, message
, processQueue
, replyBlock
);
456 xpc_release(message
);
459 static void SOSCloudTransportRequestSyncWithPeers(SOSCloudTransportRef transport
, CFArrayRef
/* CFStringRef */ peers
, CFArrayRef
/* CFStringRef */ backupPeers
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
461 secdebug(SOSCKCSCOPE
, "start");
462 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
464 xpc_object_t xpcmessage
= xpc_dictionary_create(NULL
, NULL
, 0);
466 xpc_dictionary_set_uint64(xpcmessage
, kMessageKeyVersion
, kCKDXPCVersion
);
467 xpc_dictionary_set_string(xpcmessage
, kMessageKeyOperation
, kOperationRequestSyncWithPeers
);
469 SecXPCDictionarySetCFObject(xpcmessage
, kMessageKeyPeerIDList
, peers
);
470 SecXPCDictionarySetCFObject(xpcmessage
, kMesssgeKeyBackupPeerIDList
, backupPeers
);
472 talkWithKVS(xpcTransport
, xpcmessage
, processQueue
, replyBlock
);
474 xpc_release(xpcmessage
);
478 static bool SOSCloudTransportHasPendingKey(SOSCloudTransportRef transport
, CFStringRef keyName
, CFErrorRef
* error
)
480 secdebug(SOSCKCSCOPE
, "start");
481 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
483 __block
bool kvsHasMessage
= false;
485 xpc_object_t xpcmessage
= xpc_dictionary_create(NULL
, NULL
, 0);
487 xpc_dictionary_set_uint64(xpcmessage
, kMessageKeyVersion
, kCKDXPCVersion
);
488 xpc_dictionary_set_string(xpcmessage
, kMessageKeyOperation
, kOperationHasPendingKey
);
490 SecXPCDictionarySetCFObject(xpcmessage
, kMessageKeyKey
, keyName
);
492 dispatch_semaphore_t kvsWait
= dispatch_semaphore_create(0);
493 bool kvsSent
= messageToProxy(xpcTransport
, xpcmessage
, error
, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY
, 0), ^(xpc_object_t reply
) {
494 kvsHasMessage
= xpc_dictionary_get_bool(reply
, kMessageKeyValue
);
495 dispatch_semaphore_signal(kvsWait
);
499 dispatch_semaphore_wait(kvsWait
, DISPATCH_TIME_FOREVER
);
502 dispatch_release(kvsWait
);
504 return kvsSent
&& kvsHasMessage
;
508 static void SOSCloudTransportRequestEnsurePeerRegistration(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
510 secdebug(SOSCKCSCOPE
, "start");
511 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
513 xpc_object_t xpcmessage
= xpc_dictionary_create(NULL
, NULL
, 0);
514 xpc_dictionary_set_uint64(xpcmessage
, kMessageKeyVersion
, kCKDXPCVersion
);
515 xpc_dictionary_set_string(xpcmessage
, kMessageKeyOperation
, kOperationRequestEnsurePeerRegistration
);
517 talkWithKVS(xpcTransport
, xpcmessage
, processQueue
, replyBlock
);
519 xpc_release(xpcmessage
);
522 static void SOSCloudTransportRequestPerfCounters(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
524 secdebug(SOSCKCSCOPE
, "start");
525 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
527 xpc_object_t xpcmessage
= xpc_dictionary_create(NULL
, NULL
, 0);
528 xpc_dictionary_set_uint64(xpcmessage
, kMessageKeyVersion
, kCKDXPCVersion
);
529 xpc_dictionary_set_string(xpcmessage
, kMessageKeyOperation
, kOperationPerfCounters
);
531 talkWithKVS(xpcTransport
, xpcmessage
, processQueue
, replyBlock
);
533 xpc_release(xpcmessage
);
537 static void SOSCloudTransportFlush(SOSCloudTransportRef transport
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
539 secdebug(SOSCKCSCOPE
, "start");
540 SOSXPCCloudTransportRef xpcTransport
= (SOSXPCCloudTransportRef
)transport
;
542 xpc_object_t xpcmessage
= xpc_dictionary_create(NULL
, NULL
, 0);
543 xpc_dictionary_set_uint64(xpcmessage
, kMessageKeyVersion
, kCKDXPCVersion
);
544 xpc_dictionary_set_string(xpcmessage
, kMessageKeyOperation
, kOperationFlush
);
546 talkWithKVS(xpcTransport
, xpcmessage
, processQueue
, replyBlock
);
548 xpc_release(xpcmessage
);
551 static SOSCloudTransportRef
SOSCloudTransportCreateXPCTransport(void)
553 SOSXPCCloudTransportRef st
;
554 st
= calloc(1, sizeof(*st
));
555 st
->transport
.put
= SOSCloudTransportPut
;
556 st
->transport
.updateKeys
= SOSCloudTransportUpdateKeys
;
558 st
->transport
.get
= SOSCloudTransportGet
;
559 st
->transport
.getAll
= SOSCloudTransportGetAll
;
560 st
->transport
.synchronize
= SOSCloudTransportSync
;
561 st
->transport
.synchronizeAndWait
= SOSCloudTransportSyncAndWait
;
562 st
->transport
.clearAll
= SOSCloudTransportClearAll
;
563 st
->transport
.requestSyncWithPeers
= SOSCloudTransportRequestSyncWithPeers
;
564 st
->transport
.hasPendingKey
= SOSCloudTransportHasPendingKey
;
565 st
->transport
.requestEnsurePeerRegistration
= SOSCloudTransportRequestEnsurePeerRegistration
;
566 st
->transport
.requestPerfCounters
= SOSCloudTransportRequestPerfCounters
;
567 st
->transport
.flush
= SOSCloudTransportFlush
;
568 st
->transport
.removeKeys
= SOSCloudTransportRemoveKeys
;
569 st
->transport
.itemsChangedBlock
= Block_copy(^CFArrayRef(CFDictionaryRef changes
) {
570 secerror("Calling default itemsChangedBlock - fatal: %@", changes
);
574 SOSXPCCloudTransportInit(st
);
575 return &st
->transport
;
578 // MARK: ---------- SOSCloudKeychain concrete client APIs ----------
579 void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock
)
581 secdebug(SOSCKCSCOPE
, "start");
582 SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(),
586 // MARK: ---------- SOSCloudKeychain virtual client APIs ----------
588 void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
590 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
592 cTransportRef
->put(cTransportRef
, objects
, processQueue
, replyBlock
);
595 void SOSCloudKeychainUpdateKeys(CFDictionaryRef keys
, CFStringRef accountUUID
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
597 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
599 cTransportRef
->updateKeys(cTransportRef
, keys
, accountUUID
, processQueue
, replyBlock
);
603 void SOSCloudKeychainRemoveKeys(CFArrayRef keys
, CFStringRef accountUUID
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
605 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
607 cTransportRef
->removeKeys(cTransportRef
, keys
, accountUUID
, processQueue
, replyBlock
);
610 CF_RETURNS_RETAINED CFArrayRef
SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates
)
612 CFArrayRef result
= NULL
;
613 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
614 if (cTransportRef
->itemsChangedBlock
)
615 result
= ((CloudItemsChangedBlock
)cTransportRef
->itemsChangedBlock
)(updates
);
619 void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
621 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
623 cTransportRef
->get(cTransportRef
, keysToGet
, processQueue
, replyBlock
);
626 void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
628 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
630 cTransportRef
->getAll(cTransportRef
, processQueue
, replyBlock
);
633 void SOSCloudKeychainSynchronizeAndWait(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
635 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
637 cTransportRef
->synchronizeAndWait(cTransportRef
, processQueue
, replyBlock
);
641 void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
643 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
645 cTransportRef
->synchronize(cTransportRef
, processQueue
, replyBlock
);
649 void SOSCloudKeychainClearAll(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
651 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
652 secnotice("circleOps", "SOSCloudKeychainClearAll called");
654 cTransportRef
->clearAll(cTransportRef
, processQueue
, replyBlock
);
657 void SOSCloudKeychainRequestSyncWithPeers(CFArrayRef
/* CFStringRef */ peers
, CFArrayRef
/* CFStringRef */ backupPeers
, dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
659 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
661 cTransportRef
->requestSyncWithPeers(cTransportRef
, peers
, backupPeers
, processQueue
, replyBlock
);
664 bool SOSCloudKeychainHasPendingKey(CFStringRef keyName
, CFErrorRef
* error
) {
665 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
667 return cTransportRef
&& cTransportRef
->hasPendingKey(cTransportRef
, keyName
, error
);
670 void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
672 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
674 cTransportRef
->requestEnsurePeerRegistration(cTransportRef
, processQueue
, replyBlock
);
677 void SOSCloudKeychainRequestPerfCounters(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
679 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
681 cTransportRef
->requestPerfCounters(cTransportRef
, processQueue
, replyBlock
);
685 void SOSCloudKeychainFlush(dispatch_queue_t processQueue
, CloudKeychainReplyBlock replyBlock
)
687 SOSCloudTransportRef cTransportRef
= SOSCloudTransportDefaultTransport();
689 cTransportRef
->flush(cTransportRef
, processQueue
, replyBlock
);