]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-30-xara.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-30-xara.c
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 "keychain_regressions.h"
25
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <Security/Security.h>
28 #include <Security/SecBase.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecKeychainPriv.h>
31 #include <TargetConditionals.h>
32 #include <Security/cssmapi.h>
33 #include <stdlib.h>
34
35 #include "kc-30-xara-item-helpers.h"
36 #include "kc-30-xara-key-helpers.h"
37 #include "kc-30-xara-upgrade-helpers.h"
38
39 #if TARGET_OS_MAC
40
41 #pragma clang diagnostic push
42 #pragma clang diagnostic ignored "-Wunused-variable"
43 #pragma clang diagnostic ignored "-Wunused-function"
44
45 /* Test basic add delete update copy matching stuff. */
46
47
48 /* Standard memory functions required by CSSM. */
49 static void *cssmMalloc(CSSM_SIZE size, void *allocRef) { return malloc(size); }
50 static void cssmFree(void *mem_ptr, void *allocRef) { free(mem_ptr); return; }
51 static void *cssmRealloc(void *ptr, CSSM_SIZE size, void *allocRef) { return realloc( ptr, size ); }
52 static void *cssmCalloc(uint32 num, CSSM_SIZE size, void *allocRef) { return calloc( num, size ); }
53 static CSSM_API_MEMORY_FUNCS memFuncs = { cssmMalloc, cssmFree, cssmRealloc, cssmCalloc, NULL };
54
55 static CSSM_DL_DB_HANDLE initializeDL() {
56 CSSM_VERSION version = { 2, 0 };
57 CSSM_DL_DB_HANDLE dldbHandle;
58 CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
59 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
60
61 ok_status(CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL), "cssm_init");
62 ok_status(CSSM_ModuleLoad(&gGuidAppleFileDL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL), "module_load");
63 ok_status(CSSM_ModuleAttach(&gGuidAppleFileDL, &version, &memFuncs, 0, CSSM_SERVICE_DL, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &dldbHandle.DLHandle), "module_attach");
64
65 return dldbHandle;
66 }
67 #define initializeDLTests 3
68
69 static void unloadDL(CSSM_DL_DB_HANDLE* dldbHandle) {
70 ok_status(CSSM_ModuleDetach(dldbHandle->DLHandle), "detach");
71 ok_status(CSSM_ModuleUnload(&gGuidAppleFileDL, NULL, NULL), "unload");
72 ok_status(CSSM_Terminate(), "terminate");
73 }
74 #define unloadDLTests 3
75
76 static void modifyAttributeInKeychain(char * name, CSSM_DL_DB_HANDLE dldbHandle, char * keychainName, CSSM_DB_RECORDTYPE recordType, char* attributeName, char* newValue, size_t len) {
77 CSSM_RETURN status = CSSM_OK;
78 ok_status(CSSM_DL_DbOpen(dldbHandle.DLHandle, keychainName,
79 NULL,
80 CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
81 NULL, /* Access cred? */
82 NULL, /* Open Parameters? */
83 &dldbHandle.DBHandle), "%s: CSSM_DL_DbOpen", name);
84
85 CSSM_QUERY queryAll = {};
86 queryAll.RecordType = recordType;
87
88 CSSM_HANDLE results = 0;
89 CSSM_DATA data = {};
90 CSSM_DB_UNIQUE_RECORD_PTR uniqueIdPtr = NULL;
91
92 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes = {};
93 attributes.NumberOfAttributes = 1;
94 attributes.AttributeData = malloc(sizeof(CSSM_DB_ATTRIBUTE_DATA) * attributes.NumberOfAttributes);
95 attributes.AttributeData[0].Info.Label.AttributeName = attributeName;
96 attributes.AttributeData[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
97
98 attributes.AttributeData[0].NumberOfValues = 1;
99 attributes.AttributeData[0].Value = malloc(sizeof(CSSM_DATA)*attributes.AttributeData[0].NumberOfValues);
100
101
102 status = CSSM_DL_DataGetFirst(dldbHandle, &queryAll, &results, &attributes, &data, &uniqueIdPtr);
103 while(status == CSSM_OK) {
104 // I'm sure it has one thing and that thing needs to change.
105 attributes.AttributeData[0].Value[0].Data = (void*)newValue;
106 attributes.AttributeData[0].Value[0].Length = strlen(newValue);
107
108 CSSM_DL_DataModify(dldbHandle,
109 attributes.DataRecordType,
110 uniqueIdPtr,
111 &attributes,
112 NULL, // no data modification
113 CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
114
115 CSSM_DL_FreeUniqueRecord(dldbHandle, uniqueIdPtr);
116 status = CSSM_DL_DataGetNext(dldbHandle, results, &attributes, &data, &uniqueIdPtr);
117 }
118 ok_status(CSSM_DL_DbClose(dldbHandle), "%s: CSSM_DL_DbClose", name);
119 }
120 #define modifyAttributeInKeychainTests 2
121
122 static void testAttackItem(CSSM_DL_DB_HANDLE dldbHandle) {
123 char * name = "testAttackItem";
124 secdebugfunc("integrity", "************************************* %s", name);
125
126 SecKeychainRef kc = newKeychain(name);
127 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
128
129 makeItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
130 SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
131 CFReleaseNull(kc);
132
133 char * modification = "evil_application";
134 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification));
135
136 kc = openKeychain(name);
137 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
138 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
139 }
140 #define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
141
142 static void testAttackKey(CSSM_DL_DB_HANDLE dldbHandle) {
143 char * name = "testAttackKey";
144 secdebugfunc("integrity", "************************************* %s", name);
145
146 SecKeychainRef kc = newKeychain(name);
147 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
148
149 makeKeyWithIntegrity(name, kc, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
150 SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
151 CFReleaseNull(kc);
152
153 char * modification = "evil_application";
154 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "Label", modification, strlen(modification));
155
156 kc = openKeychain(name);
157 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
158 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
159 }
160 #define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
161
162
163 static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle) {
164 char * name = "testAddAfterCorruptItem";
165 secdebugfunc("integrity", "************************************* %s", name);
166
167 SecKeychainRef kc = newKeychain(name);
168 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
169
170 makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("test_label"), CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
171 SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
172 CFReleaseNull(item);
173
174 makeDuplicateItem(name, kc, kSecClassGenericPassword);
175 CFReleaseNull(kc);
176
177 char * modification = "evil_application";
178 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification));
179
180 kc = openKeychain(name);
181 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
182
183 makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("evil_application"), CFSTR("d2aa97b30a1f96f9e61fcade2b00d9f4284976a83a5b68392251ee5ec827f8cc"));
184 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
185 makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("evil_application"));
186 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
187 }
188 #define testAddAfterCorruptItemTests (newKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeDuplicateItemTests \
189 + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1)
190
191 static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) {
192 char * name = "testAddAfterCorruptKey";
193 secdebugfunc("integrity", "************************************* %s", name);
194
195 SecKeychainRef kc = newKeychain(name);
196 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
197 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
198 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
199
200 // Make a symmetric key
201 makeCustomKeyWithIntegrity(name, kc, CFSTR("test_key"), CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
202
203 SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
204 makeCustomDuplicateKey(name, kc, CFSTR("test_key"));
205 CFReleaseNull(item);
206
207 // Make a key pair
208 SecKeyRef pub;
209 SecKeyRef priv;
210 makeCustomKeyPair(name, kc, CFSTR("test_key_pair"), &pub, &priv);
211 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
212 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
213 CFReleaseNull(pub);
214 CFReleaseNull(priv);
215
216 ok_status(SecKeychainListRemoveKeychain(&kc), "%s: SecKeychainListRemoveKeychain", name);
217
218 char * modification = "evil_application";
219 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "PrintName", modification, strlen(modification));
220 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PUBLIC_KEY, "PrintName", modification, strlen(modification));
221 modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PRIVATE_KEY, "PrintName", modification, strlen(modification));
222
223 kc = openKeychain(name);
224 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
225 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
226 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
227
228 makeCustomKeyWithIntegrity(name, kc, CFSTR("evil_application"), CFSTR("ca6d90a0b053113e43bbb67f64030230c96537f77601f66bdf821d8684431dfc"));
229 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
230
231 makeCustomDuplicateKey(name, kc, CFSTR("evil_application"));
232
233 makeCustomKeyPair(name, kc, CFSTR("evil_application"), &pub, &priv);
234 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
235 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
236
237 // We cannot create a duplicate key pair, so don't try.
238
239 CFReleaseNull(item);
240 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
241 }
242 #define testAddAfterCorruptKeyTests (newKeychainTests \
243 + checkNTests + checkNTests + checkNTests \
244 + makeCustomKeyWithIntegrityTests + checkNTests + makeCustomDuplicateKeyTests \
245 + makeCustomKeyPairTests + checkNTests + checkNTests \
246 + 1 \
247 + modifyAttributeInKeychainTests \
248 + modifyAttributeInKeychainTests \
249 + modifyAttributeInKeychainTests \
250 + openKeychainTests \
251 + checkNTests + checkNTests + checkNTests \
252 + makeCustomKeyWithIntegrityTests + checkNTests \
253 + makeCustomDuplicateKeyTests \
254 + makeCustomKeyPairTests + checkNTests + checkNTests \
255 + 1)
256
257
258 static void testKeychainUpgrade() {
259 char name[100];
260 sprintf(name, "testKeychainUpgrade");
261 secdebugfunc("integrity", "************************************* %s", name);
262
263 writeOldKeychain(name, keychainFile);
264 SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "password");
265
266 SecKeychainItemRef item;
267
268 item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
269 checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
270 makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic"));
271
272 item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1);
273 checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
274 makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet"));
275
276 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
277 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
278
279 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
280 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
281
282 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
283 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
284
285 // Now close the keychain and open it again
286 CFReleaseNull(kc);
287 kc = openCustomKeychain(name, "test.keychain", "password");
288
289 item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
290 checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
291 makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic"));
292
293 item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1);
294 checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
295 makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet"));
296
297 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
298 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
299
300 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
301 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
302
303 item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
304 checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
305
306 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
307 }
308 #define testKeychainUpgradeTests (openCustomKeychainTests \
309 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
310 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
311 + checkNTests + checkIntegrityHashTests + \
312 + checkNTests + checkIntegrityHashTests + \
313 + checkNTests + checkIntegrityHashTests + \
314 + openCustomKeychainTests \
315 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
316 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
317 + checkNTests + checkIntegrityHashTests +\
318 + checkNTests + checkIntegrityHashTests +\
319 + checkNTests + checkIntegrityHashTests +\
320 1)
321
322 static SecAccessRef makeUidAccess(uid_t uid)
323 {
324 // make the "uid/gid" ACL subject
325 // this is a CSSM_LIST_ELEMENT chain
326 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
327 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
328 CSSM_ACL_MATCH_UID, // set mask: match uids (only)
329 uid, // uid to match
330 0 // gid (not matched here)
331 };
332 CSSM_LIST_ELEMENT subject2 = { NULL, 0 };
333 subject2.Element.Word.Data = (UInt8 *)&selector;
334 subject2.Element.Word.Length = sizeof(selector);
335 CSSM_LIST_ELEMENT subject1 = {
336 &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID
337 };
338
339 // rights granted (replace with individual list if desired)
340 CSSM_ACL_AUTHORIZATION_TAG rights[] = {
341 CSSM_ACL_AUTHORIZATION_ANY // everything
342 };
343 // owner component (right to change ACL)
344 CSSM_ACL_OWNER_PROTOTYPE owner = {
345 // TypedSubject
346 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
347 // Delegate
348 false
349 };
350 // ACL entries (any number, just one here)
351 CSSM_ACL_ENTRY_INFO acls[] = {
352 {
353 // prototype
354 {
355 // TypedSubject
356 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
357 false, // Delegate
358 // rights for this entry
359 { sizeof(rights) / sizeof(rights[0]), rights },
360 // rest is defaulted
361 }
362 }
363 };
364
365 SecAccessRef access;
366 SecAccessCreateFromOwnerAndACL(&owner, sizeof(acls) / sizeof(acls[0]), acls, &access);
367 return access;
368 }
369
370 static void checkAccessLength(const char * name, SecAccessRef access, int expected) {
371 CFArrayRef acllist = NULL;
372 ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name);
373
374 // Count the number of non-integrity ACLs in this access
375 int aclsFound = 0;
376 CFStringRef output = NULL;
377
378 if(acllist) {
379 for(int i = 0; i < CFArrayGetCount(acllist); i++) {
380 SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i);
381
382 CFArrayRef auths = SecACLCopyAuthorizations(acl);
383 CFRange searchrange = CFRangeMake(0, CFArrayGetCount(auths));
384 if(!CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationIntegrity) &&
385 !CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationPartitionID)) {
386
387 aclsFound += 1;
388 }
389
390 CFReleaseNull(auths);
391 }
392
393 CFReleaseNull(acllist);
394 }
395 is(aclsFound, expected, "%s: ACL has correct number of entries", name);
396 }
397 #define checkAccessLengthTests 2
398
399 static void testUidAccess() {
400 char name[100];
401 sprintf(name, "testUidAccess");
402 secdebugfunc("integrity", "************************************* %s", name);
403
404 SecAccessRef access = makeUidAccess(getuid());
405
406 SecKeychainRef kc = newKeychain(name);
407 CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
408 CFDictionarySetValue(query, kSecAttrAccess, access);
409
410 CFTypeRef result = NULL;
411 ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
412 ok(result != NULL, "%s: SecItemAdd returned a result", name);
413
414 SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
415
416 ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name);
417 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
418
419 // Check to make sure the ACL stays
420 access = NULL;
421 ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name);
422 checkAccessLength(name, access, 2);
423
424 const char * newPassword = "newPassword";
425 ok_status(SecKeychainItemModifyContent(item, NULL, (UInt32) strlen(newPassword), newPassword), "%s: SecKeychainItemModifyContent", name);
426
427 access = NULL;
428 ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name);
429 checkAccessLength(name, access, 2);
430
431 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
432 }
433 #define testUidAccessTests (newKeychainTests + 2 + checkNTests + 1 + checkNTests + 1 + checkAccessLengthTests \
434 + 2 + checkAccessLengthTests + 1)
435
436
437 static SecAccessRef makeMultipleUidAccess(uid_t* uids, uint32 count)
438 {
439 // rights granted (replace with individual list if desired)
440 CSSM_ACL_AUTHORIZATION_TAG rights[] =
441 {
442 CSSM_ACL_AUTHORIZATION_ANY // everything
443 };
444 size_t numRights = sizeof(rights) / sizeof(rights[0]);
445
446 // allocate the arrays of objects used to define the ACL
447 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selectors[count];
448 CSSM_LIST_ELEMENT heads[count], tails[count];
449 CSSM_ACL_ENTRY_INFO acls[count];
450 // clear all the ACL objects
451 memset(heads, 0, sizeof(heads));
452 memset(acls, 0, sizeof(acls));
453
454 uint32 i = count;
455 while (i--)
456 {
457 // make the "uid/gid" ACL subject
458 selectors[i].version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
459 selectors[i].mask = CSSM_ACL_MATCH_UID; // set mask: match uids (only)
460 selectors[i].uid = uids[i]; // uid to match
461 selectors[i].gid = 0; // gid (not matched here)
462
463 // this is a CSSM_LIST_ELEMENT chain
464 heads[i].NextElement = &(tails[i]);
465 heads[i].WordID = CSSM_ACL_SUBJECT_TYPE_PROCESS;
466 heads[i].ElementType = CSSM_LIST_ELEMENT_WORDID;
467 // Element is unused
468
469 tails[i].NextElement = NULL;
470 tails[i].WordID = CSSM_WORDID__NLU_;
471 tails[i].ElementType = CSSM_LIST_ELEMENT_DATUM;
472 tails[i].Element.Word.Data = (UInt8 *)&selectors[i];
473 tails[i].Element.Word.Length = sizeof(selectors[i]);
474
475 // ACL entry
476 acls[i].EntryPublicInfo.TypedSubject.ListType = CSSM_LIST_TYPE_UNKNOWN;
477 acls[i].EntryPublicInfo.TypedSubject.Head = &heads[i];
478 acls[i].EntryPublicInfo.TypedSubject.Tail = &tails[i];
479 acls[i].EntryPublicInfo.Delegate = CSSM_FALSE;
480 acls[i].EntryPublicInfo.Authorization.NumberOfAuthTags = (uint32) numRights;
481
482 acls[i].EntryPublicInfo.Authorization.AuthTags = rights;
483 acls[i].EntryHandle = i;
484 }
485
486 // owner component (right to change ACL)
487 CSSM_ACL_OWNER_PROTOTYPE owner;
488 owner.TypedSubject = acls[0].EntryPublicInfo.TypedSubject;
489 owner.Delegate = acls[0].EntryPublicInfo.Delegate;
490
491 SecAccessRef access;
492 SecAccessCreateFromOwnerAndACL(&owner, count, acls, &access);
493 return access;
494 }
495 static void testMultipleUidAccess() {
496 char name[100];
497 sprintf(name, "testMultipleUidAccess");
498 secdebugfunc("integrity", "************************************* %s", name);
499
500 uid_t uids[5];
501 uids[0] = getuid();
502 uids[1] = 0;
503 uids[2] = 500;
504 uids[3] = 501;
505 uids[4] = 502;
506
507 SecAccessRef access = makeMultipleUidAccess(uids, 5);
508
509 SecKeychainRef kc = newKeychain(name);
510 CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
511 CFDictionarySetValue(query, kSecAttrAccess, access);
512
513 CFTypeRef result = NULL;
514 ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
515 ok(result != NULL, "%s: SecItemAdd returned a result", name);
516
517 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
518
519 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
520 }
521 #define testMultipleUidAccessTests (newKeychainTests + checkNTests + 3)
522
523 static void testRootUidAccess() {
524 char name[100];
525 sprintf(name, "testRootUidAccess");
526 secdebugfunc("integrity", "************************************* %s", name);
527
528 SecAccessRef access = SecAccessCreateWithOwnerAndACL(getuid(), 0, (kSecUseOnlyUID | kSecHonorRoot), NULL, NULL);
529
530 SecKeychainRef kc = newKeychain(name);
531 CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
532 CFDictionarySetValue(query, kSecAttrAccess, access);
533
534 CFTypeRef result = NULL;
535 ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
536 ok(result != NULL, "%s: SecItemAdd returned a result", name);
537
538 query = makeQueryItemDictionary(kc, kSecClassGenericPassword);
539
540 SecKeychainItemRef item = checkN(name, query, 1);
541
542 ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name);
543 checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
544
545 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
546 }
547 #define testRootUidAccessTests (newKeychainTests + checkNTests + 4 + checkNTests)
548
549 #define kTestCount (0 \
550 + testAddItemTests \
551 + testAddItemTests \
552 + testCopyMatchingItemTests \
553 + testCopyMatchingItemTests \
554 + testUpdateItemTests \
555 + testUpdateItemTests \
556 + testAddDuplicateItemTests \
557 + testAddDuplicateItemTests \
558 + testDeleteItemTests \
559 + testDeleteItemTests \
560 + testUpdateRetainedItemTests \
561 + testUpdateRetainedItemTests \
562 \
563 + testAddKeyTests \
564 + testAddFreeKeyTests \
565 + testCopyMatchingKeyTests \
566 + testUpdateKeyTests \
567 + testAddDuplicateKeyTests \
568 + testKeyPairTests \
569 + testExportImportKeyPairTests \
570 \
571 + initializeDLTests \
572 + testAttackItemTests \
573 + testAttackKeyTests \
574 + testAddAfterCorruptItemTests \
575 + testAddAfterCorruptKeyTests \
576 + unloadDLTests \
577 \
578 + testKeychainUpgradeTests \
579 + testUidAccessTests \
580 + testMultipleUidAccessTests \
581 + testRootUidAccessTests \
582 )
583
584 static void tests(void)
585 {
586 const char *home_dir = getenv("HOME");
587 sprintf(keychainFile, "%s/Library/Keychains/test.keychain", home_dir);
588 sprintf(keychainName, "test.keychain");
589
590 testAddItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
591 testAddItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
592
593 testCopyMatchingItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
594 testCopyMatchingItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
595
596 testUpdateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"),
597 CFSTR("7b7be2fd6ee9f81ba4c5575ea451f2c21117fc0f241625a6cf90c65180b8c9f5"));
598 testUpdateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"),
599 CFSTR("d71af9e4d54127a5dbc10c5ec097b828065cfbaf2b775caf1a3c4e3410f80851"));
600
601 testAddDuplicateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
602 testAddDuplicateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
603
604 testDeleteItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
605 testDeleteItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
606
607 testUpdateRetainedItem(kSecClassGenericPassword);
608 testUpdateRetainedItem(kSecClassInternetPassword);
609
610 testAddKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
611 testAddFreeKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
612 testCopyMatchingKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
613 testUpdateKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"),
614 CFSTR("a744ce6db8359ad264ed5f4a35ecfcc8b6599b89319e7ea316035acd3fb02c22"));
615 testAddDuplicateKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
616 testAddDuplicateFreeKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
617
618 testKeyPair();
619 testExportImportKeyPair();
620
621 CSSM_DL_DB_HANDLE dldbHandle = initializeDL();
622 testAttackItem(dldbHandle);
623 testAttackKey(dldbHandle);
624
625 testAddAfterCorruptItem(dldbHandle);
626 testAddAfterCorruptKey(dldbHandle);
627 unloadDL(&dldbHandle);
628
629 testKeychainUpgrade();
630 testUidAccess();
631 testMultipleUidAccess();
632 testRootUidAccess();
633
634 //makeOldKeychainBlob();
635 }
636
637 #pragma clang pop
638 #else
639
640 #define kTestCount (0)
641
642
643 static void tests(void)
644 {
645 }
646
647 #endif /* TARGET_OS_MAC */
648
649
650 int kc_30_xara(int argc, char *const *argv)
651 {
652 plan_tests(kTestCount);
653
654 tests();
655
656 return 0;
657 }