]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/Regressions/SOSAccountTesting.h
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / securityd / Regressions / SOSAccountTesting.h
1 /*
2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #ifndef SEC_SOSAccountTesting_h
26 #define SEC_SOSAccountTesting_h
27
28 #include <CoreFoundation/CoreFoundation.h>
29 #include <Security/SecureObjectSync/SOSAccount.h>
30 #include <Security/SecureObjectSync/SOSAccountPriv.h>
31 #include <Security/SecureObjectSync/SOSTransport.h>
32 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
33 #include "SOSTransportTestTransports.h"
34 //
35 // Account comparison
36 //
37
38 #define kAccountsAgreeTestMin 9
39 #define kAccountsAgreeTestPerPeer 1
40 #define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x))
41
42 static void SOSAccountResetToTest(SOSAccountRef a, CFStringRef accountName) {
43 SOSUnregisterTransportKeyParameter(a->key_transport);
44
45 CFReleaseNull(a->circle_transport);
46 CFReleaseNull(a->kvs_message_transport);
47 CFReleaseNull(a->key_transport);
48
49 SOSAccountEnsureFactoryCirclesTest(a, accountName);
50 }
51
52
53 static SOSAccountRef SOSAccountCreateBasicTest(CFAllocatorRef allocator,
54 CFStringRef accountName,
55 CFDictionaryRef gestalt,
56 SOSDataSourceFactoryRef factory) {
57 SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory);
58
59 return a;
60 }
61
62 static SOSAccountRef SOSAccountCreateTest(CFAllocatorRef allocator,
63 CFStringRef accountName,
64 CFDictionaryRef gestalt,
65 SOSDataSourceFactoryRef factory) {
66 SOSAccountRef a = SOSAccountCreateBasicTest(allocator, accountName, gestalt, factory);
67
68 SOSAccountResetToTest(a, accountName);
69
70 return a;
71 }
72
73 static SOSAccountRef SOSAccountCreateTestFromData(CFAllocatorRef allocator,
74 CFDataRef data,
75 CFStringRef accountName,
76 SOSDataSourceFactoryRef factory) {
77 SOSAccountRef a = SOSAccountCreateFromData(allocator, data, factory, NULL);
78 if (!a) {
79 CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(accountName);
80 a = SOSAccountCreate(allocator, gestalt, factory);
81 CFReleaseNull(gestalt);
82 }
83
84 SOSAccountResetToTest(a, accountName);
85
86 return a;
87 }
88
89
90 static inline bool SOSAccountAssertUserCredentialsAndUpdate(SOSAccountRef account,
91 CFStringRef user_account, CFDataRef user_password,
92 CFErrorRef *error)
93 {
94 bool success = false;
95 success = SOSAccountAssertUserCredentials(account, user_account, user_password, error);
96 require_quiet(success, done);
97
98 success = SOSAccountGenerationSignatureUpdate(account, error);
99
100 done:
101 return success;
102 }
103
104
105
106 static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFSetRef allowed_peers)
107 {
108 CFArrayForEach(peers, ^(const void *value) {
109 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
110
111 CFErrorRef leftError = NULL;
112 CFErrorRef rightError = NULL;
113
114 ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFSetContainsValue(allowed_peers, pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers);
115
116 CFReleaseNull(leftError);
117 CFReleaseNull(rightError);
118 });
119 }
120
121 static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers)
122 {
123 CFErrorRef error = NULL;
124 {
125 CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error);
126 ok(leftPeers, "Left peers (%@) - %s", error, label);
127 CFReleaseNull(error);
128
129 CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error);
130 ok(rightPeers, "Right peers (%@) - %s", error, label);
131 CFReleaseNull(error);
132
133 ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers);
134
135 if (check_peers) {
136 CFMutableSetRef allowed_identities = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault);
137
138 SOSFullPeerInfoRef leftFullPeer = SOSAccountCopyAccountIdentityPeerInfo(left, kCFAllocatorDefault, NULL);
139
140 if (leftFullPeer)
141 CFSetAddValue(allowed_identities, SOSFullPeerInfoGetPeerInfo(leftFullPeer));
142
143 CFReleaseNull(leftFullPeer);
144
145 SOSFullPeerInfoRef rightFullPeer = SOSAccountCopyAccountIdentityPeerInfo(right, kCFAllocatorDefault, NULL);
146
147 if (rightFullPeer)
148 CFSetAddValue(allowed_identities, SOSFullPeerInfoGetPeerInfo(rightFullPeer));
149
150 CFReleaseNull(rightFullPeer);
151
152 unretired_peers_is_subset(label, leftPeers, allowed_identities);
153
154 CFReleaseNull(allowed_identities);
155 }
156
157 CFReleaseNull(leftPeers);
158 CFReleaseNull(rightPeers);
159 }
160 {
161 CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error);
162 ok(leftConcurringPeers, "Left peers (%@) - %s", error, label);
163
164 CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error);
165 ok(rightConcurringPeers, "Right peers (%@) - %s", error, label);
166
167 ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers);
168
169 CFReleaseNull(leftConcurringPeers);
170 CFReleaseNull(rightConcurringPeers);
171 }
172 {
173 CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error);
174 ok(leftApplicants, "Left Applicants (%@) - %s", error, label);
175
176 CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error);
177 ok(rightApplicants, "Left Applicants (%@) - %s", error, label);
178
179 ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants);
180
181 CFReleaseNull(leftApplicants);
182 CFReleaseNull(rightApplicants);
183 }
184 }
185
186 static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right)
187 {
188 accounts_agree_internal(label, left, right, true);
189 }
190
191
192 //
193 // Change handling
194 //
195
196 static inline CFStringRef CFArrayCopyCompactDescription(CFArrayRef array) {
197 if (!isArray(array))
198 return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<Not an array! %@>"), array);
199
200 CFMutableStringRef result = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("["));
201
202 __block CFStringRef separator = CFSTR("");
203 CFArrayForEach(array, ^(const void *value) {
204 CFStringAppendFormat(result, NULL, CFSTR("%@%@"), separator, value);
205 separator = CFSTR(",");
206 });
207
208 CFStringAppend(result, CFSTR("]"));
209
210 CFReleaseSafe(separator);
211
212 return result;
213 }
214
215 static inline CFStringRef SOSAccountCopyName(SOSAccountRef account) {
216 SOSPeerInfoRef pi = SOSAccountGetMyPeerInfo(account);
217
218 return pi ? CFStringCreateCopy(kCFAllocatorDefault, SOSPeerInfoGetPeerName(pi)) : CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("%@"), account);
219 }
220
221 static inline CFStringRef CopyChangesDescription(CFDictionaryRef changes) {
222
223 CFStringRef pendingChanges = CFDictionaryCopyCompactDescription((CFDictionaryRef) CFDictionaryGetValue(changes, kCFNull));
224
225 CFMutableStringRef peerTable = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("["));
226
227 __block CFStringRef separator = CFSTR("");
228
229 CFDictionaryForEach(changes, ^(const void *key, const void *value) {
230 if (CFGetTypeID(key) == SOSAccountGetTypeID()) {
231 CFStringRef accountName = SOSAccountCopyName((SOSAccountRef) key);
232 CFStringRef arrayDescription = CFArrayCopyCompactDescription(value);
233
234 CFStringAppendFormat(peerTable, NULL, CFSTR("%@%@:%@"), separator, accountName, arrayDescription);
235 separator = CFSTR(", ");
236
237 CFReleaseSafe(accountName);
238 CFReleaseSafe(arrayDescription);
239 }
240 });
241
242 CFStringAppend(peerTable, CFSTR("]"));
243
244 CFStringRef result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<TestChanges %@ %@>"), pendingChanges, peerTable);
245 CFReleaseNull(pendingChanges);
246 CFReleaseNull(peerTable);
247
248 return result;
249 };
250
251 static void CFDictionaryOverlayDictionary(CFMutableDictionaryRef target, CFMutableDictionaryRef overlay) {
252 CFMutableSetRef keysToRemove = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
253
254 CFDictionaryForEach(overlay, ^(const void *key, const void *value) {
255 const void *current_value = CFDictionaryGetValue(target, key);
256 if (CFEqualSafe(current_value, value) || (isNull(value) && current_value == NULL)) {
257 CFSetAddValue(keysToRemove, key);
258 } else {
259 CFDictionarySetValue(target, key, value);
260 }
261 });
262
263 CFSetForEach(keysToRemove, ^(const void *value) {
264 CFDictionaryRemoveValue(overlay, value);
265 });
266
267 CFReleaseNull(keysToRemove);
268 }
269
270 static void CFArrayAppendKeys(CFMutableArrayRef keys, CFDictionaryRef newKeysToAdd) {
271 CFDictionaryForEach(newKeysToAdd, ^(const void *key, const void *value) {
272 CFArrayAppendValue(keys, key);
273 });
274 }
275
276 static bool AddNewChanges(CFMutableDictionaryRef changesRecord, CFMutableDictionaryRef newKeysAndValues, SOSAccountRef sender)
277 {
278 __block bool changes_added = false;
279 CFMutableDictionaryRef emptyDictionary = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
280 CFDictionaryAddValue(changesRecord, kCFNull, emptyDictionary);
281 CFReleaseNull(emptyDictionary);
282
283 CFDictionaryOverlayDictionary((CFMutableDictionaryRef) CFDictionaryGetValue(changesRecord, kCFNull), newKeysAndValues);
284
285 CFDictionaryForEach(changesRecord, ^(const void *key, const void *value) {
286 if (isArray(value) && (sender == NULL || sender != key)) {
287 CFArrayAppendKeys((CFMutableArrayRef) value, newKeysAndValues);
288 if (CFDictionaryGetCount(newKeysAndValues))
289 changes_added = true;
290 }
291 });
292
293 if (changes_added)
294 secnotice("changes", "Changes from %@: %@", sender, newKeysAndValues);
295
296 CFDictionaryRemoveAllValues(newKeysAndValues);
297
298 return changes_added;
299 }
300
301 static bool FillAllChanges(CFMutableDictionaryRef changes) {
302 __block bool changed = false;
303
304 CFMutableSetRef changedAccounts = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
305
306 CFArrayForEach(key_transports, ^(const void *value) {
307 SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
308 if (AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt))) {
309 changed |= true;
310 CFSetAddValue(changedAccounts, SOSTransportKeyParameterTestGetAccount(tpt));
311 }
312 SOSTransportKeyParameterTestClearChanges(tpt);
313 });
314 CFArrayForEach(circle_transports, ^(const void *value) {
315 SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
316 if (AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt))) {
317 changed |= true;
318 CFSetAddValue(changedAccounts, SOSTransportCircleTestGetAccount(tpt));
319 }
320 SOSTransportCircleTestClearChanges(tpt);
321 });
322 CFArrayForEach(message_transports, ^(const void *value) {
323 SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
324 CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
325 if (AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt))) {
326 changed |= true;
327 CFSetAddValue(changedAccounts, SOSTransportMessageTestGetAccount(tpt));
328 }
329 SOSTransportMessageTestClearChanges(tpt);
330 });
331
332 secnotice("process-changes", "Accounts with change (%@): %@", changed ? CFSTR("YES") : CFSTR("NO"), changedAccounts);
333
334 CFReleaseNull(changedAccounts);
335
336 return changed;
337 }
338
339 static void FillChanges(CFMutableDictionaryRef changes, SOSAccountRef forAccount)
340 {
341 CFArrayForEach(key_transports, ^(const void *value) {
342 SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
343 if(CFEqualSafe(forAccount, SOSTransportKeyParameterTestGetAccount(tpt))){
344 AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt));
345 SOSTransportKeyParameterTestClearChanges(tpt);
346 }
347 });
348 CFArrayForEach(circle_transports, ^(const void *value) {
349 SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
350 if(CFEqualSafe(forAccount, SOSTransportCircleTestGetAccount(tpt))){
351 AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt));
352 SOSTransportCircleTestClearChanges(tpt);
353 }
354 });
355 CFArrayForEach(message_transports, ^(const void *value) {
356 SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
357 if(CFEqualSafe(forAccount, SOSTransportMessageTestGetAccount(tpt))){
358 CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
359 AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt));
360 SOSTransportMessageTestClearChanges(tpt);
361 }
362 });
363
364 }
365
366 static inline void FillChangesMulti(CFMutableDictionaryRef changes, SOSAccountRef account, ...)
367 {
368 SOSAccountRef next_account = account;
369 va_list argp;
370 va_start(argp, account);
371 while(next_account != NULL) {
372 FillChanges(changes, next_account);
373 next_account = va_arg(argp, SOSAccountRef);
374 }
375 }
376
377 static inline CFMutableArrayRef CFDictionaryCopyKeys(CFDictionaryRef dictionary)
378 {
379 CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
380
381 CFArrayAppendKeys(result, dictionary);
382
383 return result;
384 }
385
386 #define kFeedChangesToTestCount 1
387 static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account)
388 {
389 CFDictionaryRef full_list = (CFDictionaryRef) CFDictionaryGetValue(changes, kCFNull);
390
391 if (!isDictionary(full_list))
392 return; // Nothing recorded to send!
393
394 CFMutableArrayRef account_pending_keys = (CFMutableArrayRef)CFDictionaryGetValue(changes, account);
395
396 if (!isArray(account_pending_keys)) {
397 CFReleaseNull(account_pending_keys);
398
399 account_pending_keys = CFDictionaryCopyKeys(full_list);
400 CFDictionaryAddValue(changes, account, account_pending_keys);
401 CFReleaseSafe(account_pending_keys); // The dictionary keeps it, we don't retain it here.
402 }
403
404 CFMutableArrayRef handled = NULL;
405
406 CFErrorRef error = NULL;
407 CFMutableDictionaryRef account_pending_messages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
408 CFArrayForEach(account_pending_keys, ^(const void *value) {
409 CFDictionaryAddValue(account_pending_messages, value, CFDictionaryGetValue(full_list, value));
410 });
411
412 secnotice("changes", "Changes for %@:", SOSTransportKeyParameterTestGetName((SOSTransportKeyParameterTestRef) account->key_transport));
413
414 CFDictionaryForEach(account_pending_messages, ^(const void *key, const void *value) {
415 secnotice("changes", " %@", key);
416 });
417
418 ok(handled = SOSTransportDispatchMessages(account, account_pending_messages, &error), "SOSTransportHandleMessages failed (%@)", error);
419
420 if (isArray(handled)) {
421 CFArrayForEach(handled, ^(const void *value) {
422 CFArrayRemoveAllValue(account_pending_keys, value);
423 });
424 }
425 CFReleaseNull(account_pending_messages);
426 CFReleaseNull(handled);
427 CFReleaseNull(error);
428 }
429
430 #define kFeedChangesToMultieTestCountPer 1
431
432 static inline void FeedChangesToMultiV(CFMutableDictionaryRef changes, va_list argp)
433 {
434 SOSAccountRef account = NULL;
435 while((account = va_arg(argp, SOSAccountRef)) != NULL) {
436 FeedChangesTo(changes, account);
437 }
438 }
439
440 static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...)
441 {
442 va_list argp;
443 va_start(argp, changes);
444
445 FeedChangesToMultiV(changes, argp);
446
447 va_end(argp);
448 }
449
450 static inline void InjectChangeToMulti(CFMutableDictionaryRef changes,
451 CFStringRef changeKey, CFTypeRef changeValue, ...)
452 {
453 CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
454 changeKey, changeValue,
455 NULL);
456 AddNewChanges(changes, changes_to_send, NULL);
457 CFReleaseNull(changes_to_send);
458
459 va_list argp;
460 va_start(argp, changeValue);
461 FeedChangesToMultiV(changes, argp);
462 va_end(argp);
463 }
464
465 static inline bool ProcessChangesOnceV(CFMutableDictionaryRef changes, va_list argp)
466 {
467 bool result = FillAllChanges(changes);
468
469 FeedChangesToMultiV(changes, argp);
470
471 return result;
472 }
473
474
475 static inline bool ProcessChangesOnce(CFMutableDictionaryRef changes, ...)
476 {
477 va_list argp;
478 va_start(argp, changes);
479
480 bool result = ProcessChangesOnceV(changes, argp);
481
482 va_end(argp);
483
484 return result;
485 }
486
487 static inline int ProcessChangesUntilNoChange(CFMutableDictionaryRef changes, ...)
488 {
489 va_list argp;
490 va_start(argp, changes);
491
492 int result = 0;
493 bool new_data = false;
494 do {
495 va_list argp_copy;
496 va_copy(argp_copy, argp);
497
498 new_data = ProcessChangesOnceV(changes, argp_copy);
499
500 ++result;
501
502 va_end(argp_copy);
503 } while (new_data);
504
505 va_end(argp);
506
507 return result;
508
509 }
510
511 //
512 // MARK: Account creation
513 //
514
515
516 static inline SOSAccountRef CreateAccountForLocalChanges(CFStringRef name, CFStringRef data_source_name)
517 {
518 SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate();
519 SOSDataSourceRef ds = SOSTestDataSourceCreate();
520 SOSTestDataSourceFactorySetDataSource(factory, data_source_name, ds);
521 SOSEngineRef engine = SOSEngineCreate(ds, NULL);
522 ds->engine = engine;
523 CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name);
524
525 SOSAccountRef result = SOSAccountCreateTest(kCFAllocatorDefault, name, gestalt, factory);
526
527 CFReleaseNull(gestalt);
528
529 return result;
530 }
531
532 static inline SOSAccountRef CreateAccountForLocalChangesFromData(CFDataRef flattenedData, CFStringRef name, CFStringRef data_source_name)
533 {
534 SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate();
535 SOSDataSourceRef ds = SOSTestDataSourceCreate();
536 SOSTestDataSourceFactorySetDataSource(factory, data_source_name, ds);
537 SOSEngineRef engine = SOSEngineCreate(ds, NULL);
538 ds->engine = engine;
539
540 SOSAccountRef result = SOSAccountCreateTestFromData(kCFAllocatorDefault, flattenedData, name, factory);
541
542 return result;
543 }
544
545
546
547 static inline int countPeers(SOSAccountRef account) {
548 CFErrorRef error = NULL;
549 CFArrayRef peers;
550
551 peers = SOSAccountCopyPeers(account, &error);
552 int retval = (int) CFArrayGetCount(peers);
553 CFReleaseNull(error);
554 CFReleaseNull(peers);
555 return retval;
556 }
557
558 static inline int countActivePeers(SOSAccountRef account) {
559 CFErrorRef error = NULL;
560 CFArrayRef peers;
561
562 peers = SOSAccountCopyActivePeers(account, &error);
563 int retval = (int) CFArrayGetCount(peers);
564 CFReleaseNull(error);
565 CFReleaseNull(peers);
566 return retval;
567 }
568
569 static inline int countActiveValidPeers(SOSAccountRef account) {
570 CFErrorRef error = NULL;
571 CFArrayRef peers;
572
573 peers = SOSAccountCopyActiveValidPeers(account, &error);
574 int retval = (int) CFArrayGetCount(peers);
575 CFReleaseNull(error);
576 CFReleaseNull(peers);
577 return retval;
578 }
579
580 static inline int countApplicants(SOSAccountRef account) {
581 CFErrorRef error = NULL;
582 CFArrayRef applicants = SOSAccountCopyApplicants(account, &error);
583 int retval = 0;
584
585 if(applicants) retval = (int)CFArrayGetCount(applicants);
586 CFReleaseNull(error);
587 CFReleaseNull(applicants);
588 return retval;
589 }
590
591
592 static inline void showActiveValidPeers(SOSAccountRef account) {
593 CFErrorRef error = NULL;
594 CFArrayRef peers;
595
596 peers = SOSAccountCopyActiveValidPeers(account, &error);
597 CFArrayForEach(peers, ^(const void *value) {
598 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
599 ok(0, "Active Valid Peer %@", pi);
600 });
601 CFReleaseNull(peers);
602 }
603
604 #endif