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");
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
);
57 typedef struct ringDef_t
{
61 } ringDef
, *ringDefPtr
;
63 static ringDefPtr
getRingDef(CFStringRef ringName
) {
64 static ringDef retval
;
67 retval
.name
= ringName
;
68 retval
.dropWhenLeaving
= true;
69 retval
.ringType
= kSOSRingEntropyKeyed
;
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;
87 static bool isRingKnown(CFStringRef ringname
) {
88 if(getRingDef(ringname
) != NULL
) return true;
89 secnotice("rings","Not a known ring");
94 static inline void SOSAccountRingForEach(void (^action
)(CFStringRef ringname
)) {
95 CFSetRef allRings
= allCurrentRings();
96 CFSetForEach(allRings
, ^(const void *value
) {
97 CFStringRef ringName
= (CFStringRef
) value
;
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
);
113 CFMutableDictionaryRef
SOSAccountGetRings(SOSAccountRef a
, CFErrorRef
*error
){
114 return a
->trusted_rings
;
117 CFMutableDictionaryRef
SOSAccountGetBackups(SOSAccountRef a
, CFErrorRef
*error
){
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
;
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
);
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
);
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
);
154 bool SOSAccountEnsureRings(SOSAccountRef a
, CFErrorRef
*error
) {
157 if(!a
->trusted_rings
) {
158 a
->trusted_rings
= CFDictionaryCreateMutableForCFTypes(NULL
);
161 require_quiet(SOSAccountEnsureFullPeerAvailable(a
, error
), errOut
);
163 SOSAccountRingForEach(^(CFStringRef ringname
) {
164 SOSRingRef ring
= SOSAccountGetRing(a
, ringname
, NULL
);
166 ring
= SOSAccountRingCreateForName(a
, ringname
, error
);
168 CFDictionaryAddValue(a
->trusted_rings
, ringname
, ring
);
169 SOSUpdateKeyInterest(a
);
180 bool SOSAccountUpdateRingFromRemote(SOSAccountRef account
, SOSRingRef newRing
, CFErrorRef
*error
) {
181 return SOSAccountHandleUpdateRing(account
, newRing
, false, error
);
184 bool SOSAccountUpdateRing(SOSAccountRef account
, SOSRingRef newRing
, CFErrorRef
*error
) {
185 return SOSAccountHandleUpdateRing(account
, newRing
, true, error
);
188 bool SOSAccountModifyRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
* error
, bool (^action
)(SOSRingRef ring
)) {
189 bool success
= false;
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")));
194 ring
= SOSRingCopyRing(ring
, error
);
195 require_quiet(ring
, fail
);
198 require_quiet(action(ring
), fail
);
200 success
= SOSAccountUpdateRing(account
, ring
, error
);
207 CFDataRef
SOSAccountRingGetPayload(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
*error
) {
208 SOSRingRef ring
= SOSAccountGetRing(account
, ringName
, error
);
209 return SOSRingGetPayload(ring
, error
);
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
);
225 bool SOSAccountResetRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef
*error
) {
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
);
234 CFReleaseNull(newring
);
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
);