kc-21-item-xattrs.c [plain text]
#import <Security/Security.h>
#include "keychain_regressions.h"
#include "kc-helpers.h"
#include "kc-keychain-file-helpers.h"
#include "test/testenv.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <Security/Security.h>
#include <Security/SecKeychainItemExtendedAttributes.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <time.h>
#include <sys/param.h>
static int TestAddItems(SecKeychainRef keychain)
{
int result = 0;
OSStatus status;
SecKeychainItemRef item = NULL;
CFDataRef blob = NULL;
status = SecKeychainAddGenericPassword(keychain,
strlen("Test Cloud Service 42"), "Test Cloud Service 42",
strlen("nobody"), "nobody",
strlen("weakpass"), "weakpass",
&item);
ok_status(status, "%s: SecKeychainAddGenericPassword", testName);
if (status && status != errSecDuplicateItem) { result++;
}
UInt8 buf1[6] = { 's', 'e', 'c', 'r', 'e', 't' };
blob = CFDataCreate(NULL, buf1, sizeof(buf1));
status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob);
ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (generic)", testName);
if (status) {
result++;
}
if (blob) {
CFRelease(blob);
blob = NULL;
}
if (item) {
CFRelease(item);
item = NULL;
}
status = SecKeychainAddInternetPassword(keychain,
strlen("test42.icloud.com"), "test42.icloud.com",
0, NULL,
strlen("nobody"), "nobody",
0, NULL,
80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault,
strlen("weakpass"), "weakpass",
&item);
ok_status(status, "%s: SecKeychainAddInternetPassword", testName);
if (status && status != errSecDuplicateItem) { result++;
}
UInt8 buf2[5] = { 'm', 'a', 'g', 'i', 'c' };
blob = CFDataCreate(NULL, buf2, sizeof(buf2));
status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob);
ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (internet)", testName);
if (status) {
result++;
}
if (blob) {
CFRelease(blob);
blob = NULL;
}
if (item) {
CFRelease(item);
item = NULL;
}
return result;
}
static int TestFindItems(SecKeychainRef keychain)
{
int result = 0;
CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
CFArrayAppendValue((CFMutableArrayRef)searchList, keychain);
{
const void *keys[] = {
kSecMatchSearchList,
kSecClass,
kSecAttrAccount,
kSecAttrService,
kSecMatchLimit,
kSecReturnRef
};
const void *values[] = {
searchList,
kSecClassGenericPassword,
CFSTR("nobody"),
CFSTR("Test Cloud Service 42"),
kSecMatchLimitOne,
kCFBooleanTrue
};
OSStatus status = noErr;
CFTypeRef results = NULL;
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemCopyMatching(query, &results);
ok_status(status, "%s: SecItemCopyMatching (generic password)", testName);
if (status) {
fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
result++;
}
if (results) {
SecKeychainItemRef item = (SecKeychainItemRef) results;
CFDataRef blob = NULL;
status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob);
ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName);
if (status) {
fprintf(stderr, "Unable to retrieve xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
result++;
}
else {
const UInt8 *dataPtr = CFDataGetBytePtr(blob);
eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "secret", strlen("secret"), "%s: Retrieved xattr value matches expected value", testName);
if (memcmp(dataPtr, "secret", strlen("secret"))) {
result++;
}
}
if (blob) {
CFRelease(blob);
}
CFRelease(results);
}
if (query) {
CFRelease(query);
}
}
{
const void *keys[] = {
kSecMatchSearchList,
kSecClass,
kSecAttrAccount,
kSecAttrServer,
kSecMatchLimit,
kSecReturnRef
};
const void *values[] = {
searchList,
kSecClassInternetPassword,
CFSTR("nobody"),
CFSTR("test42.icloud.com"),
kSecMatchLimitOne,
kCFBooleanTrue
};
OSStatus status = noErr;
CFTypeRef results = NULL;
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemCopyMatching(query, &results);
ok_status(status, "%s: SecItemCopyMatching (internet password)", testName);
if (status) {
fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status);
result++;
}
if (results) {
SecKeychainItemRef item = (SecKeychainItemRef) results;
CFDataRef blob = NULL;
status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob);
ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName);
if (status) {
fprintf(stderr, "Unable to retrieve xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status);
result++;
}
else {
const UInt8 *dataPtr = CFDataGetBytePtr(blob);
eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "magic", strlen("magic"), "%s: Retrieved xattr value matches expected value", testName);
if (memcmp(dataPtr, "magic", strlen("magic"))) {
fprintf(stderr, "Retrieved xattr value did not match expected value!\n");
result++;
}
}
if (blob) {
CFRelease(blob);
}
CFRelease(results);
}
if (query) {
CFRelease(query);
}
}
return result;
}
static int TestDeleteItems(SecKeychainRef keychain)
{
int result = 0;
CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
CFArrayAppendValue((CFMutableArrayRef)searchList, keychain);
{
const void *keys[] = {
kSecMatchSearchList,
kSecClass,
kSecAttrAccount,
kSecAttrService,
kSecMatchLimit,
kSecReturnRef
};
const void *values[] = {
searchList,
kSecClassGenericPassword,
CFSTR("nobody"),
CFSTR("Test Cloud Service 42"),
kSecMatchLimitOne,
kCFBooleanTrue
};
OSStatus status = noErr;
CFTypeRef results = NULL;
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemCopyMatching(query, &results);
ok_status(status, "%s: SecItemCopyMatching (Test Cloud Service 42)", testName);
if (status) {
fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
result++;
}
if (results) {
SecKeychainItemRef item = (SecKeychainItemRef) results;
status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL);
ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (generic password, null data)", testName);
if (status) {
fprintf(stderr, "Unable to remove xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
result++;
}
status = SecKeychainItemDelete(item);
ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName);
if (status) {
fprintf(stderr, "Unable to delete \"Test Cloud Service 42\" generic password: error %d\n", (int)status);
result++;
}
CFRelease(results);
}
if (query) {
CFRelease(query);
}
}
{
const void *keys[] = {
kSecMatchSearchList,
kSecClass,
kSecAttrAccount,
kSecAttrServer,
kSecMatchLimit,
kSecReturnRef
};
const void *values[] = {
searchList,
kSecClassInternetPassword,
CFSTR("nobody"),
CFSTR("test42.icloud.com"),
kSecMatchLimitOne,
kCFBooleanTrue
};
OSStatus status = noErr;
CFTypeRef results = NULL;
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemCopyMatching(query, &results);
ok_status(status, "%s: SecItemCopyMatching (test42.icloud.com)", testName);
if (status) {
fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status);
result++;
}
if (results) {
SecKeychainItemRef item = (SecKeychainItemRef) results;
status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL);
ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (internet password, null data)", testName);
if (status) {
fprintf(stderr, "Unable to remove xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status);
result++;
}
status = SecKeychainItemDelete(item);
ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName);
if (status) {
fprintf(stderr, "Unable to delete \"test42.icloud.com2\" internet password: error %d\n", (int)status);
result++;
}
CFRelease(results);
}
if (query) {
CFRelease(query);
}
}
return result;
}
int kc_21_item_xattrs(int argc, char *const *argv)
{
plan_tests(21);
initializeKeychainTests(__FUNCTION__);
SecKeychainRef keychain = getPopulatedTestKeychain();
TestAddItems(keychain);
TestFindItems(keychain);
TestDeleteItems(keychain);
ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
CFReleaseNull(keychain);
checkPrompts(0, "No prompts");
deleteTestFiles();
return 0;
}