[PATCH 6/6] advapi32: Enumerate host credentials through mountmgr.

Hans Leidekker hans at codeweavers.com
Thu Sep 3 07:59:09 CDT 2020


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/advapi32/Makefile.in |   1 -
 dlls/advapi32/cred.c      | 405 ++++++++++----------------------------
 2 files changed, 109 insertions(+), 297 deletions(-)

diff --git a/dlls/advapi32/Makefile.in b/dlls/advapi32/Makefile.in
index e70b1a7a07a..99bc26572ec 100644
--- a/dlls/advapi32/Makefile.in
+++ b/dlls/advapi32/Makefile.in
@@ -3,7 +3,6 @@ MODULE    = advapi32.dll
 IMPORTLIB = advapi32
 IMPORTS   = kernelbase sechost
 DELAYIMPORTS = rpcrt4
-EXTRALIBS = $(SECURITY_LIBS)
 
 C_SRCS = \
 	advapi.c \
diff --git a/dlls/advapi32/cred.c b/dlls/advapi32/cred.c
index 24bcd284145..10bcf4acb26 100644
--- a/dlls/advapi32/cred.c
+++ b/dlls/advapi32/cred.c
@@ -22,12 +22,6 @@
 #include <time.h>
 #include <limits.h>
 
-#ifdef __APPLE__
-# include <Security/SecKeychain.h>
-# include <Security/SecKeychainItem.h>
-# include <Security/SecKeychainSearch.h>
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
@@ -237,189 +231,6 @@ static DWORD registry_read_credential(HKEY hkey, PCREDENTIALW credential,
     return ret;
 }
 
-#ifdef __APPLE__
-static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require_password,
-                                           PCREDENTIALW credential, char *buffer,
-                                           DWORD *len)
-{
-    int status;
-    UInt32 i, cred_blob_len;
-    void *cred_blob;
-    WCHAR *user = NULL;
-    BOOL user_name_present = FALSE;
-    SecKeychainAttributeInfo info;
-    SecKeychainAttributeList *attr_list;
-    UInt32 info_tags[] = { kSecServiceItemAttr, kSecAccountItemAttr,
-                           kSecCommentItemAttr, kSecCreationDateItemAttr };
-    info.count = ARRAY_SIZE(info_tags);
-    info.tag = info_tags;
-    info.format = NULL;
-    status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, &cred_blob);
-    if (status == errSecAuthFailed && !require_password)
-    {
-        cred_blob_len = 0;
-        cred_blob = NULL;
-        status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, NULL);
-    }
-    if (status != noErr)
-    {
-        WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status);
-        return ERROR_NOT_FOUND;
-    }
-
-    for (i = 0; i < attr_list->count; i++)
-        if (attr_list->attr[i].tag == kSecAccountItemAttr && attr_list->attr[i].data)
-        {
-            user_name_present = TRUE;
-            break;
-        }
-    if (!user_name_present)
-    {
-        WARN("no kSecAccountItemAttr for item\n");
-        SecKeychainItemFreeAttributesAndData(attr_list, cred_blob);
-        return ERROR_NOT_FOUND;
-    }
-
-    if (buffer)
-    {
-        credential->Flags = 0;
-        credential->Type = CRED_TYPE_DOMAIN_PASSWORD;
-        credential->TargetName = NULL;
-        credential->Comment = NULL;
-        memset(&credential->LastWritten, 0, sizeof(credential->LastWritten));
-        credential->CredentialBlobSize = 0;
-        credential->CredentialBlob = NULL;
-        credential->Persist = CRED_PERSIST_LOCAL_MACHINE;
-        credential->AttributeCount = 0;
-        credential->Attributes = NULL;
-        credential->TargetAlias = NULL;
-        credential->UserName = NULL;
-    }
-    for (i = 0; i < attr_list->count; i++)
-    {
-        switch (attr_list->attr[i].tag)
-        {
-            case kSecServiceItemAttr:
-                TRACE("kSecServiceItemAttr: %.*s\n", (int)attr_list->attr[i].length,
-                      (char *)attr_list->attr[i].data);
-                if (!attr_list->attr[i].data) continue;
-                if (buffer)
-                {
-                    INT str_len;
-                    credential->TargetName = (LPWSTR)buffer;
-                    str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
-                                                  attr_list->attr[i].length, (LPWSTR)buffer, 0xffff);
-                    credential->TargetName[str_len] = '\0';
-                    buffer += (str_len + 1) * sizeof(WCHAR);
-                    *len += (str_len + 1) * sizeof(WCHAR);
-                }
-                else
-                {
-                    INT str_len;
-                    str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
-                                                  attr_list->attr[i].length, NULL, 0);
-                    *len += (str_len + 1) * sizeof(WCHAR);
-                }
-                break;
-            case kSecAccountItemAttr:
-            {
-                INT str_len;
-                TRACE("kSecAccountItemAttr: %.*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);
-                user = heap_alloc((str_len + 1) * sizeof(WCHAR));
-                MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
-                                    attr_list->attr[i].length, user, str_len);
-                user[str_len] = '\0';
-                break;
-            }
-            case kSecCommentItemAttr:
-                TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list->attr[i].length,
-                      (char *)attr_list->attr[i].data);
-                if (!attr_list->attr[i].data) continue;
-                if (buffer)
-                {
-                    INT str_len;
-                    credential->Comment = (LPWSTR)buffer;
-                    str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
-                                                  attr_list->attr[i].length, (LPWSTR)buffer, 0xffff);
-                    credential->Comment[str_len] = '\0';
-                    buffer += (str_len + 1) * sizeof(WCHAR);
-                    *len += (str_len + 1) * sizeof(WCHAR);
-                }
-                else
-                {
-                    INT str_len;
-                    str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
-                                                  attr_list->attr[i].length, NULL, 0);
-                    *len += (str_len + 1) * sizeof(WCHAR);
-                }
-                break;
-            case kSecCreationDateItemAttr:
-                TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list->attr[i].length,
-                      (char *)attr_list->attr[i].data);
-                if (!attr_list->attr[i].data) continue;
-                if (buffer)
-                {
-                    LARGE_INTEGER win_time;
-                    struct tm tm;
-                    time_t time;
-                    memset(&tm, 0, sizeof(tm));
-                    strptime(attr_list->attr[i].data, "%Y%m%d%H%M%SZ", &tm);
-                    time = mktime(&tm);
-                    RtlSecondsSince1970ToTime(time, &win_time);
-                    credential->LastWritten.dwLowDateTime = win_time.u.LowPart;
-                    credential->LastWritten.dwHighDateTime = win_time.u.HighPart;
-                }
-                break;
-            default:
-                FIXME("unhandled attribute %u\n", (unsigned)attr_list->attr[i].tag);
-                break;
-        }
-    }
-
-    if (user)
-    {
-        INT str_len;
-        if (buffer)
-            credential->UserName = (LPWSTR)buffer;
-        str_len = strlenW(user);
-        *len += (str_len + 1) * sizeof(WCHAR);
-        if (buffer)
-        {
-            memcpy(buffer, user, (str_len + 1) * sizeof(WCHAR));
-            buffer += (str_len + 1) * sizeof(WCHAR);
-            TRACE("UserName = %s\n", debugstr_w(credential->UserName));
-        }
-    }
-    heap_free(user);
-
-    if (cred_blob)
-    {
-        if (buffer)
-        {
-            INT str_len;
-            credential->CredentialBlob = (BYTE *)buffer;
-            str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len,
-                                          (LPWSTR)buffer, 0xffff);
-            credential->CredentialBlobSize = str_len * sizeof(WCHAR);
-            *len += str_len * sizeof(WCHAR);
-        }
-        else
-        {
-            INT str_len;
-            str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len,
-                                          NULL, 0);
-            *len += str_len * sizeof(WCHAR);
-        }
-    }
-    SecKeychainItemFreeAttributesAndData(attr_list, cred_blob);
-    return ERROR_SUCCESS;
-}
-#endif
-
 static DWORD write_credential_blob(HKEY hkey, LPCWSTR target_name, DWORD type,
                                    const BYTE key_data[KEY_SIZE],
                                    const BYTE *credential_blob, DWORD credential_blob_size)
@@ -736,98 +547,6 @@ static DWORD registry_enumerate_credentials(HKEY hkeyMgr, LPCWSTR filter,
     return ret;
 }
 
-#ifdef __APPLE__
-static BOOL mac_credential_matches_filter(void *data, UInt32 data_len, const WCHAR *filter)
-{
-    int len;
-    WCHAR *target_name;
-    const WCHAR *p;
-    BOOL ret;
-
-    if (!filter) return TRUE;
-
-    len = MultiByteToWideChar(CP_UTF8, 0, data, data_len, NULL, 0);
-    if (!(target_name = heap_alloc((len + 1) * sizeof(WCHAR)))) return FALSE;
-    MultiByteToWideChar(CP_UTF8, 0, data, data_len, target_name, len);
-    target_name[len] = 0;
-
-    TRACE("comparing filter %s to target name %s\n", debugstr_w(filter), debugstr_w(target_name));
-
-    p = strchrW(filter, '*');
-    ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, filter,
-                         (p && !p[1] ? p - filter : -1), target_name,
-                         (p && !p[1] ? p - filter : -1)) == CSTR_EQUAL;
-    heap_free(target_name);
-    return ret;
-}
-
-static DWORD mac_enumerate_credentials(LPCWSTR filter, PCREDENTIALW *credentials,
-                                       char *buffer, DWORD *len, DWORD *count)
-{
-    SecKeychainSearchRef search;
-    SecKeychainItemRef item;
-    int status;
-    Boolean saved_user_interaction_allowed;
-    DWORD ret;
-
-    SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed);
-    SecKeychainSetUserInteractionAllowed(false);
-
-    status = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, NULL, &search);
-    if (status == noErr)
-    {
-        while (SecKeychainSearchCopyNext(search, &item) == noErr)
-        {
-            SecKeychainAttributeInfo info;
-            SecKeychainAttributeList *attr_list;
-            UInt32 info_tags[] = { kSecServiceItemAttr };
-            BOOL match;
-
-            info.count = ARRAY_SIZE(info_tags);
-            info.tag = info_tags;
-            info.format = NULL;
-            status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL);
-            if (status != noErr)
-            {
-                WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status);
-                continue;
-            }
-            if (buffer)
-            {
-                *len = sizeof(CREDENTIALW);
-                credentials[*count] = (PCREDENTIALW)buffer;
-            }
-            else
-                *len += sizeof(CREDENTIALW);
-            if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServiceItemAttr)
-            {
-                SecKeychainItemFreeAttributesAndData(attr_list, NULL);
-                continue;
-            }
-            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);
-            SecKeychainItemFreeAttributesAndData(attr_list, NULL);
-            if (!match) continue;
-            ret = mac_read_credential_from_item(item, FALSE,
-                                                buffer ? credentials[*count] : NULL,
-                                                buffer ? buffer + sizeof(CREDENTIALW) : NULL,
-                                                len);
-            CFRelease(item);
-            if (ret == ERROR_SUCCESS)
-            {
-                (*count)++;
-                if (buffer) buffer += *len;
-            }
-        }
-        CFRelease(search);
-    }
-    else
-        ERR("SecKeychainSearchCreateFromAttributes returned status %d\n", status);
-    SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed);
-    return ERROR_SUCCESS;
-}
-#endif
-
 /******************************************************************************
  * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
  *
@@ -1194,11 +913,113 @@ BOOL WINAPI CredEnumerateA(LPCSTR Filter, DWORD Flags, DWORD *Count,
     return TRUE;
 }
 
+#define CRED_LIST_COUNT 16
+#define CRED_DATA_SIZE  2048
+static DWORD host_enumerate_credentials( const WCHAR *filter, CREDENTIALW **credentials, char *buf, DWORD *len, DWORD *count )
+{
+    static const WCHAR emptyW[] = {0};
+    struct mountmgr_credential_list *list, *tmp;
+    DWORD i, j, ret, size, filter_size, offset = 0;
+    HANDLE mgr;
+    WCHAR *ptr;
+
+    if (filter) filter_size = (strlenW( filter ) + 1) * sizeof(WCHAR);
+    else
+    {
+        filter = emptyW;
+        filter_size = sizeof(emptyW);
+    }
+
+    mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+    if (mgr == INVALID_HANDLE_VALUE) return GetLastError();
+
+    size = FIELD_OFFSET( struct mountmgr_credential_list, creds[CRED_LIST_COUNT] ) + filter_size + CRED_DATA_SIZE;
+    if (!(list = heap_alloc( size )))
+    {
+        CloseHandle( mgr );
+        return ERROR_OUTOFMEMORY;
+    }
+
+    for (;;)
+    {
+        list->filter_offset = sizeof(*list);
+        list->filter_size   = filter_size;
+        ptr = (WCHAR *)((char *)list + list->filter_offset);
+        strcpyW( ptr, filter );
+
+        if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_ENUMERATE_CREDENTIALS, list, size, list, size, NULL, NULL )) break;
+        if ((ret = GetLastError()) != ERROR_MORE_DATA) goto done;
+
+        size = list->size + filter_size;
+        if (!(tmp = heap_realloc( list, size )))
+        {
+            ret = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+        list = tmp;
+    }
+
+    for (i = 0, j = *count; i < list->count; i++)
+    {
+        CREDENTIALW *cred = (CREDENTIALW *)(buf + offset);
+
+        offset += sizeof(*cred) + list->creds[i].targetname_size + list->creds[i].comment_size + list->creds[i].blob_size +
+                  list->creds[i].username_size;
+        if (!buf) continue;
+
+        ptr = (WCHAR *)(cred + 1);
+        cred->Flags      = 0;
+        cred->Type       = CRED_TYPE_DOMAIN_PASSWORD;
+        cred->TargetName = ptr;
+        memcpy( cred->TargetName, (char *)&list->creds[i] + list->creds[i].targetname_offset, list->creds[i].targetname_size );
+        ptr += list->creds[i].targetname_size / sizeof(WCHAR);
+        if (list->creds[i].comment_size)
+        {
+            cred->Comment = ptr;
+            memcpy( cred->Comment, (char *)&list->creds[i] + list->creds[i].comment_offset, list->creds[i].comment_size );
+            ptr += list->creds[i].comment_size / sizeof(WCHAR);
+        }
+        else cred->Comment = NULL;
+        cred->LastWritten = list->creds[i].last_written;
+        if (list->creds[i].blob_size)
+        {
+            cred->CredentialBlobSize = list->creds[i].blob_size;
+            cred->CredentialBlob     = (BYTE *)ptr;
+            memcpy( cred->CredentialBlob, (char *)&list->creds[i] + list->creds[i].blob_offset, list->creds[i].blob_size );
+            ptr += list->creds[i].blob_size / sizeof(WCHAR);
+        }
+        else
+        {
+            cred->CredentialBlobSize = 0;
+            cred->CredentialBlob     = NULL;
+        }
+        cred->Persist        = CRED_PERSIST_LOCAL_MACHINE;
+        cred->AttributeCount = 0;
+        cred->Attributes     = NULL;
+        cred->TargetAlias    = NULL;
+        if (list->creds[i].username_size)
+        {
+            cred->UserName = ptr;
+            memcpy( cred->UserName, (char *)&list->creds[i] + list->creds[i].username_offset, list->creds[i].username_size );
+        }
+        else cred->UserName = NULL;
+        if (credentials) credentials[j++] = cred;
+    }
+
+    *len += offset;
+    *count += list->count;
+    ret = ERROR_SUCCESS;
+
+done:
+    heap_free( list );
+    CloseHandle( mgr );
+    return ret;
+}
+
 /******************************************************************************
  * CredEnumerateW [ADVAPI32.@]
  */
-BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
-                           PCREDENTIALW **Credentials)
+BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count, PCREDENTIALW **Credentials)
 {
     HKEY hkeyMgr;
     DWORD ret;
@@ -1252,10 +1073,8 @@ BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
     len = 0;
     ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len,
                                          key_data, NULL, NULL, &len, Count);
-#ifdef __APPLE__
     if (ret == ERROR_SUCCESS)
-        ret = mac_enumerate_credentials(Filter, NULL, NULL, &len, Count);
-#endif
+        ret = host_enumerate_credentials(Filter, NULL, NULL, &len, Count);
     if (ret == ERROR_SUCCESS && *Count == 0)
         ret = ERROR_NOT_FOUND;
     if (ret != ERROR_SUCCESS)
@@ -1275,18 +1094,12 @@ BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
         {
             buffer += *Count * sizeof(PCREDENTIALW);
             *Count = 0;
-            ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name,
-                                                 target_name_len, key_data,
-                                                 *Credentials, &buffer, &len,
-                                                 Count);
-#ifdef __APPLE__
+            ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len, key_data,
+                                                 *Credentials, &buffer, &len, Count);
             if (ret == ERROR_SUCCESS)
-                ret = mac_enumerate_credentials(Filter, *Credentials,
-                                                buffer, &len, Count);
-#endif
+                ret = host_enumerate_credentials(Filter, *Credentials, buffer, &len, Count);
         }
-        else
-            ret = ERROR_OUTOFMEMORY;
+        else ret = ERROR_OUTOFMEMORY;
     }
 
     heap_free(target_name);
-- 
2.20.1




More information about the wine-devel mailing list