SOSCloudKeychainClient.c [plain text]
#include <AssertMacros.h>
#include <xpc/xpc.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFXPCBridge.h>
#include <sysexits.h>
#include <syslog.h>
#include <os/activity.h>
#include <CoreFoundation/CFUserNotification.h>
#include <utilities/debugging.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecXPCError.h>
#include "SOSCloudKeychainConstants.h"
#include "SOSCloudKeychainClient.h"
static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error");
#define SOSCKCSCOPE "sync"
static SOSCloudTransportRef sTransport = NULL;
static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void);
void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport) {
sTransport = transport;
}
static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void)
{
static dispatch_once_t sTransportOnce;
dispatch_once(&sTransportOnce, ^{
if (!sTransport)
SOSCloudKeychainSetTransport(SOSCloudTransportCreateXPCTransport());
});
return sTransport;
}
static CFErrorRef makeError(CFIndex which)
{
CFDictionaryRef userInfo = NULL;
return CFErrorCreate(kCFAllocatorDefault, sErrorDomain, which, userInfo);
}
static void describeXPCObject(char *prefix, xpc_object_t object)
{
if (object)
{
char *desc = xpc_copy_description(object);
secdebug(SOSCKCSCOPE, "%s%s\n", prefix, desc);
free(desc);
}
else
secdebug(SOSCKCSCOPE, "%s<NULL>\n", prefix);
}
static void describeXPCType(char *prefix, xpc_type_t xtype)
{
#ifndef NDEBUG
char msg[256]={0,};
if (XPC_TYPE_CONNECTION == xtype)
strcpy(msg, "XPC_TYPE_CONNECTION");
else if (XPC_TYPE_ERROR == xtype)
strcpy(msg, "XPC_TYPE_ERROR");
else if (XPC_TYPE_DICTIONARY == xtype)
strcpy(msg, "XPC_TYPE_DICTIONARY");
else
strcpy(msg, "<unknown>");
secdebug(SOSCKCSCOPE, "%s type:%s\n", prefix, msg);
#endif
}
typedef struct SOSXPCCloudTransport *SOSXPCCloudTransportRef;
struct SOSXPCCloudTransport
{
struct SOSCloudTransport transport;
xpc_connection_t serviceConnection;
xpc_connection_t idsProxyServiceConnection;
dispatch_queue_t xpc_queue;
};
static bool xpc_event_filter(const xpc_connection_t peer, xpc_object_t event, CFErrorRef *error)
{
secdebug(SOSCKCSCOPE, "handle_connection_event\n");
xpc_type_t xtype = xpc_get_type(event);
describeXPCType("handle_xpc_event", xtype);
if (XPC_TYPE_CONNECTION == xtype)
{
secdebug(SOSCKCSCOPE, "handle_xpc_event: XPC_TYPE_CONNECTION (unexpected)");
describeXPCObject("handle_xpc_event: XPC_TYPE_CONNECTION, obj : ", event);
#if 0
if (error)
*error = makeError(kSOSOUnexpectedConnectionEvent); assert(true);
#endif
}
else
if (XPC_TYPE_ERROR == xtype)
{
#ifndef NDEBUG
const char *estr = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
#endif
secdebug(SOSCKCSCOPE, "default: xpc error: %s\n", estr);
#if 0 // just log for now
CFStringRef errStr = CFStringCreateWithCString(kCFAllocatorDefault, estr, kCFStringEncodingUTF8);
CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (errStr)
CFDictionaryAddValue(userInfo, kCFErrorLocalizedDescriptionKey, errStr);
if (error)
*error = CFErrorCreate(kCFAllocatorDefault, sErrorDomain, kSOSOXPCErrorEvent, userInfo);
CFReleaseSafe(errStr);
CFReleaseSafe(userInfo);
#endif
}
else
if (XPC_TYPE_DICTIONARY == xtype)
{
secdebug(SOSCKCSCOPE, "received dictionary event %p\n", event);
return true;
}
else
{
secdebug(SOSCKCSCOPE, "default: unexpected connection event %p\n", event);
describeXPCObject("handle_xpc_event: obj : ", event);
if (error)
*error = makeError(kSOSOUnexpectedXPCEvent);
}
return false;
}
static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport)
{
secdebug(SOSCKCSCOPE, "initXPCConnection\n");
transport->xpc_queue = dispatch_queue_create(xpcServiceName, DISPATCH_QUEUE_SERIAL);
transport->serviceConnection = xpc_connection_create_mach_service(xpcServiceName, transport->xpc_queue, 0);
secdebug(SOSCKCSCOPE, "serviceConnection: %p\n", transport->serviceConnection);
xpc_connection_set_event_handler(transport->serviceConnection, ^(xpc_object_t event)
{
secdebug(SOSCKCSCOPE, "xpc_connection_set_event_handler\n");
});
xpc_connection_resume(transport->serviceConnection);
xpc_retain(transport->serviceConnection);
transport->idsProxyServiceConnection = xpc_connection_create_mach_service(xpcIDSServiceName, transport->xpc_queue, 0);
secdebug(SOSCKCSCOPE, "ids service connection: %p\n", transport->idsProxyServiceConnection);
xpc_connection_set_event_handler(transport->idsProxyServiceConnection, ^(xpc_object_t object) {
secdebug(SOSCKCSCOPE, "IDS Transport, xpc_connection_set_event_handler\n");
});
xpc_connection_resume(transport->idsProxyServiceConnection);
xpc_retain(transport->idsProxyServiceConnection);
}
static void talkWithIDS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
CFErrorRef connectionError = NULL;
os_activity_t trace_activity = os_activity_start("talkWithIDS", OS_ACTIVITY_FLAG_DEFAULT);
require_action(transport->idsProxyServiceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen));
require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError));
dispatch_retain(processQueue);
xpc_connection_send_message_with_reply(transport->idsProxyServiceConnection, message, transport->xpc_queue, ^(xpc_object_t reply)
{
CFErrorRef serverError = NULL;
CFTypeRef object = NULL;
if (xpc_event_filter(transport->idsProxyServiceConnection, reply, &serverError) && reply)
{
describeXPCObject("IDS Proxy: reply : ", reply);
if (serverError)
secerror("Error from xpc_event_filter: %@", serverError);
xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue);
if (xrv)
{
describeXPCObject("talkwithIDS: xrv: ", xrv);
object = _CFXPCCreateCFObjectFromXPCObject(xrv); secnotice("talkwithIDS", "converted CF object: %@", object);
}
else
secerror("missing value reply");
xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError);
if (xerror)
serverError = SecCreateCFErrorWithXPCObject(xerror); }
dispatch_async(processQueue, ^{
if (replyBlock)
replyBlock(object, serverError);
CFReleaseSafe(object);
if (serverError)
{
secerror("talkwithIDS callback error: %@", serverError);
CFReleaseSafe(serverError);
}
dispatch_release(processQueue);
});
});
return;
xit:
secerror("talkWithIDS error: %@", connectionError);
dispatch_async(processQueue, ^{
if (replyBlock)
replyBlock(NULL, connectionError);
CFReleaseSafe(connectionError);
dispatch_release(processQueue);
});
os_activity_end(trace_activity);
}
static void talkWithKVS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
CFErrorRef connectionError = NULL;
os_activity_t trace_activity = os_activity_start("talkWithKVS", OS_ACTIVITY_FLAG_DEFAULT);
require_action(transport->serviceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen));
require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError));
dispatch_retain(processQueue);
xpc_connection_send_message_with_reply(transport->serviceConnection, message, transport->xpc_queue, ^(xpc_object_t reply)
{
CFErrorRef serverError = NULL;
CFTypeRef object = NULL;
if (xpc_event_filter(transport->serviceConnection, reply, &serverError) && reply)
{
describeXPCObject("getValuesFromKVS: reply : ", reply);
if (serverError)
secerror("Error from xpc_event_filter: %@", serverError);
xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue);
if (xrv)
{
describeXPCObject("talkWithKVS: xrv: ", xrv);
object = _CFXPCCreateCFObjectFromXPCObject(xrv); secnotice("talkwithkvs", "converted CF object: %@", object);
}
else
secerror("missing value reply");
xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError);
if (xerror)
serverError = SecCreateCFErrorWithXPCObject(xerror); }
dispatch_async(processQueue, ^{
if (replyBlock)
replyBlock(object, serverError);
CFReleaseSafe(object);
if (serverError)
{
secerror("callback error: %@", serverError);
CFReleaseSafe(serverError);
}
dispatch_release(processQueue);
});
});
return;
xit:
secerror("talkWithKVS error: %@", connectionError);
dispatch_async(processQueue, ^{
if (replyBlock)
replyBlock(NULL, connectionError);
CFReleaseSafe(connectionError);
dispatch_release(processQueue);
});
os_activity_end(trace_activity);
}
static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport,
CloudItemsChangedBlock itemsChangedBlock) {
if (transport->itemsChangedBlock != itemsChangedBlock)
{
secnotice(SOSCKCSCOPE, "Changing itemsChangedBlock");
if (transport->itemsChangedBlock)
Block_release(transport->itemsChangedBlock);
transport->itemsChangedBlock = Block_copy(itemsChangedBlock);
}
}
static void SOSCloudTransportPut(SOSCloudTransportRef transport, CFDictionaryRef values, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "%@", values);
CFErrorRef error = NULL;
xpc_object_t message = NULL;
xpc_object_t xobject = NULL;
require_action(values, xit, error = makeError(kSOSObjectNotFoundError));
message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationPUTDictionary);
xobject = _CFXPCCreateXPCObjectFromCFObject(values);
require_action(xobject, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject));
xpc_dictionary_set_value(message, kMessageKeyValue, xobject);
xpc_release(xobject);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
return;
xit:
if (replyBlock)
replyBlock(NULL, error);
CFReleaseSafe(error);
}
static void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "%@", keysToGet);
CFErrorRef error = NULL;
xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
xpc_object_t xkeysToGet = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create();
require_action(xkeysToGet, xit, error = makeError(kSOSObjectNotFoundError));
if (keysToGet) xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToGet);
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGETv2);
xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(xkeysToGet);
xpc_release(xkeysOfInterest);
xpc_release(message);
return;
xit:
if(xkeysOfInterest)
xpc_release(xkeysOfInterest);
if(xkeysToGet)
xpc_release(xkeysToGet);
if (replyBlock)
replyBlock(NULL, error);
CFReleaseSafe(error);
}
static void SecXPCDictionarySetCFObject(xpc_object_t xdict, const char *key, CFTypeRef object)
{
xpc_object_t xpc_obj = object ? _CFXPCCreateXPCObjectFromCFObject(object) : xpc_null_create();
xpc_dictionary_set_value(xdict, key, xpc_obj);
xpc_release(xpc_obj);
}
static void SOSCloudTransportGetIDSDeviceID(SOSCloudTransportRef transport, CloudKeychainReplyBlock replyBlock)
{
dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGetDeviceID);
talkWithIDS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
}
static void SOSCloudTransportSendIDSMessage(SOSCloudTransportRef transport, CFDataRef messageData, CFStringRef deviceName, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock){
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t xmessageData = _CFXPCCreateXPCObjectFromCFObject(messageData);
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSendIDSMessage);
xpc_dictionary_set_value(message, kMessageKeyValue, xmessageData);
SecXPCDictionarySetCFObject(message, kMessageKeyDeviceName, deviceName);
SecXPCDictionarySetCFObject(message, kMessageKeyPeerID, peerID);
talkWithIDS(xpcTransport, message, processQueue, replyBlock);
xpc_release(xmessageData);
xpc_release(message);
}
static void SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport,
CFDictionaryRef keys,
dispatch_queue_t processQueue,
CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageAllKeys, keys);
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeys);
xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
xpc_release(xkeysOfInterest);
}
static void SOSCloudTransportGetAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
secdebug(SOSCKCSCOPE, "start");
SOSCloudTransportGet(transport, NULL, processQueue, replyBlock);
}
static void SOSCloudTransportSync(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "start");
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronize);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
}
static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "%@", keysToGet);
secnotice(SOSCKCSCOPE, "%s XPC request to CKD: %s", kWAIT2MINID, kOperationSynchronizeAndWait);
xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0);
xpc_object_t xkeysToRegister = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create();
xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToRegister);
xpc_release(xkeysToRegister);
xkeysToRegister = NULL;
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronizeAndWait);
xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest);
xpc_release(xkeysOfInterest);
xkeysOfInterest = NULL;
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
}
static void SOSCloudTransportClearAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "start");
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationClearStore);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
}
static void SOSCloudTransportRemoveObjectForKey(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "start");
CFErrorRef error = NULL;
xpc_object_t message = NULL;
xpc_object_t xkeytoremove = NULL;
require_action(keyToRemove, xit, error = makeError(kSOSObjectNotFoundError));
message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRemoveObjectForKey);
xkeytoremove = _CFXPCCreateXPCObjectFromCFObject(keyToRemove);
require_action(xkeytoremove, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject));
xpc_dictionary_set_value(message, kMessageKeyKey, xkeytoremove);
xpc_release(xkeytoremove);
talkWithKVS(xpcTransport, message, processQueue, replyBlock);
xpc_release(message);
return;
xit:
if(xkeytoremove)
xpc_release(xkeytoremove);
if(message)
xpc_release(message);
if (replyBlock)
replyBlock(NULL, error);
CFReleaseSafe(error);
}
static void SOSCloudTransportLocalNotification(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
secdebug(SOSCKCSCOPE, "start");
xpc_object_t xLocalNotificationDict = xpc_dictionary_create(NULL, NULL, 0);
char *headerKey = CFStringToCString(kCFUserNotificationAlertHeaderKey);
char *message = CFStringToCString(messageToUser);
xpc_dictionary_set_string(xLocalNotificationDict, headerKey, message);
xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationUILocalNotification);
xpc_dictionary_set_value (xpcmessage, kMessageKeyValue, xLocalNotificationDict);
xpc_release(xLocalNotificationDict);
talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
free(headerKey);
free(message);
xpc_release(xpcmessage);
}
static void SOSCloudTransportRequestSyncWithAllPeers(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
secdebug(SOSCKCSCOPE, "start");
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestSyncWithAllPeers);
talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
xpc_release(xpcmessage);
}
static void SOSCloudTransportRequestEnsurePeerRegistration(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
secdebug(SOSCKCSCOPE, "start");
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestEnsurePeerRegistration);
talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
xpc_release(xpcmessage);
}
static void SOSCloudTransportFlush(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
secdebug(SOSCKCSCOPE, "start");
SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport;
xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion);
xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationFlush);
talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock);
xpc_release(xpcmessage);
}
static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void)
{
SOSXPCCloudTransportRef st;
st = calloc(1, sizeof(*st));
st->transport.put = SOSCloudTransportPut;
st->transport.updateKeys = SOSCloudTransportUpdateKeys;
st->transport.sendIDSMessage = SOSCloudTransportSendIDSMessage;
st->transport.getDeviceID = SOSCloudTransportGetIDSDeviceID;
st->transport.get = SOSCloudTransportGet;
st->transport.getAll = SOSCloudTransportGetAll;
st->transport.synchronize = SOSCloudTransportSync;
st->transport.synchronizeAndWait = SOSCloudTransportSyncAndWait;
st->transport.clearAll = SOSCloudTransportClearAll;
st->transport.removeObjectForKey = SOSCloudTransportRemoveObjectForKey;
st->transport.localNotification = SOSCloudTransportLocalNotification;
st->transport.requestSyncWithAllPeers = SOSCloudTransportRequestSyncWithAllPeers;
st->transport.requestEnsurePeerRegistration = SOSCloudTransportRequestEnsurePeerRegistration;
st->transport.flush = SOSCloudTransportFlush;
st->transport.itemsChangedBlock = Block_copy(^CFArrayRef(CFDictionaryRef changes) {
secerror("Calling default itemsChangedBlock - fatal: %@", changes);
assert(false);
return NULL;
});
SOSXPCCloudTransportInit(st);
return &st->transport;
}
void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock)
{
secdebug(SOSCKCSCOPE, "start");
SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(),
itemsChangedBlock);
}
void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->put(cTransportRef, objects, processQueue, replyBlock);
}
void SOSCloudKeychainUpdateKeys(CFDictionaryRef keys, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->updateKeys(cTransportRef, keys, processQueue, replyBlock);
}
void SOSCloudKeychainSendIDSMessage(CFDataRef message, CFStringRef deviceName, CFStringRef peerID, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if(cTransportRef)
cTransportRef->sendIDSMessage(cTransportRef, message, deviceName, peerID, processQueue, replyBlock);
}
void SOSCloudKeychainGetIDSDeviceID(CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->getDeviceID(cTransportRef, replyBlock);
}
CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates)
{
CFArrayRef result = NULL;
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef->itemsChangedBlock)
result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates);
return result;
}
void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->get(cTransportRef, keysToGet, processQueue, replyBlock);
}
void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->getAll(cTransportRef, processQueue, replyBlock);
}
void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->synchronizeAndWait(cTransportRef, keysToGet, processQueue, replyBlock);
}
void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->synchronize(cTransportRef, processQueue, replyBlock);
}
void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->clearAll(cTransportRef, processQueue, replyBlock);
}
void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->removeObjectForKey(cTransportRef, keyToRemove, processQueue, replyBlock);
}
void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->requestSyncWithAllPeers(cTransportRef, processQueue, replyBlock);
}
void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->requestEnsurePeerRegistration(cTransportRef, processQueue, replyBlock);
}
void SOSCloudKeychainFlush(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock)
{
SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport();
if (cTransportRef)
cTransportRef->flush(cTransportRef, processQueue, replyBlock);
}