]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-helpers.h
Security-57740.51.3.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 CF_RETURNS_RETAINED 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 SecKeychainRef CF_RETURNS_RETAINED getEmptyTestKeychain() {
93 deleteKeychainFiles(keychainFile);
94
95 SecKeychainRef kc = NULL;
96 ok_status(SecKeychainCreate(keychainFile, (UInt32) strlen(test_keychain_password), test_keychain_password, false, NULL, &kc), "%s: getPopulatedTestKeychain: SecKeychainCreate", testName);
97 return kc;
98 }
99 #define getEmptyTestKeychainTests 1
100
101
102 static void addToSearchList(SecKeychainRef keychain) {
103 CFArrayRef searchList = NULL;
104 SecKeychainCopySearchList(&searchList);
105 CFMutableArrayRef mutableSearchList = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(searchList) + 1, searchList);
106 CFArrayAppendValue(mutableSearchList, keychain);
107 SecKeychainSetSearchList(mutableSearchList);
108 CFRelease(searchList);
109 CFRelease(mutableSearchList);
110 }
111
112
113 /* Checks to be sure there are N elements in this search, and returns the first
114 * if it exists. */
115 static SecKeychainItemRef checkNCopyFirst(char* testName, const CFDictionaryRef CF_CONSUMED query, uint32_t n) {
116 CFArrayRef results = NULL;
117 if(n > 0) {
118 ok_status(SecItemCopyMatching(query, (CFTypeRef*) &results), "%s: SecItemCopyMatching", testName);
119 } else {
120 is(SecItemCopyMatching(query, (CFTypeRef*) &results), errSecItemNotFound, "%s: SecItemCopyMatching (for no items)", testName);
121 }
122
123 SecKeychainItemRef item = NULL;
124 if(results) {
125 is(CFArrayGetCount(results), n, "%s: Wrong number of results", testName);
126 if(n >= 1) {
127 ok(item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, 0), "%s: Couldn't get item", testName);
128 } else {
129 pass("make test numbers match");
130 }
131 } else if((!results) && n == 0) {
132 pass("%s: no results found (and none expected)", testName);
133 pass("make test numbers match");
134 } else {
135 fail("%s: no results found (and %d expected)", testName, n);
136 fflush(stdout); CFShow(query); fflush(stdout);
137 pass("make test numbers match");
138 }
139
140 CFRetainSafe(item);
141 CFReleaseNull(results);
142
143 CFRelease(query);
144 return item;
145 }
146
147 static void checkN(char* testName, const CFDictionaryRef CF_CONSUMED query, uint32_t n) {
148 SecKeychainItemRef item = checkNCopyFirst(testName, query, n);
149 CFReleaseSafe(item);
150 }
151
152 #define checkNTests 3
153
154
155 static void readPasswordContentsWithResult(SecKeychainItemRef item, OSStatus expectedResult, CFStringRef expectedContents) {
156 if(!item) {
157 fail("no item passed to readPasswordContentsWithResult");
158 fail("Match test numbers");
159 fail("Match test numbers");
160 return;
161 }
162
163 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
164
165 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
166 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
167
168 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
169 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
170 CFDictionarySetValue(query, kSecUseItemList, itemList);
171
172 CFTypeRef results = NULL;
173 if(expectedContents) {
174 is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: SecItemCopyMatching", testName);
175 CFReleaseNull(query);
176
177 if(results) {
178 ok(CFGetTypeID(results) == CFDataGetTypeID(), "%s: result is not a data", testName);
179
180 CFDataRef data = (CFDataRef) results;
181 CFStringRef str = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, false);
182 eq_cf(str, expectedContents, "%s: contents do not match", testName);
183 CFReleaseNull(str);
184 CFReleaseNull(results);
185 } else {
186 fail("Didn't get any results");
187 fail("Match test numbers");
188 }
189 } else {
190 is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: expecting error %d", testName, (int) expectedResult);
191 pass("Match test numbers");
192 pass("Match test numbers");
193 }
194 }
195 #define readPasswordContentsWithResultTests 3
196
197 static void readPasswordContents(SecKeychainItemRef item, CFStringRef expectedContents) {
198 return readPasswordContentsWithResult(item, errSecSuccess, expectedContents);
199 }
200 #define readPasswordContentsTests readPasswordContentsWithResultTests
201
202 static void changePasswordContents(SecKeychainItemRef item, CFStringRef newPassword) {
203 if(!item) {
204 fail("no item passed to changePasswordContents");
205 return;
206 }
207
208 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
209
210 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
211
212 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
213 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
214 CFDictionarySetValue(query, kSecUseItemList, itemList);
215
216 CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
217 CFDataRef data = CFDataCreate(NULL, (const UInt8*) CFStringGetCStringPtr(newPassword, kCFStringEncodingUTF8), CFStringGetLength(newPassword));
218 CFDictionarySetValue(attrs, kSecValueData, data);
219 CFReleaseNull(data);
220
221 ok_status(SecItemUpdate(query, attrs), "%s: SecItemUpdate", testName);
222 }
223 #define changePasswordContentsTests 1
224
225 static void deleteItem(SecKeychainItemRef item) {
226 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
227
228 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
229 CFArrayAppendValue((CFMutableArrayRef)itemList, item);
230 CFDictionarySetValue(query, kSecUseItemList, itemList);
231
232 ok_status(SecItemDelete(query), "%s: SecItemDelete single item", testName);
233 CFReleaseNull(query);
234 }
235 #define deleteItemTests 1
236
237 static void deleteItems(CFArrayRef items) {
238 if(!items) {
239 fail("no items passed to deleteItems");
240 return;
241 }
242
243 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
244 CFDictionarySetValue(query, kSecUseItemList, items);
245
246 size_t count = (size_t) CFArrayGetCount(items);
247 if(count > 0) {
248 ok_status(SecItemDelete(query), "%s: SecItemDelete %ld items", testName, count);
249 } else {
250 is(SecItemDelete(query), errSecItemNotFound, "%s: SecItemDelete no items", testName);
251 }
252 CFReleaseNull(query);
253 }
254 #define deleteItemsTests 1
255
256 /* Checks in with securityd to see how many prompts were generated since the last call to this function, and tests against the number expected.
257 Returns the number generated since the last call. */
258 static uint32_t checkPrompts(uint32_t expectedSinceLastCall, char* explanation) {
259 uint32_t currentPrompts = UINT_MAX;
260 uint32_t newPrompts = UINT_MAX;
261 ok_status(SecKeychainGetUserPromptAttempts(&currentPrompts), "%s: SecKeychainGetUserPromptAttempts", testName);
262
263 newPrompts = currentPrompts - promptAttempts;
264
265 is(newPrompts, expectedSinceLastCall, "%s: wrong number of prompts: %s", testName, explanation);
266 promptAttempts = currentPrompts;
267
268 return newPrompts;
269 }
270 #define checkPromptsTests 2
271
272 #pragma clang diagnostic pop
273
274 #endif /* kc_helpers_h */