]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-30-xara-item-helpers.h
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 #include "kc-30-xara-helpers.h"
25 #include "kc-item-helpers.h"
26
27 #ifndef kc_30_xara_item_helpers_h
28 #define kc_30_xara_item_helpers_h
29
30 #if TARGET_OS_MAC
31
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wunused-variable"
34 #pragma clang diagnostic ignored "-Wunused-function"
35
36 static void makeCustomItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef expectedHash) {
37 SecKeychainItemRef item = makeItem(name, kc, itemclass, label);
38 checkIntegrityHash(name, item, expectedHash);
39 checkPartitionIDs(name, (SecKeychainItemRef) item, 1);
40
41 CFReleaseNull(item);
42 }
43 #define makeCustomItemWithIntegrityTests (makeItemTests + checkIntegrityHashTests + checkPartitionIDsTests)
44
45 static void makeItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef expectedHash) {
46 makeCustomItemWithIntegrity(name, kc, itemclass, CFSTR("test_label"), expectedHash);
47 }
48 #define makeItemWithIntegrityTests (makeCustomItemWithIntegrityTests)
49
50 static void testAddItem(CFStringRef itemclass, CFStringRef expectedHash) {
51 char name[100];
52 sprintf(name, "testAddItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
53 secnotice("integrity", "************************************* %s", name);
54
55 SecKeychainRef kc = newKeychain(name);
56 makeItemWithIntegrity(name, kc, itemclass, expectedHash);
57
58 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
59 CFReleaseNull(kc);
60 }
61 #define testAddItemTests (newKeychainTests + makeItemWithIntegrityTests + 1)
62
63 static void testCopyMatchingItem(CFStringRef itemclass, CFStringRef expectedHash) {
64 char name[100];
65 sprintf(name, "testCopyMatchingItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
66 secnotice("integrity", "************************************* %s", name);
67
68 SecKeychainRef kc = newKeychain(name);
69 makeItemWithIntegrity(name, kc, itemclass, expectedHash);
70
71 SecKeychainItemRef item = checkNCopyFirst(name, createQueryItemDictionary(kc, itemclass), 1);
72 checkIntegrityHash(name, item, expectedHash);
73 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
74 CFReleaseNull(item);
75 CFReleaseNull(kc);
76 }
77 #define testCopyMatchingItemTests (newKeychainTests + makeItemWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1)
78
79 static void testUpdateItem(CFStringRef itemclass, CFStringRef expectedHashOrig, CFStringRef expectedHashAfter) {
80 char name[100];
81 sprintf(name, "testUpdateItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
82 secnotice("integrity", "************************************* %s", name);
83
84 SecKeychainRef kc = newKeychain(name);
85 makeItemWithIntegrity(name, kc, itemclass, expectedHashOrig);
86
87 CFMutableDictionaryRef query = createQueryItemDictionary(kc, itemclass);
88 CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
89 CFDictionarySetValue(update, kSecAttrComment, CFSTR("a modification"));
90 CFDictionarySetValue(update, kSecAttrAccount, CFSTR("a account modification"));
91 CFDictionarySetValue(update, kSecAttrLabel, CFSTR("a label modification"));
92 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name);
93
94 CFReleaseNull(update);
95
96 SecKeychainItemRef item = checkNCopyFirst(name, createQueryItemDictionary(kc, itemclass), 1);
97 checkIntegrityHash(name, item, expectedHashAfter);
98 CFReleaseNull(item);
99
100 // Check that updating data works
101 update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
102 CFDataRef data = CFDataCreate(NULL, (void*)"data", 4);
103 CFDictionarySetValue(update, kSecValueData, data);
104 CFReleaseNull(data);
105 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name);
106
107 item = checkNCopyFirst(name, createQueryItemDictionary(kc, itemclass), 1);
108 checkIntegrityHash(name, item, expectedHashAfter);
109 checkPartitionIDs(name, item, 1);
110
111 CFReleaseNull(query);
112 CFReleaseNull(update);
113 CFReleaseNull(item);
114
115 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
116 CFReleaseNull(kc);
117 }
118 #define testUpdateItemTests (newKeychainTests + makeItemWithIntegrityTests \
119 + 1 + checkNTests + checkIntegrityHashTests \
120 + 1 + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \
121 + 1)
122
123 static void testAddDuplicateItem(CFStringRef itemclass, CFStringRef expectedHash) {
124 char name[100];
125 sprintf(name, "testAddDuplicateItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
126 secnotice("integrity", "************************************* %s", name);
127
128 SecKeychainRef kc = newKeychain(name);
129 makeItemWithIntegrity(name, kc, itemclass, expectedHash);
130
131 makeDuplicateItem(name, kc, itemclass);
132
133 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
134 CFReleaseNull(kc);
135 }
136 #define testAddDuplicateItemTests (newKeychainTests + makeItemWithIntegrityTests + makeDuplicateItemTests + 1)
137
138 static void testDeleteItem(CFStringRef itemclass, CFStringRef expectedHash) {
139 char name[100];
140 sprintf(name, "testDeleteItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
141 secnotice("integrity", "************************************* %s", name);
142
143 SecKeychainRef kc = newKeychain(name);
144 makeItemWithIntegrity(name, kc, itemclass, expectedHash);
145
146 SecKeychainItemRef item = checkNCopyFirst(name, createQueryItemDictionary(kc, itemclass), 1);
147 checkIntegrityHash(name, item, expectedHash);
148
149 ok_status(SecKeychainItemDelete(item), "%s: SecKeychainItemDelete", name);
150 checkN(name, createQueryItemDictionary(kc, itemclass), 0);
151 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
152 CFReleaseNull(kc);
153 CFReleaseNull(item);
154 }
155 #define testDeleteItemTests (newKeychainTests + makeItemWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1 + checkNTests + 1)
156
157 static void writeEmptyV512Keychain(const char* name, const char* keychainFile);
158
159 // This test is to find <rdar://problem/23515265> CrashTracer: accountsd at …curity: Security::KeychainCore::CCallbackMgr::consume + 387
160 //
161 // The issue was that items could remain in the Keychain cache, even after the
162 // actual object was freed. The main path involved updating an item so that it
163 // had the same primary key as an item which was in the cache but not in the
164 // database (this could be caused by another process deleting the item and us
165 // not receiving the notification).
166 //
167 // This test should pass. Failure is shown by crashing.
168 //
169 static void testUpdateRetainedItem(CFStringRef itemclass) {
170 char name[100];
171 sprintf(name, "testUpdateRetainedItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8));
172 secnotice("integrity", "************************************* %s", name);
173
174 writeEmptyV512Keychain(name, keychainDbFile);
175 SecKeychainRef kc = openCustomKeychain(name, keychainName, "password");
176
177 SecKeychainItemRef item = createCustomItem(name, kc, createAddCustomItemDictionary(kc, itemclass, CFSTR("test_label"), CFSTR("account1")));
178
179 checkN(name, createQueryCustomItemDictionary(kc, itemclass, CFSTR("test_label")), 1);
180
181 cmp_ok(CFGetRetainCount(item), >=, 1, "%s: CFGetRetainCount(item)", name);
182
183 // Bump our local database version number a few times, so we'll re-read the database when we reset it later
184 CFReleaseSafe(createCustomItem(name, kc, createAddCustomItemDictionary(kc, itemclass, CFSTR("version"), CFSTR("version"))));
185 CFReleaseSafe(createCustomItem(name, kc, createAddCustomItemDictionary(kc, itemclass, CFSTR("bump"), CFSTR("bump"))));
186
187 // Simulate another process deleting the items we just made, and us not receiving the notification
188 writeEmptyV512Keychain(name, keychainDbFile);
189
190 // Generate some keychain notifications on a different keychain so the AppleDatabase will reload test.keychain
191 SecKeychainRef kc2 = newCustomKeychain(name, "unrelated.keychain", "password");
192 CFReleaseSafe(createCustomItem(name, kc2, createAddCustomItemDictionary(kc, itemclass, CFSTR("unrelated1_label"), CFSTR("unrelated1"))));
193 ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", name);
194 CFReleaseNull(kc2);
195
196 secnotice("integrity", "************************************* should reload database\n");
197
198 SecKeychainItemRef item2 = createCustomItem(name, kc, createAddCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label"), CFSTR("account2")));
199 checkN(name, createQueryCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label")), 1);
200 cmp_ok(CFGetRetainCount(item2), >=, 1, "%s: CFGetRetainCount(item2)", name);
201
202 // Now, update the second item so it would collide with the first
203 CFMutableDictionaryRef query = createQueryCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label"));
204 CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
205 CFDictionarySetValue(update, kSecAttrAccount, CFSTR("account1"));
206 CFDictionarySetValue(update, kSecAttrLabel, CFSTR("test_label"));
207 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name);
208
209 cmp_ok(CFGetRetainCount(item), >=, 1, "%s: CFGetRetainCount(item)", name);
210 CFReleaseNull(item);
211
212 checkN(name, createQueryCustomItemDictionary(kc, itemclass, CFSTR("test_label")), 1);
213 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
214 CFReleaseNull(kc);
215 }
216 #define testUpdateRetainedItemTests (openCustomKeychainTests + createCustomItemTests + checkNTests \
217 + 1 + createCustomItemTests + createCustomItemTests \
218 + newCustomKeychainTests + createCustomItemTests + 1 \
219 + createCustomItemTests + checkNTests + 1 \
220 + 1 + 1 + checkNTests + 1)
221
222 #pragma clang diagnostic pop
223 #else
224
225 #endif /* TARGET_OS_MAC */
226
227
228 #endif /* kc_30_xara_item_helpers_h */