]>
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" | |
31 | ||
32 | static char keychainFile[1000]; | |
33 | static char keychainName[1000]; | |
34 | ||
35 | #if TARGET_OS_MAC | |
36 | ||
37 | #pragma clang diagnostic push | |
38 | #pragma clang diagnostic ignored "-Wunused-variable" | |
39 | #pragma clang diagnostic ignored "-Wunused-function" | |
40 | ||
41 | /* name is the name of the test, not the name of the keychain */ | |
42 | static SecKeychainRef newKeychain(const char * name) { | |
43 | SecKeychainRef kc = NULL; | |
44 | char* password = "password"; | |
45 | ||
46 | // Kill the test keychain if it exists. | |
47 | unlink(keychainFile); | |
48 | ||
49 | ok_status(SecKeychainCreate(keychainName, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); | |
50 | return kc; | |
51 | } | |
52 | #define newKeychainTests 1 | |
53 | ||
54 | /* name is the name of the test, not the name of the keychain */ | |
55 | static SecKeychainRef newCustomKeychain(const char * name, const char * path, const char * password) { | |
56 | SecKeychainRef kc = NULL; | |
57 | ||
58 | // Kill the keychain if it exists. | |
59 | unlink(path); | |
60 | ||
61 | ok_status(SecKeychainCreate(path, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); | |
62 | return kc; | |
63 | } | |
64 | #define newCustomKeychainTests 1 | |
65 | ||
66 | static SecKeychainRef openCustomKeychain(const char * name, const char * path, const char * password) { | |
67 | SecKeychainRef kc = NULL; | |
68 | ok_status(SecKeychainOpen(path, &kc), "%s: SecKeychainOpen", name); | |
69 | ||
70 | if(password) { | |
71 | ok_status(SecKeychainUnlock(kc, (UInt32) strlen(password), password, true), "%s: SecKeychainUnlock", name); | |
72 | } else { | |
73 | pass("make test count right"); | |
74 | } | |
75 | ||
76 | return kc; | |
77 | } | |
78 | #define openCustomKeychainTests 2 | |
79 | ||
80 | static SecKeychainRef openKeychain(const char * name) { | |
81 | return openCustomKeychain(name, "test.keychain", NULL); | |
82 | } | |
83 | #define openKeychainTests (openCustomKeychainTests) | |
84 | ||
85 | #define getIntegrityHashTests 3 | |
86 | static CFStringRef getIntegrityHash(const char* name, SecKeychainItemRef item) { | |
87 | if(!item) { | |
88 | for(int i = 0; i < getIntegrityHashTests; i++) { | |
89 | fail("%s: getIntegrityHash not passed an item", name); | |
90 | } | |
91 | return NULL; | |
92 | } | |
93 | SecAccessRef access = NULL; | |
94 | ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); | |
95 | ||
96 | CFArrayRef acllist = NULL; | |
97 | ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); | |
98 | ||
99 | int hashesFound = 0; | |
100 | CFStringRef output = NULL; | |
101 | ||
102 | if(acllist) { | |
103 | for(int i = 0; i < CFArrayGetCount(acllist); i++) { | |
104 | SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i); | |
105 | ||
106 | CFArrayRef auths = SecACLCopyAuthorizations(acl); | |
107 | CFRange searchrange = {0, CFArrayGetCount(auths)}; | |
108 | if(CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationIntegrity)) { | |
109 | ||
110 | CFArrayRef applications = NULL; | |
111 | CFStringRef description = NULL; | |
112 | SecKeychainPromptSelector selector; | |
113 | SecACLCopyContents(acl, &applications, &description, &selector); | |
114 | ||
115 | // found a hash. match it. | |
116 | hashesFound++; | |
117 | ||
118 | output = description; | |
119 | } | |
120 | ||
121 | CFReleaseNull(auths); | |
122 | } | |
123 | ||
124 | CFReleaseNull(acllist); | |
125 | } | |
126 | ||
127 | is(hashesFound, 1, "%s: Wrong number of hashes found", name); | |
128 | return output; | |
129 | } | |
130 | ||
131 | // Pulls the Integrity hash out of an item and compares it against the given one. | |
132 | static void checkIntegrityHash(const char* name, SecKeychainItemRef item, CFStringRef expectedHash) { | |
133 | CFStringRef hash = getIntegrityHash(name, item); | |
134 | ||
135 | if(!hash) { | |
136 | fail("No hash to match"); | |
137 | return; | |
138 | } | |
139 | ||
140 | // We can't use use the ok macro here, because we | |
141 | // might run it too many times and mess up the test count. | |
142 | if(CFStringCompare(expectedHash, hash, 0) == kCFCompareEqualTo) { | |
143 | pass("Hashes match."); | |
144 | } else { | |
145 | printf("%s: Hashes didn't match. Was: ", name); | |
146 | fflush(stdout); | |
147 | CFShow(hash); | |
148 | fail("Hashes don't match"); | |
149 | } | |
150 | } | |
151 | #define checkIntegrityHashTests (getIntegrityHashTests + 1) | |
152 | ||
153 | static void checkHashesMatch(const char* name, SecKeychainItemRef item, SecKeychainItemRef comp) { | |
154 | CFStringRef itemhash = getIntegrityHash(name, item); | |
155 | CFStringRef comparehash = getIntegrityHash(name, comp); | |
156 | ||
157 | if(!itemhash) { | |
158 | fail("%s: original item not passed in", name); | |
159 | return; | |
160 | } | |
161 | if(!comparehash) { | |
162 | fail("%s: compare item not passed in", name); | |
163 | return; | |
164 | } | |
165 | ||
166 | is(CFStringCompare(itemhash, comparehash, 0), kCFCompareEqualTo, "%s: hashes do not match", name); | |
167 | if(CFStringCompare(itemhash, comparehash, 0) != kCFCompareEqualTo) { | |
168 | fflush(stdout); | |
169 | CFShow(itemhash); | |
170 | CFShow(comparehash); | |
171 | } | |
172 | } | |
173 | #define checkHashesMatchTests (getIntegrityHashTests + getIntegrityHashTests + 1) | |
174 | ||
175 | /* Checks to be sure there are N elements in this search, and returns the first | |
176 | * if it exists. */ | |
177 | static SecKeychainItemRef checkN(char* testName, const CFDictionaryRef query, uint32_t n) { | |
178 | CFArrayRef results = NULL; | |
179 | if(n > 0) { | |
180 | ok_status(SecItemCopyMatching(query, (CFTypeRef*) &results), "%s: SecItemCopyMatching", testName); | |
181 | } else { | |
182 | is(SecItemCopyMatching(query, (CFTypeRef*) &results), errSecItemNotFound, "%s: SecItemCopyMatching (for no items)", testName); | |
183 | } | |
184 | CFRelease(query); | |
185 | ||
186 | SecKeychainItemRef item = NULL; | |
187 | if(results) { | |
188 | is(CFArrayGetCount(results), n, "%s: Wrong number of results", testName); | |
189 | if(n >= 1) { | |
190 | ok(item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, 0), "%s: Couldn't get item", testName); | |
191 | } else { | |
192 | pass("make test numbers match"); | |
193 | } | |
194 | } else if((!results) && n == 0) { | |
195 | pass("%s: no results found (and none expected)", testName); | |
196 | pass("make test numbers match"); | |
197 | } else { | |
198 | fail("%s: no results found (and %d expected)", testName, n); | |
199 | pass("make test numbers match"); | |
200 | } | |
201 | return item; | |
202 | } | |
203 | #define checkNTests 3 | |
204 | ||
205 | #pragma clang pop | |
206 | #else | |
207 | ||
208 | #endif /* TARGET_OS_MAC */ | |
209 | ||
210 | #endif /* kc_30_xara_helpers_h */ |