]> git.saurik.com Git - apple/security.git/blob - Security/sec/securityd/Regressions/SOSAccountTesting.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / 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 <SecureObjectSync/SOSAccount.h>
30 #include <SecureObjectSync/SOSAccountPriv.h>
31 #include <SecureObjectSync/SOSTransport.h>
32 #include "SOSTransportTestTransports.h"
33 //
34 // Account comparison
35 //
36
37 #define kAccountsAgreeTestMin 9
38 #define kAccountsAgreeTestPerPeer 1
39 #define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x))
40
41
42 static SOSAccountRef SOSAccountCreateBasicTest(CFAllocatorRef allocator,
43 CFStringRef accountName,
44 CFDictionaryRef gestalt,
45 SOSDataSourceFactoryRef factory) {
46 SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory);
47
48 return a;
49 }
50
51 static SOSAccountRef SOSAccountCreateTest(CFAllocatorRef allocator,
52 CFStringRef accountName,
53 CFDictionaryRef gestalt,
54 SOSDataSourceFactoryRef factory) {
55 SOSAccountRef a = SOSAccountCreateBasicTest(allocator, accountName, gestalt, factory);
56
57 a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator);
58 SOSUnregisterTransportKeyParameter(a->key_transport);
59
60 CFReleaseNull(a->circle_transports);
61 CFReleaseNull(a->message_transports);
62 CFReleaseNull(a->key_transport);
63
64 SOSAccountEnsureFactoryCirclesTest(a, accountName);
65
66 return a;
67 }
68
69
70 static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFArrayRef allowed_peers)
71 {
72 CFArrayForEach(peers, ^(const void *value) {
73 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
74 CFErrorRef leftError = NULL;
75 CFErrorRef rightError = NULL;
76
77 ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFArrayContainsValue(allowed_peers, CFRangeMake(0, CFArrayGetCount(allowed_peers)), pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers);
78
79 CFReleaseNull(leftError);
80 CFReleaseNull(rightError);
81 });
82 }
83
84 static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers)
85 {
86 CFErrorRef error = NULL;
87 {
88 CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error);
89 ok(leftPeers, "Left peers (%@) - %s", error, label);
90 CFReleaseNull(error);
91
92 CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error);
93 ok(rightPeers, "Right peers (%@) - %s", error, label);
94 CFReleaseNull(error);
95
96 ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers);
97
98 if (check_peers) {
99 CFMutableArrayRef allowed_identities = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
100
101 CFArrayRef leftIdentities = SOSAccountCopyAccountIdentityPeerInfos(left, kCFAllocatorDefault, &error);
102 ok(leftIdentities, "Get identities (%@)", error);
103 CFReleaseNull(error);
104
105 CFArrayAppendArray(allowed_identities, leftIdentities, CFRangeMake(0, CFArrayGetCount(leftIdentities)));
106
107 CFReleaseNull(leftIdentities);
108
109 CFArrayRef rightIdentities = SOSAccountCopyAccountIdentityPeerInfos(right, kCFAllocatorDefault, &error);
110 ok(rightIdentities, "Get identities (%@)", error);
111 CFReleaseNull(error);
112
113 CFArrayAppendArray(allowed_identities, rightIdentities, CFRangeMake(0, CFArrayGetCount(rightIdentities)));
114
115 CFReleaseNull(rightIdentities);
116
117 unretired_peers_is_subset(label, leftPeers, allowed_identities);
118 }
119
120 CFReleaseNull(leftPeers);
121 CFReleaseNull(rightPeers);
122 }
123 {
124 CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error);
125 ok(leftConcurringPeers, "Left peers (%@) - %s", error, label);
126
127 CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error);
128 ok(rightConcurringPeers, "Right peers (%@) - %s", error, label);
129
130 ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers);
131
132 CFReleaseNull(leftConcurringPeers);
133 CFReleaseNull(rightConcurringPeers);
134 }
135 {
136 CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error);
137 ok(leftApplicants, "Left Applicants (%@) - %s", error, label);
138
139 CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error);
140 ok(rightApplicants, "Left Applicants (%@) - %s", error, label);
141
142 ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants);
143
144 CFReleaseNull(leftApplicants);
145 CFReleaseNull(rightApplicants);
146 }
147 }
148
149 static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right)
150 {
151 accounts_agree_internal(label, left, right, true);
152 }
153
154
155 //
156 // Change handling
157 //
158
159 static void CFDictionaryOverlayDictionary(CFMutableDictionaryRef target, CFDictionaryRef overlay) {
160 CFDictionaryForEach(overlay, ^(const void *key, const void *value) {
161 CFDictionarySetValue(target, key, value);
162 });
163 }
164
165 static void CFArrayAppendKeys(CFMutableArrayRef keys, CFDictionaryRef newKeysToAdd) {
166 CFDictionaryForEach(newKeysToAdd, ^(const void *key, const void *value) {
167 CFArrayAppendValue(keys, key);
168 });
169 }
170
171 static bool AddNewChanges(CFMutableDictionaryRef changesRecord, CFMutableDictionaryRef newKeysAndValues, SOSAccountRef sender)
172 {
173 __block bool changes_added = false;
174 CFMutableDictionaryRef emptyDictionary = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
175 CFDictionaryAddValue(changesRecord, kCFNull, emptyDictionary);
176 CFReleaseNull(emptyDictionary);
177
178 CFDictionaryOverlayDictionary((CFMutableDictionaryRef) CFDictionaryGetValue(changesRecord, kCFNull), newKeysAndValues);
179
180 CFDictionaryForEach(changesRecord, ^(const void *key, const void *value) {
181 if (isArray(value) && (sender == NULL || !CFEqual(sender, key))) {
182 CFArrayAppendKeys((CFMutableArrayRef) value, newKeysAndValues);
183 if (CFDictionaryGetCount(newKeysAndValues))
184 changes_added = true;
185 }
186 });
187
188 CFDictionaryRemoveAllValues(newKeysAndValues);
189
190 return changes_added;
191 }
192
193 static bool FillAllChanges(CFMutableDictionaryRef changes) {
194 __block bool changed = false;
195 CFArrayForEach(key_transports, ^(const void *value) {
196 SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
197 changed |= AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt));
198 });
199 CFArrayForEach(circle_transports, ^(const void *value) {
200 SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
201 changed |= AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt));
202 });
203 CFArrayForEach(message_transports, ^(const void *value) {
204 SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
205 CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
206 changed |=AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt));
207 });
208
209 return changed;
210 }
211
212 static void FillChanges(CFMutableDictionaryRef changes, SOSAccountRef forAccount)
213 {
214 CFArrayForEach(key_transports, ^(const void *value) {
215 SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
216 if(CFEqualSafe(forAccount, SOSTransportKeyParameterTestGetAccount(tpt))){
217 AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt));
218 }
219 });
220 CFArrayForEach(circle_transports, ^(const void *value) {
221 SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
222 if(CFEqualSafe(forAccount, SOSTransportCircleTestGetAccount(tpt))){
223 AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt));
224 }
225 });
226 CFArrayForEach(message_transports, ^(const void *value) {
227 SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
228 if(CFEqualSafe(forAccount, SOSTransportMessageTestGetAccount(tpt))){
229 CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
230 AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt));
231 }
232 });
233
234 }
235
236 static inline void FillChangesMulti(CFMutableDictionaryRef changes, SOSAccountRef account, ...)
237 {
238 SOSAccountRef next_account = account;
239 va_list argp;
240 va_start(argp, account);
241 while(next_account != NULL) {
242 FillChanges(changes, next_account);
243 next_account = va_arg(argp, SOSAccountRef);
244 }
245 }
246
247 static inline CFMutableArrayRef CFDictionaryCopyKeys(CFDictionaryRef dictionary)
248 {
249 CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
250
251 CFArrayAppendKeys(result, dictionary);
252
253 return result;
254 }
255
256 #define kFeedChangesToTestCount 1
257 static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account)
258 {
259 CFDictionaryRef full_list = (CFDictionaryRef) CFDictionaryGetValue(changes, kCFNull);
260
261 if (!isDictionary(full_list))
262 return; // Nothing recorded to send!
263
264 CFMutableArrayRef account_pending_keys = (CFMutableArrayRef)CFDictionaryGetValue(changes, account);
265 if (!isArray(account_pending_keys)) {
266 CFReleaseNull(account_pending_keys);
267
268 account_pending_keys = CFDictionaryCopyKeys(full_list);
269 CFDictionaryAddValue(changes, account, account_pending_keys);
270 CFReleaseSafe(account_pending_keys); // The dictionary keeps it, we don't retain it here.
271 }
272
273 CFMutableArrayRef handled = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
274
275 secerror("Changes for %@: %@", SOSTransportKeyParameterTestGetName((SOSTransportKeyParameterTestRef) account->key_transport), account_pending_keys);
276
277 CFErrorRef error = NULL;
278 CFMutableDictionaryRef account_pending_messages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
279 CFArrayForEach(account_pending_keys, ^(const void *value) {
280 CFDictionaryAddValue(account_pending_messages, value, CFDictionaryGetValue(full_list, value));
281 });
282
283 ok(handled = SOSTransportDispatchMessages(account, account_pending_messages, &error), "SOSTransportHandleMessages failed (%@)", error);
284
285 if (isArray(handled)) {
286 CFArrayForEach(handled, ^(const void *value) {
287 CFArrayRemoveAllValue(account_pending_keys, value);
288 });
289 }
290
291 CFReleaseNull(handled);
292 CFReleaseNull(error);
293 }
294
295 #define kFeedChangesToMultieTestCountPer 1
296
297 static inline void FeedChangesToMultiV(CFMutableDictionaryRef changes, va_list argp)
298 {
299 SOSAccountRef account = NULL;
300 while((account = va_arg(argp, SOSAccountRef)) != NULL) {
301 FeedChangesTo(changes, account);
302 }
303 }
304
305 static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...)
306 {
307 va_list argp;
308 va_start(argp, changes);
309
310 FeedChangesToMultiV(changes, argp);
311
312 va_end(argp);
313 }
314
315 static inline void InjectChangeToMulti(CFMutableDictionaryRef changes,
316 CFStringRef changeKey, CFTypeRef changeValue, ...)
317 {
318 CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
319 changeKey, changeValue,
320 NULL);
321 AddNewChanges(changes, changes_to_send, NULL);
322 CFReleaseNull(changes_to_send);
323
324 va_list argp;
325 va_start(argp, changeValue);
326 FeedChangesToMultiV(changes, argp);
327
328 }
329
330
331 static inline bool ProcessChangesOnceV(CFMutableDictionaryRef changes, va_list argp)
332 {
333 bool result = FillAllChanges(changes);
334
335 FeedChangesToMultiV(changes, argp);
336
337 return result;
338 }
339
340
341 static inline bool ProcessChangesOnce(CFMutableDictionaryRef changes, ...)
342 {
343 va_list argp;
344 va_start(argp, changes);
345
346 bool result = ProcessChangesOnceV(changes, argp);
347
348 va_end(argp);
349
350 return result;
351 }
352
353 static inline int ProcessChangesUntilNoChange(CFMutableDictionaryRef changes, ...)
354 {
355 va_list argp;
356 va_start(argp, changes);
357
358 int result = 0;
359 bool new_data = false;
360 do {
361 va_list argp_copy;
362 va_copy(argp_copy, argp);
363
364 new_data = ProcessChangesOnceV(changes, argp_copy);
365
366 ++result;
367
368 va_end(argp_copy);
369 } while (new_data);
370
371 va_end(argp);
372
373 return result;
374
375 }
376
377 //
378 // MARK: Account creation
379 //
380
381 static SOSAccountRef CreateAccountForLocalChanges(CFStringRef name, CFStringRef data_source_name)
382 {
383 SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate();
384 SOSDataSourceRef ds = SOSTestDataSourceCreate();
385 SOSTestDataSourceFactoryAddDataSource(factory, data_source_name, ds);
386 SOSEngineRef engine = SOSEngineCreate(ds, NULL);
387 ds->engine = engine;
388 CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name);
389
390 SOSAccountRef result = SOSAccountCreateTest(kCFAllocatorDefault, name, gestalt, factory);
391
392 CFReleaseNull(gestalt);
393
394 return result;
395 }
396
397
398 static inline int countPeers(SOSAccountRef account) {
399 CFErrorRef error = NULL;
400 CFArrayRef peers;
401
402 peers = SOSAccountCopyPeers(account, &error);
403 int retval = (int) CFArrayGetCount(peers);
404 CFReleaseNull(error);
405 CFReleaseNull(peers);
406 return retval;
407 }
408
409 static inline int countActivePeers(SOSAccountRef account) {
410 CFErrorRef error = NULL;
411 CFArrayRef peers;
412
413 peers = SOSAccountCopyActivePeers(account, &error);
414 int retval = (int) CFArrayGetCount(peers);
415 CFReleaseNull(error);
416 CFReleaseNull(peers);
417 return retval;
418 }
419
420 static inline int countActiveValidPeers(SOSAccountRef account) {
421 CFErrorRef error = NULL;
422 CFArrayRef peers;
423
424 peers = SOSAccountCopyActiveValidPeers(account, &error);
425 int retval = (int) CFArrayGetCount(peers);
426 CFReleaseNull(error);
427 CFReleaseNull(peers);
428 return retval;
429 }
430
431 static inline int countApplicants(SOSAccountRef account) {
432 CFErrorRef error = NULL;
433 CFArrayRef applicants = SOSAccountCopyApplicants(account, &error);
434 int retval = 0;
435
436 if(applicants) retval = (int)CFArrayGetCount(applicants);
437 CFReleaseNull(error);
438 CFReleaseNull(applicants);
439 return retval;
440 }
441
442
443 static inline void showActiveValidPeers(SOSAccountRef account) {
444 CFErrorRef error = NULL;
445 CFArrayRef peers;
446
447 peers = SOSAccountCopyActiveValidPeers(account, &error);
448 CFArrayForEach(peers, ^(const void *value) {
449 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
450 ok(0, "Active Valid Peer %@", pi);
451 });
452 CFReleaseNull(peers);
453 }
454
455 #endif