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