]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-21-item-xattrs.c
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-21-item-xattrs.c
1 /*
2 * Copyright (c) 2016 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 xLicense.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import <Security/Security.h>
25 #include "keychain_regressions.h"
26 #include "kc-helpers.h"
27 #include "kc-keychain-file-helpers.h"
28 #include "regressions/test/testenv.h"
29 //
30 // testKeychainXattrs.c
31 //
32 // Basic test of SecKeychainItemExtendedAttributes functionality
33 // to store arbitrary data in the extended attributes of a keychain
34 // item.
35 //
36
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <CoreServices/CoreServices.h>
39 #include <Security/Security.h>
40 #include <Security/SecKeychainItemExtendedAttributes.h> /* private */
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <syslog.h>
45 #include <unistd.h>
46 #include <time.h>
47 #include <sys/param.h>
48
49 static int TestAddItems(SecKeychainRef keychain)
50 {
51 int result = 0;
52 OSStatus status;
53 SecKeychainItemRef item = NULL;
54 CFDataRef blob = NULL;
55
56 /* add generic password item */
57 status = SecKeychainAddGenericPassword(keychain,
58 strlen("Test Cloud Service 42"), "Test Cloud Service 42",
59 strlen("nobody"), "nobody",
60 strlen("weakpass"), "weakpass",
61 &item);
62 ok_status(status, "%s: SecKeychainAddGenericPassword", testName);
63
64 if (status && status != errSecDuplicateItem) { // ignore error if duplicate
65 result++;
66 }
67 /* add an extended CFDataRef attribute to this item */
68 UInt8 buf1[6] = { 's', 'e', 'c', 'r', 'e', 't' };
69 blob = CFDataCreate(NULL, buf1, sizeof(buf1));
70 status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob);
71 ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (generic)", testName);
72
73 if (status) {
74 result++;
75 }
76 if (blob) {
77 CFRelease(blob);
78 blob = NULL;
79 }
80 if (item) {
81 CFRelease(item);
82 item = NULL;
83 }
84
85 /* add internet password item */
86 status = SecKeychainAddInternetPassword(keychain,
87 strlen("test42.icloud.com"), "test42.icloud.com",
88 0, NULL,
89 strlen("nobody"), "nobody",
90 0, NULL,
91 80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault,
92 strlen("weakpass"), "weakpass",
93 &item);
94 ok_status(status, "%s: SecKeychainAddInternetPassword", testName);
95 if (status && status != errSecDuplicateItem) { // ignore error if duplicate
96 result++;
97 }
98 /* add an extended CFDataRef attribute to this item */
99 UInt8 buf2[5] = { 'm', 'a', 'g', 'i', 'c' };
100 blob = CFDataCreate(NULL, buf2, sizeof(buf2));
101 status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob);
102 ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (internet)", testName);
103
104 if (status) {
105 result++;
106 }
107 if (blob) {
108 CFRelease(blob);
109 blob = NULL;
110 }
111 if (item) {
112 CFRelease(item);
113 item = NULL;
114 }
115
116
117 return result;
118 }
119
120 static int TestFindItems(SecKeychainRef keychain)
121 {
122 int result = 0;
123
124 CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
125 CFArrayAppendValue((CFMutableArrayRef)searchList, keychain);
126
127 /* find generic password we added previously */
128 {
129 const void *keys[] = {
130 kSecMatchSearchList,
131 kSecClass,
132 kSecAttrAccount,
133 kSecAttrService,
134 kSecMatchLimit,
135 kSecReturnRef
136 };
137 const void *values[] = {
138 searchList,
139 kSecClassGenericPassword,
140 CFSTR("nobody"),
141 CFSTR("Test Cloud Service 42"),
142 kSecMatchLimitOne,
143 kCFBooleanTrue
144 };
145
146 OSStatus status = noErr;
147 CFTypeRef results = NULL;
148 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
149 sizeof(keys) / sizeof(*keys),
150 &kCFTypeDictionaryKeyCallBacks,
151 &kCFTypeDictionaryValueCallBacks);
152
153 status = SecItemCopyMatching(query, &results);
154 ok_status(status, "%s: SecItemCopyMatching (generic password)", testName);
155
156 if (status) {
157 fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
158 result++;
159 }
160 if (results) {
161 /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */
162 SecKeychainItemRef item = (SecKeychainItemRef) results;
163 CFDataRef blob = NULL;
164 status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob);
165 ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName);
166
167 if (status) {
168 fprintf(stderr, "Unable to retrieve xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
169 result++;
170 }
171 else {
172 const UInt8 *dataPtr = CFDataGetBytePtr(blob);
173
174 eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "secret", strlen("secret"), "%s: Retrieved xattr value matches expected value", testName);
175 if (memcmp(dataPtr, "secret", strlen("secret"))) {
176 result++;
177 }
178 }
179 if (blob) {
180 CFRelease(blob);
181 }
182 CFRelease(results);
183 }
184 if (query) {
185 CFRelease(query);
186 }
187 }
188
189 /* find internet password we added previously */
190 {
191 const void *keys[] = {
192 kSecMatchSearchList,
193 kSecClass,
194 kSecAttrAccount,
195 kSecAttrServer,
196 kSecMatchLimit,
197 kSecReturnRef
198 };
199 const void *values[] = {
200 searchList,
201 kSecClassInternetPassword,
202 CFSTR("nobody"),
203 CFSTR("test42.icloud.com"),
204 kSecMatchLimitOne,
205 kCFBooleanTrue
206 };
207
208 OSStatus status = noErr;
209 CFTypeRef results = NULL;
210 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
211 sizeof(keys) / sizeof(*keys),
212 &kCFTypeDictionaryKeyCallBacks,
213 &kCFTypeDictionaryValueCallBacks);
214
215 status = SecItemCopyMatching(query, &results);
216 ok_status(status, "%s: SecItemCopyMatching (internet password)", testName);
217 if (status) {
218 fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status);
219 result++;
220 }
221 if (results) {
222 /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */
223 SecKeychainItemRef item = (SecKeychainItemRef) results;
224 CFDataRef blob = NULL;
225 status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob);
226 ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName);
227 if (status) {
228 fprintf(stderr, "Unable to retrieve xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status);
229 result++;
230 }
231 else {
232 const UInt8 *dataPtr = CFDataGetBytePtr(blob);
233 eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "magic", strlen("magic"), "%s: Retrieved xattr value matches expected value", testName);
234
235 if (memcmp(dataPtr, "magic", strlen("magic"))) {
236 fprintf(stderr, "Retrieved xattr value did not match expected value!\n");
237 result++;
238 }
239 }
240 if (blob) {
241 CFRelease(blob);
242 }
243 CFRelease(results);
244 }
245 if (query) {
246 CFRelease(query);
247 }
248 }
249
250 return result;
251 }
252
253 static int TestDeleteItems(SecKeychainRef keychain)
254 {
255 int result = 0;
256
257 CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
258 CFArrayAppendValue((CFMutableArrayRef)searchList, keychain);
259
260 /* find generic password we added previously */
261 {
262 const void *keys[] = {
263 kSecMatchSearchList,
264 kSecClass,
265 kSecAttrAccount,
266 kSecAttrService,
267 kSecMatchLimit,
268 kSecReturnRef
269 };
270 const void *values[] = {
271 searchList,
272 kSecClassGenericPassword,
273 CFSTR("nobody"),
274 CFSTR("Test Cloud Service 42"),
275 kSecMatchLimitOne,
276 kCFBooleanTrue
277 };
278
279 OSStatus status = noErr;
280 CFTypeRef results = NULL;
281 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
282 sizeof(keys) / sizeof(*keys),
283 &kCFTypeDictionaryKeyCallBacks,
284 &kCFTypeDictionaryValueCallBacks);
285
286 status = SecItemCopyMatching(query, &results);
287 ok_status(status, "%s: SecItemCopyMatching (Test Cloud Service 42)", testName);
288
289 if (status) {
290 fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
291 result++;
292 }
293 if (results) {
294 /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */
295 SecKeychainItemRef item = (SecKeychainItemRef) results;
296
297 /* set the xattr to NULL in order to delete it */
298 status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL);
299 ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (generic password, null data)", testName);
300
301 if (status) {
302 fprintf(stderr, "Unable to remove xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
303 result++;
304 }
305
306 /* delete the item itself */
307 status = SecKeychainItemDelete(item);
308 ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName);
309
310 if (status) {
311 fprintf(stderr, "Unable to delete \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
312 result++;
313 }
314
315 CFRelease(results);
316 }
317 if (query) {
318 CFRelease(query);
319 }
320 }
321
322 /* find internet password we added previously */
323 {
324 const void *keys[] = {
325 kSecMatchSearchList,
326 kSecClass,
327 kSecAttrAccount,
328 kSecAttrServer,
329 kSecMatchLimit,
330 kSecReturnRef
331 };
332 const void *values[] = {
333 searchList,
334 kSecClassInternetPassword,
335 CFSTR("nobody"),
336 CFSTR("test42.icloud.com"),
337 kSecMatchLimitOne,
338 kCFBooleanTrue
339 };
340
341 OSStatus status = noErr;
342 CFTypeRef results = NULL;
343 CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
344 sizeof(keys) / sizeof(*keys),
345 &kCFTypeDictionaryKeyCallBacks,
346 &kCFTypeDictionaryValueCallBacks);
347
348 status = SecItemCopyMatching(query, &results);
349 ok_status(status, "%s: SecItemCopyMatching (test42.icloud.com)", testName);
350
351 if (status) {
352 fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status);
353 result++;
354 }
355 if (results) {
356 /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */
357 SecKeychainItemRef item = (SecKeychainItemRef) results;
358
359 /* set the xattr to NULL in order to delete it */
360 status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL);
361 ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (internet password, null data)", testName);
362
363 if (status) {
364 fprintf(stderr, "Unable to remove xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status);
365 result++;
366 }
367
368 /* delete the item itself */
369 status = SecKeychainItemDelete(item);
370 ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName);
371
372 if (status) {
373 fprintf(stderr, "Unable to delete \"test42.icloud.com2\" internet password: error %d\n", (int)status);
374 result++;
375 }
376
377 CFRelease(results);
378 }
379 if (query) {
380 CFRelease(query);
381 }
382 }
383
384 return result;
385 }
386
387 int kc_21_item_xattrs(int argc, char *const *argv)
388 {
389 plan_tests(21);
390 initializeKeychainTests(__FUNCTION__);
391
392 SecKeychainRef keychain = getPopulatedTestKeychain();
393
394 TestAddItems(keychain);
395 TestFindItems(keychain);
396 TestDeleteItems(keychain);
397
398 ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
399 CFReleaseNull(keychain);
400 checkPrompts(0, "No prompts");
401
402 deleteTestFiles();
403 return 0;
404 }