6 #include "SOSAccountPriv.h"
7 #include <Security/SecureObjectSync/SOSTransport.h>
8 #include <Security/SecureObjectSync/SOSRingUtils.h>
11 // MARK: Ring management
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");
31 const CFStringRef kSOSRingKey
= CFSTR("trusted_rings");
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
);
58 typedef struct ringDef_t
{
62 } ringDef
, *ringDefPtr
;
64 static ringDefPtr
getRingDef(CFStringRef ringName
) {
65 static ringDef retval
;
68 retval
.name
= ringName
;
69 retval
.dropWhenLeaving
= true;
70 retval
.ringType
= kSOSRingEntropyKeyed
;
73 if(CFSetContainsValue(allCurrentRings(), ringName
)) {
74 retval
.ringType
= kSOSRingBase
;
75 retval
.dropWhenLeaving
= false;
77 retval
.ringType
= kSOSRingBackup
;
78 retval
.dropWhenLeaving
= false;
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
)) {
95 void SOSAccountAddRingDictionary(SOSAccountRef a
) {
97 if(!CFDictionaryGetValue(a
->expansion
, kSOSRingKey
)) {
98 CFMutableDictionaryRef rings
= CFDictionaryCreateMutableForCFTypes(NULL
);
99 CFDictionarySetValue(a
->expansion
, kSOSRingKey
, rings
);
100 CFReleaseNull(rings
);
105 static CFMutableDictionaryRef
SOSAccountGetRings(SOSAccountRef a
, CFErrorRef
*error
){
106 CFMutableDictionaryRef rings
= (CFMutableDictionaryRef
) CFDictionaryGetValue(a
->expansion
, kSOSRingKey
);
108 SOSAccountAddRingDictionary(a
);
109 rings
= SOSAccountGetRings(a
, error
);
114 static void SOSAccountSetRings(SOSAccountRef a
, CFMutableDictionaryRef newrings
){
115 CFDictionarySetValue(a
->expansion
, newrings
, kSOSRingKey
);
118 bool SOSAccountForEachRing(SOSAccountRef account
, SOSRingRef (^action
)(CFStringRef name
, SOSRingRef ring
)) {
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
);
132 CFDataRef newringder
= SOSRingCopyEncodedData(newring
, NULL
);
133 CFDictionaryReplaceValue(ringscopy
, key
, newringder
);
134 CFReleaseNull(newringder
);
138 CFReleaseNull(ringder
);
139 CFReleaseNull(newring
);
142 SOSAccountSetRings(account
, ringscopy
);
146 CFReleaseNull(ringscopy
);
150 CFMutableDictionaryRef
SOSAccountGetBackups(SOSAccountRef a
, CFErrorRef
*error
){
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
;
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
);
179 void SOSAccountRemoveRing(SOSAccountRef a
, CFStringRef ringName
) {
180 CFMutableDictionaryRef rings
= SOSAccountGetRings(a
, NULL
);
181 require_quiet(rings
, fail
);
182 CFDictionaryRemoveValue(rings
, ringName
);
188 SOSRingRef
SOSAccountCopyRingNamed(SOSAccountRef a
, CFStringRef ringName
, CFErrorRef
*error
) {
189 SOSRingRef found
= SOSAccountCopyRing(a
, ringName
, error
);
190 if (isSOSRing(found
)) return found
;
192 secerror("Non ring in ring table: %@, purging!", found
);
193 SOSAccountRemoveRing(a
, ringName
);
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
);
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
) {
213 if(!SOSRingIsStable(ring
)) {
215 secnotice("ring", "Ring %@ not stable", ringname
);
221 SOSCreateError(kSOSErrorNotReady
, CFSTR("Rings not present"), NULL
, error
);
227 bool SOSAccountUpdateRingFromRemote(SOSAccountRef account
, SOSRingRef newRing
, CFErrorRef
*error
) {
228 return SOSAccountHandleUpdateRing(account
, newRing
, false, error
);
231 bool SOSAccountUpdateRing(SOSAccountRef account
, SOSRingRef newRing
, CFErrorRef
*error
) {
232 return SOSAccountHandleUpdateRing(account
, newRing
, true, error
);
237 bool SOSAccountModifyRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
* error
, bool (^action
)(SOSRingRef ring
)) {
238 bool success
= false;
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")));
244 require_quiet(action(ring
), fail
);
246 success
= SOSAccountUpdateRing(account
, ring
, error
);
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
);
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
);
273 bool SOSAccountResetRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
*error
) {
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
);
281 retval
= SOSAccountUpdateRing(account
, newring
, error
);
283 CFReleaseNull(newring
);
287 bool SOSAccountResetAllRings(SOSAccountRef account
, CFErrorRef
*error
) {
288 __block
bool retval
= true;
289 CFMutableSetRef ringList
= CFSetCreateMutableForCFTypes(kCFAllocatorDefault
);
290 require_quiet(ringList
, errOut
);
292 SOSAccountForEachRing(account
, ^SOSRingRef(CFStringRef name
, SOSRingRef ring
) {
293 CFSetAddValue(ringList
, name
);
294 return NULL
; // just using this to grab names.
297 CFSetForEach(ringList
, ^(const void *value
) {
298 CFStringRef ringName
= (CFStringRef
) value
;
299 retval
= retval
&& SOSAccountResetRing(account
, ringName
, error
);
303 CFReleaseNull(ringList
);
308 bool SOSAccountUpdateNamedRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
*error
,
309 SOSRingRef (^create
)(CFStringRef ringName
, CFErrorRef
*error
),
310 SOSRingRef (^copyModified
)(SOSRingRef existing
, CFErrorRef
*error
)) {
312 SOSRingRef found
= SOSAccountCopyRing(account
, ringName
, error
);
313 SOSRingRef newRing
= NULL
;
315 found
= create(ringName
, error
);
317 require_quiet(found
, errOut
);
318 newRing
= copyModified(found
, error
);
319 CFReleaseNull(found
);
321 require_quiet(newRing
, errOut
);
323 result
= SOSAccountHandleUpdateRing(account
, newRing
, true, error
);
326 CFReleaseNull(found
);
327 CFReleaseNull(newRing
);