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