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 <AssertMacros.h> 39 40#include <stdio.h> 41#include <unistd.h> 42#include <sys/stat.h> 43#include <pthread.h> 44 45#include "SecdTestKeychainUtilities.h" 46 47static OSStatus do_query(void) 48{ 49 /* querying a password */ 50 const void *keys[] = { 51 kSecClass, 52 kSecAttrServer, 53 kSecReturnAttributes, 54 }; 55 const void *values[] = { 56 kSecClassInternetPassword, 57 CFSTR("corrupt.spamcop.net"), 58 kCFBooleanTrue, 59 }; 60 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 61 array_size(keys), NULL, NULL); 62 CFTypeRef results = NULL; 63 64 OSStatus err = SecItemCopyMatching(query, &results); 65 CFReleaseNull(query); 66 return err; 67} 68 69static void *do_add(void *arg) 70{ 71 int tid=(int)(arg); 72 73 for(int i=0;i<20;i++) { 74 /* Creating a password */ 75 SInt32 v_eighty = (tid+1)*1000+i; 76 CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); 77 const char *v_data = "test"; 78 CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); 79 const void *keys[] = { 80 kSecClass, 81 kSecAttrServer, 82 kSecAttrAccount, 83 kSecAttrPort, 84 kSecAttrProtocol, 85 kSecAttrAuthenticationType, 86 kSecValueData 87 }; 88 const void *values[] = { 89 kSecClassInternetPassword, 90 CFSTR("members.spamcop.net"), 91 CFSTR("smith"), 92 eighty, 93 CFSTR("http"), 94 CFSTR("dflt"), 95 pwdata 96 }; 97 98 CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values, 99 array_size(keys), NULL, NULL); 100 101 ok_status(SecItemAdd(item, NULL), "add internet password"); 102 } 103 104 return NULL; 105} 106 107 108#define N_THREADS 10 109 110static const char *corrupt_item_sql = "UPDATE inet SET data=X'12345678' WHERE rowid=1"; 111 112 113int secd_03_corrupted_items(int argc, char *const *argv) 114{ 115 plan_tests(4 + N_THREADS*21 + kSecdTestSetupTestCount); 116 117 /* custom keychain dir */ 118 secd_test_setup_temp_keychain("secd_03_corrupted_items", NULL); 119 120 /* add a password */ 121 int v_eighty = 80; 122 CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); 123 const char *v_data = "test"; 124 CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); 125 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); 126 CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); 127 CFDictionaryAddValue(query, kSecAttrServer, CFSTR("corrupt.spamcop.net")); 128 CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); 129 CFDictionaryAddValue(query, kSecAttrPort, eighty); 130 CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); 131 CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); 132 CFDictionaryAddValue(query, kSecValueData, pwdata); 133 ok_status(SecItemAdd(query, NULL), "add internet password"); 134 135 /* corrupt the password */ 136 CFStringRef keychain_path_cf = __SecKeychainCopyPath(); 137 138 CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { 139 /* Create a new keychain sqlite db */ 140 sqlite3 *db; 141 142 is(sqlite3_open(keychain_path, &db), SQLITE_OK, "create keychain"); 143 is(sqlite3_exec(db, corrupt_item_sql, NULL, NULL, NULL), SQLITE_OK, 144 "corrupting keychain item1"); 145 146 }); 147 148 pthread_t add_thread[N_THREADS]; 149 void *add_err[N_THREADS] = {NULL,}; 150 151 for(int i=0; i<N_THREADS; i++) 152 pthread_create(&add_thread[i], NULL, do_add, (void*)(intptr_t)i); 153 154 is_status(do_query(), errSecItemNotFound, "query"); 155 156 for(int i=0; i<N_THREADS; i++) 157 pthread_join(add_thread[i], &add_err[i]); 158 159 for(int i=0; i<N_THREADS; i++) 160 ok(add_err[i]==NULL, "add thread"); 161 162 return 0; 163} 164