]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / SOSCircle / Regressions / SOSRegressionUtilities.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 // SOSRegressionUtilities.c
26 //
27
28 #include <AssertMacros.h>
29 #include <stdio.h>
30 #include <Security/SecItem.h>
31
32 #include <utilities/SecCFWrappers.h>
33 #include <utilities/debugging.h>
34
35 #include <SecureObjectSync/SOSAccount.h>
36 #include <SecureObjectSync/SOSCircle.h>
37 #include <SecureObjectSync/SOSInternal.h>
38 #include <SecureObjectSync/SOSPeerInfoInternal.h>
39
40 #include <SOSCloudKeychainClient.h>
41 #include "SOSRegressionUtilities.h"
42 #include "SOSInternal.h"
43
44 #if TARGET_OS_IPHONE
45 #include <MobileGestalt.h>
46 #endif
47
48 static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
49
50 // MARK: ----- SOS General -----
51
52 const char *cloudKeychainProxyPath = "/System/Library/Frameworks/Security.framework/Resources/CloudKeychainProxy.bundle/CloudKeychainProxy";
53
54 static const char *basecfabsoluteTimeToString(CFAbsoluteTime abstime, CFTimeZoneRef tz)
55 {
56 CFGregorianDate greg = CFAbsoluteTimeGetGregorianDate(abstime, NULL);
57 char str[20];
58 if (19 != snprintf(str, 20, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d",
59 (int)greg.year, greg.month, greg.day, greg.hour, greg.minute, (int)greg.second))
60 str[0]=0;
61 char *data = (char *)malloc(20);
62 strncpy(data, str, 20);
63 return data;
64 }
65
66 const char *cfabsoluteTimeToString(CFAbsoluteTime abstime)
67 {
68 return basecfabsoluteTimeToString(abstime, NULL);
69 }
70
71 const char *cfabsoluteTimeToStringLocal(CFAbsoluteTime abstime)
72 {
73 // Caller must release using free
74 CFDateFormatterRef formatter = NULL;
75 CFTimeZoneRef tz = NULL;
76 CFLocaleRef locale = NULL;
77 CFDateRef date = NULL;
78 CFStringRef cftime_string = NULL;
79 char *time_string = NULL;
80 char buffer[1024] = {0,};
81 size_t sz;
82
83 require(tz = CFTimeZoneCopySystem(), xit);
84 require(locale = CFLocaleCreate(NULL, CFSTR("en_US")), xit);
85
86 require(formatter = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterShortStyle), xit);
87 CFDateFormatterSetFormat(formatter, CFSTR("MM/dd/yy HH:mm:ss.SSS zzz"));
88 require(date = CFDateCreate(kCFAllocatorDefault, abstime), xit);
89 require(cftime_string = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatter, date), xit);
90
91 CFStringGetCString(cftime_string, buffer, 1024, kCFStringEncodingUTF8);
92 sz = strnlen(buffer, 1024);
93 time_string = (char *)malloc(sz);
94 strncpy(time_string, buffer, sz+1);
95 xit:
96 CFReleaseSafe(tz);
97 CFReleaseSafe(formatter);
98 CFReleaseSafe(locale);
99 CFReleaseSafe(date);
100 CFReleaseSafe(cftime_string);
101 return time_string;
102 }
103
104 #include <sys/stat.h>
105
106 static int file_exist (const char *filename)
107 {
108 struct stat buffer;
109 return (stat (filename, &buffer) == 0);
110 }
111
112 bool XPCServiceInstalled(void)
113 {
114 return file_exist(cloudKeychainProxyPath);
115 }
116
117 void registerForKVSNotifications(const void *observer, CFStringRef name, CFNotificationCallback callBack)
118 {
119 // observer is basically a context; name may not be null
120 CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
121 CFNotificationSuspensionBehavior suspensionBehavior = CFNotificationSuspensionBehaviorDeliverImmediately; //ignored?
122 CFNotificationCenterAddObserver(center, observer, callBack, name, NULL, suspensionBehavior);
123 }
124
125 bool testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
126 {
127 bool result = testPutObjectInCloud(key, object, error, dgroup, processQueue);
128 testSynchronize(processQueue, dgroup);
129
130 return result;
131 }
132
133 bool testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
134 {
135 secerror("testPutObjectInCloud: key: %@, %@", key, object);
136 CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, object, NULL);
137 if (objects)
138 {
139 dispatch_group_enter(dgroup);
140 SOSCloudKeychainPutObjectsInCloud(objects, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
141 {
142 secerror("testPutObjectInCloud returned: %@", returnedValues);
143 if (error)
144 {
145 secerror("testPutObjectInCloud returned: %@", error);
146 CFRelease(error);
147 }
148 dispatch_group_leave(dgroup);
149 });
150 CFRelease(objects);
151 }
152
153 return true;
154 }
155
156 CFTypeRef testGetObjectFromCloud(CFStringRef key, dispatch_queue_t processQueue, dispatch_group_t dgroup)
157 {
158 // TODO: make sure we return NULL, not CFNull
159 secerror("start");
160 CFMutableArrayRef keysToGet = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
161 CFArrayAppendValue(keysToGet, key);
162
163 __block CFTypeRef object = NULL;
164
165 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
166 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
167
168 dispatch_group_enter(dgroup);
169 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
170 {
171 secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
172 if (returnedValues)
173 {
174 object = (CFTypeRef)CFDictionaryGetValue(returnedValues, key);
175 if (object)
176 CFRetain(object);
177 }
178 if (error)
179 {
180 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
181 // CFRelease(*error);
182 }
183 dispatch_group_leave(dgroup);
184 secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
185 dispatch_semaphore_signal(waitSemaphore);
186 });
187
188 dispatch_semaphore_wait(waitSemaphore, finishTime);
189 dispatch_release(waitSemaphore);
190 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
191 {
192 CFRelease(object);
193 object = NULL;
194 }
195 secerror("returned: %@", object);
196 return object;
197 }
198
199 CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
200 {
201 __block CFTypeRef object = NULL;
202
203 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
204 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
205
206 dispatch_group_enter(dgroup);
207
208 CloudKeychainReplyBlock replyBlock =
209 ^ (CFDictionaryRef returnedValues, CFErrorRef error)
210 {
211 secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
212 object = returnedValues;
213 if (object)
214 CFRetain(object);
215 if (error)
216 {
217 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
218 // CFRelease(*error);
219 }
220 dispatch_group_leave(dgroup);
221 secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
222 dispatch_semaphore_signal(waitSemaphore);
223 };
224
225 if (!keysToGet)
226 SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
227 else
228 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
229
230 dispatch_semaphore_wait(waitSemaphore, finishTime);
231 dispatch_release(waitSemaphore);
232 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
233 {
234 CFRelease(object);
235 object = NULL;
236 }
237 secerror("returned: %@", object);
238 return object;
239 }
240
241 bool testSynchronize(dispatch_queue_t processQueue, dispatch_group_t dgroup)
242 {
243 __block bool result = false;
244 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
245 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
246
247 dispatch_group_enter(dgroup);
248
249 SOSCloudKeychainSynchronize(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
250 {
251 result = true;
252 dispatch_group_leave(dgroup);
253 dispatch_semaphore_signal(waitSemaphore);
254 });
255
256 dispatch_semaphore_wait(waitSemaphore, finishTime);
257 dispatch_release(waitSemaphore);
258 return result;
259 }
260
261 bool testClearAll(dispatch_queue_t processQueue, dispatch_group_t dgroup)
262 {
263 __block bool result = false;
264 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
265 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
266
267 dispatch_group_enter(dgroup);
268
269 SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
270 {
271 result = true;
272 secerror("SOSCloudKeychainClearAll returned: %@", error);
273 dispatch_group_leave(dgroup);
274 dispatch_semaphore_signal(waitSemaphore);
275 });
276
277 dispatch_semaphore_wait(waitSemaphore, finishTime);
278 dispatch_release(waitSemaphore);
279 secerror("SOSCloudKeychainClearAll exit");
280 return result;
281 }
282
283 void unregisterFromKVSNotifications(const void *observer)
284 {
285 CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer);
286 }
287
288 //
289 // MARK: SOSPeerInfo creation helpers
290 //
291
292 CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name)
293 {
294 return CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
295 kPIUserDefinedDeviceName, name,
296 NULL);
297 }
298
299
300 SOSPeerInfoRef SOSCreatePeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
301 {
302 SOSPeerInfoRef result = NULL;
303 SecKeyRef publicKey = NULL;
304 CFDictionaryRef gestalt = NULL;
305
306 require(outSigningKey, exit);
307
308 GeneratePermanentECPair(256, &publicKey, outSigningKey);
309
310 gestalt = SOSCreatePeerGestaltFromName(name);
311 require(gestalt, exit);
312
313 result = SOSPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
314
315 exit:
316 CFReleaseNull(gestalt);
317 CFReleaseNull(publicKey);
318
319 return result;
320 }
321
322 SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
323 {
324 SOSFullPeerInfoRef result = NULL;
325 SecKeyRef publicKey = NULL;
326 CFDictionaryRef gestalt = NULL;
327
328 require(outSigningKey, exit);
329
330 GeneratePermanentECPair(256, &publicKey, outSigningKey);
331
332 gestalt = SOSCreatePeerGestaltFromName(name);
333 require(gestalt, exit);
334
335 result = SOSFullPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
336
337 exit:
338 CFReleaseNull(gestalt);
339 CFReleaseNull(publicKey);
340
341 return result;
342 }
343
344 // MARK: ----- MAC Address -----
345
346 /*
347 * Name: GetHardwareAdress
348 *
349 * Parameters: None.
350 *
351 * Returns: Nothing
352 *
353 * Description: Retrieve the hardare address for a specified network interface
354 *
355 */
356
357 #include <stdlib.h>
358 #include <string.h>
359
360 #include <sys/socket.h>
361 #include <netinet/in.h>
362 #include <sys/sysctl.h>
363 #include <net/if.h>
364 #include <net/if_dl.h>
365 #include <net/route.h>
366
367 #include <unistd.h>
368 #include <netdb.h>
369 #include <sys/stat.h>
370
371 static int getHardwareAddress(const char *interfaceName, size_t maxLenAllowed, size_t *outActualLength, char *outHardwareAddress)
372 {
373 char *end;
374 struct if_msghdr *ifm;
375 struct sockaddr_dl *sdl;
376 char *buf;
377 int result = -1;
378 size_t buffSize;
379 int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
380
381 buf = 0;
382 *outActualLength = 0;
383 // see how much space is needed
384 require_noerr(result = sysctl(mib, 6, NULL, &buffSize, NULL, 0), xit);
385
386 // allocate the buffer
387 require(buf = malloc(buffSize), xit);
388
389 // get the interface info
390 require_noerr(result = sysctl(mib, 6, buf, &buffSize, NULL, 0), xit);
391
392 ifm = (struct if_msghdr *) buf;
393 end = buf + buffSize;
394 do
395 {
396 if (ifm->ifm_type == RTM_IFINFO) // should always be true
397 {
398 sdl = (struct sockaddr_dl *) (ifm + 1);
399 if ( sdl->sdl_nlen == strlen( interfaceName ) && ( bcmp( sdl->sdl_data, interfaceName, sdl->sdl_nlen ) == 0 ) )
400 {
401 if ( sdl->sdl_alen > 0 )
402 {
403 size_t hardwareLen;
404
405 result = 0; // indicate found the interface
406 hardwareLen = sdl->sdl_alen;
407 if ( hardwareLen > maxLenAllowed )
408 {
409 hardwareLen = maxLenAllowed;
410 result = -2; // indicate truncation of the address
411 }
412 memcpy( outHardwareAddress, sdl->sdl_data + sdl->sdl_nlen, hardwareLen );
413 *outActualLength = hardwareLen;
414 break;
415
416 }
417 }
418 }
419 ifm = (struct if_msghdr *) ((char*)ifm + ifm->ifm_msglen);
420 } while ( (char*)ifm < end );
421
422 xit:
423 if (buf)
424 free(buf);
425
426 return result;
427 }
428
429 // MARK: ----- cloudTransportTests -----
430
431 CFStringRef myMacAddress(void)
432 {
433 // 6 bytes, no ":"s
434 CFStringRef result = NULL;
435 const char *interfaceName = "en0";
436 size_t maxLenAllowed = 1024;
437 size_t outActualLength = 0;
438 char outHardwareAddress[1024];
439
440 require_noerr(getHardwareAddress(interfaceName, maxLenAllowed, &outActualLength, outHardwareAddress), xit);
441 require(outActualLength==6, xit);
442 unsigned char buf[32]={0,};
443
444 unsigned char *ps = (unsigned char *)buf;
445 unsigned char *pa = (unsigned char *)outHardwareAddress;
446 for (int ix = 0; ix < 6; ix++, pa++)
447 ps += sprintf((char *)ps, "%02x", *pa);
448
449 result = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)buf, kCFStringEncodingUTF8);
450
451 xit:
452 return result;
453 }