]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c
4783d877fbf4d3eb575276644e0bccbcd9d48a21
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSTransport.c
1
2 #include <Security/SecureObjectSync/SOSInternal.h>
3 #include <Security/SecureObjectSync/SOSKVSKeys.h>
4 #include <Security/SecureObjectSync/SOSAccountPriv.h>
5 #include <Security/SecureObjectSync/SOSTransport.h>
6 #include <Security/SecureObjectSync/SOSTransportKeyParameterKVS.h>
7 #include <Security/SecureObjectSync/SOSTransportCircleKVS.h>
8 #include <Security/SecureObjectSync/SOSTransportMessageKVS.h>
9 #include <Security/SecureObjectSync/SOSTransportMessageIDS.h>
10 #include <Security/SecureObjectSync/SOSTransportMessage.h>
11 #include <Security/SecureObjectSync/SOSRing.h>
12
13 #include <SOSCloudKeychainClient.h>
14 #include <utilities/debugging.h>
15 #include <utilities/SecCFWrappers.h>
16 #include <CoreFoundation/CFBase.h>
17
18 CFStringRef kKeyParameter = CFSTR("KeyParameter");
19 CFStringRef kCircle = CFSTR("Circle");
20 CFStringRef kMessage = CFSTR("Message");
21 CFStringRef kAlwaysKeys = CFSTR("AlwaysKeys");
22 CFStringRef kFirstUnlocked = CFSTR("FirstUnlockKeys");
23 CFStringRef kUnlocked = CFSTR("UnlockedKeys");
24 extern CFStringRef kSOSAccountDebugScope;
25
26 #define DATE_LENGTH 18
27
28 CFStringRef SOSInterestListCopyDescription(CFArrayRef interests)
29 {
30 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
31 CFStringAppendFormat(description, NULL, CFSTR("<Interest: "));
32
33 if (interests) {
34 CFArrayForEach(interests, ^(const void* string) {
35 if (isString(string))
36
37 CFStringAppendFormat(description, NULL, CFSTR(" '%@'"), string);
38 });
39 }
40 CFStringAppend(description, CFSTR(">"));
41
42 return description;
43 }
44
45
46 //
47 // MARK: Key Interest Processing
48 //
49
50 CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportMessages, sTransportMessages, ^{
51 *sTransportMessages = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
52 });
53
54 CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportKeyParameters, sTransportKeyParameters, ^{
55 *sTransportKeyParameters = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
56 });
57
58 CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportCircles, sTransportCircles, ^{
59 *sTransportCircles = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
60 });
61
62
63 void SOSRegisterTransportMessage(SOSTransportMessageRef additional) {
64 CFArrayAppendValue(SOSGetTransportMessages(), additional);
65 }
66
67 void SOSUnregisterTransportMessage(SOSTransportMessageRef removal) {
68 CFArrayRemoveAllValue(SOSGetTransportMessages(), removal);
69 }
70
71 void SOSUnregisterAllTransportMessages() {
72 CFArrayRemoveAllValues(SOSGetTransportMessages());
73 }
74
75 void SOSRegisterTransportCircle(SOSTransportCircleRef additional) {
76 CFArrayAppendValue(SOSGetTransportCircles(), additional);
77 }
78
79 void SOSUnregisterTransportCircle(SOSTransportCircleRef removal) {
80 CFArrayRemoveAllValue(SOSGetTransportCircles(), removal);
81 }
82
83 void SOSUnregisterAllTransportCircles() {
84 CFArrayRemoveAllValues(SOSGetTransportCircles());
85 }
86
87 void SOSRegisterTransportKeyParameter(SOSTransportKeyParameterRef additional) {
88 CFArrayAppendValue(SOSGetTransportKeyParameters(), additional);
89 }
90
91 void SOSUnregisterTransportKeyParameter(SOSTransportKeyParameterRef removal) {
92 CFArrayRemoveAllValue(SOSGetTransportKeyParameters(), removal);
93 }
94
95 void SOSUnregisterAllTransportKeyParameters() {
96 CFArrayRemoveAllValues(SOSGetTransportKeyParameters());
97 }
98
99 //
100 // Should we be dispatching back to our queue to handle later
101 //
102 void SOSUpdateKeyInterest(SOSAccountRef account)
103 {
104 CFMutableArrayRef alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
105 CFMutableArrayRef afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
106 CFMutableArrayRef whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
107 CFMutableDictionaryRef keyDict = CFDictionaryCreateMutableForCFTypes (kCFAllocatorDefault);
108
109 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) {
110 SOSTransportKeyParameterRef tKP = (SOSTransportKeyParameterRef) value;
111 if (SOSTransportKeyParameterGetAccount(tKP) == account && SOSTransportKeyParameterGetTransportType(tKP, NULL) == kKVS) {
112 SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef) value;
113 CFErrorRef localError = NULL;
114
115 if (!SOSTransportKeyParameterKVSAppendKeyInterests(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)) {
116 secerror("Error getting key parameters interests %@", localError);
117 }
118 CFReleaseNull(localError);
119 }
120 });
121 CFMutableDictionaryRef keyParamsDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
122 CFDictionarySetValue(keyParamsDict, kAlwaysKeys, alwaysKeys);
123 CFDictionarySetValue(keyParamsDict, kFirstUnlocked, afterFirstUnlockKeys);
124 CFDictionarySetValue(keyParamsDict, kUnlocked, whenUnlockedKeys);
125 CFDictionarySetValue(keyDict, kKeyParameter, keyParamsDict);
126
127 CFReleaseNull(alwaysKeys);
128 CFReleaseNull(afterFirstUnlockKeys);
129 CFReleaseNull(whenUnlockedKeys);
130 alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
131 afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
132 whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
133
134 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
135 if (SOSTransportCircleGetAccount((SOSTransportCircleRef)value) == account && SOSTransportCircleGetTransportType((SOSTransportCircleRef)value, NULL) == kKVS) {
136 SOSTransportCircleKVSRef tkvs = (SOSTransportCircleKVSRef) value;
137 CFErrorRef localError = NULL;
138
139 if(!SOSTransportCircleKVSAppendKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){
140 secerror("Error getting circle interests %@", localError);
141 }
142 if(!SOSTransportCircleKVSAppendPeerInfoKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){
143 secerror("Error getting peer info interests %@", localError);
144 }
145 if(!SOSTransportCircleKVSAppendRingKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){
146 secerror("Error getting ring interests %@", localError);
147 }
148 if(!SOSTransportCircleKVSAppendDebugKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){
149 secerror("Error getting debug key interests %@", localError);
150 }
151 CFReleaseNull(localError);
152 }
153
154 });
155 CFMutableDictionaryRef circleDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
156 CFDictionarySetValue(circleDict, kAlwaysKeys, alwaysKeys);
157 CFDictionarySetValue(circleDict, kFirstUnlocked, afterFirstUnlockKeys);
158 CFDictionarySetValue(circleDict, kUnlocked, whenUnlockedKeys);
159 CFDictionarySetValue(keyDict, kCircle, circleDict);
160
161 CFReleaseNull(alwaysKeys);
162 CFReleaseNull(afterFirstUnlockKeys);
163 CFReleaseNull(whenUnlockedKeys);
164 alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
165 afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
166 whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
167
168 CFArrayForEach(SOSGetTransportMessages(), ^(const void *value) {
169 if (SOSTransportMessageGetAccount((SOSTransportMessageRef) value) == account && SOSTransportMessageGetTransportType((SOSTransportMessageRef) value, NULL) == kKVS) {
170 SOSTransportMessageKVSRef tkvs = (SOSTransportMessageKVSRef) value;
171 CFErrorRef localError = NULL;
172
173 if(!SOSTransportMessageKVSAppendKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){
174 secerror("Error getting message interests %@", localError);
175 }
176 CFReleaseNull(localError);
177 }
178 });
179
180 CFMutableDictionaryRef messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
181 CFDictionarySetValue(messageDict, kAlwaysKeys, alwaysKeys);
182 CFDictionarySetValue(messageDict, kFirstUnlocked, afterFirstUnlockKeys);
183 CFDictionarySetValue(messageDict, kUnlocked, whenUnlockedKeys);
184 CFDictionarySetValue(keyDict, kMessage, messageDict);
185
186 //
187 // Log what we are about to do.
188 //
189 secnotice("key-interests", "Updating interests: %@", keyDict);
190
191 CFStringRef uuid = SOSAccountCopyUUID(account);
192 SOSCloudKeychainUpdateKeys(keyDict, uuid, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) {
193 if (error) {
194 secerror("Error updating keys: %@", error);
195 }
196 });
197 CFReleaseNull(uuid);
198
199 CFReleaseNull(alwaysKeys);
200 CFReleaseNull(afterFirstUnlockKeys);
201 CFReleaseNull(whenUnlockedKeys);
202 CFReleaseNull(keyParamsDict);
203 CFReleaseNull(circleDict);
204 CFReleaseNull(messageDict);
205 CFReleaseNull(keyDict);
206 }
207
208
209 static void showWhatWasHandled(CFDictionaryRef updates, CFMutableArrayRef handledKeys) {
210
211 CFMutableStringRef updateStr = CFStringCreateMutable(kCFAllocatorDefault, 0);
212 CFMutableStringRef handledKeysStr = CFStringCreateMutable(kCFAllocatorDefault, 0);
213
214 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
215 if (isString(key)) {
216 CFStringAppendFormat(updateStr, NULL, CFSTR("%@ "), (CFStringRef)key);
217 }
218 });
219 CFArrayForEach(handledKeys, ^(const void *value) {
220 if (isString(value)) {
221 CFStringAppendFormat(handledKeysStr, NULL, CFSTR("%@ "), (CFStringRef)value);
222 }
223 });
224 secinfo("updates", "Updates [%ld]: %@", CFDictionaryGetCount(updates), updateStr);
225 secinfo("updates", "Handled [%ld]: %@", CFArrayGetCount(handledKeys), handledKeysStr);
226
227 CFReleaseSafe(updateStr);
228 CFReleaseSafe(handledKeysStr);
229 }
230
231 #define KVS_STATE_INTERVAL 50
232
233 CF_RETURNS_RETAINED
234 CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountTransactionRef txn, CFDictionaryRef updates, CFErrorRef *error){
235 SOSAccountRef account = txn->account;
236
237 CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
238 CFStringRef dsid = NULL;
239
240 if(CFDictionaryGetValueIfPresent(updates, kSOSKVSAccountChangedKey, (const void**)&dsid)){
241 secnotice("accountChange", "SOSTransportDispatchMessages received kSOSKVSAccountChangedKey");
242
243 // While changing accounts we may modify the key params array. To avoid stepping on ourselves we
244 // copy the list for iteration. Now modifying the transport outside of the list iteration.
245 CFMutableArrayRef transportsToUse = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
246
247 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) {
248 SOSTransportKeyParameterRef transport = (SOSTransportKeyParameterRef) value;
249 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(transport), account)){
250 CFArrayAppendValue(transportsToUse, transport);
251 }
252
253 });
254
255 CFArrayForEach(transportsToUse, ^(const void *value) {
256 SOSTransportKeyParameterRef tempTransport = (SOSTransportKeyParameterRef) value;
257
258 CFStringRef accountDSID = (CFStringRef)SOSAccountGetValue(account, kSOSDSIDKey, error);
259
260 if(accountDSID == NULL){
261 SOSTransportKeyParameterHandleNewAccount(tempTransport, account);
262 SOSAccountSetValue(account, kSOSDSIDKey, dsid, error);
263 secdebug("dsid", "Assigning new DSID: %@", dsid);
264 } else if(accountDSID != NULL && CFStringCompare(accountDSID, dsid, 0) != 0 ) {
265 SOSTransportKeyParameterHandleNewAccount(tempTransport, account);
266 SOSAccountSetValue(account, kSOSDSIDKey, dsid, error);
267 secdebug("dsid", "Assigning new DSID: %@", dsid);
268 } else {
269 secdebug("dsid", "DSIDs are the same!");
270 }
271 });
272
273 CFReleaseNull(transportsToUse);
274
275 CFArrayAppendValue(handledKeys, kSOSKVSAccountChangedKey);
276 }
277
278
279 // Iterate through keys in updates. Perform circle change update.
280 // Then instantiate circles and engines and peers for all peers that
281 // are receiving a message in updates.
282 CFMutableDictionaryRef circle_peer_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
283 CFMutableDictionaryRef circle_circle_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
284 CFMutableDictionaryRef circle_retirement_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
285 CFMutableDictionaryRef ring_update_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
286 CFMutableDictionaryRef peer_info_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
287 CFMutableDictionaryRef debug_info_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
288
289 __block CFDataRef newParameters = NULL;
290 __block bool initial_sync = false;
291 __block bool new_account = false;
292
293 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
294 CFErrorRef localError = NULL;
295 CFStringRef circle_name = NULL;
296 CFStringRef ring_name = NULL;
297 CFStringRef peer_info_name = NULL;
298 CFStringRef from_name = NULL;
299 CFStringRef to_name = NULL;
300 CFStringRef backup_name = NULL;
301
302 require_quiet(isString(key), errOut);
303 switch (SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &peer_info_name, &ring_name, &backup_name, &from_name, &to_name)) {
304 case kCircleKey:
305 CFDictionarySetValue(circle_circle_messages_table, circle_name, value);
306 break;
307 case kInitialSyncKey:
308 initial_sync = true;
309 break;
310 case kParametersKey:
311 if (isData(value)) {
312 newParameters = (CFDataRef) CFRetainSafe(value);
313 }
314 break;
315 case kMessageKey: {
316 CFMutableDictionaryRef circle_messages = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_peer_messages_table, circle_name);
317 CFDictionarySetValue(circle_messages, from_name, value);
318 break;
319 }
320 case kRetirementKey: {
321 CFMutableDictionaryRef circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_retirement_messages_table, circle_name);
322 CFDictionarySetValue(circle_retirements, from_name, value);
323 break;
324 }
325 case kAccountChangedKey:
326 new_account = true;
327 break;
328 case kPeerInfoKey:
329 CFDictionarySetValue(peer_info_message_table, peer_info_name, value);
330 break;
331 case kRingKey:
332 if(isString(ring_name))
333 CFDictionarySetValue(ring_update_message_table, ring_name, value);
334 break;
335 case kDebugInfoKey:
336 CFDictionarySetValue(debug_info_message_table, peer_info_name, value);
337 break;
338 case kLastCircleKey:
339 case kLastKeyParameterKey:
340 case kUnknownKey:
341 secnotice("updates", "Unknown key '%@', ignoring", key);
342 break;
343
344 }
345
346 errOut:
347 CFReleaseNull(circle_name);
348 CFReleaseNull(from_name);
349 CFReleaseNull(to_name);
350 CFReleaseNull(ring_name);
351 CFReleaseNull(peer_info_name);
352 CFReleaseNull(backup_name);
353
354 if (error && *error)
355 secerror("Peer message processing error for: %@ -> %@ (%@)", key, value, *error);
356 if (localError)
357 secerror("Peer message local processing error for: %@ -> %@ (%@)", key, value, localError);
358
359 CFReleaseNull(localError);
360 });
361
362
363 if (newParameters) {
364 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) {
365 SOSTransportKeyParameterRef tkvs = (SOSTransportKeyParameterRef) value;
366 CFErrorRef localError = NULL;
367 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(tkvs), account)){
368 if(!SOSTransportKeyParameterHandleKeyParameterChanges(tkvs, newParameters, localError))
369 secerror("Transport failed to handle new key parameters: %@", localError);
370 }
371 });
372 CFArrayAppendValue(handledKeys, kSOSKVSKeyParametersKey);
373 }
374 CFReleaseNull(newParameters);
375
376 if(initial_sync){
377 CFArrayAppendValue(handledKeys, kSOSKVSInitialSyncKey);
378 }
379
380 if(CFDictionaryGetCount(debug_info_message_table)) {
381 /* check for a newly set circle debug scope */
382 CFTypeRef debugScope = CFDictionaryGetValue(debug_info_message_table, kSOSAccountDebugScope);
383 if (debugScope) {
384 if(isString(debugScope)){
385 ApplyScopeListForID(debugScope, kScopeIDCircle);
386 }else if(isDictionary(debugScope)){
387 ApplyScopeDictionaryForID(debugScope, kScopeIDCircle);
388 }
389 }
390 CFStringRef debugInfoKey = SOSDebugInfoKeyCreateWithTypeName(kSOSAccountDebugScope);
391 CFArrayAppendValue(handledKeys, debugInfoKey);
392 CFReleaseNull(debugInfoKey);
393 }
394
395 if(CFDictionaryGetCount(circle_retirement_messages_table)) {
396 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
397 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
398 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
399 CFErrorRef localError = NULL;
400 CFDictionaryRef handledRetirementKeys = SOSTransportCircleHandleRetirementMessages(tkvs, circle_retirement_messages_table, error);
401 if(handledRetirementKeys == NULL){
402 secerror("Transport failed to handle retirement messages: %@", localError);
403 } else {
404 CFDictionaryForEach(handledRetirementKeys, ^(const void *key, const void *value) {
405 CFStringRef circle_name = (CFStringRef)key;
406 CFArrayRef handledPeerIDs = (CFArrayRef)value;
407 CFArrayForEach(handledPeerIDs, ^(const void *value) {
408 CFStringRef peer_id = (CFStringRef)value;
409 CFStringRef keyHandled = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, peer_id);
410 CFArrayAppendValue(handledKeys, keyHandled);
411 CFReleaseNull(keyHandled);
412 });
413 });
414 }
415 CFReleaseNull(handledRetirementKeys);
416 CFReleaseNull(localError);
417 }
418 });
419 }
420 if(CFDictionaryGetCount(peer_info_message_table)){
421 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
422 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
423 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
424 CFErrorRef localError = NULL;
425 CFArrayRef handledPeerInfoMessages = SOSTransportCircleKVSHandlePeerInfoV2Messages(tkvs, peer_info_message_table, error);
426 if(handledPeerInfoMessages == NULL){
427 secerror("Transport failed to handle peer info messages: %@", localError);
428 } else {
429 CFArrayForEach(handledPeerInfoMessages, ^(const void *value) {
430 CFStringRef peer_id = (CFStringRef)value;
431 CFStringRef keyHandled = SOSPeerInfoV2KeyCreateWithPeerName(peer_id);
432 CFArrayAppendValue(handledKeys, keyHandled);
433 CFReleaseNull(keyHandled);
434 });
435 }
436 CFReleaseNull(handledPeerInfoMessages);
437 CFReleaseNull(localError);
438 }
439 });
440 }
441 if(CFDictionaryGetCount(circle_peer_messages_table)) {
442 CFArrayForEach(SOSGetTransportMessages(), ^(const void *value) {
443 SOSTransportMessageRef tmsg = (SOSTransportMessageRef) value;
444 CFDictionaryRef circleToPeersHandled = NULL;
445 CFErrorRef handleMessagesError = NULL;
446 CFErrorRef flushError = NULL;
447
448 require_quiet(CFEqualSafe(SOSTransportMessageGetAccount(tmsg), account), done);
449
450 circleToPeersHandled = SOSTransportMessageHandleMessages(tmsg, circle_peer_messages_table, &handleMessagesError);
451 require_action_quiet(circleToPeersHandled, done, secnotice("msg", "No messages handled: %@", handleMessagesError));
452
453 CFArrayRef handledPeers = asArray(CFDictionaryGetValue(circleToPeersHandled, SOSTransportMessageGetCircleName(tmsg)), NULL);
454
455 if (handledPeers) {
456 CFArrayForEach(handledPeers, ^(const void *value) {
457 CFStringRef peerID = asString(value, NULL);
458 if (peerID) {
459
460 CFStringRef kvsHandledKey = SOSMessageKeyCreateFromPeerToTransport(tmsg, peerID);
461 if (kvsHandledKey) {
462 CFArrayAppendValue(handledKeys, kvsHandledKey);
463 }
464 CFReleaseNull(kvsHandledKey);
465 }
466 });
467 }
468
469 require_action_quiet(SOSTransportMessageFlushChanges(tmsg, &flushError), done, secnotice("msg", "Flush failed: %@", flushError););
470
471 done:
472 CFReleaseNull(flushError);
473 CFReleaseNull(circleToPeersHandled);
474 CFReleaseNull(handleMessagesError);
475 });
476 }
477 if(CFDictionaryGetCount(circle_circle_messages_table)) {
478 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
479 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
480 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
481 CFArrayRef handleCircleMessages = SOSTransportCircleHandleCircleMessages(tkvs, circle_circle_messages_table, error);
482 CFErrorRef localError = NULL;
483 if(handleCircleMessages == NULL){
484 secerror("Transport failed to handle circle messages: %@", localError);
485 } else if(CFArrayGetCount(handleCircleMessages) == 0) {
486 if(CFDictionaryGetCount(circle_circle_messages_table) != 0) {
487 secerror("Transport failed to process all circle messages: (%ld/%ld) %@",
488 CFArrayGetCount(handleCircleMessages),
489 CFDictionaryGetCount(circle_circle_messages_table), localError);
490 } else {
491 secnotice("circle", "Transport handled no circle messages");
492 }
493 } else {
494 CFArrayForEach(handleCircleMessages, ^(const void *value) {
495 CFStringRef keyHandled = SOSCircleKeyCreateWithName((CFStringRef)value, error);
496 CFArrayAppendValue(handledKeys, keyHandled);
497 CFReleaseNull(keyHandled);
498 });
499 }
500
501 CFReleaseNull(localError);
502 CFReleaseNull(handleCircleMessages);
503 }
504
505 });
506 }
507 if(CFDictionaryGetCount(ring_update_message_table)){
508 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
509 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
510 CFErrorRef localError = NULL;
511 CFMutableArrayRef handledRingMessages = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
512
513 CFDictionaryForEach(ring_update_message_table, ^(const void *key, const void *value) {
514 CFDataRef ringData = asData(value, NULL);
515 SOSRingRef ring = SOSRingCreateFromData(error, ringData);
516
517 if(SOSAccountUpdateRingFromRemote(account, ring, error)){
518 CFArrayAppendValue(handledRingMessages, key);
519 }
520 CFReleaseNull(ring);
521 });
522 if(CFArrayGetCount(handledRingMessages) == 0){
523 secerror("Transport failed to handle ring messages: %@", localError);
524 } else {
525 CFArrayForEach(handledRingMessages, ^(const void *value) {
526 CFStringRef ring_name = (CFStringRef)value;
527 CFStringRef keyHandled = SOSRingKeyCreateWithRingName(ring_name);
528 CFArrayAppendValue(handledKeys, keyHandled);
529 CFReleaseNull(keyHandled);
530 });
531 }
532 CFReleaseNull(handledRingMessages);
533 CFReleaseNull(localError);
534 }
535 });
536 }
537
538 CFReleaseNull(circle_retirement_messages_table);
539 CFReleaseNull(circle_circle_messages_table);
540 CFReleaseNull(circle_peer_messages_table);
541 CFReleaseNull(debug_info_message_table);
542 CFReleaseNull(ring_update_message_table);
543 CFReleaseNull(peer_info_message_table);
544 CFReleaseNull(debug_info_message_table);
545
546 showWhatWasHandled(updates, handledKeys);
547
548 return handledKeys;
549 }
550