osxkeychain: erase matching passwords only
Other credential helpers support deleting credentials that match a specified password. See7144dee3ec
(credential/libsecret: erase matching creds only, 2023-07-26) andcb626f8e5c
(credential/wincred: erase matching creds only, 2023-07-26). Support this in osxkeychain too by extracting, decrypting and comparing the stored password before deleting. Fixes the following test failure with osxkeychain: 11 - helper (osxkeychain) does not erase a password distinct from input Signed-off-by: Bo Anderson <mail@boanderson.me> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
9032bcad82
commit
e3cef40db8
@ -169,9 +169,55 @@ out:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static OSStatus delete_ref(const void *itemRef)
|
||||||
|
{
|
||||||
|
CFArrayRef item_ref_list;
|
||||||
|
CFDictionaryRef delete_query;
|
||||||
|
OSStatus result;
|
||||||
|
|
||||||
|
item_ref_list = CFArrayCreate(kCFAllocatorDefault,
|
||||||
|
&itemRef,
|
||||||
|
1,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
delete_query = create_dictionary(kCFAllocatorDefault,
|
||||||
|
kSecClass, kSecClassInternetPassword,
|
||||||
|
kSecMatchItemList, item_ref_list,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (password) {
|
||||||
|
/* We only want to delete items with a matching password */
|
||||||
|
CFIndex capacity;
|
||||||
|
CFMutableDictionaryRef query;
|
||||||
|
CFDataRef data;
|
||||||
|
|
||||||
|
capacity = CFDictionaryGetCount(delete_query) + 1;
|
||||||
|
query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
|
||||||
|
capacity,
|
||||||
|
delete_query);
|
||||||
|
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
|
||||||
|
result = SecItemCopyMatching(query, (CFTypeRef *)&data);
|
||||||
|
if (!result) {
|
||||||
|
if (CFEqual(data, password))
|
||||||
|
result = SecItemDelete(delete_query);
|
||||||
|
|
||||||
|
CFRelease(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(query);
|
||||||
|
} else {
|
||||||
|
result = SecItemDelete(delete_query);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(delete_query);
|
||||||
|
CFRelease(item_ref_list);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static OSStatus delete_internet_password(void)
|
static OSStatus delete_internet_password(void)
|
||||||
{
|
{
|
||||||
CFDictionaryRef attrs;
|
CFDictionaryRef attrs;
|
||||||
|
CFArrayRef refs;
|
||||||
OSStatus result;
|
OSStatus result;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -183,10 +229,18 @@ static OSStatus delete_internet_password(void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll,
|
attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll,
|
||||||
|
kSecReturnRef, kCFBooleanTrue,
|
||||||
NULL);
|
NULL);
|
||||||
result = SecItemDelete(attrs);
|
result = SecItemCopyMatching(attrs, (CFTypeRef *)&refs);
|
||||||
CFRelease(attrs);
|
CFRelease(attrs);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
for (CFIndex i = 0; !result && i < CFArrayGetCount(refs); i++)
|
||||||
|
result = delete_ref(CFArrayGetValueAtIndex(refs, i));
|
||||||
|
|
||||||
|
CFRelease(refs);
|
||||||
|
}
|
||||||
|
|
||||||
/* We consider not found to not be an error */
|
/* We consider not found to not be an error */
|
||||||
if (result == errSecItemNotFound)
|
if (result == errSecItemNotFound)
|
||||||
result = errSecSuccess;
|
result = errSecSuccess;
|
||||||
|
Reference in New Issue
Block a user