1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-28 04:49:43 +01:00

osxkeychain: erase matching passwords only

Other credential helpers support deleting credentials that match a
specified password. See 7144dee3ec (credential/libsecret: erase matching
creds only, 2023-07-26) and cb626f8e5c (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:
Bo Anderson 2024-02-17 23:34:55 +00:00 committed by Junio C Hamano
parent 9032bcad82
commit e3cef40db8

View file

@ -169,9 +169,55 @@ static OSStatus find_internet_password(void)
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)
{
CFDictionaryRef attrs;
CFArrayRef refs;
OSStatus result;
/*
@ -183,10 +229,18 @@ static OSStatus delete_internet_password(void)
return -1;
attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll,
kSecReturnRef, kCFBooleanTrue,
NULL);
result = SecItemDelete(attrs);
result = SecItemCopyMatching(attrs, (CFTypeRef *)&refs);
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 */
if (result == errSecItemNotFound)
result = errSecSuccess;