Hans Leidekker : mountmgr: Add ioctl to write host credentials on macOS.

Alexandre Julliard julliard at winehq.org
Thu Sep 3 15:26:46 CDT 2020


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Thu Sep  3 14:59:04 2020 +0200

mountmgr: Add ioctl to write host credentials on macOS.

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

---

 dlls/mountmgr.sys/mountmgr.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
 include/ddk/mountmgr.h       |  1 +
 2 files changed, 100 insertions(+)

diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c
index d55ca64301..c3b9135ce1 100644
--- a/dlls/mountmgr.sys/mountmgr.c
+++ b/dlls/mountmgr.sys/mountmgr.c
@@ -731,6 +731,94 @@ static NTSTATUS read_credential( void *buff, SIZE_T insize, SIZE_T outsize, IO_S
     iosb->Information = size;
     return (size > outsize) ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
 }
+
+static NTSTATUS write_credential( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb )
+{
+    const struct mountmgr_credential *cred = buff;
+    int status, len, len_password = 0;
+    const WCHAR *ptr;
+    SecKeychainItemRef keychain_item;
+    char *targetname, *username = NULL, *password = NULL;
+    SecKeychainAttribute attrs[1];
+    SecKeychainAttributeList attr_list;
+    NTSTATUS ret = STATUS_NO_MEMORY;
+
+    if (!check_credential_string( buff, insize, cred->targetname_size, cred->targetname_offset ) ||
+        !check_credential_string( buff, insize, cred->username_size, cred->username_offset ) ||
+        ((cred->blob_size && cred->blob_size % sizeof(WCHAR)) || cred->blob_offset + cred->blob_size > insize) ||
+        (cred->comment_size && !check_credential_string( buff, insize, cred->comment_size, cred->comment_offset )) ||
+        sizeof(*cred) + cred->targetname_size + cred->username_size + cred->blob_size + cred->comment_size > insize)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    ptr = (const WCHAR *)((const char *)cred + cred->targetname_offset);
+    len = WideCharToMultiByte( CP_UTF8, 0, ptr, -1, NULL, 0, NULL, NULL );
+    if (!(targetname = RtlAllocateHeap( GetProcessHeap(), 0, len ))) goto error;
+    WideCharToMultiByte( CP_UTF8, 0, ptr, -1, targetname, len, NULL, NULL );
+
+    ptr = (const WCHAR *)((const char *)cred + cred->username_offset);
+    len = WideCharToMultiByte( CP_UTF8, 0, ptr, -1, NULL, 0, NULL, NULL );
+    if (!(username = RtlAllocateHeap( GetProcessHeap(), 0, len ))) goto error;
+    WideCharToMultiByte( CP_UTF8, 0, ptr, -1, username, len, NULL, NULL );
+
+    if (cred->blob_size)
+    {
+        ptr = (const WCHAR *)((const char *)cred + cred->blob_offset);
+        len_password = WideCharToMultiByte( CP_UTF8, 0, ptr, cred->blob_size / sizeof(WCHAR), NULL, 0, NULL, NULL );
+        if (!(password = RtlAllocateHeap( GetProcessHeap(), 0, len_password ))) goto error;
+        WideCharToMultiByte( CP_UTF8, 0, ptr, cred->blob_size / sizeof(WCHAR), password, len_password, NULL, NULL );
+    }
+
+    TRACE("adding target %s, username %s using Keychain\n", targetname, username );
+    status = SecKeychainAddGenericPassword( NULL, strlen(targetname), targetname, strlen(username), username,
+                                            len_password, password, &keychain_item );
+    if (status != noErr) ERR( "SecKeychainAddGenericPassword returned %d\n", status );
+    if (status == errSecDuplicateItem)
+    {
+        status = SecKeychainFindGenericPassword( NULL, strlen(targetname), targetname, strlen(username), username, NULL,
+                                                 NULL, &keychain_item );
+        if (status != noErr) ERR( "SecKeychainFindGenericPassword returned %d\n", status );
+    }
+    RtlFreeHeap( GetProcessHeap(), 0, username );
+    RtlFreeHeap( GetProcessHeap(), 0, targetname );
+    if (status != noErr)
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, password );
+        return STATUS_UNSUCCESSFUL;
+    }
+    if (cred->comment_size)
+    {
+        attr_list.count = 1;
+        attr_list.attr  = attrs;
+        attrs[0].tag    = kSecCommentItemAttr;
+        ptr = (const WCHAR *)((const char *)cred + cred->comment_offset);
+        attrs[0].length = WideCharToMultiByte( CP_UTF8, 0, ptr, -1, NULL, 0, NULL, NULL );
+        if (attrs[0].length) attrs[0].length--;
+        if (!(attrs[0].data = RtlAllocateHeap( GetProcessHeap(), 0, attrs[0].length ))) goto error;
+        WideCharToMultiByte( CP_UTF8, 0, ptr, -1, attrs[0].data, attrs[0].length, NULL, NULL );
+    }
+    else
+    {
+        attr_list.count = 0;
+        attr_list.attr  = NULL;
+    }
+    status = SecKeychainItemModifyAttributesAndData( keychain_item, &attr_list, cred->blob_preserve ? 0 : len_password,
+                                                     cred->blob_preserve ? NULL : password );
+
+    if (cred->comment_size) RtlFreeHeap( GetProcessHeap(), 0, attrs[0].data );
+    RtlFreeHeap( GetProcessHeap(), 0, password );
+    /* FIXME: set TargetAlias attribute */
+    CFRelease( keychain_item );
+    if (status != noErr) return STATUS_UNSUCCESSFUL;
+    return STATUS_SUCCESS;
+
+error:
+    RtlFreeHeap( GetProcessHeap(), 0, username );
+    RtlFreeHeap( GetProcessHeap(), 0, targetname );
+    RtlFreeHeap( GetProcessHeap(), 0, password );
+    return ret;
+}
 #endif /* __APPLE__ */
 
 /* handler for ioctls on the mount manager device */
@@ -810,6 +898,17 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp )
                                                   irpsp->Parameters.DeviceIoControl.OutputBufferLength,
                                                   &irp->IoStatus );
         break;
+    case IOCTL_MOUNTMGR_WRITE_CREDENTIAL:
+        if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_credential))
+        {
+            irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
+            break;
+        }
+        irp->IoStatus.u.Status = write_credential( irp->AssociatedIrp.SystemBuffer,
+                                                   irpsp->Parameters.DeviceIoControl.InputBufferLength,
+                                                   irpsp->Parameters.DeviceIoControl.OutputBufferLength,
+                                                   &irp->IoStatus );
+        break;
 #endif
     default:
         FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
diff --git a/include/ddk/mountmgr.h b/include/ddk/mountmgr.h
index c3d9407819..162bbf7107 100644
--- a/include/ddk/mountmgr.h
+++ b/include/ddk/mountmgr.h
@@ -75,6 +75,7 @@ struct mountmgr_unix_drive
 };
 
 #define IOCTL_MOUNTMGR_READ_CREDENTIAL       CTL_CODE(MOUNTMGRCONTROLTYPE, 48, METHOD_BUFFERED, FILE_READ_ACCESS)
+#define IOCTL_MOUNTMGR_WRITE_CREDENTIAL      CTL_CODE(MOUNTMGRCONTROLTYPE, 49, METHOD_BUFFERED, FILE_WRITE_ACCESS)
 
 struct mountmgr_credential
 {




More information about the wine-cvs mailing list