]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/Regressions/sc-75-circle-engine.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / SOSCircle / Regressions / sc-75-circle-engine.c
1 /*
2 * Copyright (c) 2012-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 #include <SecureObjectSync/SOSEngine.h>
26 #include <SecureObjectSync/SOSPeer.h>
27
28 #include "SOSCircle_regressions.h"
29
30 #include <corecrypto/ccsha2.h>
31
32 #include <utilities/SecCFWrappers.h>
33
34 #include <stdint.h>
35
36 #include <AssertMacros.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <CoreFoundation/CFDate.h>
42
43 #include <utilities/SecCFWrappers.h>
44
45 #include <Security/SecKey.h>
46
47 #include <SecureObjectSync/SOSPeerInfo.h>
48 #include <SecureObjectSync/SOSCircle.h>
49 #include <SecureObjectSync/SOSCloudCircle.h>
50 #include <SecureObjectSync/SOSInternal.h>
51 #include <SecureObjectSync/SOSUserKeygen.h>
52 #include <SecureObjectSync/SOSPeerCoder.h>
53 #include <SecureObjectSync/SOSTransportMessageKVS.h>
54 #include <SecureObjectSync/SOSTransportMessage.h>
55
56 #include <SecureObjectSync/SOSAccountPriv.h>
57
58 #include "SOSCircle_regressions.h"
59 #include "SOSRegressionUtilities.h"
60 #include "SOSTestDataSource.h"
61
62 #include <securityd/Regressions/SOSAccountTesting.h>
63 #include <securityd/Regressions/SOSTransportTestTransports.h>
64
65 #ifndef SEC_CONST_DECL
66 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
67 #endif
68
69 #include <securityd/SOSCloudCircleServer.h>
70
71
72 // MARK: ----- Constants -----
73
74 static CFStringRef circleKey = CFSTR("Circle");
75
76 static int kTestTestCount = 68;
77
78 static bool withEngine(SOSCircleRef circle, SOSDataSourceFactoryRef factory, bool readOnly, CFErrorRef *error, bool (^action)(SOSEngineRef engine, CFErrorRef *block_error)) {
79 bool success = false;
80 SOSDataSourceRef ds = NULL;
81 SOSEngineRef engine = NULL;
82
83 ds = factory->create_datasource(factory, SOSCircleGetName(circle), error);
84 require_quiet(ds, exit);
85
86 engine = SOSEngineCreate(ds, error); // Hand off DS to engine.
87 ds = NULL;
88 require_quiet(engine, exit);
89
90 success = action(engine, error);
91
92 exit:
93 if (engine)
94 SOSEngineDispose(engine);
95
96 return success;
97 }
98
99 static bool SOSCircleSyncWithPeer(SOSAccountRef account ,SOSFullPeerInfoRef myRef, SOSCircleRef circle, SOSDataSourceFactoryRef factory,
100 SOSPeerInfoRef peerInfo, CFErrorRef *error)
101 {
102 return withEngine(circle, factory, true, error, ^bool(SOSEngineRef engine, CFErrorRef *block_error) {
103 SOSPeerRef peer = SOSPeerCreate(engine, peerInfo, block_error);
104 if (!peer) return false;
105
106 CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
107 CFMutableArrayRef peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
108 CFArrayAppendValue(peer_ids, SOSPeerGetID(peer));
109 CFDictionaryAddValue(circleToPeerIDs, SOSCircleGetName(circle), peer_ids);
110
111 SOSTransportMessageRef transport = (SOSTransportMessageRef)CFDictionaryGetValue(SOSAccountGetMessageTransports(account), SOSCircleGetName(circle));
112
113 bool result = SOSTransportMessageSyncWithPeers(transport, circleToPeerIDs, error);
114 CFReleaseSafe(peer);
115 return result;
116 });
117 }
118
119 static bool SOSCircleHandlePeerMessage(SOSAccountRef account, SOSCircleRef circle, SOSFullPeerInfoRef myRef, SOSDataSourceFactoryRef factory,
120 SOSPeerInfoRef peerInfo, CFDataRef message, CFErrorRef *error) {
121
122 return withEngine(circle, factory, true, error, ^bool(SOSEngineRef engine, CFErrorRef *block_error) {
123 CFDataRef decodedMessage = NULL;
124 SOSPeerRef peer = SOSPeerCreate(engine, peerInfo, block_error);
125 if (!peer) return false;
126 CFDictionaryRef message_transports = (CFDictionaryRef)SOSAccountGetMessageTransports(account);
127 SOSTransportMessageRef transport = (SOSTransportMessageRef)CFDictionaryGetValue(message_transports, SOSCircleGetName(circle));
128 bool result = SOSTransportMessageHandlePeerMessage(transport, SOSPeerGetID(peer), message, error);
129
130 CFReleaseSafe(peer);
131 CFReleaseNull(decodedMessage);
132 return result;
133 });
134 }
135
136
137
138 static void tests()
139 {
140 CFErrorRef error = NULL;
141
142 CFStringRef aliceID = CFSTR("Alice");
143 CFStringRef bobID = CFSTR("Bob"); // not really remote, just another client on same machine
144
145 SecKeyRef alice_key = NULL;
146 SecKeyRef bob_key = NULL;
147
148 CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10);
149
150 CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error);
151 ok(parameters, "No parameters!");
152 ok(error == NULL, "Error: (%@)", error);
153 CFReleaseNull(error);
154
155 SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error);
156 CFReleaseNull(parameters);
157 CFReleaseSafe(cfpassword);
158
159 CFStringRef circleName = CFSTR("Woot Circle");
160 SOSAccountRef alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), circleName);
161 SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), circleName);
162
163
164 SOSFullPeerInfoRef alice_full_peer_info = SOSCreateFullPeerInfoFromName(aliceID, &alice_key, &error);
165 SOSPeerInfoRef alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info);
166
167 SOSFullPeerInfoRef bob_full_peer_info = SOSCreateFullPeerInfoFromName(bobID, &bob_key, &error);
168 SOSPeerInfoRef bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info);
169
170 SOSCircleRef aliceCircle = SOSCircleCreate(kCFAllocatorDefault, circleName, &error);
171
172 ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, alice_full_peer_info, &error));
173 ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, alice_full_peer_info, NULL));
174 ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, bob_full_peer_info, &error), "requested admission");
175 ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, bob_full_peer_info, &error), "accepted them all!");
176
177 alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info);
178 bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info);
179
180 CFDataRef aliceCircleEncoded;
181 ok(aliceCircleEncoded = SOSCircleCopyEncodedData(aliceCircle, kCFAllocatorDefault, &error), "encode alice circle: %@", error);
182 CFReleaseNull(error);
183 SOSCircleRef bobCircle;
184 ok(bobCircle = SOSCircleCreateFromData(0, aliceCircleEncoded, &error), "decode bobCircle: %@", error);
185 CFReleaseNull(aliceCircleEncoded);
186 CFReleaseNull(error);
187
188 SOSTransportMessageRef alice_message_transport = (SOSTransportMessageRef)CFDictionaryGetValue(SOSAccountGetMessageTransports(alice_account), circleName);
189 SOSTransportMessageRef bob_message_transport = (SOSTransportMessageRef)CFDictionaryGetValue(bob_account->message_transports, circleName);
190
191 ok(SOSPeerCoderInitializeForPeer(alice_message_transport, alice_full_peer_info, bob_peer_info, NULL));
192 ok(SOSPeerCoderInitializeForPeer(bob_message_transport, bob_full_peer_info, alice_peer_info, NULL));
193
194 SOSDataSourceFactoryRef aliceDsf = alice_account->factory;
195 SOSDataSourceFactoryRef bobDsf = bob_account->factory;
196
197 /* Test passing peer messages to the engine. */
198 CFDataRef message;
199
200 ok(SOSCircleSyncWithPeer(alice_account, alice_full_peer_info, aliceCircle, aliceDsf, bob_peer_info, &error), "Start sync [error %@]", error);
201 CFReleaseNull(error);
202
203 ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "Alice sent message");
204 CFDictionaryRef changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport);
205 CFDictionaryRef peer_dict = CFDictionaryGetValue(changes, circleName);
206 message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info));
207 is(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), true,
208 "Bob accepted message: %@", error);
209
210 is(SOSCircleSyncWithPeer(bob_account, bob_full_peer_info, bobCircle, bobDsf, alice_peer_info, &error), true, "Bob sent response");
211 CFReleaseNull(error);
212
213 #if 1
214 ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport)) != 0, "we got a message from Bob");
215 changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport);
216 peer_dict = CFDictionaryGetValue(changes, circleName);
217 message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(alice_peer_info));
218
219 ok(SOSCircleHandlePeerMessage(alice_account, aliceCircle, alice_full_peer_info, aliceDsf, bob_peer_info, message, &error),
220 "Alice accepted message: %@", error);
221
222 ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "we got a reply from Alice");
223 changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport);
224 peer_dict = CFDictionaryGetValue(changes, circleName);
225 message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info));
226 ok(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error),
227 "Bob accepted message: %@", error);
228 #endif
229
230 #if 0
231 SOSDataSourceRef aliceDs = aliceDsf->create_datasource(aliceDsf, circleName, NULL);
232 ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport)) == 0, "we got no message from Bob");
233
234 SOSObjectRef object = SOSDataSourceCreateGenericItem(aliceDs, CFSTR("75_circle_engine_account"), CFSTR("test service"));
235 ok(SOSTestDataSourceAddObject(aliceDs, object, &error), "add empty object to datasource: %@", error);
236 CFReleaseNull(error);
237 CFReleaseNull(object);
238
239 ok(SOSCircleSyncWithPeer(alice_account, alice_full_peer_info, aliceCircle, aliceDsf, bob_peer_info, &error), "Restart sync [error %@]", error);
240 CFReleaseNull(error);
241
242 ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "Alice started again");
243 changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport);
244 peer_dict = CFDictionaryGetValue(changes, circleName);
245 message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info));
246
247 is(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), true,
248 "bob accepted %@", message);
249 CFReleaseNull(error);
250 #endif
251
252 #if 1
253 bool alice = true;
254 int max_loops = 50;
255 changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport);
256 while (max_loops-- && (CFDictionaryGetCount(changes) != 0)) {
257 peer_dict = CFDictionaryGetValue(changes, circleName);
258 message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info));
259 if (alice) {
260 ok(SOSCircleHandlePeerMessage(alice_account, aliceCircle, alice_full_peer_info, aliceDsf, bob_peer_info, message, &error),
261 "alice accepted %@: %@", message, error);
262 } else {
263 ok(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error),
264 "bob accepted %@: %@", message, error);
265 }
266 alice = !alice;
267 }
268 #endif
269
270 CFReleaseNull(aliceCircle);
271 CFReleaseNull(bobCircle);
272
273 CFReleaseNull(alice_peer_info);
274 CFReleaseNull(bob_peer_info);
275
276 aliceDsf->release(aliceDsf);
277 bobDsf->release(bobDsf);
278
279 SOSUnregisterAllTransportMessages();
280 SOSUnregisterAllTransportCircles();
281 SOSUnregisterAllTransportKeyParameters();
282 CFArrayRemoveAllValues(key_transports);
283 CFArrayRemoveAllValues(circle_transports);
284 CFArrayRemoveAllValues(message_transports);
285 }
286
287 // MARK: ----- start of all tests -----
288
289 int sc_75_circle_engine(int argc, char *const *argv)
290 {
291 plan_tests(kTestTestCount);
292
293 tests();
294
295 return 0;
296 }