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 <AssertMacros.h> 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <unistd.h> 30#include <xpc/xpc.h> 31 32#include <Security/SecBase.h> 33#include <Security/SecItem.h> 34 35#include <SecureObjectSync/SOSAccount.h> 36#include <CKBridge/SOSCloudKeychainClient.h> 37 38#include <utilities/SecCFWrappers.h> 39#include <utilities/debugging.h> 40 41#include "SOSCircle_regressions.h" 42#include "SOSRegressionUtilities.h" 43 44 45static bool verboseCKDClientDebugging = false; 46 47static CFStringRef kTestKeyIDTimestamp = CFSTR("IDTimestamp"); 48static dispatch_group_t sDispatchGroup = NULL; 49static dispatch_queue_t xpc_queue = NULL; 50 51// MARK: ----- Test Data ----- 52 53static CFStringRef kTestKeyString = CFSTR("teststring"); 54static CFStringRef kTestKeyData = CFSTR("testdata"); 55static const UInt8 tdata[] = {0x01, 0x02, 0x03, 0x04, 'a', 'b', 'c'}; 56static CFStringRef kTestKeyArray = CFSTR("testarray"); 57static const CFStringRef adata[] = {CFSTR("A"), CFSTR("b"), CFSTR("C"), CFSTR("D")}; 58static const CFStringRef circleKeyStrings[] = {CFSTR("circleA"), CFSTR("circleB"), CFSTR("circleC"), CFSTR("circleD")}; 59static const CFStringRef keysWhenUnlockedKeyStrings[] = {CFSTR("foo"), CFSTR("bar"), CFSTR("baz")}; 60 61static CFDataRef testData = NULL; 62static CFArrayRef testArray = NULL; 63static CFArrayRef circleKeys = NULL; 64static CFArrayRef keysWhenUnlocked = NULL; 65 66static void initializeTestData(void) 67{ 68 testData = CFDataCreate(kCFAllocatorDefault, tdata, sizeof(tdata)/sizeof(UInt8)); 69 testArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&adata, sizeof(adata)/sizeof(CFStringRef), &kCFTypeArrayCallBacks); 70 // Register keys 71 circleKeys = CFArrayCreate(kCFAllocatorDefault, (const void **)&circleKeyStrings, sizeof(circleKeyStrings)/sizeof(CFStringRef), &kCFTypeArrayCallBacks); 72 keysWhenUnlocked = CFArrayCreate(kCFAllocatorDefault, (const void **)&keysWhenUnlockedKeyStrings, sizeof(keysWhenUnlockedKeyStrings)/sizeof(CFStringRef), 73 &kCFTypeArrayCallBacks); 74} 75 76// MARK: ----- utilities ----- 77 78static void printTimeNow(const char *msg) 79{ 80 if (verboseCKDClientDebugging) 81 { 82 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 83 const char *nowstr = cfabsoluteTimeToString(now); 84 if (nowstr) 85 { 86 printf("%s %s\n", nowstr, msg); 87 free((void *)nowstr); 88 } 89 } 90} 91 92// MARK: ----- basicKVSTests ----- 93 94static bool testPostGet(CFStringRef key, CFTypeRef cfobj, dispatch_queue_t processQueue, dispatch_group_t dgroup) 95{ 96 CFErrorRef error = NULL; 97 bool result = false; 98 CFTypeRef cfv = NULL; 99 100 testPutObjectInCloud(key, cfobj, &error, dgroup, processQueue); 101 CFTypeRef cfvalue = testGetObjectFromCloud(key, processQueue, dgroup); 102 printTimeNow("finished getObjectFromCloud"); 103 if (!cfvalue) 104 return false; 105 if (CFGetTypeID(cfvalue)==CFDictionaryGetTypeID()) 106 cfv = CFDictionaryGetValue(cfvalue, key); 107 else 108 cfv = cfvalue; 109 result = CFEqual(cfobj, cfv); 110 return result; 111} 112 113static bool postIDTimestamp(dispatch_queue_t theq, dispatch_group_t dgroup) 114{ 115 bool result = false; 116 CFStringRef macaddr = myMacAddress(); 117 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 118 const char *nowstr = cfabsoluteTimeToStringLocal(now); 119 CFStringRef cfidstr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@: %@ %s"), kTestKeyIDTimestamp, macaddr ,nowstr); 120 secerror("Setting %@ key: %@", kTestKeyIDTimestamp, cfidstr); 121 result = testPostGet(kTestKeyIDTimestamp, cfidstr, theq, dgroup); 122 123 if (nowstr) 124 free((void *)nowstr); 125 CFReleaseSafe(cfidstr); 126 return result; 127} 128 129 130static const int kbasicKVSTestsCount = 9; 131static void basicKVSTests(dispatch_group_t dgroup) 132{ 133 dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); 134 135 printTimeNow("Start tests [basicKVSTests]"); 136 // dispatch_group_enter(dgroup); 137 138 // synchronize first to make sure we see cloud values 139 ok(testSynchronize(generalq, dgroup), "test synchronize"); 140 141 // Next, get the TimeNow value, since this is the only one that differs from test to test (i.e. sc-90-ckdclient) 142 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 143 const char *nowstr = cfabsoluteTimeToStringLocal(now); 144 CFStringRef cfstrtime = CFStringCreateWithCString(kCFAllocatorDefault, nowstr, kCFStringEncodingUTF8); 145 ok(testGetObjectFromCloud(kTestKeyIDTimestamp, generalq, dgroup) != nil, "testGet for %@", kTestKeyIDTimestamp); 146 147 ok(postIDTimestamp(generalq, dgroup), "testPostGet for %@", kTestKeyIDTimestamp); 148 149 ok(testPostGet(kTestKeyString, CFSTR("test string"), generalq, dgroup), "testPostGet for CFStringRef"); 150 151 // Now the fixed values 152 ok(testPostGet(kTestKeyString, CFSTR("test string"), generalq, dgroup), "testPostGet for CFStringRef"); 153 ok(testPostGet(kTestKeyData, testData, generalq, dgroup), "testPostGet for CFDataRef"); 154 ok(testPostGet(kTestKeyArray, testArray, generalq, dgroup), "testPostGet for CFDataRef"); 155 156 ok(postIDTimestamp(generalq, dgroup), "testPostGet for %@", kTestKeyIDTimestamp); 157 158 // Synchronize one more time before exit 159 ok(testSynchronize(generalq, dgroup), "test synchronize"); 160/**/ 161 printTimeNow("End tests [basicKVSTests]"); 162 163// dispatch_group_leave(dgroup); 164 165 // Release test data 166 CFRelease(testData); 167 CFRelease(testArray); 168 CFRelease(circleKeys); 169 CFRelease(keysWhenUnlocked); 170 CFRelease(cfstrtime); 171 if (nowstr) 172 free((void *)nowstr); 173} 174 175// MARK: ----- start of all tests ----- 176 177static int kTestTestCount = kbasicKVSTestsCount; 178static void tests(void) 179{ 180 SKIP: { 181 skip("Skipping ckdclient tests because CloudKeychainProxy.xpc is not installed", kTestTestCount, XPCServiceInstalled()); 182 // dispatch_queue_t dqueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 183 xpc_queue = dispatch_queue_create("sc_90_ckdclient", DISPATCH_QUEUE_SERIAL); 184 185 sDispatchGroup = dispatch_group_create(); 186 187 initializeTestData(); 188 basicKVSTests(sDispatchGroup); 189 } 190} 191 192int sc_90_ckdclient(int argc, char *const *argv) 193{ 194 plan_tests(kTestTestCount); 195 196 tests(); 197 198 return 0; 199} 200 201 202