]>
Commit | Line | Data |
---|---|---|
5c19dc3a A |
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); | |
e0e0d90e | 169 | SOSUpdateKeyInterest(a); |
5c19dc3a 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 | ||
e0e0d90e A |
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 | } | |
5c19dc3a | 246 |