forked from Mirrors/wine-wine
advapi32: Use a generic Keychain item to store credentials on MacOS.
parent
b5073646c6
commit
fbb669d0d4
|
@ -238,15 +238,13 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
DWORD *len)
|
DWORD *len)
|
||||||
{
|
{
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
UInt32 i;
|
UInt32 i, cred_blob_len;
|
||||||
UInt32 cred_blob_len;
|
|
||||||
void *cred_blob;
|
void *cred_blob;
|
||||||
LPWSTR domain = NULL;
|
WCHAR *user = NULL;
|
||||||
LPWSTR user = NULL;
|
|
||||||
BOOL user_name_present = FALSE;
|
BOOL user_name_present = FALSE;
|
||||||
SecKeychainAttributeInfo info;
|
SecKeychainAttributeInfo info;
|
||||||
SecKeychainAttributeList *attr_list;
|
SecKeychainAttributeList *attr_list;
|
||||||
UInt32 info_tags[] = { kSecServerItemAttr, kSecSecurityDomainItemAttr, kSecAccountItemAttr,
|
UInt32 info_tags[] = { kSecServiceItemAttr, kSecAccountItemAttr,
|
||||||
kSecCommentItemAttr, kSecCreationDateItemAttr };
|
kSecCommentItemAttr, kSecCreationDateItemAttr };
|
||||||
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
||||||
info.tag = info_tags;
|
info.tag = info_tags;
|
||||||
|
@ -296,8 +294,8 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
{
|
{
|
||||||
switch (attr_list->attr[i].tag)
|
switch (attr_list->attr[i].tag)
|
||||||
{
|
{
|
||||||
case kSecServerItemAttr:
|
case kSecServiceItemAttr:
|
||||||
TRACE("kSecServerItemAttr: %.*s\n", (int)attr_list->attr[i].length,
|
TRACE("kSecServiceItemAttr: %.*s\n", (int)attr_list->attr[i].length,
|
||||||
(char *)attr_list->attr[i].data);
|
(char *)attr_list->attr[i].data);
|
||||||
if (!attr_list->attr[i].data) continue;
|
if (!attr_list->attr[i].data) continue;
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
@ -354,20 +352,6 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
*len += (str_len + 1) * sizeof(WCHAR);
|
*len += (str_len + 1) * sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kSecSecurityDomainItemAttr:
|
|
||||||
{
|
|
||||||
INT str_len;
|
|
||||||
TRACE("kSecSecurityDomainItemAttr: %.*s\n", (int)attr_list->attr[i].length,
|
|
||||||
(char *)attr_list->attr[i].data);
|
|
||||||
if (!attr_list->attr[i].data) continue;
|
|
||||||
str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
|
|
||||||
attr_list->attr[i].length, NULL, 0);
|
|
||||||
domain = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
|
|
||||||
attr_list->attr[i].length, domain, str_len);
|
|
||||||
domain[str_len] = '\0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kSecCreationDateItemAttr:
|
case kSecCreationDateItemAttr:
|
||||||
TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list->attr[i].length,
|
TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list->attr[i].length,
|
||||||
(char *)attr_list->attr[i].data);
|
(char *)attr_list->attr[i].data);
|
||||||
|
@ -384,6 +368,9 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
credential->LastWritten.dwHighDateTime = win_time.u.HighPart;
|
credential->LastWritten.dwHighDateTime = win_time.u.HighPart;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("unhandled attribute %lu\n", attr_list->attr[i].tag);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,18 +379,6 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
INT str_len;
|
INT str_len;
|
||||||
if (buffer)
|
if (buffer)
|
||||||
credential->UserName = (LPWSTR)buffer;
|
credential->UserName = (LPWSTR)buffer;
|
||||||
if (domain)
|
|
||||||
{
|
|
||||||
str_len = strlenW(domain);
|
|
||||||
*len += (str_len + 1) * sizeof(WCHAR);
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
memcpy(credential->UserName, domain, str_len * sizeof(WCHAR));
|
|
||||||
/* FIXME: figure out when to use an '@' */
|
|
||||||
credential->UserName[str_len] = '\\';
|
|
||||||
buffer += (str_len + 1) * sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str_len = strlenW(user);
|
str_len = strlenW(user);
|
||||||
*len += (str_len + 1) * sizeof(WCHAR);
|
*len += (str_len + 1) * sizeof(WCHAR);
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
@ -414,7 +389,6 @@ static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, user);
|
HeapFree(GetProcessHeap(), 0, user);
|
||||||
HeapFree(GetProcessHeap(), 0, domain);
|
|
||||||
|
|
||||||
if (cred_blob)
|
if (cred_blob)
|
||||||
{
|
{
|
||||||
|
@ -522,15 +496,8 @@ static DWORD mac_write_credential(const CREDENTIALW *credential, BOOL preserve_b
|
||||||
{
|
{
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
SecKeychainItemRef keychain_item;
|
SecKeychainItemRef keychain_item;
|
||||||
char *username;
|
char *username, *password, *servername;
|
||||||
char *domain = NULL;
|
UInt32 userlen, pwlen, serverlen;
|
||||||
char *password;
|
|
||||||
char *servername;
|
|
||||||
UInt32 userlen;
|
|
||||||
UInt32 domainlen = 0;
|
|
||||||
UInt32 pwlen;
|
|
||||||
UInt32 serverlen;
|
|
||||||
LPCWSTR p;
|
|
||||||
SecKeychainAttribute attrs[1];
|
SecKeychainAttribute attrs[1];
|
||||||
SecKeychainAttributeList attr_list;
|
SecKeychainAttributeList attr_list;
|
||||||
|
|
||||||
|
@ -543,54 +510,31 @@ static DWORD mac_write_credential(const CREDENTIALW *credential, BOOL preserve_b
|
||||||
if (credential->AttributeCount)
|
if (credential->AttributeCount)
|
||||||
FIXME("custom attributes not supported\n");
|
FIXME("custom attributes not supported\n");
|
||||||
|
|
||||||
p = strchrW(credential->UserName, '\\');
|
userlen = WideCharToMultiByte(CP_UTF8, 0, credential->UserName, -1, NULL, 0, NULL, NULL);
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
domainlen = WideCharToMultiByte(CP_UTF8, 0, credential->UserName,
|
|
||||||
p - credential->UserName, NULL, 0, NULL, NULL);
|
|
||||||
domain = HeapAlloc(GetProcessHeap(), 0, (domainlen + 1) * sizeof(*domain));
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, credential->UserName, p - credential->UserName,
|
|
||||||
domain, domainlen, NULL, NULL);
|
|
||||||
domain[domainlen] = '\0';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p = credential->UserName;
|
|
||||||
userlen = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL);
|
|
||||||
username = HeapAlloc(GetProcessHeap(), 0, userlen * sizeof(*username));
|
username = HeapAlloc(GetProcessHeap(), 0, userlen * sizeof(*username));
|
||||||
WideCharToMultiByte(CP_UTF8, 0, p, -1, username, userlen, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, credential->UserName, -1, username, userlen, NULL, NULL);
|
||||||
|
|
||||||
serverlen = WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, NULL, 0, NULL, NULL);
|
serverlen = WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, NULL, 0, NULL, NULL);
|
||||||
servername = HeapAlloc(GetProcessHeap(), 0, serverlen * sizeof(*servername));
|
servername = HeapAlloc(GetProcessHeap(), 0, serverlen * sizeof(*servername));
|
||||||
WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, servername, serverlen, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, servername, serverlen, NULL, NULL);
|
||||||
pwlen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
|
pwlen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
|
||||||
credential->CredentialBlobSize / sizeof(WCHAR), NULL, 0, NULL, NULL);
|
credential->CredentialBlobSize / sizeof(WCHAR), NULL, 0, NULL, NULL);
|
||||||
password = HeapAlloc(GetProcessHeap(), 0, pwlen * sizeof(*domain));
|
password = HeapAlloc(GetProcessHeap(), 0, pwlen * sizeof(*password));
|
||||||
WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
|
WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
|
||||||
credential->CredentialBlobSize / sizeof(WCHAR), password, pwlen, NULL, NULL);
|
credential->CredentialBlobSize / sizeof(WCHAR), password, pwlen, NULL, NULL);
|
||||||
|
|
||||||
TRACE("adding server %s, domain %s, username %s using Keychain\n", servername, domain, username);
|
TRACE("adding server %s, username %s using Keychain\n", servername, username);
|
||||||
status = SecKeychainAddInternetPassword(NULL, strlen(servername), servername,
|
status = SecKeychainAddGenericPassword(NULL, strlen(servername), servername, strlen(username),
|
||||||
domain ? strlen(domain) : 0, domain, strlen(username),
|
username, strlen(password), password, &keychain_item);
|
||||||
username, 0, NULL, 0,
|
|
||||||
0 /* no protocol */,
|
|
||||||
kSecAuthenticationTypeDefault,
|
|
||||||
strlen(password), password, &keychain_item);
|
|
||||||
if (status != noErr)
|
if (status != noErr)
|
||||||
ERR("SecKeychainAddInternetPassword returned %ld\n", status);
|
ERR("SecKeychainAddGenericPassword returned %ld\n", status);
|
||||||
if (status == errSecDuplicateItem)
|
if (status == errSecDuplicateItem)
|
||||||
{
|
{
|
||||||
status = SecKeychainFindInternetPassword(NULL, strlen(servername), servername,
|
status = SecKeychainFindGenericPassword(NULL, strlen(servername), servername, strlen(username),
|
||||||
domain ? strlen(domain) : 0, domain,
|
username, NULL, NULL, &keychain_item);
|
||||||
strlen(username), username,
|
|
||||||
0, NULL /* any path */, 0,
|
|
||||||
0 /* any protocol */,
|
|
||||||
0 /* any authentication type */,
|
|
||||||
0, NULL, &keychain_item);
|
|
||||||
if (status != noErr)
|
if (status != noErr)
|
||||||
ERR("SecKeychainFindInternetPassword returned %ld\n", status);
|
ERR("SecKeychainFindGenericPassword returned %ld\n", status);
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, domain);
|
|
||||||
HeapFree(GetProcessHeap(), 0, username);
|
HeapFree(GetProcessHeap(), 0, username);
|
||||||
HeapFree(GetProcessHeap(), 0, servername);
|
HeapFree(GetProcessHeap(), 0, servername);
|
||||||
if (status != noErr)
|
if (status != noErr)
|
||||||
|
@ -835,14 +779,14 @@ static DWORD mac_enumerate_credentials(LPCWSTR filter, PCREDENTIALW *credentials
|
||||||
SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed);
|
SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed);
|
||||||
SecKeychainSetUserInteractionAllowed(false);
|
SecKeychainSetUserInteractionAllowed(false);
|
||||||
|
|
||||||
status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
|
status = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, NULL, &search);
|
||||||
if (status == noErr)
|
if (status == noErr)
|
||||||
{
|
{
|
||||||
while (SecKeychainSearchCopyNext(search, &item) == noErr)
|
while (SecKeychainSearchCopyNext(search, &item) == noErr)
|
||||||
{
|
{
|
||||||
SecKeychainAttributeInfo info;
|
SecKeychainAttributeInfo info;
|
||||||
SecKeychainAttributeList *attr_list;
|
SecKeychainAttributeList *attr_list;
|
||||||
UInt32 info_tags[] = { kSecServerItemAttr };
|
UInt32 info_tags[] = { kSecServiceItemAttr };
|
||||||
BOOL match;
|
BOOL match;
|
||||||
|
|
||||||
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
||||||
|
@ -861,12 +805,12 @@ static DWORD mac_enumerate_credentials(LPCWSTR filter, PCREDENTIALW *credentials
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*len += sizeof(CREDENTIALW);
|
*len += sizeof(CREDENTIALW);
|
||||||
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr)
|
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServiceItemAttr)
|
||||||
{
|
{
|
||||||
SecKeychainItemFreeAttributesAndData(attr_list, NULL);
|
SecKeychainItemFreeAttributesAndData(attr_list, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("server item: %.*s\n", (int)attr_list->attr[0].length, (char *)attr_list->attr[0].data);
|
TRACE("service item: %.*s\n", (int)attr_list->attr[0].length, (char *)attr_list->attr[0].data);
|
||||||
match = mac_credential_matches_filter(attr_list->attr[0].data, attr_list->attr[0].length, filter);
|
match = mac_credential_matches_filter(attr_list->attr[0].data, attr_list->attr[0].length, filter);
|
||||||
SecKeychainItemFreeAttributesAndData(attr_list, NULL);
|
SecKeychainItemFreeAttributesAndData(attr_list, NULL);
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
|
@ -893,7 +837,7 @@ static DWORD mac_delete_credential(LPCWSTR TargetName)
|
||||||
{
|
{
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
SecKeychainSearchRef search;
|
SecKeychainSearchRef search;
|
||||||
status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
|
status = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, NULL, &search);
|
||||||
if (status == noErr)
|
if (status == noErr)
|
||||||
{
|
{
|
||||||
SecKeychainItemRef item;
|
SecKeychainItemRef item;
|
||||||
|
@ -901,7 +845,7 @@ static DWORD mac_delete_credential(LPCWSTR TargetName)
|
||||||
{
|
{
|
||||||
SecKeychainAttributeInfo info;
|
SecKeychainAttributeInfo info;
|
||||||
SecKeychainAttributeList *attr_list;
|
SecKeychainAttributeList *attr_list;
|
||||||
UInt32 info_tags[] = { kSecServerItemAttr };
|
UInt32 info_tags[] = { kSecServiceItemAttr };
|
||||||
LPWSTR target_name;
|
LPWSTR target_name;
|
||||||
INT str_len;
|
INT str_len;
|
||||||
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
||||||
|
@ -913,7 +857,7 @@ static DWORD mac_delete_credential(LPCWSTR TargetName)
|
||||||
WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
|
WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr)
|
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServiceItemAttr)
|
||||||
{
|
{
|
||||||
CFRelease(item);
|
CFRelease(item);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1481,7 +1425,7 @@ BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW
|
||||||
{
|
{
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
SecKeychainSearchRef search;
|
SecKeychainSearchRef search;
|
||||||
status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
|
status = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, NULL, &search);
|
||||||
if (status == noErr)
|
if (status == noErr)
|
||||||
{
|
{
|
||||||
SecKeychainItemRef item;
|
SecKeychainItemRef item;
|
||||||
|
@ -1489,7 +1433,7 @@ BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW
|
||||||
{
|
{
|
||||||
SecKeychainAttributeInfo info;
|
SecKeychainAttributeInfo info;
|
||||||
SecKeychainAttributeList *attr_list;
|
SecKeychainAttributeList *attr_list;
|
||||||
UInt32 info_tags[] = { kSecServerItemAttr };
|
UInt32 info_tags[] = { kSecServiceItemAttr };
|
||||||
LPWSTR target_name;
|
LPWSTR target_name;
|
||||||
INT str_len;
|
INT str_len;
|
||||||
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
info.count = sizeof(info_tags)/sizeof(info_tags[0]);
|
||||||
|
@ -1502,7 +1446,7 @@ BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW
|
||||||
WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
|
WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr)
|
if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServiceItemAttr)
|
||||||
{
|
{
|
||||||
CFRelease(item);
|
CFRelease(item);
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue