]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / 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 the main security code cannot 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 <CoreFoundation/CFUserNotification.h>
47
48 #include <utilities/debugging.h>
49 #include <utilities/SecCFWrappers.h>
50 #include <utilities/SecXPCError.h>
51
52 #include "SOSCloudKeychainConstants.h"
53 #include "SOSCloudKeychainClient.h"
54
55 static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error");
56
57 #define SOSCKCSCOPE "sync"
58
59 // MARK: ---------- SOSCloudTransport ----------
60
61 /* SOSCloudTransport, a statically initialized transport singleton. */
62 static SOSCloudTransportRef sTransport = NULL;
63
64 static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void);
65
66 void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport) {
67 sTransport = transport;
68 }
69
70 /* Return the singleton cloud transport instance. */
71 static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void)
72 {
73 static dispatch_once_t sTransportOnce;
74 dispatch_once(&sTransportOnce, ^{
75 if (!sTransport)
76 SOSCloudKeychainSetTransport(SOSCloudTransportCreateXPCTransport());
77 });
78 return sTransport;
79 }
80
81
82 // MARK: ----- utilities -----
83
84 static CFErrorRef makeError(CFIndex which)
85 {
86 CFDictionaryRef userInfo = NULL;
87 return CFErrorCreate(kCFAllocatorDefault, sErrorDomain, which, userInfo);
88 }
89
90 // MARK: ----- DEBUG Utilities -----
91
92 //------------------------------------------------------------------------------------------------
93 // DEBUG only
94 //------------------------------------------------------------------------------------------------
95
96 static void describeXPCObject(char *prefix, xpc_object_t object)
97 {
98 //#ifndef NDEBUG
99 // This is useful for debugging.
100 if (object)
101 {
102 char *desc = xpc_copy_description(object);
103 secdebug(SOSCKCSCOPE, "%s%s\n", prefix, desc);
104 free(desc);
105 }
106 else
107 secdebug(SOSCKCSCOPE, "%s<NULL>\n", prefix);
108 //#endif
109 }
110
111 static void describeXPCType(char *prefix, xpc_type_t xtype)
112 {
113 // Add others as necessary, e.g. XPC_TYPE_DOUBLE
114 #ifndef NDEBUG
115 // This is useful for debugging.
116 char msg[256]={0,};
117 if (XPC_TYPE_CONNECTION == xtype)
118 strcpy(msg, "XPC_TYPE_CONNECTION");
119 else if (XPC_TYPE_ERROR == xtype)
120 strcpy(msg, "XPC_TYPE_ERROR");
121 else if (XPC_TYPE_DICTIONARY == xtype)
122 strcpy(msg, "XPC_TYPE_DICTIONARY");
123 else
124 strcpy(msg, "<unknown>");
125
126 secdebug(SOSCKCSCOPE, "%s type:%s\n", prefix, msg);
127 #endif
128 }
129
130 // MARK: ---------- SOSXPCCloudTransport ----------
131
132 typedef struct SOSXPCCloudTransport *SOSXPCCloudTransportRef;
133 struct SOSXPCCloudTransport
134 {
135 struct SOSCloudTransport transport;
136 xpc_connection_t serviceConnection;
137 dispatch_queue_t xpc_queue;
138 };
139
140 static bool xpc_event_filter(const xpc_connection_t peer, xpc_object_t event, CFErrorRef *error)
141 {
142 // return true if the type is XPC_TYPE_DICTIONARY (and therefore something more to process)
143 secdebug(SOSCKCSCOPE, "handle_connection_event\n");
144 xpc_type_t xtype = xpc_get_type(event);
145 describeXPCType("handle_xpc_event", xtype);
146 if (XPC_TYPE_CONNECTION == xtype)
147 {
148 secdebug(SOSCKCSCOPE, "handle_xpc_event: XPC_TYPE_CONNECTION (unexpected)");
149 // The client of an XPC service does not get connection events
150 // For now, we log this and keep going
151 describeXPCObject("handle_xpc_event: XPC_TYPE_CONNECTION, obj : ", event);
152 #if 0
153 if (error)
154 *error = makeError(kSOSOUnexpectedConnectionEvent); // FIX
155 assert(true);
156 #endif
157 }
158 else
159 if (XPC_TYPE_ERROR == xtype)
160 {
161 #ifndef NDEBUG
162 const char *estr = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
163 #endif
164 secdebug(SOSCKCSCOPE, "default: xpc error: %s\n", estr);
165 #if 0 // just log for now
166 CFStringRef errStr = CFStringCreateWithCString(kCFAllocatorDefault, estr, kCFStringEncodingUTF8);
167 CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
168 if (errStr)
169 CFDictionaryAddValue(userInfo, kCFErrorLocalizedDescriptionKey, errStr);
170 if (error)
171 *error = CFErrorCreate(kCFAllocatorDefault, sErrorDomain, kSOSOXPCErrorEvent, userInfo);
172 CFReleaseSafe(errStr);
173 CFReleaseSafe(userInfo);
174 #endif
175 }
176 else
177 if (XPC_TYPE_DICTIONARY == xtype)
178 {
179 secdebug(SOSCKCSCOPE, "received dictionary event %p\n", event);
180 return true;
181 }
182 else
183 {
184 secdebug(SOSCKCSCOPE, "default: unexpected connection event %p\n", event);
185 describeXPCObject("handle_xpc_event: obj : ", event);
186 if (error)
187 *error = makeError(kSOSOUnexpectedXPCEvent);
188 }
189 return false;
190 }
191
192 static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport)
193 {
194 secdebug(SOSCKCSCOPE, "initXPCConnection\n");
195
196 transport->xpc_queue = dispatch_queue_create(xpcServiceName, DISPATCH_QUEUE_SERIAL);
197
198 transport->serviceConnection = xpc_connection_create_mach_service(xpcServiceName, transport->xpc_queue, 0);
199
200 secdebug(SOSCKCSCOPE, "serviceConnection: %p\n", transport->serviceConnection);
201
202 xpc_connection_set_event_handler(transport->serviceConnection, ^(xpc_object_t event)
203 {
204 secdebug(SOSCKCSCOPE, "xpc_connection_set_event_handler\n");
205 });
206
207 xpc_connection_resume(transport->serviceConnection);
208 xpc_retain(transport->serviceConnection);
209 }
210
211 static void talkWithKVS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
212 {
213 CFErrorRef connectionError = NULL;
214 require_action(transport->serviceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen));
215 require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError));
216 dispatch_retain(processQueue);
217
218 xpc_connection_send_message_with_reply(transport->serviceConnection, message, transport->xpc_queue, ^(xpc_object_t reply)
219 {
220 CFErrorRef serverError = NULL;
221 CFTypeRef object = NULL;
222 if (xpc_event_filter(transport->serviceConnection, reply, &serverError) && reply)
223 {
224 describeXPCObject("getValuesFromKVS: reply : ", reply);
225 if (serverError)
226 secerror("Error from xpc_event_filter: %@", serverError);
227 xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue);
228 if (xrv)
229 {
230 describeXPCObject("talkWithKVS: xrv: ", xrv);
231 /*
232 * The given XPC object must be one that was previously returned by
233 * _CFXPCCreateXPCMessageWithCFObject().
234 */
235 object = _CFXPCCreateCFObjectFromXPCObject(xrv); // CF object is retained; release in callback
236 secnotice("talkwithkvs", "converted CF object: %@", object);
237 }
238 else
239 secerror("missing value reply");
240
241 xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError);
242 if (xerror)
243 serverError = SecCreateCFErrorWithXPCObject(xerror); // use SecCFCreateErrorWithFormat?
244 }
245 dispatch_async(processQueue, ^{
246 if (replyBlock)
247 replyBlock(object, serverError);
248 CFReleaseSafe(object);
249 if (serverError)
250 {
251 secerror("callback error: %@", serverError);
252 CFReleaseSafe(serverError);
253 }
254 dispatch_release(processQueue);
255 });
256 });
257 return;
258
259 xit:
260 secerror("talkWithKVS error: %@", connectionError);
261 dispatch_async(processQueue, ^{
262 if (replyBlock)
263 replyBlock(NULL, connectionError);
264 CFReleaseSafe(connectionError);
265 dispatch_release(processQueue);
266 });
267 }
268
269 // MARK: ---------- SOSXPCCloudTransport Client Calls ----------
270
271 /* Concrete function backend implementations. */
272 static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport,
273 CloudItemsChangedBlock itemsChangedBlock) {
274 if (transport->itemsChangedBlock != itemsChangedBlock)
275 {
276 secnotice(SOSCKCSCOPE, "Changing itemsChangedBlock");
277 if (transport->itemsChangedBlock)
278 Block_release(transport->itemsChangedBlock);
279 transport->itemsChangedBlock = Block_copy(itemsChangedBlock);
280 }
281 }
282
283 /* Virtual function backend implementations. */
284 static void SOSCloudTransportPut(SOSCloudTransportRef transport, CFDictionaryRef values, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
285 {
286 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
287 secdebug(SOSCKCSCOPE, "%@", values);
288 CFErrorRef error = NULL;
289 xpc_object_t message = NULL;
290 xpc_object_t xobject = NULL;
291 require_action(values, xit, error = makeError(kSOSObjectNotFoundError));
292
293 message = xpc_dictionary_create(NULL, NULL, 0);
294 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
295 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationPUTDictionary);
296
297 xobject = _CFXPCCreateXPCObjectFromCFObject(values);
298 require_action(xobject, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject));
299 xpc_dictionary_set_value(message, kMessageKeyValue, xobject);
300 xpc_release(xobject);
301
302 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
303 xpc_release(message);
304 return;
305
306 xit:
307 if (replyBlock)
308 replyBlock(NULL, error);
309 CFReleaseSafe(error);
310 }
311
312 /* Get from KVS */
313 static void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
314 {
315 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
316 secdebug(SOSCKCSCOPE, "%@", keysToGet);
317 CFErrorRef error = NULL;
318 xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
319 xpc_object_t xkeysToGet = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create();
320
321 require_action(xkeysToGet, xit, error = makeError(kSOSObjectNotFoundError));
322
323 if (keysToGet) // don't add if nulll; will call getall
324 xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToGet);
325
326 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
327 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
328 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGETv2);
329 xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
330
331 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
332 xpc_release(xkeysToGet);
333 xpc_release(xkeysOfInterest);
334 xpc_release(message);
335 return;
336
337 xit:
338 if(xkeysOfInterest)
339 xpc_release(xkeysOfInterest);
340 if(xkeysToGet)
341 xpc_release(xkeysToGet);
342 if (replyBlock)
343 replyBlock(NULL, error);
344 CFReleaseSafe(error);
345 }
346
347 //
348 // Handles NULL by seting xpc_null.
349 static void SecXPCDictionarySetCFObject(xpc_object_t xdict, const char *key, CFTypeRef object)
350 {
351 xpc_object_t xpc_obj = object ? _CFXPCCreateXPCObjectFromCFObject(object) : xpc_null_create();
352 xpc_dictionary_set_value(xdict, key, xpc_obj);
353 xpc_release(xpc_obj);
354 }
355
356 static bool SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport,
357 CFDictionaryRef keys,
358 CFErrorRef *error)
359 {
360 __block bool success = true;
361 dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
362
363 CloudKeychainReplyBlock replyBlock = ^(CFDictionaryRef returnedValues, CFErrorRef returnedError)
364 {
365 if (returnedError) {
366 success = false;
367 if (error) {
368 *error = returnedError;
369 CFRetain(*error);
370 }
371 }
372 CFReleaseSafe(returnedError);
373 };
374
375 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
376
377 xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
378 SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageAllKeys, keys);
379
380 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
381 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
382 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeys);
383 xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
384
385 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
386 xpc_release(message);
387 xpc_release(xkeysOfInterest);
388
389 return success;
390 }
391
392 static void SOSCloudTransportGetAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
393 {
394 secdebug(SOSCKCSCOPE, "start");
395 SOSCloudTransportGet(transport, NULL, processQueue, replyBlock);
396 }
397
398 static void SOSCloudTransportSync(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
399 {
400 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
401 secdebug(SOSCKCSCOPE, "start");
402 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
403 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
404 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronize);
405 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
406 xpc_release(message);
407 }
408
409 static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
410 {
411 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
412 secdebug(SOSCKCSCOPE, "%@", keysToGet);
413 secnotice(SOSCKCSCOPE, "%s XPC request to CKD: %s", kWAIT2MINID, kOperationSynchronizeAndWait);
414 xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
415
416 xpc_object_t xkeysToRegister = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create();
417 xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToRegister);
418 xpc_release(xkeysToRegister);
419 xkeysToRegister = NULL;
420
421 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
422 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
423 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronizeAndWait);
424 xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
425 xpc_release(xkeysOfInterest);
426 xkeysOfInterest = NULL;
427
428 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
429 xpc_release(message);
430 }
431
432 static void SOSCloudTransportClearAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
433 {
434 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
435 secdebug(SOSCKCSCOPE, "start");
436 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
437 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
438 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationClearStore);
439 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
440 xpc_release(message);
441 }
442
443 static void SOSCloudTransportRemoveObjectForKey(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
444 {
445 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
446 secdebug(SOSCKCSCOPE, "start");
447 CFErrorRef error = NULL;
448 xpc_object_t message = NULL;
449 xpc_object_t xkeytoremove = NULL;
450
451 require_action(keyToRemove, xit, error = makeError(kSOSObjectNotFoundError));
452
453 message = xpc_dictionary_create(NULL, NULL, 0);
454 xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
455 xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRemoveObjectForKey);
456
457 xkeytoremove = _CFXPCCreateXPCObjectFromCFObject(keyToRemove);
458 require_action(xkeytoremove, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject));
459 xpc_dictionary_set_value(message, kMessageKeyKey, xkeytoremove);
460 xpc_release(xkeytoremove);
461
462 talkWithKVS(xpcTransport, message, processQueue, replyBlock);
463 xpc_release(message);
464 return;
465
466 xit:
467 if(xkeytoremove)
468 xpc_release(xkeytoremove);
469 if(message)
470 xpc_release(message);
471 if (replyBlock)
472 replyBlock(NULL, error);
473 CFReleaseSafe(error);
474 }
475 static void SOSCloudTransportLocalNotification(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
476 {
477 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
478 secdebug(SOSCKCSCOPE, "start");
479 xpc_object_t xLocalNotificationDict = xpc_dictionary_create(NULL, NULL, 0);
480 char *headerKey = CFStringToCString(kCFUserNotificationAlertHeaderKey);
481 char *message = CFStringToCString(messageToUser);
482 xpc_dictionary_set_string(xLocalNotificationDict, headerKey, message);
483
484 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
485 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
486 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationUILocalNotification);
487 xpc_dictionary_set_value (xpcmessage, kMessageKeyValue, xLocalNotificationDict);
488 xpc_release(xLocalNotificationDict);
489
490 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
491
492 free(headerKey);
493 free(message);
494 xpc_release(xpcmessage);
495 }
496
497 static void SOSCloudTransportRequestSyncWithAllPeers(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
498 {
499 secdebug(SOSCKCSCOPE, "start");
500 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
501
502 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
503 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
504 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestSyncWithAllPeers);
505
506 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
507
508 xpc_release(xpcmessage);
509 }
510
511 static void SOSCloudTransportRequestEnsurePeerRegistration(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
512 {
513 secdebug(SOSCKCSCOPE, "start");
514 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
515
516 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
517 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
518 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestEnsurePeerRegistration);
519
520 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
521
522 xpc_release(xpcmessage);
523 }
524
525 static void SOSCloudTransportFlush(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
526 {
527 secdebug(SOSCKCSCOPE, "start");
528 SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
529
530 xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
531 xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
532 xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationFlush);
533
534 talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
535
536 xpc_release(xpcmessage);
537 }
538
539 static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void)
540 {
541 SOSXPCCloudTransportRef st;
542 st = calloc(1, sizeof(*st));
543 st->transport.put = SOSCloudTransportPut;
544 st->transport.updateKeys = SOSCloudTransportUpdateKeys;
545 st->transport.get = SOSCloudTransportGet;
546 st->transport.getAll = SOSCloudTransportGetAll;
547 st->transport.synchronize = SOSCloudTransportSync;
548 st->transport.synchronizeAndWait = SOSCloudTransportSyncAndWait;
549 st->transport.clearAll = SOSCloudTransportClearAll;
550 st->transport.removeObjectForKey = SOSCloudTransportRemoveObjectForKey;
551 st->transport.localNotification = SOSCloudTransportLocalNotification;
552 st->transport.requestSyncWithAllPeers = SOSCloudTransportRequestSyncWithAllPeers;
553 st->transport.requestEnsurePeerRegistration = SOSCloudTransportRequestEnsurePeerRegistration;
554 st->transport.flush = SOSCloudTransportFlush;
555 st->transport.itemsChangedBlock = Block_copy(^CFArrayRef(CFDictionaryRef changes) {
556 secerror("Calling default itemsChangedBlock - fatal: %@", changes);
557 assert(false);
558 return NULL;
559 });
560 SOSXPCCloudTransportInit(st);
561 return &st->transport;
562 }
563
564 // MARK: ---------- SOSCloudKeychain concrete client APIs ----------
565 void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock)
566 {
567 secdebug(SOSCKCSCOPE, "start");
568 SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(),
569 itemsChangedBlock);
570 }
571
572 // MARK: ---------- SOSCloudKeychain virtual client APIs ----------
573
574 void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
575 {
576 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
577 if (cTransportRef)
578 cTransportRef->put(cTransportRef, objects, processQueue, replyBlock);
579 }
580
581 bool SOSCloudKeychainUpdateKeys(CFDictionaryRef keys,
582 CFErrorRef *error)
583 {
584 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
585 if (cTransportRef)
586 return cTransportRef->updateKeys(cTransportRef, keys, error);
587
588 return false;
589 }
590
591 CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateKeyParameter(CFDictionaryRef updates)
592 {
593 CFArrayRef result = NULL;
594 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
595 if (cTransportRef->itemsChangedBlock)
596 result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates);
597 return result;
598
599 }
600 CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateCircle(CFDictionaryRef updates)
601 {
602 CFArrayRef result = NULL;
603 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
604 if (cTransportRef->itemsChangedBlock)
605 result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates);
606 return result;
607 }
608
609 CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates)
610 {
611 CFArrayRef result = NULL;
612 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
613 if (cTransportRef->itemsChangedBlock)
614 result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates);
615 return result;
616 }
617
618
619 void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
620 {
621 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
622 if (cTransportRef)
623 cTransportRef->get(cTransportRef, keysToGet, processQueue, replyBlock);
624 }
625
626 void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
627 {
628 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
629 if (cTransportRef)
630 cTransportRef->getAll(cTransportRef, processQueue, replyBlock);
631 }
632
633 void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
634 {
635 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
636 if (cTransportRef)
637 cTransportRef->synchronizeAndWait(cTransportRef, keysToGet, processQueue, replyBlock);
638 }
639
640 //DEBUG ONLY
641 void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
642 {
643 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
644 if (cTransportRef)
645 cTransportRef->synchronize(cTransportRef, processQueue, replyBlock);
646 }
647
648 //DEBUG ONLY
649 void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
650 {
651 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
652 if (cTransportRef)
653 cTransportRef->clearAll(cTransportRef, processQueue, replyBlock);
654 }
655
656 void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
657 {
658 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
659 if (cTransportRef)
660 cTransportRef->removeObjectForKey(cTransportRef, keyToRemove, processQueue, replyBlock);
661 }
662
663 void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
664 {
665 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
666 if (cTransportRef)
667 cTransportRef->requestSyncWithAllPeers(cTransportRef, processQueue, replyBlock);
668 }
669
670 void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
671 {
672 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
673 if (cTransportRef)
674 cTransportRef->requestEnsurePeerRegistration(cTransportRef, processQueue, replyBlock);
675 }
676
677 void SOSCloudKeychainFlush(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
678 {
679 SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
680 if (cTransportRef)
681 cTransportRef->flush(cTransportRef, processQueue, replyBlock);
682 }