]> git.saurik.com Git - apple/security.git/blobdiff - sec/SOSCircle/Regressions/SOSRegressionUtilities.c
Security-55471.tar.gz
[apple/security.git] / sec / SOSCircle / Regressions / SOSRegressionUtilities.c
diff --git a/sec/SOSCircle/Regressions/SOSRegressionUtilities.c b/sec/SOSCircle/Regressions/SOSRegressionUtilities.c
new file mode 100644 (file)
index 0000000..6c7729d
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+//
+//  SOSRegressionUtilities.c
+//
+
+#include <AssertMacros.h>
+#include <stdio.h>
+#include <Security/SecItem.h>
+
+#include <utilities/SecCFWrappers.h>
+#include <utilities/debugging.h>
+
+#include <SecureObjectSync/SOSAccount.h>
+#include <SecureObjectSync/SOSCircle.h>
+#include <SecureObjectSync/SOSInternal.h>
+#include <SecureObjectSync/SOSPeerInfoInternal.h>
+
+#include <SOSCloudKeychainClient.h>
+#include "SOSRegressionUtilities.h"
+#include "SOSInternal.h"
+
+#if TARGET_OS_IPHONE
+#include <MobileGestalt.h>
+#endif
+
+static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
+
+// MARK: ----- SOS General -----
+
+const char *cloudKeychainProxyPath = "/System/Library/Frameworks/Security.framework/Resources/CloudKeychainProxy.bundle/CloudKeychainProxy";
+
+static const char *basecfabsoluteTimeToString(CFAbsoluteTime abstime, CFTimeZoneRef tz)
+{
+    CFGregorianDate greg = CFAbsoluteTimeGetGregorianDate(abstime, NULL);
+    char str[20];
+    if (19 != snprintf(str, 20, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d",
+        (int)greg.year, greg.month, greg.day, greg.hour, greg.minute, (int)greg.second))
+        str[0]=0;
+    char *data = (char *)malloc(20);
+    strncpy(data, str, 20);
+    return data;
+}
+
+const char *cfabsoluteTimeToString(CFAbsoluteTime abstime)
+{
+    return basecfabsoluteTimeToString(abstime, NULL);
+}
+
+const char *cfabsoluteTimeToStringLocal(CFAbsoluteTime abstime)
+{
+    // Caller must release using free
+    CFDateFormatterRef formatter = NULL;
+    CFTimeZoneRef tz = NULL;
+       CFLocaleRef locale = NULL;
+    CFDateRef date = NULL;
+    CFStringRef cftime_string = NULL;
+    char *time_string = NULL;
+    char buffer[1024] = {0,};
+    size_t sz;
+    
+    require(tz = CFTimeZoneCopySystem(), xit);
+    require(locale = CFLocaleCreate(NULL, CFSTR("en_US")), xit);
+    
+    require(formatter = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterShortStyle), xit);
+    CFDateFormatterSetFormat(formatter, CFSTR("MM/dd/yy HH:mm:ss.SSS zzz"));
+    require(date = CFDateCreate(kCFAllocatorDefault, abstime), xit);
+    require(cftime_string = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatter, date), xit);
+
+    CFStringGetCString(cftime_string, buffer, 1024, kCFStringEncodingUTF8);
+    sz = strnlen(buffer, 1024);
+    time_string = (char *)malloc(sz);
+    strncpy(time_string, buffer, sz+1);
+xit:
+    CFReleaseSafe(tz);
+    CFReleaseSafe(formatter);
+    CFReleaseSafe(locale);
+    CFReleaseSafe(date);
+    CFReleaseSafe(cftime_string);
+    return time_string;
+}
+
+#include <sys/stat.h>
+
+static int file_exist (const char *filename)
+{
+    struct stat buffer;   
+    return (stat (filename, &buffer) == 0);
+}
+
+bool XPCServiceInstalled(void)
+{
+    return file_exist(cloudKeychainProxyPath);
+}
+
+void registerForKVSNotifications(const void *observer, CFStringRef name, CFNotificationCallback callBack)
+{
+    // observer is basically a context; name may not be null
+    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
+    CFNotificationSuspensionBehavior suspensionBehavior = CFNotificationSuspensionBehaviorDeliverImmediately;    //ignored?
+    CFNotificationCenterAddObserver(center, observer, callBack, name, NULL, suspensionBehavior);
+}
+
+void testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
+{
+    testPutObjectInCloud(key, object, error, dgroup, processQueue);
+    testSynchronize(processQueue, dgroup);
+}
+
+void testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue)
+{
+    secerror("testPutObjectInCloud: key: %@, %@", key, object);
+    CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, object, NULL);
+    if (objects)
+    {
+        dispatch_group_enter(dgroup);
+        SOSCloudKeychainPutObjectsInCloud(objects, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
+        {
+            secerror("testPutObjectInCloud returned: %@", returnedValues);
+            if (error)
+            {
+                secerror("testPutObjectInCloud returned: %@", error);
+                CFRelease(error);
+            }
+            dispatch_group_leave(dgroup);
+        });
+        CFRelease(objects);
+    }    
+}
+
+CFTypeRef testGetObjectFromCloud(CFStringRef key, dispatch_queue_t processQueue, dispatch_group_t dgroup)
+{
+    // TODO: make sure we return NULL, not CFNull
+    secerror("start");
+    CFMutableArrayRef keysToGet = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
+    CFArrayAppendValue(keysToGet, key);
+
+    __block CFTypeRef object = NULL;
+
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
+
+    dispatch_group_enter(dgroup);
+    SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error)
+    {
+        secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
+        if (returnedValues)
+        {
+            object = (CFTypeRef)CFDictionaryGetValue(returnedValues, key);
+            if (object)
+                CFRetain(object);
+        }
+        if (error)
+        {
+            secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
+     //       CFRelease(*error);
+        }
+        dispatch_group_leave(dgroup);
+        secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
+        dispatch_semaphore_signal(waitSemaphore);
+    });
+    
+       dispatch_semaphore_wait(waitSemaphore, finishTime);
+       dispatch_release(waitSemaphore);
+    if (object && (CFGetTypeID(object) == CFNullGetTypeID()))   // return a NULL instead of a CFNull
+    {
+        CFRelease(object);
+        object = NULL;
+    }
+    secerror("returned: %@", object);
+    return object;
+}
+
+CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
+{
+    __block CFTypeRef object = NULL;
+
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
+
+    dispatch_group_enter(dgroup);
+    
+    CloudKeychainReplyBlock replyBlock =
+        ^ (CFDictionaryRef returnedValues, CFErrorRef error)
+    {
+        secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
+        object = returnedValues;
+        if (object)
+            CFRetain(object);
+        if (error)
+        {
+            secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
+     //       CFRelease(*error);
+        }
+        dispatch_group_leave(dgroup);
+        secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
+        dispatch_semaphore_signal(waitSemaphore);
+    };
+    
+    if (!keysToGet)
+        SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
+    else
+        SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
+    
+       dispatch_semaphore_wait(waitSemaphore, finishTime);
+       dispatch_release(waitSemaphore);
+    if (object && (CFGetTypeID(object) == CFNullGetTypeID()))   // return a NULL instead of a CFNull
+    {
+        CFRelease(object);
+        object = NULL;
+    }
+    secerror("returned: %@", object);
+    return object;
+}
+
+bool testRegisterKeys(CFArrayRef keysToRegister, dispatch_queue_t processQueue, dispatch_group_t dgroup)
+{
+    __block bool result = false;
+
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
+
+        dispatch_group_enter(dgroup);
+    SOSCloudKeychainRegisterKeysAndGet(keysToRegister, processQueue,
+            ^ (CFDictionaryRef returnedValues, CFErrorRef error)
+            {
+                secerror("testRegisterKeys returned: %@", returnedValues);
+                if (error)
+                {
+                secerror("testRegisterKeys returned: %@", error);
+                CFRelease(error);
+                }
+                dispatch_group_leave(dgroup);
+                result = true;
+            dispatch_semaphore_signal(waitSemaphore);
+            },
+           ^ (CFDictionaryRef returnedValues)
+           {
+               secerror("testRegisterKeys returned: %@", returnedValues);
+               dispatch_group_leave(dgroup);
+               result = true;
+               dispatch_semaphore_signal(waitSemaphore);
+           });
+
+       dispatch_semaphore_wait(waitSemaphore, finishTime);
+       dispatch_release(waitSemaphore);
+//    printTimeNow("finished registerKeysForKVS");
+    return result;
+}
+
+bool testSynchronize(dispatch_queue_t processQueue, dispatch_group_t dgroup)
+{
+    __block bool result = false;
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
+
+    dispatch_group_enter(dgroup);
+
+    SOSCloudKeychainSynchronize(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
+        {
+            result = true;
+            dispatch_group_leave(dgroup);
+            dispatch_semaphore_signal(waitSemaphore);
+        });
+    
+       dispatch_semaphore_wait(waitSemaphore, finishTime);
+       dispatch_release(waitSemaphore);
+    return result;
+}
+
+bool testClearAll(dispatch_queue_t processQueue, dispatch_group_t dgroup)
+{
+    __block bool result = false;
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
+
+    dispatch_group_enter(dgroup);
+
+    SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error)
+        {
+            result = true;
+            secerror("SOSCloudKeychainClearAll returned: %@", error);
+            dispatch_group_leave(dgroup);
+            dispatch_semaphore_signal(waitSemaphore);
+        });
+    
+       dispatch_semaphore_wait(waitSemaphore, finishTime);
+       dispatch_release(waitSemaphore);
+    secerror("SOSCloudKeychainClearAll exit");
+    return result;
+}
+
+void unregisterFromKVSNotifications(const void *observer)
+{
+    CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer);
+}
+
+//
+// MARK: SOSPeerInfo creation helpers
+//
+
+CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name)
+{
+    return CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
+                                        kPIUserDefinedDeviceName, name,
+                                        NULL);
+}
+
+
+SOSPeerInfoRef SOSCreatePeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
+{
+    SOSPeerInfoRef result = NULL;
+    SecKeyRef publicKey = NULL;
+    CFDictionaryRef gestalt = NULL;
+
+    require(outSigningKey, exit);
+
+    GeneratePermanentECPair(256, &publicKey, outSigningKey);
+
+    gestalt = SOSCreatePeerGestaltFromName(name);
+    require(gestalt, exit);
+
+    result = SOSPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
+
+exit:
+    CFReleaseNull(gestalt);
+    CFReleaseNull(publicKey);
+
+    return result;
+}
+
+SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef* outSigningKey, CFErrorRef *error)
+{
+    SOSFullPeerInfoRef result = NULL;
+    SecKeyRef publicKey = NULL;
+    CFDictionaryRef gestalt = NULL;
+
+    require(outSigningKey, exit);
+
+    GeneratePermanentECPair(256, &publicKey, outSigningKey);
+
+    gestalt = SOSCreatePeerGestaltFromName(name);
+    require(gestalt, exit);
+
+    result = SOSFullPeerInfoCreate(NULL, gestalt, *outSigningKey, error);
+
+exit:
+    CFReleaseNull(gestalt);
+    CFReleaseNull(publicKey);
+
+    return result;
+}
+
+// MARK: ----- MAC Address -----
+
+/*
+ *     Name:                   GetHardwareAdress
+ *
+ *     Parameters:             None.
+ *
+ *     Returns:                Nothing
+ *
+ *     Description:    Retrieve the hardare address for a specified network interface
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/stat.h>
+
+static int getHardwareAddress(const char *interfaceName, size_t maxLenAllowed, size_t *outActualLength, char *outHardwareAddress)
+{
+       char                            *end;
+       struct if_msghdr        *ifm;
+       struct sockaddr_dl      *sdl;
+       char                            *buf;
+       int                             result;
+       size_t                          buffSize;
+       int                                     mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
+       
+       buf = 0;
+       *outActualLength = 0;
+       result = -1;
+       //      see how much space is needed
+       require_noerr(result = sysctl(mib, 6, NULL, &buffSize, NULL, 0), xit);
+
+       //      allocate the buffer
+       require(buf = malloc(buffSize), xit);
+               
+       //      get the interface info  
+       require_noerr(result = sysctl(mib, 6, buf, &buffSize, NULL, 0), xit);
+    
+       ifm = (struct if_msghdr *) buf;
+       end = buf + buffSize;
+       do
+       {
+               if (ifm->ifm_type == RTM_IFINFO)                //      should always be true
+               {
+                       sdl = (struct sockaddr_dl *) (ifm + 1);
+                       if ( sdl->sdl_nlen == strlen( interfaceName ) && ( bcmp( sdl->sdl_data, interfaceName, sdl->sdl_nlen ) == 0 ) )
+                       {
+                               if (  sdl->sdl_alen > 0 )
+                               {
+                                       size_t hardwareLen;
+                                       
+                                       result = 0;                                             //      indicate found the interface
+                                       hardwareLen = sdl->sdl_alen;
+                                       if ( hardwareLen > maxLenAllowed )
+                                       {
+                                               hardwareLen = maxLenAllowed;
+                                               result = -2;                            //      indicate truncation of the address
+                                       } 
+                                       memcpy( outHardwareAddress, sdl->sdl_data + sdl->sdl_nlen, hardwareLen );
+                                       *outActualLength = hardwareLen;
+                                       break;
+                                       
+                               }       
+                       }       
+               }
+               ifm = (struct if_msghdr *)  ((char*)ifm + ifm->ifm_msglen);
+       } while ( (char*)ifm < end );
+       
+xit:
+       if (buf)
+               free(buf);
+
+       return result;  
+}
+
+// MARK: ----- cloudTransportTests -----
+
+CFStringRef myMacAddress(void)
+{
+    // 6 bytes, no ":"s
+    CFStringRef result = NULL;
+    const char *interfaceName = "en0";
+    size_t maxLenAllowed = 1024;
+    size_t outActualLength = 0;
+    char outHardwareAddress[1024];
+    
+    require_noerr(getHardwareAddress(interfaceName, maxLenAllowed, &outActualLength, outHardwareAddress), xit);
+    require(outActualLength==6, xit);
+    unsigned char buf[32]={0,};
+    
+    unsigned char *ps = (unsigned char *)buf;
+    unsigned char *pa = (unsigned char *)outHardwareAddress;
+    for (int ix = 0; ix < 6; ix++, pa++)
+        ps += sprintf((char *)ps, "%02x", *pa);
+
+    result = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)buf, kCFStringEncodingUTF8);
+    
+xit:
+    return result;    
+}