--- /dev/null
+//
+// SOSAccountCircles.c
+// sec
+//
+
+#include "SOSAccountPriv.h"
+#include <Security/SecureObjectSync/SOSTransport.h>
+#include <Security/SecureObjectSync/SOSTransportKeyParameterKVS.h>
+#include <Security/SecureObjectSync/SOSTransportCircleKVS.h>
+#include <Security/SecureObjectSync/SOSTransportMessageKVS.h>
+#include <Security/SecureObjectSync/SOSTransportMessageIDS.h>
+#include "SOSCloudKeychainClient.h"
+
+
+//
+// MARK: Circle management
+//
+
+CFIndex whichTransportType;
+
+
+SecKeyRef SOSAccountCopyPublicKeyForPeer(SOSAccountRef account, CFStringRef peer_id, CFErrorRef *error) {
+ SecKeyRef publicKey = NULL;
+ SOSPeerInfoRef peer = NULL;
+
+ require_action_quiet(account->trusted_circle, fail, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to get peer key from")));
+
+ peer = SOSCircleCopyPeerWithID(account->trusted_circle, peer_id, error);
+ require_quiet(peer, fail);
+
+ publicKey = SOSPeerInfoCopyPubKey(peer);
+
+fail:
+ CFReleaseSafe(peer);
+ return publicKey;
+}
+
+
+SOSCircleRef SOSAccountGetCircle(SOSAccountRef a, CFErrorRef *error)
+{
+ CFTypeRef entry = a->trusted_circle;
+
+ require_action_quiet(!isNull(entry), fail,
+ SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle in KVS"), NULL, error));
+
+ require_action_quiet(entry, fail,
+ SOSCreateError(kSOSErrorNoCircle, CFSTR("No circle found"), NULL, error));
+
+
+ return (SOSCircleRef) entry;
+
+fail:
+ return NULL;
+}
+
+static void setup_defaults_settings(){
+
+ Boolean keyExistsAndHasValue = false;
+
+ whichTransportType = CFPreferencesGetAppIntegerValue(CFSTR("Transport"), CFSTR("com.apple.security"), &keyExistsAndHasValue);
+ if(whichTransportType == kSOSTransportFuture)
+ secdebug("IDS", "Successfully retrieved value: %d, We are a Galarch + 1 device: %ld", keyExistsAndHasValue, whichTransportType);
+ else if (whichTransportType == kSOSTransportPresent)
+ secdebug("IDS", "Successfully retrieved value: %d, We are a Galarch device: %ld", keyExistsAndHasValue, whichTransportType);
+
+ else if (whichTransportType == kSOSTransportIDS)
+ secdebug("IDS", "Successfully retrieved value: %d, We are an IDS device: %ld", keyExistsAndHasValue, whichTransportType);
+
+ else if (whichTransportType == kSOSTransportKVS)
+ secdebug("IDS", "Successfully retrieved value: %d, We are a KVS device: %ld", keyExistsAndHasValue, whichTransportType);
+ else
+ secdebug("IDS", "Successfully retrieved value: %d, We are a KVS device: %ld", keyExistsAndHasValue, whichTransportType);
+
+}
+
+static void SOSTransportInit(void) {
+ static dispatch_once_t sdOnceToken;
+ dispatch_once(&sdOnceToken, ^{
+ setup_defaults_settings();
+ });
+}
+
+static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){
+ bool success = false;
+
+ SOSTransportKeyParameterRef tKey = NULL;
+ SOSTransportCircleRef tCircle = NULL;
+ SOSTransportMessageRef tidsMessage = NULL;
+ SOSTransportMessageRef tkvsMessage = NULL;
+
+ SOSTransportInit();
+
+ tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error);
+ tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error);
+
+ require_quiet(tKey, fail);
+ require_quiet(tCircle, fail);
+
+
+ if (whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportPresent) {
+ tidsMessage = (SOSTransportMessageRef)SOSTransportMessageIDSCreate(account, circleName, error);
+ require_quiet(tidsMessage, fail);
+
+ CFRetainAssign(account->ids_message_transport, tidsMessage);
+
+ secnotice("transport", "We are going to use an IDS transport");
+ }
+
+ tkvsMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error);
+ require_quiet(tkvsMessage, fail);
+
+ CFRetainAssign(account->kvs_message_transport, tkvsMessage);
+
+ CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey);
+ CFRetainAssign(account->circle_transport, tCircle);
+
+
+ success = true;
+fail:
+ CFReleaseNull(tKey);
+ CFReleaseNull(tCircle);
+ CFReleaseNull(tidsMessage);
+ CFReleaseNull(tkvsMessage);
+ return success;
+}
+
+SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error)
+{
+ CFErrorRef localError = NULL;
+
+ if (a->trusted_circle == NULL) {
+ a->trusted_circle = SOSCircleCreate(NULL, name, NULL);
+ SOSUpdateKeyInterest();
+ }
+
+
+ SOSCircleRef circle = SOSAccountGetCircle(a, &localError);
+
+ require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail,
+ if (error) { *error = localError; localError = NULL; });
+
+ require_quiet(SOSAccountInflateTransportsForCircle(a, name, error), fail);
+
+fail:
+ CFReleaseNull(localError);
+ return circle;
+}
+
+
+bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error)
+{
+ return SOSAccountHandleUpdateCircle(account, newCircle, false, error);
+}
+
+bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error)
+{
+ return SOSAccountHandleUpdateCircle(account, newCircle, true, error);
+}
+
+bool SOSAccountModifyCircle(SOSAccountRef account,
+ CFErrorRef* error,
+ bool (^action)(SOSCircleRef circle))
+{
+ bool success = false;
+
+ SOSCircleRef circle = NULL;
+ require_action_quiet(account->trusted_circle, fail, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to get peer key from")));
+
+ circle = SOSCircleCopyCircle(kCFAllocatorDefault, account->trusted_circle, error);
+ require_quiet(circle, fail);
+
+ success = true;
+ require_quiet(action(circle), fail);
+
+ success = SOSAccountUpdateCircle(account, circle, error);
+
+fail:
+ CFReleaseSafe(circle);
+ return success;
+}
+