]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-21-item-use-callback.c
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-21-item-use-callback.c
1 #include <Security/SecKeychainItem.h>
2 #include <Security/SecKeychain.h>
3 #include <CoreFoundation/CFRunLoop.h>
4 #include <unistd.h>
5
6 #include "keychain_regressions.h"
7 #include "kc-helpers.h"
8
9 /*
10 Note: to force a failure, run this as root:
11 chmod o-r /var/db/mds/messages/se_SecurityMessages
12 Restore with
13 chmod o+r /var/db/mds/messages/se_SecurityMessages
14 */
15
16 static char account[] = "account";
17 static char service[] = "service";
18 static char password[] = "password";
19 static bool callbackCalled = false;
20
21 static void checkContent(SecKeychainItemRef itemRef)
22 {
23 SecItemClass itemClass;
24
25 SecKeychainAttribute attrs[] =
26 {
27 { kSecLabelItemAttr, 0, NULL },
28 { kSecAccountItemAttr, 0, NULL },
29 { kSecServiceItemAttr, 0, NULL }
30 };
31
32 SecKeychainAttributeList attrList =
33 { sizeof(attrs) / sizeof(*attrs), attrs };
34 UInt32 length;
35 void *data;
36
37 ok_status(SecKeychainItemCopyContent(itemRef, &itemClass, &attrList,
38 &length, &data), "get item data in callback");
39 is(length, sizeof(password), "<rdar://problem/3867900> "
40 "SecKeychainItemCopyContent() returns bad data on items "
41 "from notifications");
42 ok(data, "received data from item");
43
44 ok(!memcmp(password, data, length), "password data matches.");
45
46 ok_status(SecKeychainItemFreeContent(&attrList, data),
47 "free item data in callback");
48 }
49
50 static OSStatus callbackFunction(SecKeychainEvent keychainEvent,
51 SecKeychainCallbackInfo *info, void *context)
52 {
53 is(keychainEvent, kSecAddEvent, "Got an incorrect keychain event");
54 ok(context != NULL, "context is null");
55 ok(info != NULL, "info is NULL");
56 ok(info->item != NULL, "info-<item is NULL");
57
58 checkContent(info->item);
59 *((UInt32 *)context) = 1;
60
61 ok_status(SecKeychainItemDelete(info->item), "delete item");
62
63 // We processed an item, quit the run loop
64 callbackCalled = true;
65 CFRunLoopStop(CFRunLoopGetCurrent());
66 return 0;
67 }
68
69 int
70 kc_21_item_use_callback(int argc, char *const *argv)
71 {
72 plan_tests(16);
73
74 // Run the CFRunLoop to clear out existing notifications
75 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, false);
76
77 UInt32 didGetNotification = 0;
78 ok_status(SecKeychainAddCallback(callbackFunction, kSecAddEventMask,
79 &didGetNotification), "add callback");
80
81 SecKeychainRef keychain = createNewKeychain("test", "test");
82 SecKeychainItemRef itemRef;
83 ok_status(SecKeychainAddGenericPassword(keychain,
84 sizeof(account), account,
85 sizeof(service), service,
86 sizeof(password), password,
87 &itemRef),
88 "add generic password, release and wait for callback");
89
90 // Run the CFRunLoop to process events (and call our callback)
91 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10.0, false);
92 is(callbackCalled, true, "Keychain callback function was not called or did not finish");
93
94 CFRelease(itemRef);
95
96 ok_status(SecKeychainRemoveCallback(callbackFunction), "Remove callback");
97
98 ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
99 CFRelease(keychain);
100
101 deleteTestFiles();
102 return 0;
103 }