]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRings.c
Security-57740.60.18.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountRings.c
1 //
2 // SOSAccountRings.c
3 // sec
4 //
5
6 #include "SOSAccountPriv.h"
7 #include <Security/SecureObjectSync/SOSTransport.h>
8 #include <Security/SecureObjectSync/SOSRingUtils.h>
9
10 //
11 // MARK: Ring management
12 //
13
14 const CFStringRef kSOSRingCircleV2 = CFSTR("Ring-CircleV2");
15 const CFStringRef kSOSRingKeychainV0 = CFSTR("Ring-KeychainV0");
16 const CFStringRef kSOSRingPCSHyperion = CFSTR("Ring-PCS-Photos");
17 const CFStringRef kSOSRingPCSBladerunner = CFSTR("Ring-PCS-iCloudDrive");
18 const CFStringRef kSOSRingPCSLiverpool = CFSTR("Ring-PCS-CloudKit");
19 const CFStringRef kSOSRingPCSEscrow = CFSTR("Ring-PCS-Escrow");
20 const CFStringRef kSOSRingPCSPianoMover = CFSTR("Ring-PCS-Maildrop");
21 const CFStringRef kSOSRingPCSNotes = CFSTR("Ring-PCS-Notes");
22 const CFStringRef kSOSRingPCSFeldspar = CFSTR("Ring-PCS-Feldspar");
23 const CFStringRef kSOSRingAppleTV = CFSTR("Ring-AppleTV");
24 const CFStringRef kSOSRingHomeKit = CFSTR("Ring-HomeKit");
25 const CFStringRef kSOSRingWifi = CFSTR("Ring-WiFi");
26 const CFStringRef kSOSRingPasswords = CFSTR("Ring-Passwords");
27 const CFStringRef kSOSRingCreditCards = CFSTR("Ring-CreditCards");
28 const CFStringRef kSOSRingiCloudIdentity = CFSTR("Ring-iCloudIdentity");
29 const CFStringRef kSOSRingOtherSyncable = CFSTR("Ring-OtherSyncable");
30
31 const CFStringRef kSOSRingKey = CFSTR("trusted_rings");
32
33 static CFSetRef allCurrentRings(void) {
34 static dispatch_once_t dot;
35 static CFMutableSetRef allRings = NULL;
36 dispatch_once(&dot, ^{
37 allRings = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
38 CFSetAddValue(allRings, kSOSRingCircleV2);
39 CFSetAddValue(allRings, kSOSRingKeychainV0);
40 CFSetAddValue(allRings, kSOSRingPCSHyperion);
41 CFSetAddValue(allRings, kSOSRingPCSBladerunner);
42 CFSetAddValue(allRings, kSOSRingPCSLiverpool);
43 CFSetAddValue(allRings, kSOSRingPCSEscrow);
44 CFSetAddValue(allRings, kSOSRingPCSPianoMover);
45 CFSetAddValue(allRings, kSOSRingPCSNotes);
46 CFSetAddValue(allRings, kSOSRingPCSFeldspar);
47 CFSetAddValue(allRings, kSOSRingAppleTV);
48 CFSetAddValue(allRings, kSOSRingHomeKit);
49 CFSetAddValue(allRings, kSOSRingWifi);
50 CFSetAddValue(allRings, kSOSRingPasswords);
51 CFSetAddValue(allRings, kSOSRingCreditCards);
52 CFSetAddValue(allRings, kSOSRingiCloudIdentity);
53 CFSetAddValue(allRings, kSOSRingOtherSyncable);
54 });
55 return allRings;
56 }
57
58 typedef struct ringDef_t {
59 CFStringRef name;
60 SOSRingType ringType;
61 bool dropWhenLeaving;
62 } ringDef, *ringDefPtr;
63
64 static ringDefPtr getRingDef(CFStringRef ringName) {
65 static ringDef retval;
66
67 // Defaults
68 retval.name = ringName;
69 retval.dropWhenLeaving = true;
70 retval.ringType = kSOSRingEntropyKeyed;
71
72
73 if(CFSetContainsValue(allCurrentRings(), ringName)) {
74 retval.ringType = kSOSRingBase;
75 retval.dropWhenLeaving = false;
76 } else {
77 retval.ringType = kSOSRingBackup;
78 retval.dropWhenLeaving = false;
79 }
80 return &retval;
81 }
82
83 __unused static inline void SOSAccountRingForEachRingMatching(SOSAccountRef a, void (^action)(SOSRingRef ring), bool (^condition)(SOSRingRef ring)) {
84 CFSetRef allRings = allCurrentRings();
85 CFSetForEach(allRings, ^(const void *value) {
86 CFStringRef ringName = (CFStringRef) value;
87 SOSRingRef ring = SOSAccountCopyRing(a, ringName, NULL);
88 if (condition(ring)) {
89 action(ring);
90 }
91 CFReleaseNull(ring);
92 });
93 }
94
95 void SOSAccountAddRingDictionary(SOSAccountRef a) {
96 if(a->expansion) {
97 if(!CFDictionaryGetValue(a->expansion, kSOSRingKey)) {
98 CFMutableDictionaryRef rings = CFDictionaryCreateMutableForCFTypes(NULL);
99 CFDictionarySetValue(a->expansion, kSOSRingKey, rings);
100 CFReleaseNull(rings);
101 }
102 }
103 }
104
105 static CFMutableDictionaryRef SOSAccountGetRings(SOSAccountRef a, CFErrorRef *error){
106 CFMutableDictionaryRef rings = (CFMutableDictionaryRef) CFDictionaryGetValue(a->expansion, kSOSRingKey);
107 if(!rings) {
108 SOSAccountAddRingDictionary(a);
109 rings = SOSAccountGetRings(a, error);
110 }
111 return rings;
112 }
113
114 static void SOSAccountSetRings(SOSAccountRef a, CFMutableDictionaryRef newrings){
115 CFDictionarySetValue(a->expansion, newrings, kSOSRingKey);
116 }
117
118 bool SOSAccountForEachRing(SOSAccountRef account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)) {
119 bool retval = false;
120 __block bool changed = false;
121 CFMutableDictionaryRef rings = SOSAccountGetRings(account, NULL);
122 CFMutableDictionaryRef ringscopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
123 require_quiet(rings, errOut);
124 require_quiet(ringscopy, errOut);
125 CFDictionaryForEach(rings, ^(const void *key, const void *value) {
126 CFStringRef ringname = (CFStringRef) key;
127 CFDataRef ringder = CFDataCreateCopy(kCFAllocatorDefault, (CFDataRef) value);
128 CFDictionaryAddValue(ringscopy, key, ringder);
129 SOSRingRef ring = SOSRingCreateFromData(NULL, ringder);
130 SOSRingRef newring = action(ringname, ring);
131 if(newring) {
132 CFDataRef newringder = SOSRingCopyEncodedData(newring, NULL);
133 CFDictionaryReplaceValue(ringscopy, key, newringder);
134 CFReleaseNull(newringder);
135 changed = true;
136 }
137 CFReleaseNull(ring);
138 CFReleaseNull(ringder);
139 CFReleaseNull(newring);
140 });
141 if(changed) {
142 SOSAccountSetRings(account, ringscopy);
143 }
144 retval = true;
145 errOut:
146 CFReleaseNull(ringscopy);
147 return retval;
148 }
149
150 CFMutableDictionaryRef SOSAccountGetBackups(SOSAccountRef a, CFErrorRef *error){
151 return a->backups;
152 }
153
154 SOSRingRef SOSAccountCopyRing(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
155 CFMutableDictionaryRef rings = SOSAccountGetRings(a, error);
156 require_action_quiet(rings, errOut, SOSCreateError(kSOSErrorNoRing, CFSTR("No Rings found"), NULL, error));
157 CFTypeRef ringder = CFDictionaryGetValue(rings, ringName);
158 require_action_quiet(ringder, errOut, SOSCreateError(kSOSErrorNoRing, CFSTR("No Ring found"), NULL, error));
159 SOSRingRef ring = SOSRingCreateFromData(NULL, ringder);
160 return (SOSRingRef) ring;
161
162 errOut:
163 return NULL;
164 }
165
166 bool SOSAccountSetRing(SOSAccountRef a, SOSRingRef addRing, CFStringRef ringName, CFErrorRef *error) {
167 require_quiet(addRing, errOut);
168 CFMutableDictionaryRef rings = SOSAccountGetRings(a, error);
169 require_action_quiet(rings, errOut, SOSCreateError(kSOSErrorNoRing, CFSTR("No Rings found"), NULL, error));
170 CFDataRef ringder = SOSRingCopyEncodedData(addRing, error);
171 require_quiet(ringder, errOut);
172 CFDictionarySetValue(rings, ringName, ringder);
173 CFReleaseNull(ringder);
174 return true;
175 errOut:
176 return false;
177 }
178
179 void SOSAccountRemoveRing(SOSAccountRef a, CFStringRef ringName) {
180 CFMutableDictionaryRef rings = SOSAccountGetRings(a, NULL);
181 require_quiet(rings, fail);
182 CFDictionaryRemoveValue(rings, ringName);
183 fail:
184 return;
185 }
186
187
188 SOSRingRef SOSAccountCopyRingNamed(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
189 SOSRingRef found = SOSAccountCopyRing(a, ringName, error);
190 if (isSOSRing(found)) return found;
191 if (found) {
192 secerror("Non ring in ring table: %@, purging!", found);
193 SOSAccountRemoveRing(a, ringName);
194 }
195 found = NULL;
196 return found;
197 }
198
199 /* Unused? */
200 SOSRingRef SOSAccountRingCreateForName(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
201 ringDefPtr rdef = getRingDef(ringName);
202 if(!rdef) return NULL;
203 SOSRingRef retval = SOSRingCreate(rdef->name, SOSAccountGetMyPeerID(a), rdef->ringType, error);
204 return retval;
205 }
206
207 bool SOSAccountCheckForRings(SOSAccountRef a, CFErrorRef *error) {
208 __block bool retval = true;
209 CFMutableDictionaryRef rings = SOSAccountGetRings(a, error);
210 if(rings && isDictionary(rings)) {
211 SOSAccountForEachRing(a, ^SOSRingRef(CFStringRef ringname, SOSRingRef ring) {
212 if(retval == true) {
213 if(!SOSRingIsStable(ring)) {
214 retval = false;
215 secnotice("ring", "Ring %@ not stable", ringname);
216 }
217 }
218 return NULL;
219 });
220 } else {
221 SOSCreateError(kSOSErrorNotReady, CFSTR("Rings not present"), NULL, error);
222 retval = false;
223 }
224 return retval;
225 }
226
227 bool SOSAccountUpdateRingFromRemote(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
228 return SOSAccountHandleUpdateRing(account, newRing, false, error);
229 }
230
231 bool SOSAccountUpdateRing(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
232 return SOSAccountHandleUpdateRing(account, newRing, true, error);
233 }
234
235
236 /* Unused? */
237 bool SOSAccountModifyRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef* error, bool (^action)(SOSRingRef ring)) {
238 bool success = false;
239
240 SOSRingRef ring = SOSAccountCopyRing(account, ringName, error);
241 require_action_quiet(ring, fail, SOSErrorCreate(kSOSErrorNoRing, error, NULL, CFSTR("No Ring to get peer key from")));
242
243 success = true;
244 require_quiet(action(ring), fail);
245
246 success = SOSAccountUpdateRing(account, ring, error);
247
248 fail:
249 CFReleaseSafe(ring);
250 return success;
251 }
252
253 /* Unused? */
254 CFDataRef SOSAccountRingCopyPayload(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error) {
255 SOSRingRef ring = SOSAccountCopyRing(account, ringName, error);
256 CFDataRef payload = SOSRingGetPayload(ring, error);
257 CFDataRef retval = CFDataCreateCopy(kCFAllocatorDefault, payload);
258 CFReleaseNull(ring);
259 return retval;
260 }
261
262 /* Unused? */
263 SOSRingRef SOSAccountRingCopyWithPayload(SOSAccountRef account, CFStringRef ringName, CFDataRef payload, CFErrorRef *error) {
264 SOSRingRef ring = SOSAccountCopyRing(account, ringName, error);
265 require_quiet(ring, errOut);
266 CFDataRef oldpayload = SOSRingGetPayload(ring, error);
267 require_quiet(!CFEqualSafe(oldpayload, payload), errOut);
268 require_quiet(SOSRingSetPayload(ring, NULL, payload, account->my_identity, error), errOut);
269 errOut:
270 return ring;
271 }
272
273 bool SOSAccountResetRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error) {
274 bool retval = false;
275 SOSRingRef ring = SOSAccountCopyRing(account, ringName, error);
276 SOSRingRef newring = SOSRingCreate(ringName, NULL, SOSRingGetType(ring), error);
277 SOSRingGenerationCreateWithBaseline(newring, ring);
278 SOSBackupRingSetViews(newring, account->my_identity, SOSBackupRingGetViews(ring, NULL), error);
279 require_quiet(newring, errOut);
280 CFReleaseNull(ring);
281 retval = SOSAccountUpdateRing(account, newring, error);
282 errOut:
283 CFReleaseNull(newring);
284 return retval;
285 }
286
287 bool SOSAccountResetAllRings(SOSAccountRef account, CFErrorRef *error) {
288 __block bool retval = true;
289 CFMutableSetRef ringList = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
290 require_quiet(ringList, errOut);
291
292 SOSAccountForEachRing(account, ^SOSRingRef(CFStringRef name, SOSRingRef ring) {
293 CFSetAddValue(ringList, name);
294 return NULL; // just using this to grab names.
295 });
296
297 CFSetForEach(ringList, ^(const void *value) {
298 CFStringRef ringName = (CFStringRef) value;
299 retval = retval && SOSAccountResetRing(account, ringName, error);
300 });
301
302 errOut:
303 CFReleaseNull(ringList);
304 return retval;
305 }
306
307
308 bool SOSAccountUpdateNamedRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error,
309 SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error),
310 SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) {
311 bool result = false;
312 SOSRingRef found = SOSAccountCopyRing(account, ringName, error);
313 SOSRingRef newRing = NULL;
314 if(!found) {
315 found = create(ringName, error);
316 }
317 require_quiet(found, errOut);
318 newRing = copyModified(found, error);
319 CFReleaseNull(found);
320
321 require_quiet(newRing, errOut);
322
323 result = SOSAccountHandleUpdateRing(account, newRing, true, error);
324
325 errOut:
326 CFReleaseNull(found);
327 CFReleaseNull(newRing);
328 return result;
329 }
330
331