1/* 2 * Copyright (c) 2013-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 "secd_regressions.h" 26 27#include <securityd/SecDbItem.h> 28#include <utilities/array_size.h> 29#include <utilities/SecCFWrappers.h> 30#include <utilities/SecFileLocations.h> 31#include <utilities/fileIo.h> 32 33#include <securityd/SOSCloudCircleServer.h> 34#include <securityd/SecItemServer.h> 35 36#include <Security/SecBasePriv.h> 37 38#include <TargetConditionals.h> 39#include <AssertMacros.h> 40 41#include <stdio.h> 42#include <unistd.h> 43#include <sys/stat.h> 44#include <pthread.h> 45 46#if TARGET_OS_IPHONE && USE_KEYSTORE 47#include <libaks.h> 48 49#include "SecdTestKeychainUtilities.h" 50 51#include "ios6_1_keychain_2_db.h" 52 53static OSStatus query_one(void) 54{ 55 OSStatus ok; 56 57 /* querying a password */ 58 const void *keys[] = { 59 kSecClass, 60 kSecAttrServer, 61 }; 62 const void *values[] = { 63 kSecClassInternetPassword, 64 CFSTR("members.spamcop.net"), 65 }; 66 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 67 array_size(keys), NULL, NULL); 68 CFTypeRef results = NULL; 69 70 ok = SecItemCopyMatching(query, &results); 71 72 CFReleaseSafe(results); 73 CFReleaseSafe(query); 74 75 return ok; 76} 77 78 79 80static void *do_query(void *arg) 81{ 82 /* querying a password */ 83 const void *keys[] = { 84 kSecClass, 85 kSecAttrServer, 86 }; 87 const void *values[] = { 88 kSecClassInternetPassword, 89 CFSTR("members.spamcop.net"), 90 }; 91 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 92 array_size(keys), NULL, NULL); 93 CFTypeRef results = NULL; 94 95 for(int i=0;i<20;i++) 96 verify_action(SecItemCopyMatching(query, &results)==errSecUpgradePending, CFReleaseSafe(query); return (void *)-1); 97 98 CFReleaseSafe(query); 99 100 return NULL; 101} 102 103static void *do_sos(void *arg) 104{ 105 106 for(int i=0;i<20;i++) 107 verify_action(SOSCCThisDeviceIsInCircle_Server(NULL)==-1, return (void *)-1); 108 109 return NULL; 110} 111 112 113#define N_THREADS 10 114 115int secd_02_upgrade_while_locked(int argc, char *const *argv) 116{ 117 plan_tests(11 + N_THREADS + kSecdTestSetupTestCount); 118 119 __block keybag_handle_t keybag; 120 __block keybag_state_t state; 121 char *passcode="password"; 122 int passcode_len=(int)strlen(passcode); 123 124 /* custom keychain dir */ 125 secd_test_setup_temp_keychain("secd_02_upgrade_while_locked", ^{ 126 CFStringRef keychain_path_cf = __SecKeychainCopyPath(); 127 128 CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { 129 writeFile(keychain_path, ios6_1_keychain_2_db, ios6_1_keychain_2_db_len); 130 131 /* custom notification */ 132 SecItemServerSetKeychainChangedNotification("com.apple.secdtests.keychainchanged"); 133 134 /* Create and lock custom keybag */ 135 ok(kIOReturnSuccess==aks_create_bag(passcode, passcode_len, kAppleKeyStoreDeviceBag, &keybag), "create keybag"); 136 ok(kIOReturnSuccess==aks_get_lock_state(keybag, &state), "get keybag state"); 137 ok(!(state&keybag_state_locked), "keybag unlocked"); 138 SecItemServerSetKeychainKeybag(keybag); 139 140 /* lock */ 141 ok(kIOReturnSuccess==aks_lock_bag(keybag), "lock keybag"); 142 ok(kIOReturnSuccess==aks_get_lock_state(keybag, &state), "get keybag state"); 143 ok(state&keybag_state_locked, "keybag locked"); 144 }); 145 146 CFReleaseSafe(keychain_path_cf); 147 }); 148 149 pthread_t query_thread[N_THREADS]; 150 pthread_t sos_thread; 151 void *query_err[N_THREADS] = {NULL,}; 152 void *sos_err = NULL; 153 154 for(int i=0; i<N_THREADS; i++) 155 pthread_create(&query_thread[i], NULL, do_query, NULL); 156 pthread_create(&sos_thread, NULL, do_sos, NULL); 157 158 for(int i=0; i<N_THREADS; i++) 159 pthread_join(query_thread[i],&query_err[i]); 160 pthread_join(sos_thread, &sos_err); 161 162 for(int i=0; i<N_THREADS; i++) 163 ok(query_err[i]==NULL, "query thread ok"); 164 ok(sos_err==NULL, "sos thread ok"); 165 166 ok(kIOReturnSuccess==aks_unlock_bag(keybag, passcode, passcode_len), "lock keybag"); 167 ok(kIOReturnSuccess==aks_get_lock_state(keybag, &state), "get keybag state"); 168 ok(!(state&keybag_state_locked), "keybag unlocked"); 169 170 is_status(query_one(), errSecItemNotFound, "Query after unlock"); 171 172 /* Reset keybag */ 173 SecItemServerResetKeychainKeybag(); 174 175 return 0; 176} 177 178#else 179 180int secd_02_upgrade_while_locked(int argc, char *const *argv) 181{ 182 plan_tests(1); 183 184 todo("Not yet working in simulator"); 185 186TODO: { 187 ok(false); 188} 189 /* not implemented in simulator (no keybag) */ 190 /* Not implemented in OSX (no upgrade scenario) */ 191 return 0; 192} 193#endif 194