Hans Leidekker : advapi32: Read host credentials through mountmgr.

Alexandre Julliard julliard at winehq.org
Wed Sep 2 15:24:32 CDT 2020


Module: wine
Branch: master
Commit: faef38479c8519d95d6947f920497c0f020f712b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=faef38479c8519d95d6947f920497c0f020f712b

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Sep  2 15:08:00 2020 +0200

advapi32: Read host credentials through mountmgr.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/advapi32/cred.c | 154 +++++++++++++++++++++++++++++----------------------
 1 file changed, 88 insertions(+), 66 deletions(-)

diff --git a/dlls/advapi32/cred.c b/dlls/advapi32/cred.c
index 49a1c34d1c..07f4b9b03a 100644
--- a/dlls/advapi32/cred.c
+++ b/dlls/advapi32/cred.c
@@ -33,6 +33,9 @@
 #include "winreg.h"
 #include "wincred.h"
 #include "winternl.h"
+#include "winioctl.h"
+#define WINE_MOUNTMGR_EXTENSIONS
+#include "ddk/mountmgr.h"
 
 #include "crypt.h"
 
@@ -1389,6 +1392,86 @@ BOOL WINAPI CredReadA(LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *
     return TRUE;
 }
 
+static DWORD host_read_credential( const WCHAR *targetname, CREDENTIALW **ret_credential )
+{
+    struct mountmgr_credential *cred_in, *cred_out = NULL, *tmp;
+    DWORD err = ERROR_OUTOFMEMORY, size_in, size_out, size_name = (strlenW( targetname ) + 1) * sizeof(WCHAR);
+    HANDLE mgr;
+    WCHAR *ptr;
+    BOOL ret;
+
+    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_in = sizeof(*cred_in) + size_name;
+    if (!(cred_in = heap_alloc( size_in )))
+    {
+        CloseHandle( mgr );
+        return ERROR_OUTOFMEMORY;
+    }
+    cred_in->targetname_offset = sizeof(*cred_in);
+    cred_in->targetname_size   = size_name;
+    ptr = (WCHAR *)(cred_in + 1);
+    strcpyW( ptr, targetname );
+
+    size_out = 256;
+    if (!(cred_out = heap_alloc( size_out ))) goto done;
+
+    for (;;)
+    {
+        ret = DeviceIoControl( mgr, IOCTL_MOUNTMGR_READ_CREDENTIAL, cred_in, size_in, cred_out, size_out, NULL, NULL );
+        if (ret || (err = GetLastError()) != ERROR_MORE_DATA) break;
+        size_out *= 2;
+        if (!(tmp = heap_realloc( cred_out, size_out ))) goto done;
+        cred_out = tmp;
+    }
+
+    if (ret)
+    {
+        CREDENTIALW *credential;
+        DWORD size = sizeof(*credential) + cred_out->targetname_size + cred_out->username_size + cred_out->comment_size +
+                     cred_out->blob_size;
+
+        if (!(credential = heap_alloc_zero( size )))
+        {
+            err = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+        ptr = (WCHAR *)(credential + 1);
+
+        credential->Type = CRED_TYPE_DOMAIN_PASSWORD;
+        memcpy( ptr, (char *)cred_out + cred_out->targetname_offset, cred_out->targetname_size );
+        credential->TargetName = ptr;
+        ptr += strlenW( ptr ) + 1;
+        if (cred_out->comment_size)
+        {
+            memcpy( ptr, (char *)cred_out + cred_out->comment_offset, cred_out->comment_size );
+            credential->Comment = ptr;
+            ptr += strlenW( ptr ) + 1;
+        }
+        credential->LastWritten = cred_out->last_written;
+        if ((credential->CredentialBlobSize = cred_out->blob_size))
+        {
+            memcpy( ptr, (char *)cred_out + cred_out->blob_offset, cred_out->blob_size );
+            credential->CredentialBlob = (BYTE *)ptr;
+            ptr += cred_out->blob_size / sizeof(WCHAR);
+        }
+        credential->Persist = CRED_PERSIST_LOCAL_MACHINE;
+        memcpy( ptr, (char *)cred_out + cred_out->username_offset, cred_out->username_size );
+        credential->UserName = ptr;
+
+        *ret_credential = credential;
+        err = ERROR_SUCCESS;
+    }
+
+done:
+    heap_free( cred_in );
+    heap_free( cred_out );
+    CloseHandle( mgr );
+    return err;
+}
+
 /******************************************************************************
  * CredReadW [ADVAPI32.@]
  */
@@ -1423,77 +1506,16 @@ BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW
         return FALSE;
     }
 
-#ifdef __APPLE__
     if (Type == CRED_TYPE_DOMAIN_PASSWORD)
     {
-        int status;
-        SecKeychainSearchRef search;
-        status = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, NULL, &search);
-        if (status == noErr)
+        ret = host_read_credential( TargetName, Credential );
+        if (ret != ERROR_SUCCESS && ret != ERROR_NOT_SUPPORTED)
         {
-            SecKeychainItemRef item;
-            while (SecKeychainSearchCopyNext(search, &item) == noErr)
-            {
-                SecKeychainAttributeInfo info;
-                SecKeychainAttributeList *attr_list;
-                UInt32 info_tags[] = { kSecServiceItemAttr };
-                LPWSTR target_name;
-                INT str_len;
-                info.count = ARRAY_SIZE(info_tags);
-                info.tag = info_tags;
-                info.format = NULL;
-                status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL);
-                len = sizeof(**Credential);
-                if (status != noErr)
-                {
-                    WARN("SecKeychainItemCopyAttributesAndData returned status %d\n", status);
-                    continue;
-                }
-                if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServiceItemAttr)
-                {
-                    CFRelease(item);
-                    continue;
-                }
-                str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, NULL, 0);
-                target_name = heap_alloc((str_len + 1) * sizeof(WCHAR));
-                MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, target_name, str_len);
-                /* nul terminate */
-                target_name[str_len] = '\0';
-                if (strcmpiW(TargetName, target_name))
-                {
-                    CFRelease(item);
-                    heap_free(target_name);
-                    continue;
-                }
-                heap_free(target_name);
-                SecKeychainItemFreeAttributesAndData(attr_list, NULL);
-                ret = mac_read_credential_from_item(item, TRUE, NULL, NULL, &len);
-                if (ret == ERROR_SUCCESS)
-                {
-                    *Credential = heap_alloc(len);
-                    if (*Credential)
-                    {
-                        len = sizeof(**Credential);
-                        ret = mac_read_credential_from_item(item, TRUE, *Credential,
-                                                            (char *)(*Credential + 1), &len);
-                    }
-                    else
-                        ret = ERROR_OUTOFMEMORY;
-                    CFRelease(item);
-                    CFRelease(search);
-                    if (ret != ERROR_SUCCESS)
-                    {
-                        SetLastError(ret);
-                        return FALSE;
-                    }
-                    return TRUE;
-                }
-                CFRelease(item);
-            }
-            CFRelease(search);
+            SetLastError(ret);
+            return FALSE;
         }
+        if (ret == ERROR_SUCCESS) return TRUE;
     }
-#endif
 
     ret = open_cred_mgr_key(&hkeyMgr, FALSE);
     if (ret != ERROR_SUCCESS)




More information about the wine-cvs mailing list