kc-21-item-use-callback.c [plain text]
#include <Security/SecKeychainItem.h>
#include <Security/SecKeychain.h>
#include <CoreFoundation/CFRunLoop.h>
#include <unistd.h>
#include "keychain_regressions.h"
#include "kc-helpers.h"
static char account[] = "account";
static char service[] = "service";
static char password[] = "password";
static bool callbackCalled = false;
static void checkContent(SecKeychainItemRef itemRef)
{
SecItemClass itemClass;
SecKeychainAttribute attrs[] =
{
{ kSecLabelItemAttr, 0, NULL },
{ kSecAccountItemAttr, 0, NULL },
{ kSecServiceItemAttr, 0, NULL }
};
SecKeychainAttributeList attrList =
{ sizeof(attrs) / sizeof(*attrs), attrs };
UInt32 length;
void *data;
ok_status(SecKeychainItemCopyContent(itemRef, &itemClass, &attrList,
&length, &data), "get item data in callback");
is(length, sizeof(password), "<rdar://problem/3867900> "
"SecKeychainItemCopyContent() returns bad data on items "
"from notifications");
ok(data, "received data from item");
ok(!memcmp(password, data, length), "password data matches.");
ok_status(SecKeychainItemFreeContent(&attrList, data),
"free item data in callback");
}
static OSStatus callbackFunction(SecKeychainEvent keychainEvent,
SecKeychainCallbackInfo *info, void *context)
{
is(keychainEvent, kSecAddEvent, "Got an incorrect keychain event");
ok(context != NULL, "context is null");
ok(info != NULL, "info is NULL");
ok(info->item != NULL, "info-<item is NULL");
checkContent(info->item);
*((UInt32 *)context) = 1;
ok_status(SecKeychainItemDelete(info->item), "delete item");
callbackCalled = true;
CFRunLoopStop(CFRunLoopGetCurrent());
return 0;
}
int
kc_21_item_use_callback(int argc, char *const *argv)
{
plan_tests(16);
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, false);
UInt32 didGetNotification = 0;
ok_status(SecKeychainAddCallback(callbackFunction, kSecAddEventMask,
&didGetNotification), "add callback");
SecKeychainRef keychain = createNewKeychain("test", "test");
SecKeychainItemRef itemRef;
ok_status(SecKeychainAddGenericPassword(keychain,
sizeof(account), account,
sizeof(service), service,
sizeof(password), password,
&itemRef),
"add generic password, release and wait for callback");
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10.0, false);
is(callbackCalled, true, "Keychain callback function was not called or did not finish");
CFRelease(itemRef);
ok_status(SecKeychainRemoveCallback(callbackFunction), "Remove callback");
ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
CFRelease(keychain);
deleteTestFiles();
return 0;
}