]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSAccountRings.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSAccountRings.m
1 //
2 // SOSAccountRings.c
3 // sec
4 //
5
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"
11
12 #include "AssertMacros.h"
13
14 //
15 // MARK: Ring management
16 //
17
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");
34
35 const CFStringRef kSOSRingKey = CFSTR("trusted_rings");
36
37 static CFSetRef allCurrentRings(void) {
38 static dispatch_once_t dot;
39 static CFMutableSetRef allRings = NULL;
40 dispatch_once(&dot, ^{
41 allRings = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
42 CFSetAddValue(allRings, kSOSRingCircleV2);
43 CFSetAddValue(allRings, kSOSRingKeychainV0);
44 CFSetAddValue(allRings, kSOSRingPCSHyperion);
45 CFSetAddValue(allRings, kSOSRingPCSBladerunner);
46 CFSetAddValue(allRings, kSOSRingPCSLiverpool);
47 CFSetAddValue(allRings, kSOSRingPCSEscrow);
48 CFSetAddValue(allRings, kSOSRingPCSPianoMover);
49 CFSetAddValue(allRings, kSOSRingPCSNotes);
50 CFSetAddValue(allRings, kSOSRingPCSFeldspar);
51 CFSetAddValue(allRings, kSOSRingAppleTV);
52 CFSetAddValue(allRings, kSOSRingHomeKit);
53 CFSetAddValue(allRings, kSOSRingWifi);
54 CFSetAddValue(allRings, kSOSRingPasswords);
55 CFSetAddValue(allRings, kSOSRingCreditCards);
56 CFSetAddValue(allRings, kSOSRingiCloudIdentity);
57 CFSetAddValue(allRings, kSOSRingOtherSyncable);
58 });
59 return allRings;
60 }
61
62 typedef struct ringDef_t {
63 CFStringRef name;
64 SOSRingType ringType;
65 bool dropWhenLeaving;
66 } ringDef, *ringDefPtr;
67
68 static ringDefPtr getRingDef(CFStringRef ringName) {
69 static ringDef retval;
70
71 // Defaults
72 retval.name = ringName;
73 retval.dropWhenLeaving = true;
74 retval.ringType = kSOSRingEntropyKeyed;
75
76
77 if(CFSetContainsValue(allCurrentRings(), ringName)) {
78 retval.ringType = kSOSRingBase;
79 retval.dropWhenLeaving = false;
80 } else {
81 retval.ringType = kSOSRingBackup;
82 retval.dropWhenLeaving = false;
83 }
84 return &retval;
85 }
86
87 __unused static inline void SOSAccountRingForEachRingMatching(SOSAccount* a, void (^action)(SOSRingRef ring), bool (^condition)(SOSRingRef ring)) {
88 CFSetRef allRings = allCurrentRings();
89 CFSetForEach(allRings, ^(const void *value) {
90 CFStringRef ringName = (CFStringRef) value;
91 SOSRingRef ring = [a.trust copyRing:ringName err:NULL];
92 if (condition(ring)) {
93 action(ring);
94 }
95 CFReleaseNull(ring);
96 });
97 }
98
99
100
101
102
103 static void SOSAccountSetRings(SOSAccount* a, CFMutableDictionaryRef newrings){
104 SOSAccountTrustClassic *trust = a.trust;
105 [trust.expansion setObject:(__bridge NSMutableDictionary*)newrings forKey:(__bridge NSString* _Nonnull)(kSOSRingKey)];
106 }
107
108 bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)) {
109 bool retval = false;
110 __block bool changed = false;
111 __block CFStringRef ringname = NULL;
112 __block CFDataRef ringder = NULL;
113 __block SOSRingRef ring = NULL;
114 __block SOSRingRef newring = NULL;
115 __block CFDataRef newringder = NULL;
116
117 CFMutableDictionaryRef rings = [account.trust getRings:NULL];
118 CFMutableDictionaryRef ringscopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
119 if(!rings){
120 CFReleaseNull(ringscopy);
121 return retval;
122 }
123 if(!ringscopy){
124 CFReleaseNull(ringscopy);
125 return retval;
126 }
127 CFDictionaryForEach(rings, ^(const void *key, const void *value) {
128 ringname = (CFStringRef) key;
129 ringder = CFDataCreateCopy(kCFAllocatorDefault, (CFDataRef) value);
130 CFDictionaryAddValue(ringscopy, key, ringder);
131 ring = SOSRingCreateFromData(NULL, ringder);
132 newring = action(ringname, ring);
133 if(newring) {
134 newringder = SOSRingCopyEncodedData(newring, NULL);
135 CFDictionaryReplaceValue(ringscopy, key, newringder);
136 CFReleaseNull(newringder);
137 changed = true;
138 }
139 CFReleaseNull(ring);
140 CFReleaseNull(ringder);
141 CFReleaseNull(newring);
142 });
143 if(changed) {
144 SOSAccountSetRings(account, ringscopy);
145 }
146 retval = true;
147
148 CFReleaseNull(ringscopy);
149 return retval;
150 }
151
152 void SOSAccountRemoveRing(SOSAccount* a, CFStringRef ringName) {
153 CFMutableDictionaryRef rings = [a.trust getRings:NULL];
154 require_quiet(rings, fail);
155 CFDictionaryRemoveValue(rings, ringName);
156 fail:
157 return;
158 }
159
160
161 SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorRef *error) {
162 if(!a.trust)
163 {
164 return NULL;
165 }
166 SOSRingRef found = [a.trust copyRing:ringName err:error];
167
168 if (isSOSRing(found)) return found;
169 if (found) {
170 secerror("Non ring in ring table: %@, purging!", found);
171 SOSAccountRemoveRing(a, ringName);
172 }
173 CFReleaseNull(found); // I'm very skeptical of this function...
174 found = NULL;
175 return found;
176 }
177
178 /* Unused? */
179 SOSRingRef SOSAccountRingCreateForName(SOSAccount* a, CFStringRef ringName, CFErrorRef *error) {
180 ringDefPtr rdef = getRingDef(ringName);
181 if(!rdef) return NULL;
182 SOSRingRef retval = SOSRingCreate(rdef->name, (__bridge CFStringRef) a.peerID, rdef->ringType, error);
183 return retval;
184 }
185
186 bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
187 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
188
189 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:false err:error];
190 errOut:
191 return false;
192 }
193
194 bool SOSAccountUpdateRing(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
195 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
196
197 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
198
199 errOut:
200 return false;
201 }
202
203 bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error,
204 SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error),
205 SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) {
206 bool result = false;
207 SOSRingRef found = [account.trust copyRing:ringName err:error];
208
209 SOSRingRef newRing = NULL;
210 if(!found) {
211 found = create(ringName, error);
212 }
213 require_quiet(found, errOut);
214 newRing = copyModified(found, error);
215 CFReleaseNull(found);
216
217 require_quiet(newRing, errOut);
218
219 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
220 require_quiet(SOSAccountHasCircle(account, error), errOut);
221
222 result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
223
224 errOut:
225 CFReleaseNull(found);
226 CFReleaseNull(newRing);
227 return result;
228 }
229
230