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