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