]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRings.c
Security-57337.20.44.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
32 static CFSetRef allCurrentRings(void) {
33 static dispatch_once_t dot;
34 static CFMutableSetRef allRings = NULL;
35 dispatch_once(&dot, ^{
36 allRings = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
37 CFSetAddValue(allRings, kSOSRingCircleV2);
38 CFSetAddValue(allRings, kSOSRingKeychainV0);
39 CFSetAddValue(allRings, kSOSRingPCSHyperion);
40 CFSetAddValue(allRings, kSOSRingPCSBladerunner);
41 CFSetAddValue(allRings, kSOSRingPCSLiverpool);
42 CFSetAddValue(allRings, kSOSRingPCSEscrow);
43 CFSetAddValue(allRings, kSOSRingPCSPianoMover);
44 CFSetAddValue(allRings, kSOSRingPCSNotes);
45 CFSetAddValue(allRings, kSOSRingPCSFeldspar);
46 CFSetAddValue(allRings, kSOSRingAppleTV);
47 CFSetAddValue(allRings, kSOSRingHomeKit);
48 CFSetAddValue(allRings, kSOSRingWifi);
49 CFSetAddValue(allRings, kSOSRingPasswords);
50 CFSetAddValue(allRings, kSOSRingCreditCards);
51 CFSetAddValue(allRings, kSOSRingiCloudIdentity);
52 CFSetAddValue(allRings, kSOSRingOtherSyncable);
53 });
54 return allRings;
55 }
56
57 typedef struct ringDef_t {
58 CFStringRef name;
59 SOSRingType ringType;
60 bool dropWhenLeaving;
61 } ringDef, *ringDefPtr;
62
63 static ringDefPtr getRingDef(CFStringRef ringName) {
64 static ringDef retval;
65
66 // Defaults
67 retval.name = ringName;
68 retval.dropWhenLeaving = true;
69 retval.ringType = kSOSRingEntropyKeyed;
70
71
72 if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
73 } else if(CFEqual(ringName, kSOSRingPCSHyperion) == 0) {
74 } else if(CFEqual(ringName, kSOSRingPCSBladerunner) == 0) {
75 } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
76 } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
77 } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
78 } else if(CFEqual(ringName, kSOSRingKeychainV0) == 0) {
79 } else if(CFEqual(ringName, kSOSRingCircleV2) == 0) {
80 retval.ringType = kSOSRingBase;
81 retval.dropWhenLeaving = false;
82 } else return NULL;
83 return &retval;
84 }
85
86 #if 0
87 static bool isRingKnown(CFStringRef ringname) {
88 if(getRingDef(ringname) != NULL) return true;
89 secnotice("rings","Not a known ring");
90 return false;
91 }
92 #endif
93
94 static inline void SOSAccountRingForEach(void (^action)(CFStringRef ringname)) {
95 CFSetRef allRings = allCurrentRings();
96 CFSetForEach(allRings, ^(const void *value) {
97 CFStringRef ringName = (CFStringRef) value;
98 action(ringName);
99 });
100 }
101
102
103 __unused static inline void SOSAccountRingForEachRingMatching(SOSAccountRef a, void (^action)(SOSRingRef ring), bool (^condition)(SOSRingRef ring)) {
104 CFSetRef allRings = allCurrentRings();
105 CFSetForEach(allRings, ^(const void *value) {
106 CFStringRef ringName = (CFStringRef) value;
107 SOSRingRef ring = SOSAccountGetRing(a, ringName, NULL);
108 if (condition(ring))
109 action(ring);
110 });
111 }
112
113 CFMutableDictionaryRef SOSAccountGetRings(SOSAccountRef a, CFErrorRef *error){
114 return a->trusted_rings;
115 }
116
117 CFMutableDictionaryRef SOSAccountGetBackups(SOSAccountRef a, CFErrorRef *error){
118 return a->backups;
119 }
120
121 SOSRingRef SOSAccountGetRing(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
122 CFTypeRef entry = CFDictionaryGetValue(a->trusted_rings, ringName);
123 require_action_quiet(entry, fail,
124 SOSCreateError(kSOSErrorNoRing, CFSTR("No Ring found"), NULL, error));
125 return (SOSRingRef) entry;
126
127 fail:
128 return NULL;
129 }
130
131 CFStringRef SOSAccountGetMyPeerID(SOSAccountRef a) {
132 SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInfo(a);
133 require_quiet(fpi, errOut);
134 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi);
135 require_quiet(pi, errOut);
136 return SOSPeerInfoGetPeerID(pi);
137 errOut:
138 return NULL;
139 }
140
141 SOSRingRef SOSAccountRingCreateForName(SOSAccountRef a, CFStringRef ringName, CFErrorRef *error) {
142 ringDefPtr rdef = getRingDef(ringName);
143 if(!rdef) return NULL;
144 SOSRingRef retval = SOSRingCreate(rdef->name, SOSAccountGetMyPeerID(a), rdef->ringType, error);
145 return retval;
146 }
147
148 bool SOSAccountCheckForRings(SOSAccountRef a, CFErrorRef *error) {
149 bool retval = isDictionary(a->trusted_rings);
150 if(!retval) SOSCreateError(kSOSErrorNotReady, CFSTR("Rings not present"), NULL, error);
151 return retval;
152 }
153
154 bool SOSAccountEnsureRings(SOSAccountRef a, CFErrorRef *error) {
155 bool status = false;
156
157 if(!a->trusted_rings) {
158 a->trusted_rings = CFDictionaryCreateMutableForCFTypes(NULL);
159 }
160
161 require_quiet(SOSAccountEnsureFullPeerAvailable(a, error), errOut);
162
163 SOSAccountRingForEach(^(CFStringRef ringname) {
164 SOSRingRef ring = SOSAccountGetRing(a, ringname, NULL);
165 if(!ring) {
166 ring = SOSAccountRingCreateForName(a, ringname, error);
167 if(ring) {
168 CFDictionaryAddValue(a->trusted_rings, ringname, ring);
169 SOSUpdateKeyInterest(a);
170 }
171 CFReleaseNull(ring);
172 }
173 });
174
175 status = true;
176 errOut:
177 return status;
178 }
179
180 bool SOSAccountUpdateRingFromRemote(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
181 return SOSAccountHandleUpdateRing(account, newRing, false, error);
182 }
183
184 bool SOSAccountUpdateRing(SOSAccountRef account, SOSRingRef newRing, CFErrorRef *error) {
185 return SOSAccountHandleUpdateRing(account, newRing, true, error);
186 }
187
188 bool SOSAccountModifyRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef* error, bool (^action)(SOSRingRef ring)) {
189 bool success = false;
190
191 SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
192 require_action_quiet(ring, fail, SOSErrorCreate(kSOSErrorNoRing, error, NULL, CFSTR("No Ring to get peer key from")));
193
194 ring = SOSRingCopyRing(ring, error);
195 require_quiet(ring, fail);
196
197 success = true;
198 require_quiet(action(ring), fail);
199
200 success = SOSAccountUpdateRing(account, ring, error);
201
202 fail:
203 CFReleaseSafe(ring);
204 return success;
205 }
206
207 CFDataRef SOSAccountRingGetPayload(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error) {
208 SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
209 return SOSRingGetPayload(ring, error);
210 }
211
212 SOSRingRef SOSAccountRingCopyWithPayload(SOSAccountRef account, CFStringRef ringName, CFDataRef payload, CFErrorRef *error) {
213 SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
214 require_quiet(ring, errOut);
215 SOSRingRef new = SOSRingCopyRing(ring, error);
216 require_quiet(new, errOut);
217 CFDataRef oldpayload = SOSRingGetPayload(ring, error);
218 require_quiet(!CFEqualSafe(oldpayload, payload), errOut);
219 require_quiet(SOSRingSetPayload(new, NULL, payload, account->my_identity, error), errOut);
220
221 errOut:
222 return NULL;
223 }
224
225 bool SOSAccountResetRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error) {
226 bool retval = false;
227 SOSRingRef ring = SOSAccountGetRing(account, ringName, error);
228 SOSRingRef newring = SOSRingCreate(ringName, NULL, SOSRingGetType(ring), error);
229 SOSRingGenerationCreateWithBaseline(newring, ring);
230 SOSBackupRingSetViews(newring, account->my_identity, SOSBackupRingGetViews(ring, NULL), error);
231 require_quiet(newring, errOut);
232 retval = SOSAccountUpdateRing(account, newring, error);
233 errOut:
234 CFReleaseNull(newring);
235 return retval;
236 }
237
238 bool SOSAccountResetAllRings(SOSAccountRef account, CFErrorRef *error) {
239 __block bool retval = true;
240 CFDictionaryForEach(account->trusted_rings, ^(const void *key, const void *value) {
241 CFStringRef ringName = (CFStringRef) key;
242 retval = retval && SOSAccountResetRing(account, ringName, error);
243 });
244 return retval;
245 }
246