]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-helpers.h
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-helpers.h
1 /*
2 * Copyright (c) 2016 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 #ifndef kc_helpers_h
25 #define kc_helpers_h
26
27 #include <stdlib.h>
28 #include <unistd.h>
29
30 #include <Security/Security.h>
31 #include <Security/SecKeychainPriv.h>
32 #include "utilities/SecCFRelease.h"
33
34 #include "kc-keychain-file-helpers.h"
35
36 /* redefine this since the headers are mixed up */
37 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
38 {
39 if (left == NULL || right == NULL)
40 return left == right;
41 else
42 return CFEqual(left, right);
43 }
44
45 static char keychainFile[1000];
46 static char keychainDbFile[1000];
47 static char keychainTempFile[1000];
48 static char keychainName[1000];
49 static char testName[1000];
50 static uint32_t promptAttempts;
51
52 #pragma clang diagnostic push
53 #pragma clang diagnostic ignored "-Wunused-variable"
54 #pragma clang diagnostic ignored "-Wunused-function"
55
56 static void startTest(const char* thisTestName) {
57 strlcpy(testName, thisTestName, sizeof(testName));
58 }
59
60 static void initializeKeychainTests(const char* thisTestName) {
61 const char *home_dir = getenv("HOME");
62 sprintf(keychainName, "test-%s.asdf", thisTestName);
63 sprintf(keychainFile, "%s/Library/Keychains/%s", home_dir, keychainName);
64 sprintf(keychainDbFile, "%s/Library/Keychains/%s-db", home_dir, keychainName);
65 sprintf(keychainTempFile, "%s/Library/Keychains/test_temp", home_dir);
66
67 deleteKeychainFiles(keychainFile);
68
69 startTest(thisTestName);
70
71 SecKeychainGetUserPromptAttempts(&promptAttempts);
72 SecKeychainSetUserInteractionAllowed(FALSE);
73 }
74
75 // Use this at the bottom of every test to make sure everything is gone
76 static void deleteTestFiles() {
77 deleteKeychainFiles(keychainFile);
78 }
79
80 static SecKeychainRef getPopulatedTestKeychain() {
81 deleteKeychainFiles(keychainFile);
82
83 writeFile(keychainFile, test_keychain, sizeof(test_keychain));
84
85 SecKeychainRef kc = NULL;
86 ok_status(SecKeychainOpen(keychainFile, &kc), "%s: getPopulatedTestKeychain: SecKeychainOpen", testName);
87 ok_status(SecKeychainUnlock(kc, (UInt32) strlen(test_keychain_password), test_keychain_password, true), "%s: getPopulatedTestKeychain: SecKeychainUnlock", testName);
88 return kc;
89 }
90 #define getPopulatedTestKeychainTests 2
91
92 static void addToSearchList(SecKeychainRef keychain) {
93 CFArrayRef searchList = NULL;
94 SecKeychainCopySearchList(&searchList);
95 CFMutableArrayRef mutableSearchList = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(searchList) + 1, searchList);
96 CFArrayAppendValue(mutableSearchList, keychain);
97 SecKeychainSetSearchList(mutableSearchList);
98 CFRelease(searchList);
99 CFRelease(mutableSearchList);
100 }
101
102
103 /* Checks to be sure there are N elements in this search, and returns the first
104 * if it exists. */
105 static SecKeychainItemRef checkN(char* testName, const CFDictionaryRef query, uint32_t n) {
106 CFArrayRef results = NULL;
107 if(n > 0) {
108 ok_status(SecItemCopyMatching(query, (CFTypeRef*) &results), "%s: SecItemCopyMatching", testName);
109 } else {
110 is(SecItemCopyMatching(query, (CFTypeRef*) &results), errSecItemNotFound, "%s: SecItemCopyMatching (for no items)", testName);
111 }
112
113 SecKeychainItemRef item = NULL;
114 if(results) {
115 is(CFArrayGetCount(results), n, "%s: Wrong number of results", testName);
116 if(n >= 1) {
117 ok(item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, 0), "%s: Couldn't get item", testName);
118 } else {
119 pass("make test numbers match");
120 }
121 } else if((!results) && n == 0) {
122 pass("%s: no results found (and none expected)", testName);
123 pass("make test numbers match");
124 } else {
125 fail("%s: no results found (and %d expected)", testName, n);
126 fflush(stdout); CFShow(query); fflush(stdout);
127 pass("make test numbers match");
128 }
129
130 CFRelease(query);
131 return item;
132 }
133 #define checkNTests 3
134
135
136 static void readPasswordContentsWithResult(SecKeychainItemRef item, OSStatus expectedResult, CFStringRef expectedContents) {
137 if(!item) {
138 fail("no item passed to readPasswordContentsWithResult");
139 fail("Match test numbers");
140 fail("Match test numbers");
141 return;
142 }
143
144 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
145
146 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
147 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
148
149 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
150 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
151 CFDictionarySetValue(query, kSecUseItemList, itemList);
152
153 CFTypeRef results = NULL;
154 if(expectedContents) {
155 is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: SecItemCopyMatching", testName);
156 CFReleaseNull(query);
157
158 if(results) {
159 ok(CFGetTypeID(results) == CFDataGetTypeID(), "%s: result is not a data", testName);
160
161 CFDataRef data = (CFDataRef) results;
162 CFStringRef str = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, false);
163 eq_cf(str, expectedContents, "%s: contents do not match", testName);
164 CFReleaseNull(str);
165 CFReleaseNull(results);
166 } else {
167 fail("Didn't get any results");
168 fail("Match test numbers");
169 }
170 } else {
171 is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: expecting error %d", testName, (int) expectedResult);
172 pass("Match test numbers");
173 pass("Match test numbers");
174 }
175 }
176 #define readPasswordContentsWithResultTests 3
177
178 static void readPasswordContents(SecKeychainItemRef item, CFStringRef expectedContents) {
179 return readPasswordContentsWithResult(item, errSecSuccess, expectedContents);
180 }
181 #define readPasswordContentsTests readPasswordContentsWithResultTests
182
183 static void changePasswordContents(SecKeychainItemRef item, CFStringRef newPassword) {
184 if(!item) {
185 fail("no item passed to changePasswordContents");
186 return;
187 }
188
189 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
190
191 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
192
193 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
194 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
195 CFDictionarySetValue(query, kSecUseItemList, itemList);
196
197 CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
198 CFDictionarySetValue(attrs, kSecValueData, CFDataCreate(NULL, (const UInt8*) CFStringGetCStringPtr(newPassword, kCFStringEncodingUTF8), CFStringGetLength(newPassword)));
199
200 ok_status(SecItemUpdate(query, attrs), "%s: SecItemUpdate", testName);
201 }
202 #define changePasswordContentsTests 1
203
204 static void deleteItem(SecKeychainItemRef item) {
205 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
206
207 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
208 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
209 CFDictionarySetValue(query, kSecUseItemList, itemList);
210
211 ok_status(SecItemDelete(query), "%s: SecItemDelete single item", testName);
212 CFReleaseNull(query);
213 }
214 #define deleteItemTests 1
215
216 static void deleteItems(CFArrayRef items) {
217 if(!items) {
218 fail("no items passed to deleteItems");
219 return;
220 }
221
222 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
223 CFDictionarySetValue(query, kSecUseItemList, items);
224
225 size_t count = (size_t) CFArrayGetCount(items);
226 if(count > 0) {
227 ok_status(SecItemDelete(query), "%s: SecItemDelete %ld items", testName, count);
228 } else {
229 is(SecItemDelete(query), errSecItemNotFound, "%s: SecItemDelete no items", testName);
230 }
231 CFReleaseNull(query);
232 }
233 #define deleteItemsTests 1
234
235 /* Checks in with securityd to see how many prompts were generated since the last call to this function, and tests against the number expected.
236 Returns the number generated since the last call. */
237 static uint32_t checkPrompts(uint32_t expectedSinceLastCall, char* explanation) {
238 uint32_t currentPrompts = UINT_MAX;
239 uint32_t newPrompts = UINT_MAX;
240 ok_status(SecKeychainGetUserPromptAttempts(&currentPrompts), "%s: SecKeychainGetUserPromptAttempts", testName);
241
242 newPrompts = currentPrompts - promptAttempts;
243
244 is(newPrompts, expectedSinceLastCall, "%s: wrong number of prompts: %s", testName, explanation);
245 promptAttempts = currentPrompts;
246
247 return newPrompts;
248 }
249 #define checkPromptsTests 2
250
251 #pragma clang diagnostic pop
252
253 #endif /* kc_helpers_h */