]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountTransaction.c
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountTransaction.c
1 //
2 // SOSAccountTransaction.c
3 // sec
4 //
5 //
6
7 #include "SOSAccountTransaction.h"
8
9 #include <utilities/SecCFWrappers.h>
10 #include <CoreFoundation/CoreFoundation.h>
11
12 #include <Security/SecureObjectSync/SOSAccount.h>
13 #include <Security/SecureObjectSync/SOSAccountPriv.h>
14 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
15 #include <Security/SecureObjectSync/SOSTransport.h>
16 #include <Security/SecureObjectSync/SOSTransportCircle.h>
17
18 #define kPublicKeyNotAvailable "com.apple.security.publickeynotavailable"
19
20 CFGiblisFor(SOSAccountTransaction);
21
22 static void SOSAccountTransactionDestroy(CFTypeRef aObj) {
23 SOSAccountTransactionRef at = (SOSAccountTransactionRef) aObj;
24
25 CFReleaseNull(at->initialUnsyncedViews);
26 CFReleaseNull(at->initialID);
27 CFReleaseNull(at->account);
28 CFReleaseNull(at->initialViews);
29 CFReleaseNull(at->initialKeyParameters);
30 }
31
32 static CFStringRef SOSAccountTransactionCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOptions) {
33 SOSAccountTransactionRef at = (SOSAccountTransactionRef) aObj;
34
35 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
36
37 CFStringAppendFormat(description, NULL, CFSTR("<SOSAccountTransactionRef@%p %ld>"),
38 at, at->initialViews ? CFSetGetCount(at->initialViews) : 0);
39
40 return description;
41 }
42
43 static void SOSAccountTransactionRestart(SOSAccountTransactionRef txn) {
44 txn->initialInCircle = SOSAccountIsInCircle(txn->account, NULL);
45
46 if(txn->account)
47 txn->initialTrusted = (txn->account)->user_public_trusted;
48
49 if (txn->initialInCircle) {
50 SOSAccountEnsureSyncChecking(txn->account);
51 }
52
53 CFAssignRetained(txn->initialUnsyncedViews, SOSAccountCopyOutstandingViews(txn->account));
54
55 CFReleaseNull(txn->initialKeyParameters);
56
57 if(txn->account && txn->account->user_key_parameters){
58 CFReleaseNull(txn->initialKeyParameters);
59 txn->initialKeyParameters = CFDataCreateCopy(kCFAllocatorDefault, txn->account->user_key_parameters);
60 }
61 SOSPeerInfoRef mpi = SOSAccountGetMyPeerInfo(txn->account);
62 CFAssignRetained(txn->initialViews, mpi ? SOSPeerInfoCopyEnabledViews(mpi) : NULL);
63
64 CFRetainAssign(txn->initialID, SOSPeerInfoGetPeerID(mpi));
65
66 CFStringSetPerformWithDescription(txn->initialViews, ^(CFStringRef description) {
67 secnotice("acct-txn", "Starting as:%s v:%@", txn->initialInCircle ? "member" : "non-member", description);
68 });
69 }
70
71
72 SOSAccountTransactionRef SOSAccountTransactionCreate(SOSAccountRef account) {
73 SOSAccountTransactionRef at = CFTypeAllocate(SOSAccountTransaction, struct __OpaqueSOSAccountTransaction, kCFAllocatorDefault);
74
75 at->account = CFRetainSafe(account);
76
77 at->initialInCircle = false;
78 at->initialViews = NULL;
79 at->initialKeyParameters = NULL;
80 at->initialTrusted = false;
81 at->initialUnsyncedViews = NULL;
82 at->initialID = NULL;
83
84 SOSAccountTransactionRestart(at);
85
86 return at;
87 }
88
89 #define ACCOUNT_STATE_INTERVAL 20
90
91 void SOSAccountTransactionFinish(SOSAccountTransactionRef txn) {
92 CFErrorRef localError = NULL;
93 bool notifyEngines = false;
94 static int do_account_state_at_zero = 0;
95
96 SOSPeerInfoRef mpi = SOSAccountGetMyPeerInfo(txn->account);
97
98 bool inCircle = SOSAccountIsInCircle(txn->account, NULL);
99
100 if (inCircle) {
101 SOSAccountEnsureSyncChecking(txn->account);
102 } else {
103 SOSAccountCancelSyncChecking(txn->account);
104 }
105
106 // If our identity changed our inital set should be everything.
107 if (!CFEqualSafe(txn->initialID, SOSPeerInfoGetPeerID(mpi))) {
108 CFAssignRetained(txn->initialUnsyncedViews, SOSViewCopyViewSet(kViewSetAll));
109 }
110
111 CFSetRef finalUnsyncedViews = SOSAccountCopyOutstandingViews(txn->account);
112 if (!CFEqualSafe(txn->initialUnsyncedViews, finalUnsyncedViews)) {
113 if (SOSAccountHandleOutOfSyncUpdate(txn->account, txn->initialUnsyncedViews, finalUnsyncedViews)) {
114 notifyEngines = true;
115 }
116
117 CFStringSetPerformWithDescription(txn->initialUnsyncedViews, ^(CFStringRef newUnsyncedDescripion) {
118 CFStringSetPerformWithDescription(finalUnsyncedViews, ^(CFStringRef unsyncedDescription) {
119 secnotice("initial-sync", "Unsynced was: %@", unsyncedDescription);
120 secnotice("initial-sync", "Unsynced is: %@", newUnsyncedDescripion);
121 });
122 });
123 }
124 CFReleaseNull(finalUnsyncedViews);
125
126 if (txn->account->engine_peer_state_needs_repair) {
127 // We currently only get here from a failed syncwithallpeers, so
128 // that will retry. If this logic changes, force a syncwithallpeers
129 if (!SOSAccountEnsurePeerRegistration(txn->account, &localError)) {
130 secerror("Ensure peer registration while repairing failed: %@", localError);
131 }
132 CFReleaseNull(localError);
133
134 notifyEngines = true;
135 }
136
137 if(txn->account->circle_rings_retirements_need_attention){
138 SOSAccountRecordRetiredPeersInCircle(txn->account);
139
140 SOSAccountEnsureInBackupRings(txn->account);
141
142 CFErrorRef localError = NULL;
143 if(!SOSTransportCircleFlushChanges(txn->account->circle_transport, &localError)) {
144 secerror("flush circle failed %@", localError);
145 }
146 CFReleaseSafe(localError);
147
148 notifyEngines = true;
149 }
150
151 if (notifyEngines) {
152 SOSAccountNotifyEngines(txn->account);
153 }
154
155 if(txn->account->key_interests_need_updating){
156 SOSUpdateKeyInterest(txn->account);
157 }
158
159 txn->account->key_interests_need_updating = false;
160 txn->account->circle_rings_retirements_need_attention = false;
161 txn->account->engine_peer_state_needs_repair = false;
162
163 SOSAccountFlattenToSaveBlock(txn->account);
164
165 // Check for firing view membership change. On change of view membership or circle membership
166 bool isInCircle = SOSAccountIsInCircle(txn->account, NULL);
167
168 mpi = SOSAccountGetMyPeerInfo(txn->account);
169 CFSetRef views = mpi ? SOSPeerInfoCopyEnabledViews(mpi) : NULL;
170
171 CFStringSetPerformWithDescription(views, ^(CFStringRef description) {
172 secnotice("acct-txn", "Finished as:%s v:%@", isInCircle ? "member" : "non-member", description);
173 });
174 if(!CFEqualSafe(txn->initialViews, views) || txn->initialInCircle != isInCircle) {
175 notify_post(kSOSCCViewMembershipChangedNotification);
176 do_account_state_at_zero = 0;
177 }
178
179 if((txn->initialTrusted != (txn->account)->user_public_trusted) || (!CFEqualSafe(txn->initialKeyParameters, txn->account->user_key_parameters))){
180 notify_post(kPublicKeyNotAvailable);
181 do_account_state_at_zero = 0;
182 }
183
184 if(do_account_state_at_zero <= 0) {
185 SOSAccountLogState(txn->account);
186 SOSAccountLogViewState(txn->account);
187 do_account_state_at_zero = ACCOUNT_STATE_INTERVAL;
188 }
189 do_account_state_at_zero--;
190
191 CFReleaseNull(views);
192
193 }
194
195 void SOSAccountTransactionFinishAndRestart(SOSAccountTransactionRef txn) {
196 SOSAccountTransactionFinish(txn);
197 SOSAccountTransactionRestart(txn);
198 }
199