]>
Commit | Line | Data |
---|---|---|
e3d460c9 A |
1 | /* |
2 | * Copyright (c) 2015 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_30_xara_helpers_h | |
25 | #define kc_30_xara_helpers_h | |
26 | ||
27 | #include <Security/Security.h> | |
28 | #include <Security/cssmapi.h> | |
29 | #include <security_utilities/debugging.h> | |
30 | #include "utilities/SecCFRelease.h" | |
fa7225c8 | 31 | #include "kc-helpers.h" |
e3d460c9 A |
32 | |
33 | #if TARGET_OS_MAC | |
34 | ||
35 | #pragma clang diagnostic push | |
36 | #pragma clang diagnostic ignored "-Wunused-variable" | |
37 | #pragma clang diagnostic ignored "-Wunused-function" | |
38 | ||
39 | /* name is the name of the test, not the name of the keychain */ | |
ecaf5866 | 40 | static CF_RETURNS_RETAINED SecKeychainRef newKeychain(const char * name) { |
e3d460c9 A |
41 | SecKeychainRef kc = NULL; |
42 | char* password = "password"; | |
43 | ||
44 | // Kill the test keychain if it exists. | |
45 | unlink(keychainFile); | |
fa7225c8 A |
46 | unlink(keychainDbFile); |
47 | ||
48 | // Delete from CDSA-land? No tests, here, it'll work or it won't. | |
49 | SecKeychainOpen(keychainName, &kc); | |
50 | if(kc) { | |
51 | SecKeychainDelete(kc); | |
52 | CFReleaseNull(kc); | |
53 | } | |
e3d460c9 A |
54 | |
55 | ok_status(SecKeychainCreate(keychainName, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); | |
fa7225c8 A |
56 | |
57 | char path[400]; | |
58 | UInt32 len = sizeof(path); | |
59 | ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetPath", name); | |
60 | eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); | |
e3d460c9 A |
61 | return kc; |
62 | } | |
fa7225c8 | 63 | #define newKeychainTests 3 |
e3d460c9 A |
64 | |
65 | /* name is the name of the test, not the name of the keychain */ | |
66 | static SecKeychainRef newCustomKeychain(const char * name, const char * path, const char * password) { | |
67 | SecKeychainRef kc = NULL; | |
68 | ||
69 | // Kill the keychain if it exists. | |
70 | unlink(path); | |
71 | ||
72 | ok_status(SecKeychainCreate(path, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); | |
73 | return kc; | |
74 | } | |
75 | #define newCustomKeychainTests 1 | |
76 | ||
ecaf5866 | 77 | static CF_RETURNS_RETAINED SecKeychainRef openCustomKeychain(const char * name, const char * path, const char * password) { |
e3d460c9 A |
78 | SecKeychainRef kc = NULL; |
79 | ok_status(SecKeychainOpen(path, &kc), "%s: SecKeychainOpen", name); | |
80 | ||
81 | if(password) { | |
82 | ok_status(SecKeychainUnlock(kc, (UInt32) strlen(password), password, true), "%s: SecKeychainUnlock", name); | |
83 | } else { | |
84 | pass("make test count right"); | |
85 | } | |
86 | ||
87 | return kc; | |
88 | } | |
89 | #define openCustomKeychainTests 2 | |
90 | ||
ecaf5866 | 91 | static CF_RETURNS_RETAINED SecKeychainRef openKeychain(const char * name) { |
fa7225c8 | 92 | return openCustomKeychain(name, keychainName, NULL); |
e3d460c9 A |
93 | } |
94 | #define openKeychainTests (openCustomKeychainTests) | |
95 | ||
fa7225c8 A |
96 | #define checkPartitionIDsTests 3 |
97 | static void checkPartitionIDs(const char* name, SecKeychainItemRef item, uint32_t n) { | |
98 | if(!item) { | |
99 | for(int i = 0; i < checkPartitionIDsTests; i++) { | |
100 | fail("%s: checkNoPartitionIDs not passed an item", name); | |
101 | } | |
102 | return; | |
103 | } | |
104 | SecAccessRef access = NULL; | |
105 | ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); | |
106 | ||
107 | CFArrayRef acllist = NULL; | |
108 | ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); | |
109 | ||
110 | int partitionIDsFound = 0; | |
111 | CFStringRef output = NULL; | |
112 | ||
113 | if(acllist) { | |
114 | for(int i = 0; i < CFArrayGetCount(acllist); i++) { | |
115 | SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i); | |
116 | ||
117 | CFArrayRef auths = SecACLCopyAuthorizations(acl); | |
118 | CFRange searchrange = {0, CFArrayGetCount(auths)}; | |
119 | if(CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationPartitionID)) { | |
120 | ||
121 | // found a hash. match it. | |
122 | partitionIDsFound++; | |
123 | } | |
124 | ||
125 | CFReleaseNull(auths); | |
126 | } | |
127 | ||
128 | CFReleaseNull(acllist); | |
129 | } | |
130 | ||
131 | is(partitionIDsFound, n, "%s: Wrong number of partition IDs found", name); | |
132 | } | |
133 | ||
e3d460c9 A |
134 | #define getIntegrityHashTests 3 |
135 | static CFStringRef getIntegrityHash(const char* name, SecKeychainItemRef item) { | |
136 | if(!item) { | |
137 | for(int i = 0; i < getIntegrityHashTests; i++) { | |
138 | fail("%s: getIntegrityHash not passed an item", name); | |
139 | } | |
140 | return NULL; | |
141 | } | |
142 | SecAccessRef access = NULL; | |
143 | ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); | |
144 | ||
145 | CFArrayRef acllist = NULL; | |
146 | ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); | |
147 | ||
148 | int hashesFound = 0; | |
149 | CFStringRef output = NULL; | |
150 | ||
151 | if(acllist) { | |
152 | for(int i = 0; i < CFArrayGetCount(acllist); i++) { | |
153 | SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i); | |
154 | ||
155 | CFArrayRef auths = SecACLCopyAuthorizations(acl); | |
156 | CFRange searchrange = {0, CFArrayGetCount(auths)}; | |
157 | if(CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationIntegrity)) { | |
158 | ||
159 | CFArrayRef applications = NULL; | |
160 | CFStringRef description = NULL; | |
161 | SecKeychainPromptSelector selector; | |
162 | SecACLCopyContents(acl, &applications, &description, &selector); | |
163 | ||
164 | // found a hash. match it. | |
165 | hashesFound++; | |
166 | ||
167 | output = description; | |
168 | } | |
169 | ||
170 | CFReleaseNull(auths); | |
171 | } | |
172 | ||
173 | CFReleaseNull(acllist); | |
174 | } | |
175 | ||
176 | is(hashesFound, 1, "%s: Wrong number of hashes found", name); | |
177 | return output; | |
178 | } | |
179 | ||
180 | // Pulls the Integrity hash out of an item and compares it against the given one. | |
181 | static void checkIntegrityHash(const char* name, SecKeychainItemRef item, CFStringRef expectedHash) { | |
182 | CFStringRef hash = getIntegrityHash(name, item); | |
183 | ||
184 | if(!hash) { | |
185 | fail("No hash to match"); | |
186 | return; | |
187 | } | |
188 | ||
189 | // We can't use use the ok macro here, because we | |
190 | // might run it too many times and mess up the test count. | |
191 | if(CFStringCompare(expectedHash, hash, 0) == kCFCompareEqualTo) { | |
192 | pass("Hashes match."); | |
193 | } else { | |
194 | printf("%s: Hashes didn't match. Was: ", name); | |
195 | fflush(stdout); | |
196 | CFShow(hash); | |
fa7225c8 A |
197 | printf(" expected: "); |
198 | fflush(stdout); | |
199 | CFShow(expectedHash); | |
200 | fflush(stdout); | |
e3d460c9 A |
201 | fail("Hashes don't match"); |
202 | } | |
203 | } | |
204 | #define checkIntegrityHashTests (getIntegrityHashTests + 1) | |
205 | ||
206 | static void checkHashesMatch(const char* name, SecKeychainItemRef item, SecKeychainItemRef comp) { | |
207 | CFStringRef itemhash = getIntegrityHash(name, item); | |
208 | CFStringRef comparehash = getIntegrityHash(name, comp); | |
209 | ||
210 | if(!itemhash) { | |
211 | fail("%s: original item not passed in", name); | |
212 | return; | |
213 | } | |
214 | if(!comparehash) { | |
215 | fail("%s: compare item not passed in", name); | |
216 | return; | |
217 | } | |
218 | ||
219 | is(CFStringCompare(itemhash, comparehash, 0), kCFCompareEqualTo, "%s: hashes do not match", name); | |
220 | if(CFStringCompare(itemhash, comparehash, 0) != kCFCompareEqualTo) { | |
221 | fflush(stdout); | |
222 | CFShow(itemhash); | |
223 | CFShow(comparehash); | |
224 | } | |
225 | } | |
226 | #define checkHashesMatchTests (getIntegrityHashTests + getIntegrityHashTests + 1) | |
227 | ||
6b200bc3 | 228 | #pragma clang diagnostic pop |
e3d460c9 A |
229 | #else |
230 | ||
231 | #endif /* TARGET_OS_MAC */ | |
232 | ||
233 | #endif /* kc_30_xara_helpers_h */ |