]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/Regressions/secd-201-coders.m
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / sec / securityd / Regressions / secd-201-coders.m
1 /*
2 * Copyright (c) 2013-2016 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 // secd_201_coders
25 // sec
26 //
27
28 #include <stdio.h>
29
30
31
32
33 #include <Security/SecBase.h>
34 #include <Security/SecItem.h>
35
36 #include <CoreFoundation/CFDictionary.h>
37
38 #include <Security/SecureObjectSync/SOSAccount.h>
39 #include <Security/SecureObjectSync/SOSCloudCircle.h>
40 #include <Security/SecureObjectSync/SOSInternal.h>
41 #include <Security/SecureObjectSync/SOSUserKeygen.h>
42 #include <Security/SecureObjectSync/SOSTransport.h>
43 #include <Security/SecureObjectSync/SOSEngine.h>
44 #import <Security/SecureObjectSync/SOSAccountTrustClassic+Circle.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47
48 #include "secd_regressions.h"
49 #include "SOSTestDataSource.h"
50 #include "SOSTestDevice.h"
51
52 #include "SOSRegressionUtilities.h"
53 #include <utilities/SecCFWrappers.h>
54 #include <Security/SecKeyPriv.h>
55
56 #include <securityd/SOSCloudCircleServer.h>
57
58 #include "SOSAccountTesting.h"
59
60 #include "SecdTestKeychainUtilities.h"
61
62 static bool SOSAccountIsThisPeerIDMe(SOSAccount* account, CFStringRef peerID) {
63 SOSAccountTrustClassic*trust = account.trust;
64 SOSPeerInfoRef mypi = trust.peerInfo;
65 CFStringRef myPeerID = SOSPeerInfoGetPeerID(mypi);
66
67 return myPeerID && CFEqualSafe(myPeerID, peerID);
68 }
69
70 static void compareCoders(CFMutableDictionaryRef beforeCoders, CFMutableDictionaryRef afterCoderState)
71 {
72 CFDictionaryForEach(beforeCoders, ^(const void *key, const void *value) {
73 CFStringRef beforePeerid = (CFStringRef)key;
74 SOSCoderRef beforeCoderData = (SOSCoderRef)value;
75 SOSCoderRef afterCoderData = (SOSCoderRef)CFDictionaryGetValue(afterCoderState, beforePeerid);
76 ok(CFEqual(beforeCoderData,afterCoderData));
77 });
78 }
79
80 static void ids_test_sync(SOSAccount* alice_account, SOSAccount* bob_account){
81
82 CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
83 __block bool SyncingCompletedOverIDS = false;
84 __block CFErrorRef localError = NULL;
85 __block bool done = false;
86 SOSAccountTrustClassic *aliceTrust = alice_account.trust;
87 SOSAccountTrustClassic *bobTrust = bob_account.trust;
88
89 do{
90 SOSCircleForEachValidPeer(aliceTrust.trustedCircle, alice_account.accountKey, ^(SOSPeerInfoRef peer) {
91 if (!SOSAccountIsThisPeerIDMe(alice_account, SOSPeerInfoGetPeerID(peer))) {
92 if(SOSPeerInfoShouldUseIDSTransport(aliceTrust.peerInfo, peer) &&
93 SOSPeerInfoShouldUseIDSMessageFragmentation(aliceTrust.peerInfo, peer)){
94 secnotice("IDS Transport","Syncing with IDS capable peers using IDS!");
95
96 CFMutableSetRef ids = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
97 CFSetAddValue(ids, SOSPeerInfoGetPeerID(peer));
98
99 CFTypeRef alice_engine = [(SOSMessageIDSTest*)alice_account.ids_message_transport SOSTransportMessageGetEngine];
100
101 //testing loading and saving coders
102 ok(TestSOSEngineGetCoders(alice_engine));
103 CFMutableDictionaryRef beforeCoders = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(TestSOSEngineGetCoders(alice_engine)), TestSOSEngineGetCoders(alice_engine));
104 TestSOSEngineDoTxnOnQueue(alice_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
105 ok(TestSOSEngineLoadCoders((SOSEngineRef)[(SOSMessageIDSTest*)alice_account.ids_message_transport SOSTransportMessageGetEngine], txn, &localError));
106 });
107
108 ok(TestSOSEngineGetCoders(alice_engine));
109
110 TestSOSEngineDoTxnOnQueue(alice_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
111 ok(SOSTestEngineSaveCoders(alice_engine, txn, &localError));
112 });
113
114 compareCoders(beforeCoders, TestSOSEngineGetCoders(alice_engine));
115
116 //syncing with all peers
117 SyncingCompletedOverIDS = [(SOSMessageIDSTest*)alice_account.ids_message_transport SOSTransportMessageSyncWithPeers:(SOSMessageIDSTest*)alice_account.ids_message_transport p:ids err:&localError];
118 //testing load after sync with all peers
119 CFMutableDictionaryRef codersAfterSyncBeforeLoad = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(TestSOSEngineGetCoders(alice_engine)), TestSOSEngineGetCoders(alice_engine));
120 TestSOSEngineDoTxnOnQueue(alice_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
121 ok(TestSOSEngineLoadCoders((SOSEngineRef)[(SOSMessageIDSTest*)alice_account.ids_message_transport SOSTransportMessageGetEngine], txn, &localError));
122 });
123 compareCoders(codersAfterSyncBeforeLoad, TestSOSEngineGetCoders(alice_engine));
124
125 CFReleaseNull(codersAfterSyncBeforeLoad);
126 CFReleaseNull(beforeCoders);
127 CFReleaseNull(ids);
128 }
129 }
130 });
131
132 ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL);
133
134 SOSCircleForEachValidPeer(bobTrust.trustedCircle, bob_account.accountKey, ^(SOSPeerInfoRef peer) {
135 if (!SOSAccountIsThisPeerIDMe(bob_account, SOSPeerInfoGetPeerID(peer))) {
136 if(SOSPeerInfoShouldUseIDSTransport(bobTrust.peerInfo, peer) &&
137 SOSPeerInfoShouldUseIDSMessageFragmentation(bobTrust.peerInfo, peer)){
138 secnotice("IDS Transport","Syncing with IDS capable peers using IDS!");
139
140 CFMutableSetRef ids = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
141 CFSetAddValue(ids, SOSPeerInfoGetPeerID(peer));
142
143 SOSEngineRef bob_engine = (SOSEngineRef)[(SOSMessageIDSTest*)bob_account.ids_message_transport SOSTransportMessageGetEngine];
144
145 //testing loading and saving coders
146 ok(TestSOSEngineGetCoders(bob_engine));
147 CFMutableDictionaryRef beforeCoders = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(TestSOSEngineGetCoders(bob_engine)), TestSOSEngineGetCoders(bob_engine));
148 TestSOSEngineDoTxnOnQueue(bob_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
149 ok(TestSOSEngineLoadCoders((SOSEngineRef)[(SOSMessageIDSTest*)bob_account.ids_message_transport SOSTransportMessageGetEngine], txn, &localError));
150 });
151
152 ok((SOSEngineRef)TestSOSEngineGetCoders(bob_engine));
153
154 TestSOSEngineDoTxnOnQueue(bob_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
155 ok(SOSTestEngineSaveCoders(bob_engine, txn, &localError));
156 });
157
158 compareCoders(beforeCoders, TestSOSEngineGetCoders(bob_engine));
159
160 SyncingCompletedOverIDS &= [(SOSMessageIDSTest*)bob_account.ids_message_transport SOSTransportMessageSyncWithPeers:(SOSMessageIDSTest*)bob_account.ids_message_transport p:ids err:&localError];
161
162 //testing load after sync with all peers
163 CFMutableDictionaryRef codersAfterSyncBeforeLoad = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(TestSOSEngineGetCoders(bob_engine)), TestSOSEngineGetCoders(bob_engine));
164 TestSOSEngineDoTxnOnQueue(bob_engine, &localError, ^(SOSTransactionRef txn, bool *commit) {
165 ok(TestSOSEngineLoadCoders((SOSEngineRef)[(SOSMessageIDSTest*)bob_account.ids_message_transport SOSTransportMessageGetEngine], txn, &localError));
166 });
167 compareCoders(codersAfterSyncBeforeLoad, TestSOSEngineGetCoders(bob_engine));
168 CFReleaseNull(codersAfterSyncBeforeLoad);
169 CFReleaseNull(beforeCoders);
170 CFReleaseNull(ids);
171 }
172 }
173 });
174 if(!SyncingCompletedOverIDS)
175 return;
176
177 if(CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)alice_account.ids_message_transport)) == 0 && CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)bob_account.ids_message_transport)) == 0){
178 done = true;
179 break;
180 }
181
182 ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL);
183
184 }while(done == false);
185 CFReleaseNull(changes);
186
187 ok(SyncingCompletedOverIDS, "synced items over IDS");
188
189 }
190
191 static void tests(void)
192 {
193
194 __block CFErrorRef error = NULL;
195 CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10);
196 CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 10);
197 CFStringRef cfaccount = CFSTR("test@test.org");
198
199 CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
200 SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource"));
201 SOSAccount* bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), CFSTR("TestSource"));
202
203 ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error);
204
205 // Bob wins writing at this point, feed the changes back to alice.
206 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates");
207
208 ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error);
209 CFReleaseNull(error);
210 ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error);
211 CFReleaseNull(cfpassword);
212
213 CFReleaseNull(error);
214 ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error);
215 CFReleaseNull(cfwrong_password);
216 is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword");
217 CFReleaseNull(error);
218
219 ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error);
220 CFReleaseNull(error);
221
222 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates");
223
224 ok(SOSAccountHasCompletedInitialSync(alice_account), "Alice thinks she's completed initial sync");
225
226 ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error);
227 CFReleaseNull(error);
228
229 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates");
230
231 {
232 CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error);
233
234 ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error);
235 ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error);
236 CFReleaseNull(error);
237 CFReleaseNull(applicants);
238 }
239
240 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates");
241
242 accounts_agree("bob&alice pair", bob_account, alice_account);
243
244 CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error);
245 ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error);
246 CFReleaseNull(peers);
247
248 //creating test devices
249 CFIndex version = 0;
250
251 // Optionally prefix each peer with name to make them more unique.
252 CFArrayRef deviceIDs = CFArrayCreateForCFTypes(kCFAllocatorDefault,alice_account.peerID, bob_account.peerID, NULL);
253 CFSetRef views = SOSViewsCopyTestV2Default();
254 CFMutableArrayRef peerMetas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
255 CFStringRef deviceID;
256 CFArrayForEachC(deviceIDs, deviceID) {
257 SOSPeerMetaRef peerMeta = SOSPeerMetaCreateWithComponents(deviceID, views, NULL);
258 CFArrayAppendValue(peerMetas, peerMeta);
259 CFReleaseNull(peerMeta);
260 }
261
262 CFReleaseNull(views);
263 CFArrayForEachC(deviceIDs, deviceID) {
264 SOSTestDeviceRef device = SOSTestDeviceCreateWithDbNamed(kCFAllocatorDefault, deviceID, deviceID);
265 SOSTestDeviceSetPeerIDs(device, peerMetas, version, NULL);
266
267 if([alice_account.peerID isEqual: (__bridge id) deviceID]){
268 alice_account.factory = device->dsf;
269 SOSTestDeviceAddGenericItem(device, CFSTR("Alice"), CFSTR("Alice-add"));
270 }
271 else{
272 bob_account.factory = device->dsf;
273 SOSTestDeviceAddGenericItem(device, CFSTR("Bob"), CFSTR("Bob-add"));
274 }
275
276 CFReleaseNull(device);
277 }
278 CFReleaseNull(deviceIDs);
279 CFReleaseNull(peerMetas);
280
281 SOSUnregisterAllTransportMessages();
282 CFArrayRemoveAllValues(message_transports);
283
284 SOSAccountTrustClassic *aliceTrust = alice_account.trust;
285 SOSAccountTrustClassic *bobTrust = bob_account.trust;
286
287 alice_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:alice_account andAccountName:CFSTR("Alice") andCircleName:CFSTR("TestSource") err:&error];
288
289 bob_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:bob_account andAccountName:CFSTR("Bob") andCircleName:CFSTR("TestSource") err:&error];
290
291 bool result = [alice_account.trust modifyCircle:alice_account.circle_transport err:&error action:^(SOSCircleRef circle) {
292
293 CFErrorRef localError = NULL;
294
295 SOSFullPeerInfoUpdateTransportType(aliceTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError);
296 SOSFullPeerInfoUpdateTransportPreference(aliceTrust.fullPeerInfo, kCFBooleanFalse, &localError);
297 SOSFullPeerInfoUpdateTransportFragmentationPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError);
298 SOSFullPeerInfoUpdateTransportAckModelPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError);
299
300 return SOSCircleHasPeer(circle, aliceTrust.peerInfo, NULL);
301 }];
302
303 ok(result, "Alice account update circle with transport type");
304
305 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates");
306
307 result = [bob_account.trust modifyCircle:bob_account.circle_transport err:&error action:^(SOSCircleRef circle) {
308 CFErrorRef localError = NULL;
309
310 SOSFullPeerInfoUpdateTransportType(bobTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError);
311 SOSFullPeerInfoUpdateTransportPreference(bobTrust.fullPeerInfo, kCFBooleanFalse, &localError);
312 SOSFullPeerInfoUpdateTransportFragmentationPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError);
313 SOSFullPeerInfoUpdateTransportAckModelPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError);
314
315 return SOSCircleHasPeer(circle, bobTrust.peerInfo, NULL);
316 }];
317
318 ok(result, "Bob account update circle with transport type");
319 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates");
320
321 CFStringRef alice_transportType =SOSPeerInfoCopyTransportType(alice_account.peerInfo);
322 CFStringRef bob_accountTransportType = SOSPeerInfoCopyTransportType(bob_account.peerInfo);
323 ok(CFEqualSafe(alice_transportType, CFSTR("IDS2.0")), "Alice transport type not IDS");
324 ok(CFEqualSafe(bob_accountTransportType, CFSTR("IDS2.0")), "Bob transport type not IDS");
325
326 CFReleaseNull(alice_transportType);
327 CFReleaseNull(bob_accountTransportType);
328
329 SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)alice_account.ids_message_transport, CFSTR("Alice Account"));
330 ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)alice_account.ids_message_transport) != NULL, "retrieved getting account name");
331 ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(alice_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy");
332
333 SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)bob_account.ids_message_transport, CFSTR("Bob Account"));
334 ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)bob_account.ids_message_transport) != NULL, "retrieved getting account name");
335 ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(bob_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy");
336
337
338 ok(SOSAccountSetMyDSID_wTxn(alice_account, CFSTR("Alice"),&error), "Setting IDS device ID");
339 CFStringRef alice_dsid = SOSAccountCopyDeviceID(alice_account, &error);
340 ok(CFEqualSafe(alice_dsid, CFSTR("Alice")), "Getting IDS device ID");
341 CFReleaseNull(alice_dsid);
342
343 ok(SOSAccountSetMyDSID_wTxn(bob_account, CFSTR("Bob"),&error), "Setting IDS device ID");
344 CFStringRef bob_dsid = SOSAccountCopyDeviceID(bob_account, &error);
345 ok(CFEqualSafe(bob_dsid, CFSTR("Bob")), "Getting IDS device ID");
346 CFReleaseNull(bob_dsid);
347
348 is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates");
349
350 ok(SOSAccountEnsurePeerRegistration(alice_account, NULL), "ensure peer registration - alice");
351 ok(SOSAccountEnsurePeerRegistration(bob_account, NULL), "ensure peer registration - bob");
352
353 ids_test_sync(alice_account, bob_account);
354
355 alice_account = nil;
356 bob_account = nil;
357
358 SOSTestCleanup();
359
360
361 CFReleaseNull(changes);
362 }
363
364 int secd_201_coders(int argc, char *const *argv)
365 {
366 plan_tests(166);
367
368 secd_test_setup_temp_keychain(__FUNCTION__, NULL);
369
370 tests();
371
372 return 0;
373 }