]> git.saurik.com Git - apple/security.git/blob - sec/SOSCircle/Regressions/SOSRegressionUtilities.c
Security-55471.14.8.tar.gz
[apple/security.git] / sec / SOSCircle / Regressions / SOSRegressionUtilities.c
1 /*
2 * Copyright (c) 2012 Apple Computer, 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 void testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
126 {
127 testPutObjectInCloud(key, object, error, dgroup, processQueue);
128 testSynchronize(processQueue, dgroup);
129 }
130
131 void testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
132 {
133 secerror("testPutObjectInCloud: key: %@, %@", key, object);
134 CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, object, NULL);
135 if (objects)
136 {
137 dispatch_group_enter(dgroup);
138 SOSCloudKeychainPutObjectsInCloud(objects, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
139 {
140 secerror("testPutObjectInCloud returned: %@", returnedValues);
141 if (error)
142 {
143 secerror("testPutObjectInCloud returned: %@", error);
144 CFRelease(error);
145 }
146 dispatch_group_leave(dgroup);
147 });
148 CFRelease(objects);
149 }
150 }
151
152 CFTypeRef testGetObjectFromCloud(CFStringRef key, dispatch_queue_t processQueue, dispatch_group_t dgroup)
153 {
154 // TODO: make sure we return NULL, not CFNull
155 secerror("start");
156 CFMutableArrayRef keysToGet = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
157 CFArrayAppendValue(keysToGet, key);
158
159 __block CFTypeRef object = NULL;
160
161 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
162 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
163
164 dispatch_group_enter(dgroup);
165 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
166 {
167 secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
168 if (returnedValues)
169 {
170 object = (CFTypeRef)CFDictionaryGetValue(returnedValues, key);
171 if (object)
172 CFRetain(object);
173 }
174 if (error)
175 {
176 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
177 // CFRelease(*error);
178 }
179 dispatch_group_leave(dgroup);
180 secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
181 dispatch_semaphore_signal(waitSemaphore);
182 });
183
184 dispatch_semaphore_wait(waitSemaphore, finishTime);
185 dispatch_release(waitSemaphore);
186 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
187 {
188 CFRelease(object);
189 object = NULL;
190 }
191 secerror("returned: %@", object);
192 return object;
193 }
194
195 CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
196 {
197 __block CFTypeRef object = NULL;
198
199 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
200 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
201
202 dispatch_group_enter(dgroup);
203
204 CloudKeychainReplyBlock replyBlock =
205 ^ (CFDictionaryRef returnedValues, CFErrorRef error)
206 {
207 secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
208 object = returnedValues;
209 if (object)
210 CFRetain(object);
211 if (error)
212 {
213 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
214 // CFRelease(*error);
215 }
216 dispatch_group_leave(dgroup);
217 secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
218 dispatch_semaphore_signal(waitSemaphore);
219 };
220
221 if (!keysToGet)
222 SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
223 else
224 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
225
226 dispatch_semaphore_wait(waitSemaphore, finishTime);
227 dispatch_release(waitSemaphore);
228 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
229 {
230 CFRelease(object);
231 object = NULL;
232 }
233 secerror("returned: %@", object);
234 return object;
235 }
236
237 bool testRegisterKeys(CFArrayRef keysToRegister, dispatch_queue_t processQueue, dispatch_group_t dgroup)
238 {
239 __block bool result = false;
240
241 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
242 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
243
244 dispatch_group_enter(dgroup);
245 SOSCloudKeychainRegisterKeysAndGet(keysToRegister, processQueue,
246 ^ (CFDictionaryRef returnedValues, CFErrorRef error)
247 {
248 secerror("testRegisterKeys returned: %@", returnedValues);
249 if (error)
250 {
251 secerror("testRegisterKeys returned: %@", error);
252 CFRelease(error);
253 }
254 dispatch_group_leave(dgroup);
255 result = true;
256 dispatch_semaphore_signal(waitSemaphore);
257 },
258 ^ (CFDictionaryRef returnedValues)
259 {
260 secerror("testRegisterKeys returned: %@", returnedValues);
261 dispatch_group_leave(dgroup);
262 result = true;
263 dispatch_semaphore_signal(waitSemaphore);
264 });
265
266 dispatch_semaphore_wait(waitSemaphore, finishTime);
267 dispatch_release(waitSemaphore);
268 // printTimeNow("finished registerKeysForKVS");
269 return result;
270 }
271
272 bool testSynchronize(dispatch_queue_t processQueue, dispatch_group_t dgroup)
273 {
274 __block bool result = false;
275 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
276 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
277
278 dispatch_group_enter(dgroup);
279
280 SOSCloudKeychainSynchronize(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
281 {
282 result = true;
283 dispatch_group_leave(dgroup);
284 dispatch_semaphore_signal(waitSemaphore);
285 });
286
287 dispatch_semaphore_wait(waitSemaphore, finishTime);
288 dispatch_release(waitSemaphore);
289 return result;
290 }
291
292 bool testClearAll(dispatch_queue_t processQueue, dispatch_group_t dgroup)
293 {
294 __block bool result = false;
295 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
296 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
297
298 dispatch_group_enter(dgroup);
299
300 SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
301 {
302 result = true;
303 secerror("SOSCloudKeychainClearAll returned: %@", error);
304 dispatch_group_leave(dgroup);
305 dispatch_semaphore_signal(waitSemaphore);
306 });
307
308 dispatch_semaphore_wait(waitSemaphore, finishTime);
309 dispatch_release(waitSemaphore);
310 secerror("SOSCloudKeychainClearAll exit");
311 return result;
312 }
313
314 void unregisterFromKVSNotifications(const void *observer)
315 {
316 CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer);
317 }
318
319 //
320 // MARK: SOSPeerInfo creation helpers
321 //
322
323 CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name)
324 {
325 return CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
326 kPIUserDefinedDeviceName, name,
327 NULL);
328 }
329
330
331 SOSPeerInfoRef SOSCreatePeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
332 {
333 SOSPeerInfoRef result = NULL;
334 SecKeyRef publicKey = NULL;
335 CFDictionaryRef gestalt = NULL;
336
337 require(outSigningKey, exit);
338
339 GeneratePermanentECPair(256, &publicKey, outSigningKey);
340
341 gestalt = SOSCreatePeerGestaltFromName(name);
342 require(gestalt, exit);
343
344 result = SOSPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
345
346 exit:
347 CFReleaseNull(gestalt);
348 CFReleaseNull(publicKey);
349
350 return result;
351 }
352
353 SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
354 {
355 SOSFullPeerInfoRef result = NULL;
356 SecKeyRef publicKey = NULL;
357 CFDictionaryRef gestalt = NULL;
358
359 require(outSigningKey, exit);
360
361 GeneratePermanentECPair(256, &publicKey, outSigningKey);
362
363 gestalt = SOSCreatePeerGestaltFromName(name);
364 require(gestalt, exit);
365
366 result = SOSFullPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
367
368 exit:
369 CFReleaseNull(gestalt);
370 CFReleaseNull(publicKey);
371
372 return result;
373 }
374
375 // MARK: ----- MAC Address -----
376
377 /*
378 * Name: GetHardwareAdress
379 *
380 * Parameters: None.
381 *
382 * Returns: Nothing
383 *
384 * Description: Retrieve the hardare address for a specified network interface
385 *
386 */
387
388 #include <stdlib.h>
389 #include <string.h>
390
391 #include <sys/socket.h>
392 #include <netinet/in.h>
393 #include <sys/sysctl.h>
394 #include <net/if.h>
395 #include <net/if_dl.h>
396 #include <net/route.h>
397
398 #include <unistd.h>
399 #include <netdb.h>
400 #include <sys/stat.h>
401
402 static int getHardwareAddress(const char *interfaceName, size_t maxLenAllowed, size_t *outActualLength, char *outHardwareAddress)
403 {
404 char *end;
405 struct if_msghdr *ifm;
406 struct sockaddr_dl *sdl;
407 char *buf;
408 int result;
409 size_t buffSize;
410 int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
411
412 buf = 0;
413 *outActualLength = 0;
414 result = -1;
415 // see how much space is needed
416 require_noerr(result = sysctl(mib, 6, NULL, &buffSize, NULL, 0), xit);
417
418 // allocate the buffer
419 require(buf = malloc(buffSize), xit);
420
421 // get the interface info
422 require_noerr(result = sysctl(mib, 6, buf, &buffSize, NULL, 0), xit);
423
424 ifm = (struct if_msghdr *) buf;
425 end = buf + buffSize;
426 do
427 {
428 if (ifm->ifm_type == RTM_IFINFO) // should always be true
429 {
430 sdl = (struct sockaddr_dl *) (ifm + 1);
431 if ( sdl->sdl_nlen == strlen( interfaceName ) && ( bcmp( sdl->sdl_data, interfaceName, sdl->sdl_nlen ) == 0 ) )
432 {
433 if ( sdl->sdl_alen > 0 )
434 {
435 size_t hardwareLen;
436
437 result = 0; // indicate found the interface
438 hardwareLen = sdl->sdl_alen;
439 if ( hardwareLen > maxLenAllowed )
440 {
441 hardwareLen = maxLenAllowed;
442 result = -2; // indicate truncation of the address
443 }
444 memcpy( outHardwareAddress, sdl->sdl_data + sdl->sdl_nlen, hardwareLen );
445 *outActualLength = hardwareLen;
446 break;
447
448 }
449 }
450 }
451 ifm = (struct if_msghdr *) ((char*)ifm + ifm->ifm_msglen);
452 } while ( (char*)ifm < end );
453
454 xit:
455 if (buf)
456 free(buf);
457
458 return result;
459 }
460
461 // MARK: ----- cloudTransportTests -----
462
463 CFStringRef myMacAddress(void)
464 {
465 // 6 bytes, no ":"s
466 CFStringRef result = NULL;
467 const char *interfaceName = "en0";
468 size_t maxLenAllowed = 1024;
469 size_t outActualLength = 0;
470 char outHardwareAddress[1024];
471
472 require_noerr(getHardwareAddress(interfaceName, maxLenAllowed, &outActualLength, outHardwareAddress), xit);
473 require(outActualLength==6, xit);
474 unsigned char buf[32]={0,};
475
476 unsigned char *ps = (unsigned char *)buf;
477 unsigned char *pa = (unsigned char *)outHardwareAddress;
478 for (int ix = 0; ix < 6; ix++, pa++)
479 ps += sprintf((char *)ps, "%02x", *pa);
480
481 result = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)buf, kCFStringEncodingUTF8);
482
483 xit:
484 return result;
485 }