]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/ProjectHeaders/Security/SecureObjectSync/SOSAccountRings.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / ProjectHeaders / Security / SecureObjectSync / SOSAccountRings.c
diff --git a/OSX/sec/ProjectHeaders/Security/SecureObjectSync/SOSAccountRings.c b/OSX/sec/ProjectHeaders/Security/SecureObjectSync/SOSAccountRings.c
new file mode 100644 (file)
index 0000000..75052f2
--- /dev/null
@@ -0,0 +1,225 @@
+//
+//  SOSAccountRings.c
+//  sec
+//
+
+#include "SOSAccountPriv.h"
+#include <Security/SecureObjectSync/SOSTransport.h>
+#include <Security/SecureObjectSync/SOSRingUtils.h>
+
+//
+// MARK: Ring management
+//
+
+const CFStringRef kSOSRingCircleV2              = CFSTR("Ring-CircleV2");
+const CFStringRef kSOSRingKeychainV0            = CFSTR("Ring-KeychainV0");
+const CFStringRef kSOSRingPCSHyperion           = CFSTR("Ring-PCS-Photos");
+const CFStringRef kSOSRingPCSBladerunner        = CFSTR("Ring-PCS-iCloudDrive");
+const CFStringRef kSOSRingPCSLiverpool          = CFSTR("Ring-PCS-CloudKit");
+const CFStringRef kSOSRingPCSEscrow             = CFSTR("Ring-PCS-Escrow");
+const CFStringRef kSOSRingPCSPianoMover         = CFSTR("Ring-PCS-Maildrop");
+const CFStringRef kSOSRingPCSNotes              = CFSTR("Ring-PCS-Notes");
+const CFStringRef kSOSRingPCSFeldspar           = CFSTR("Ring-PCS-Feldspar");
+const CFStringRef kSOSRingAppleTV               = CFSTR("Ring-AppleTV");
+const CFStringRef kSOSRingHomeKit               = CFSTR("Ring-HomeKit");
+const CFStringRef kSOSRingWifi                  = CFSTR("Ring-WiFi");
+const CFStringRef kSOSRingPasswords             = CFSTR("Ring-Passwords");
+const CFStringRef kSOSRingCreditCards           = CFSTR("Ring-CreditCards");
+const CFStringRef kSOSRingiCloudIdentity        = CFSTR("Ring-iCloudIdentity");
+const CFStringRef kSOSRingOtherSyncable         = CFSTR("Ring-OtherSyncable");
+
+
+static CFSetRef allCurrentRings(void) {
+    static dispatch_once_t dot;
+    static CFMutableSetRef allRings = NULL;
+    dispatch_once(&dot, ^{
+        allRings = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+        CFSetAddValue(allRings, kSOSRingCircleV2);
+        CFSetAddValue(allRings, kSOSRingKeychainV0);
+        CFSetAddValue(allRings, kSOSRingPCSHyperion);
+        CFSetAddValue(allRings, kSOSRingPCSBladerunner);
+        CFSetAddValue(allRings, kSOSRingPCSLiverpool);
+        CFSetAddValue(allRings, kSOSRingPCSEscrow);
+        CFSetAddValue(allRings, kSOSRingPCSPianoMover);
+        CFSetAddValue(allRings, kSOSRingPCSNotes);
+        CFSetAddValue(allRings, kSOSRingPCSFeldspar);
+        CFSetAddValue(allRings, kSOSRingAppleTV);
+        CFSetAddValue(allRings, kSOSRingHomeKit);
+        CFSetAddValue(allRings, kSOSRingWifi);
+        CFSetAddValue(allRings, kSOSRingPasswords);
+        CFSetAddValue(allRings, kSOSRingCreditCards);
+        CFSetAddValue(allRings, kSOSRingiCloudIdentity);
+        CFSetAddValue(allRings, kSOSRingOtherSyncable);
+    });
+    return allRings;
+}
+
+typedef struct ringDef_t {
+    CFStringRef name;
+    SOSRingType ringType;
+    bool dropWhenLeaving;
+} ringDef, *ringDefPtr;
+
+static ringDefPtr getRingDef(CFStringRef ringName) {
+    static ringDef retval;
+
+    // Defaults
+    retval.name = ringName;
+    retval.dropWhenLeaving = true;
+    retval.ringType = kSOSRingEntropyKeyed;
+
+
+    if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
+    } else if(CFEqual(ringName, kSOSRingPCSHyperion) == 0) {
+    } else if(CFEqual(ringName, kSOSRingPCSBladerunner) == 0) {
+    } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
+    } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
+    } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
+    } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
+    } else if(CFEqual(ringName, kSOSRingCircleV2) == 0) {
+        retval.ringType = kSOSRingBase;
+        retval.dropWhenLeaving = false;
+    } else return NULL;
+    return &retval;
+}
+
+#if 0
+static bool isRingKnown(CFStringRef ringname) {
+    if(getRingDef(ringname) != NULL) return true;
+    secnotice("rings","Not a known ring");
+    return false;
+}
+#endif
+
+static inline void SOSAccountRingForEach(void (^action)(CFStringRef ringname)) {
+    CFSetRef allRings = allCurrentRings();
+    CFSetForEach(allRings, ^(const void *value) {
+        CFStringRef ringName = (CFStringRef) value;
+            action(ringName);
+    });
+}
+
+
+__unused static inline void SOSAccountRingForEachRingMatching(SOSAccountRef a, void (^action)(SOSRingRef ring), bool (^condition)(SOSRingRef ring)) {
+    CFSetRef allRings = allCurrentRings();
+    CFSetForEach(allRings, ^(const void *value) {
+        CFStringRef ringName = (CFStringRef) value;
+        SOSRingRef ring = SOSAccountGetRing(a, ringName, NULL);
+        if (condition(ring))
+            action(ring);
+    });
+}
+
+CFMutableDictionaryRef SOSAccountGetRings(SOSAccountRef a, CFErrorRef *error){
+    return a->trusted_rings;
+}
+
+CFMutableDictionaryRef SOSAccountGetBackups(SOSAccountRef a, CFErrorRef *error){
+    return a->backups;
+}
+
+SOSRingRef SOSAccountGetRing(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
+    CFTypeRef entry = CFDictionaryGetValue(a->trusted_rings, ringName);
+    require_action_quiet(entry, fail,
+                         SOSCreateError(kSOSErrorNoRing, CFSTR("No Ring found"), NULL, error));
+    return (SOSRingRef) entry;
+
+fail:
+    return NULL;
+}
+
+CFStringRef SOSAccountGetMyPeerID(SOSAccountRef a) {
+    SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInfo(a);
+    require_quiet(fpi, errOut);
+    SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi);
+    require_quiet(pi, errOut);
+    return SOSPeerInfoGetPeerID(pi);
+errOut:
+    return NULL;
+}
+
+SOSRingRef SOSAccountRingCreateForName(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
+    ringDefPtr rdef = getRingDef(ringName);
+    if(!rdef) return NULL;
+    SOSRingRef retval = SOSRingCreate(rdef->name, SOSAccountGetMyPeerID(a), rdef->ringType, error);
+    return retval;
+}
+
+bool SOSAccountCheckForRings(SOSAccountRef a, CFErrorRef *error) {
+    bool retval = isDictionary(a->trusted_rings);
+    if(!retval) SOSCreateError(kSOSErrorNotReady, CFSTR("Rings not present"), NULL, error);
+    return retval;
+}
+
+bool SOSAccountEnsureRings(SOSAccountRef a, CFErrorRef *error) {
+    bool status = false;
+
+    if(!a->trusted_rings) {
+        a->trusted_rings = CFDictionaryCreateMutableForCFTypes(NULL);
+    }
+
+    require_quiet(SOSAccountEnsureFullPeerAvailable(a, error), errOut);
+
+    SOSAccountRingForEach(^(CFStringRef ringname) {
+        SOSRingRef ring = SOSAccountGetRing(a, ringname, NULL);
+        if(!ring) {
+            ring = SOSAccountRingCreateForName(a, ringname, error);
+            if(ring) {
+                CFDictionaryAddValue(a->trusted_rings, ringname, ring);
+                SOSUpdateKeyInterest();
+            }
+            CFReleaseNull(ring);
+        }
+    });
+
+    status = true;
+errOut:
+    return status;
+}
+
+bool SOSAccountUpdateRingFromRemote(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
+    return SOSAccountHandleUpdateRing(account, newRing, false, error);
+}
+
+bool SOSAccountUpdateRing(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
+    return SOSAccountHandleUpdateRing(account, newRing, true, error);
+}
+
+bool SOSAccountModifyRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef* error, bool (^action)(SOSRingRef ring)) {
+    bool success = false;
+
+    SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
+    require_action_quiet(ring, fail, SOSErrorCreate(kSOSErrorNoRing, error, NULL, CFSTR("No Ring to get peer key from")));
+
+    ring = SOSRingCopyRing(ring, error);
+    require_quiet(ring, fail);
+
+    success = true;
+    require_quiet(action(ring), fail);
+
+    success = SOSAccountUpdateRing(account, ring, error);
+
+fail:
+    CFReleaseSafe(ring);
+    return success;
+}
+
+CFDataRef SOSAccountRingGetPayload(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error) {
+    SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
+    return SOSRingGetPayload(ring, error);
+}
+
+SOSRingRef SOSAccountRingCopyWithPayload(SOSAccountRef account, CFStringRef ringName, CFDataRef payload, CFErrorRef *error) {
+    SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
+    require_quiet(ring, errOut);
+    SOSRingRef new = SOSRingCopyRing(ring, error);
+    require_quiet(new, errOut);
+    CFDataRef oldpayload = SOSRingGetPayload(ring, error);
+    require_quiet(!CFEqualSafe(oldpayload, payload), errOut);
+    require_quiet(SOSRingSetPayload(new, NULL, payload, account->my_identity, error), errOut);
+
+errOut:
+    return NULL;
+}
+
+