]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c
Security-57337.50.23.tar.gz
[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 SOSCloudKeychainUpdateKeys(keyDict, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) {
192 if (error) {
193 secerror("Error updating keys: %@", error);
194 }
195 });
196
197 CFReleaseNull(alwaysKeys);
198 CFReleaseNull(afterFirstUnlockKeys);
199 CFReleaseNull(whenUnlockedKeys);
200 CFReleaseNull(keyParamsDict);
201 CFReleaseNull(circleDict);
202 CFReleaseNull(messageDict);
203 CFReleaseNull(keyDict);
204 }
205
206
207 static void showWhatWasHandled(CFDictionaryRef updates, CFMutableArrayRef handledKeys) {
208
209 CFMutableStringRef updateStr = CFStringCreateMutable(kCFAllocatorDefault, 0);
210 CFMutableStringRef handledKeysStr = CFStringCreateMutable(kCFAllocatorDefault, 0);
211
212 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
213 if (isString(key)) {
214 CFStringAppendFormat(updateStr, NULL, CFSTR("%@ "), (CFStringRef)key);
215 }
216 });
217 CFArrayForEach(handledKeys, ^(const void *value) {
218 if (isString(value)) {
219 CFStringAppendFormat(handledKeysStr, NULL, CFSTR("%@ "), (CFStringRef)value);
220 }
221 });
222 secinfo("updates", "Updates [%ld]: %@", CFDictionaryGetCount(updates), updateStr);
223 secinfo("updates", "Handled [%ld]: %@", CFArrayGetCount(handledKeys), handledKeysStr);
224
225 CFReleaseSafe(updateStr);
226 CFReleaseSafe(handledKeysStr);
227 }
228
229 CF_RETURNS_RETAINED
230 CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictionaryRef updates, CFErrorRef *error){
231
232 CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
233
234 if(CFDictionaryContainsKey(updates, kSOSKVSAccountChangedKey)){
235 secnotice("accountChange", "SOSTransportDispatchMessages received kSOSKVSAccountChangedKey");
236 // While changing accounts we may modify the key params array. To avoid stepping on ourselves we
237 // copy the list for iteration. Now modifying the transport outside of the list iteration.
238 __block SOSTransportKeyParameterRef tempTransport = NULL;
239 CFMutableArrayRef originalKeyParams = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(SOSGetTransportKeyParameters()), SOSGetTransportKeyParameters());
240 do{
241 tempTransport = NULL;
242 CFArrayForEach(originalKeyParams, ^(const void *value) {
243 SOSTransportKeyParameterRef transport = (SOSTransportKeyParameterRef) value;
244 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(transport), account)){
245 tempTransport = transport;
246 }
247 });
248 if(tempTransport != NULL){
249 SOSTransportKeyParameterHandleNewAccount(tempTransport, account);
250 CFStringRef dsid = NULL;
251 if(CFDictionaryGetValueIfPresent(updates, kSOSKVSAccountChangedKey, (const void**)&dsid)){
252 if(dsid != NULL){
253 CFStringRef accountDSID = (CFStringRef)SOSAccountGetValue(account, kSOSDSIDKey, error);
254
255 if(accountDSID == NULL){
256 SOSAccountSetValue(account, kSOSDSIDKey, dsid, error);
257 secdebug("dsid", "Assigning new DSID: %@", dsid);
258 }
259 else if(accountDSID != NULL && CFStringCompare(accountDSID, dsid, 0) != 0 ){
260 SOSAccountSetValue(account, kSOSDSIDKey, dsid, error);
261 secdebug("dsid", "Assigning new DSID: %@", dsid);
262 }
263 else
264 secdebug("dsid", "DSIDs are the same!");
265 }
266 }
267 CFArrayRemoveAllValue(originalKeyParams, tempTransport);
268 }
269 }while(tempTransport != NULL);
270 CFArrayAppendValue(handledKeys, kSOSKVSAccountChangedKey);
271 CFReleaseNull(originalKeyParams);
272
273 }
274
275
276 // Iterate through keys in updates. Perform circle change update.
277 // Then instantiate circles and engines and peers for all peers that
278 // are receiving a message in updates.
279 CFMutableDictionaryRef circle_peer_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
280 CFMutableDictionaryRef circle_circle_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
281 CFMutableDictionaryRef circle_retirement_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
282 CFMutableDictionaryRef ring_update_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
283 CFMutableDictionaryRef peer_info_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
284 CFMutableDictionaryRef debug_info_message_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
285
286 __block CFDataRef newParameters = NULL;
287 __block bool initial_sync = false;
288 __block bool new_account = false;
289
290 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
291 CFErrorRef localError = NULL;
292 CFStringRef circle_name = NULL;
293 CFStringRef ring_name = NULL;
294 CFStringRef peer_info_name = NULL;
295 CFStringRef from_name = NULL;
296 CFStringRef to_name = NULL;
297 CFStringRef backup_name = NULL;
298
299 switch (SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &peer_info_name, &ring_name, &backup_name, &from_name, &to_name)) {
300 case kCircleKey:
301 CFDictionarySetValue(circle_circle_messages_table, circle_name, value);
302 break;
303 case kInitialSyncKey:
304 initial_sync = true;
305 break;
306 case kParametersKey:
307 if (isData(value)) {
308 newParameters = (CFDataRef) CFRetainSafe(value);
309 }
310 break;
311 case kMessageKey: {
312 CFMutableDictionaryRef circle_messages = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_peer_messages_table, circle_name);
313 CFDictionarySetValue(circle_messages, from_name, value);
314 break;
315 }
316 case kRetirementKey: {
317 CFMutableDictionaryRef circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_retirement_messages_table, circle_name);
318 CFDictionarySetValue(circle_retirements, from_name, value);
319 break;
320 }
321 case kAccountChangedKey:
322 new_account = true;
323 break;
324 case kPeerInfoKey:
325 CFDictionarySetValue(peer_info_message_table, peer_info_name, value);
326 break;
327 case kRingKey:
328 if(isString(ring_name))
329 CFDictionarySetValue(ring_update_message_table, ring_name, value);
330 break;
331 case kDebugInfoKey:
332 CFDictionarySetValue(debug_info_message_table, peer_info_name, value);
333 break;
334 case kLastCircleKey:
335 case kLastKeyParameterKey:
336 case kUnknownKey:
337 secnotice("updates", "Unknown key '%@', ignoring", key);
338 break;
339
340 }
341
342 CFReleaseNull(circle_name);
343 CFReleaseNull(from_name);
344 CFReleaseNull(to_name);
345 CFReleaseNull(ring_name);
346 CFReleaseNull(peer_info_name);
347 CFReleaseNull(backup_name);
348
349 if (error && *error)
350 secerror("Peer message processing error for: %@ -> %@ (%@)", key, value, *error);
351 if (localError)
352 secerror("Peer message local processing error for: %@ -> %@ (%@)", key, value, localError);
353
354 CFReleaseNull(localError);
355 });
356
357
358 if (newParameters) {
359 CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) {
360 SOSTransportKeyParameterRef tkvs = (SOSTransportKeyParameterRef) value;
361 CFErrorRef localError = NULL;
362 if(CFEqualSafe(SOSTransportKeyParameterGetAccount(tkvs), account)){
363 if(!SOSTransportKeyParameterHandleKeyParameterChanges(tkvs, newParameters, localError))
364 secerror("Transport failed to handle new key parameters: %@", localError);
365 }
366 });
367 CFArrayAppendValue(handledKeys, kSOSKVSKeyParametersKey);
368 }
369 CFReleaseNull(newParameters);
370
371 if(initial_sync){
372 CFArrayAppendValue(handledKeys, kSOSKVSInitialSyncKey);
373 }
374
375 if(CFDictionaryGetCount(debug_info_message_table)) {
376 /* check for a newly set circle debug scope */
377 CFTypeRef debugScope = CFDictionaryGetValue(debug_info_message_table, kSOSAccountDebugScope);
378 if (debugScope) {
379 if(isString(debugScope)){
380 ApplyScopeListForID(debugScope, kScopeIDCircle);
381 }else if(isDictionary(debugScope)){
382 ApplyScopeDictionaryForID(debugScope, kScopeIDCircle);
383 }
384 }
385 CFStringRef debugInfoKey = SOSDebugInfoKeyCreateWithTypeName(kSOSAccountDebugScope);
386 CFArrayAppendValue(handledKeys, debugInfoKey);
387 CFReleaseNull(debugInfoKey);
388 }
389
390 if(CFDictionaryGetCount(circle_retirement_messages_table)) {
391 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
392 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
393 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
394 CFErrorRef localError = NULL;
395 CFDictionaryRef handledRetirementKeys = SOSTransportCircleHandleRetirementMessages(tkvs, circle_retirement_messages_table, error);
396 if(handledRetirementKeys == NULL){
397 secerror("Transport failed to handle retirement messages: %@", localError);
398 } else {
399 CFDictionaryForEach(handledRetirementKeys, ^(const void *key, const void *value) {
400 CFStringRef circle_name = (CFStringRef)key;
401 CFArrayRef handledPeerIDs = (CFArrayRef)value;
402 CFArrayForEach(handledPeerIDs, ^(const void *value) {
403 CFStringRef peer_id = (CFStringRef)value;
404 CFStringRef keyHandled = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, peer_id);
405 CFArrayAppendValue(handledKeys, keyHandled);
406 CFReleaseNull(keyHandled);
407 });
408 });
409 }
410 CFReleaseNull(handledRetirementKeys);
411 CFReleaseNull(localError);
412 }
413 });
414 }
415 if(CFDictionaryGetCount(peer_info_message_table)){
416 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
417 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
418 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
419 CFErrorRef localError = NULL;
420 CFArrayRef handledPeerInfoMessages = SOSTransportCircleKVSHandlePeerInfoV2Messages(tkvs, peer_info_message_table, error);
421 if(handledPeerInfoMessages == NULL){
422 secerror("Transport failed to handle peer info messages: %@", localError);
423 } else {
424 CFArrayForEach(handledPeerInfoMessages, ^(const void *value) {
425 CFStringRef peer_id = (CFStringRef)value;
426 CFStringRef keyHandled = SOSPeerInfoV2KeyCreateWithPeerName(peer_id);
427 CFArrayAppendValue(handledKeys, keyHandled);
428 CFReleaseNull(keyHandled);
429 });
430 }
431 CFReleaseNull(handledPeerInfoMessages);
432 CFReleaseNull(localError);
433 }
434 });
435 }
436 if(CFDictionaryGetCount(circle_peer_messages_table)) {
437 CFArrayForEach(SOSGetTransportMessages(), ^(const void *value) {
438 SOSTransportMessageRef tkvs = (SOSTransportMessageRef) value;
439 if(SOSTransportMessageGetTransportType(tkvs, error) != kIDS){
440 if(CFEqualSafe(SOSTransportMessageGetAccount((SOSTransportMessageRef)value), account)){
441 CFErrorRef handleMessagesError = NULL;
442 CFDictionaryRef handledPeers = SOSTransportMessageHandleMessages(account->kvs_message_transport, circle_peer_messages_table, &handleMessagesError);
443
444 if (handledPeers) {
445 // We need to look for and send responses.
446 SOSAccountSyncWithAllPeers(account, error);
447
448 CFDictionaryForEach(handledPeers, ^(const void *key, const void *value) {
449 if (isString(key) && isArray(value)) {
450 CFArrayForEach(value, ^(const void *value) {
451 if (isString(value)) {
452 CFStringRef peerID = (CFStringRef) value;
453
454 CFStringRef kvsHandledKey = SOSMessageKeyCreateFromPeerToTransport((SOSTransportMessageKVSRef)account->kvs_message_transport, peerID);
455 CFArrayAppendValue(handledKeys, kvsHandledKey);
456 CFReleaseSafe(kvsHandledKey);
457 }
458 });
459 }
460 });
461 CFErrorRef flushError = NULL;
462 if (!SOSTransportMessageFlushChanges((SOSTransportMessageRef)account->kvs_message_transport, &flushError)) {
463 secerror("Flush failed: %@", flushError);
464 }
465 }
466 else {
467 secerror("Didn't handle? : %@", handleMessagesError);
468 }
469 CFReleaseNull(handledPeers);
470 CFReleaseNull(handleMessagesError);
471 }
472 }
473 });
474
475 }
476 if(CFDictionaryGetCount(circle_circle_messages_table)) {
477 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
478 SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value;
479 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
480 CFArrayRef handleCircleMessages = SOSTransportCircleHandleCircleMessages(tkvs, circle_circle_messages_table, error);
481 CFErrorRef localError = NULL;
482 if(handleCircleMessages == NULL){
483 secerror("Transport failed to handle circle messages: %@", localError);
484 } else if(CFArrayGetCount(handleCircleMessages) == 0) {
485 if(CFDictionaryGetCount(circle_circle_messages_table) != 0) {
486 secerror("Transport failed to process all circle messages: (%ld/%ld) %@",
487 CFArrayGetCount(handleCircleMessages),
488 CFDictionaryGetCount(circle_circle_messages_table), localError);
489 } else {
490 secnotice("circle", "Transport handled no circle messages");
491 }
492 } else {
493 CFArrayForEach(handleCircleMessages, ^(const void *value) {
494 CFStringRef keyHandled = SOSCircleKeyCreateWithName((CFStringRef)value, error);
495 CFArrayAppendValue(handledKeys, keyHandled);
496 CFReleaseNull(keyHandled);
497 });
498 }
499
500 CFReleaseNull(localError);
501 CFReleaseNull(handleCircleMessages);
502 }
503
504 });
505 }
506 if(CFDictionaryGetCount(ring_update_message_table)){
507 CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) {
508 if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){
509 CFErrorRef localError = NULL;
510 CFMutableArrayRef handledRingMessages = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
511
512 CFDictionaryForEach(ring_update_message_table, ^(const void *key, const void *value) {
513 CFDataRef ringData = (CFDataRef)value;
514 SOSRingRef ring = SOSRingCreateFromData(error, ringData);
515
516 if(SOSAccountUpdateRingFromRemote(account, ring, error)){
517 CFArrayAppendValue(handledRingMessages, key);
518 }
519 CFReleaseNull(ring);
520 });
521 if(CFArrayGetCount(handledRingMessages) == 0){
522 secerror("Transport failed to handle ring messages: %@", localError);
523 } else {
524 CFArrayForEach(handledRingMessages, ^(const void *value) {
525 CFStringRef ring_name = (CFStringRef)value;
526 CFStringRef keyHandled = SOSRingKeyCreateWithRingName(ring_name);
527 CFArrayAppendValue(handledKeys, keyHandled);
528 CFReleaseNull(keyHandled);
529 });
530 }
531 CFReleaseNull(handledRingMessages);
532 CFReleaseNull(localError);
533 }
534 });
535 }
536
537 CFReleaseNull(circle_retirement_messages_table);
538 CFReleaseNull(circle_circle_messages_table);
539 CFReleaseNull(circle_peer_messages_table);
540 CFReleaseNull(debug_info_message_table);
541 CFReleaseNull(ring_update_message_table);
542 CFReleaseNull(peer_info_message_table);
543 CFReleaseNull(debug_info_message_table);
544
545 showWhatWasHandled(updates, handledKeys);
546
547 return handledKeys;
548 }
549