]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSAccountRings.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSAccountRings.m
1 //
2 // SOSAccountRings.c
3 // sec
4 //
5
6 #include "SOSAccountPriv.h"
7 #import "keychain/SecureObjectSync/SOSTransport.h"
8 #import "keychain/SecureObjectSync/SOSRingUtils.h"
9 #import "keychain/SecureObjectSync/SOSAccountTrust.h"
10 #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h"
11
12 #include "AssertMacros.h"
13
14 //
15 // MARK: Ring management
16 //
17
18 const CFStringRef kSOSRingCircleV2 = CFSTR("Ring-CircleV2");
19 const CFStringRef kSOSRingKeychainV0 = CFSTR("Ring-KeychainV0");
20 const CFStringRef kSOSRingPCSHyperion = CFSTR("Ring-PCS-Photos");
21 const CFStringRef kSOSRingPCSBladerunner = CFSTR("Ring-PCS-iCloudDrive");
22 const CFStringRef kSOSRingPCSLiverpool = CFSTR("Ring-PCS-CloudKit");
23 const CFStringRef kSOSRingPCSEscrow = CFSTR("Ring-PCS-Escrow");
24 const CFStringRef kSOSRingPCSPianoMover = CFSTR("Ring-PCS-Maildrop");
25 const CFStringRef kSOSRingPCSNotes = CFSTR("Ring-PCS-Notes");
26 const CFStringRef kSOSRingPCSFeldspar = CFSTR("Ring-PCS-Feldspar");
27 const CFStringRef kSOSRingAppleTV = CFSTR("Ring-AppleTV");
28 const CFStringRef kSOSRingHomeKit = CFSTR("Ring-HomeKit");
29 const CFStringRef kSOSRingWifi = CFSTR("Ring-WiFi");
30 const CFStringRef kSOSRingPasswords = CFSTR("Ring-Passwords");
31 const CFStringRef kSOSRingCreditCards = CFSTR("Ring-CreditCards");
32 const CFStringRef kSOSRingiCloudIdentity = CFSTR("Ring-iCloudIdentity");
33 const CFStringRef kSOSRingOtherSyncable = CFSTR("Ring-OtherSyncable");
34
35 const CFStringRef kSOSRingKey = CFSTR("trusted_rings");
36
37 typedef struct ringDef_t {
38 CFStringRef name;
39 SOSRingType ringType;
40 bool dropWhenLeaving;
41 } ringDef, *ringDefPtr;
42
43 static void SOSAccountSetRings(SOSAccount* a, CFMutableDictionaryRef newrings){
44 SOSAccountTrustClassic *trust = a.trust;
45 [trust.expansion setObject:(__bridge NSMutableDictionary*)newrings forKey:(__bridge NSString* _Nonnull)(kSOSRingKey)];
46 }
47
48 bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)) {
49 bool retval = false;
50 __block bool changed = false;
51 __block CFStringRef ringname = NULL;
52 __block CFDataRef ringder = NULL;
53 __block SOSRingRef ring = NULL;
54 __block SOSRingRef newring = NULL;
55 __block CFDataRef newringder = NULL;
56
57 CFMutableDictionaryRef rings = [account.trust getRings:NULL];
58 CFMutableDictionaryRef ringscopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
59 if(!rings){
60 CFReleaseNull(ringscopy);
61 return retval;
62 }
63 if(!ringscopy){
64 CFReleaseNull(ringscopy);
65 return retval;
66 }
67 CFDictionaryForEach(rings, ^(const void *key, const void *value) {
68 ringname = (CFStringRef) key;
69 ringder = CFDataCreateCopy(kCFAllocatorDefault, (CFDataRef) value);
70 CFDictionaryAddValue(ringscopy, key, ringder);
71 ring = SOSRingCreateFromData(NULL, ringder);
72 newring = action(ringname, ring);
73 if(newring) {
74 newringder = SOSRingCopyEncodedData(newring, NULL);
75 CFDictionaryReplaceValue(ringscopy, key, newringder);
76 CFReleaseNull(newringder);
77 changed = true;
78 }
79 CFReleaseNull(ring);
80 CFReleaseNull(ringder);
81 CFReleaseNull(newring);
82 });
83 if(changed) {
84 SOSAccountSetRings(account, ringscopy);
85 }
86 retval = true;
87
88 CFReleaseNull(ringscopy);
89 return retval;
90 }
91
92 void SOSAccountRemoveRing(SOSAccount* a, CFStringRef ringName) {
93 CFMutableDictionaryRef rings = [a.trust getRings:NULL];
94 require_quiet(rings, fail);
95 CFDictionaryRemoveValue(rings, ringName);
96 fail:
97 return;
98 }
99
100
101 SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorRef *error) {
102 if(!a.trust)
103 {
104 return NULL;
105 }
106 SOSRingRef found = [a.trust copyRing:ringName err:error];
107
108 if (isSOSRing(found)) return found;
109 if (found) {
110 secerror("Non ring in ring table: %@, purging!", found);
111 SOSAccountRemoveRing(a, ringName);
112 }
113 CFReleaseNull(found); // I'm very skeptical of this function...
114 found = NULL;
115 return found;
116 }
117
118 bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
119 if(account && account.accountIsChanging) {
120 secnotice("circleOps", "SOSAccountUpdateRingFromRemote called before signing in to new account");
121 return true; // we want to drop circle notifications when account is changing
122 }
123
124 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
125
126 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:false err:error];
127 errOut:
128 return false;
129 }
130
131 bool SOSAccountUpdateRing(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) {
132 require_quiet(SOSAccountHasPublicKey(account, error), errOut);
133
134 return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
135
136 errOut:
137 return false;
138 }
139
140 bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error,
141 SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error),
142 SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) {
143 if(![account isInCircle:NULL]) {
144 return false;
145 }
146 bool result = false;
147 SOSRingRef found = NULL;
148 SOSRingRef newRing = NULL;
149 found = [account.trust copyRing:ringName err:error];
150 if(!found) {
151 found = create(ringName, error);
152 }
153 if(found) {
154 newRing = copyModified(found, error);
155 if(newRing) {
156 result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error];
157 }
158 }
159 CFReleaseNull(found);
160 CFReleaseNull(newRing);
161 return result;
162 }
163
164