6 #include "SOSAccountPriv.h"
7 #import "keychain/SecureObjectSync/SOSTransport.h"
8 #import "keychain/SecureObjectSync/SOSRingUtils.h"
9 #import "keychain/SecureObjectSync/SOSAccountTrust.h"
10 #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h"
12 #include "AssertMacros.h"
15 // MARK: Ring management
18 const CFStringRef kSOSRingCircleV2 = CFSTR("Ring-CircleV2");
19 const CFStringRef kSOSRingKeychainV0 = CFSTR("Ring-KeychainV0");
20 const CFStringRef kSOSRingPCSHyperion = CFSTR("Ring-PCS-Photos");
21 const CFStringRef kSOSRingPCSBladerunner = CFSTR("Ring-PCS-iCloudDrive");
22 const CFStringRef kSOSRingPCSLiverpool = CFSTR("Ring-PCS-CloudKit");
23 const CFStringRef kSOSRingPCSEscrow = CFSTR("Ring-PCS-Escrow");
24 const CFStringRef kSOSRingPCSPianoMover = CFSTR("Ring-PCS-Maildrop");
25 const CFStringRef kSOSRingPCSNotes = CFSTR("Ring-PCS-Notes");
26 const CFStringRef kSOSRingPCSFeldspar = CFSTR("Ring-PCS-Feldspar");
27 const CFStringRef kSOSRingAppleTV = CFSTR("Ring-AppleTV");
28 const CFStringRef kSOSRingHomeKit = CFSTR("Ring-HomeKit");
29 const CFStringRef kSOSRingWifi = CFSTR("Ring-WiFi");
30 const CFStringRef kSOSRingPasswords = CFSTR("Ring-Passwords");
31 const CFStringRef kSOSRingCreditCards = CFSTR("Ring-CreditCards");
32 const CFStringRef kSOSRingiCloudIdentity = CFSTR("Ring-iCloudIdentity");
33 const CFStringRef kSOSRingOtherSyncable = CFSTR("Ring-OtherSyncable");
35 const CFStringRef kSOSRingKey = CFSTR("trusted_rings");
37 typedef struct ringDef_t {
41 } ringDef, *ringDefPtr;
43 static void SOSAccountSetRings(SOSAccount* a, CFMutableDictionaryRef newrings){
44 SOSAccountTrustClassic *trust = a.trust;
45 [trust.expansion setObject:(__bridge NSMutableDictionary*)newrings forKey:(__bridge NSString* _Nonnull)(kSOSRingKey)];
48 bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)) {
50 __block bool changed = false;
51 __block CFStringRef ringname = NULL;
52 __block CFDataRef ringder = NULL;
53 __block SOSRingRef ring = NULL;
54 __block SOSRingRef newring = NULL;
55 __block CFDataRef newringder = NULL;
57 CFMutableDictionaryRef rings = [account.trust getRings:NULL];
58 CFMutableDictionaryRef ringscopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
60 CFReleaseNull(ringscopy);
64 CFReleaseNull(ringscopy);
67 CFDictionaryForEach(rings, ^(const void *key, const void *value) {
68 ringname = (CFStringRef) key;
69 ringder = CFDataCreateCopy(kCFAllocatorDefault, (CFDataRef) value);
70 CFDictionaryAddValue(ringscopy, key, ringder);
71 ring = SOSRingCreateFromData(NULL, ringder);
72 newring = action(ringname, ring);
74 newringder = SOSRingCopyEncodedData(newring, NULL);
75 CFDictionaryReplaceValue(ringscopy, key, newringder);
76 CFReleaseNull(newringder);
80 CFReleaseNull(ringder);
81 CFReleaseNull(newring);
84 SOSAccountSetRings(account, ringscopy);
88 CFReleaseNull(ringscopy);
92 void SOSAccountRemoveRing(SOSAccount* a, CFStringRef ringName) {
93 CFMutableDictionaryRef rings = [a.trust getRings:NULL];
94 require_quiet(rings, fail);
95 CFDictionaryRemoveValue(rings, ringName);
101 SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorRef *error) {
106 SOSRingRef found = [a.trust copyRing:ringName err:error];
108 if (isSOSRing(found)) return found;
110 secerror("Non ring in ring table: %@, purging!", found);
111 SOSAccountRemoveRing(a, ringName);
113 CFReleaseNull(found); // I'm very skeptical of this function...
118 bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
119 if(account && account.accountIsChanging) {
120 secnotice("circleOps", "SOSAccountUpdateRingFromRemote called before signing in to new account");
121 return true; // we want to drop circle notifications when account is changing
124 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
126 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:false err:error];
131 bool SOSAccountUpdateRing(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
132 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
134 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
140 bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error,
141 SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error),
142 SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) {
143 if(![account isInCircle:NULL]) {
147 SOSRingRef found = NULL;
148 SOSRingRef newRing = NULL;
149 found = [account.trust copyRing:ringName err:error];
151 found = create(ringName, error);
154 newRing = copyModified(found, error);
156 result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
159 CFReleaseNull(found);
160 CFReleaseNull(newRing);