This could be fixed by @cron2 when he will apply this patch :)

ti 23. heinäk. 2019 klo 15.12 tincanteksup (tincantek...@gmail.com)
kirjoitti:

> Looks like a typo below:
>
> On 23/07/2019 10:21, Lev Stipakov wrote:
> > From: Lev Stipakov <l...@openvpn.net>
> >
> > This patch enables interactive service to open tun device.
> > This is mostly needed by Wintun, which could be opened
> > only by privileged process.
> >
> > When interactive service is used, instead of calling
> > CreateFile() directly by openvpn process we pass tun device path
> > into service process. There we open device, duplicate handle
> > and pass it back to openvpn process.
> >
> > Signed-off-by: Lev Stipakov <l...@openvpn.net>
> > ---
> >   v6:
> >    - simplify and strengthen guid check with wcsspn()
> >    - fix doxygen comment
> >
> >   v5:
> >    - further strengthen security by passing only device guid from client
> process
> >    to service, validating guid and constructing device path on service
> side
> >
> >   v4:
> >    - strengthen security by adding basic validation to device path
> >    - reorder fields in msg_open_tun_device_result for backward
> compatibility
> >
> >   v3:
> >    - ensure that device path passed by client is null-terminated
> >    - support for multiple openvpn processes
> >    - return proper error code when device handle is invalid
> >
> >   v2:
> >    - introduce send_msg_iservice_ex() instead of changing
> >    signature of existing send_msg_iservice()
> >    - use wchar_t strings in interactive service code
> >
> >   include/openvpn-msg.h         | 12 +++++++
> >   src/openvpn/tun.c             | 83
> ++++++++++++++++++++++++++++++++++---------
> >   src/openvpn/win32.c           |  9 ++++-
> >   src/openvpn/win32.h           | 30 +++++++++++++---
> >   src/openvpnserv/interactive.c | 78
> ++++++++++++++++++++++++++++++++++++++--
> >   5 files changed, 188 insertions(+), 24 deletions(-)
> >
> > diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h
> > index 66177a2..5dbdca5 100644
> > --- a/include/openvpn-msg.h
> > +++ b/include/openvpn-msg.h
> > @@ -39,6 +39,8 @@ typedef enum {
> >       msg_del_block_dns,
> >       msg_register_dns,
> >       msg_enable_dhcp,
> > +    msg_open_tun_device,
> > +    msg_open_tun_device_result,
> >   } message_type_t;
> >
> >   typedef struct {
> > @@ -117,4 +119,14 @@ typedef struct {
> >       interface_t iface;
> >   } enable_dhcp_message_t;
> >
> > +typedef struct {
> > +    message_header_t header;
> > +    char device_guid[36+2+1]; /* length of guid with dashes + braces +
> nul terminator */
> > +} open_tun_device_message_t;
> > +
> > +typedef struct {
> > +    message_header_t header;
> > +    int error_number;
> > +    HANDLE handle;
> > +} open_tun_device_result_message_t;
> >   #endif /* ifndef OPENVPN_MSG_H_ */
> > diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
> > index 8f8f7c6..df26ccf 100644
> > --- a/src/openvpn/tun.c
> > +++ b/src/openvpn/tun.c
> > @@ -5248,6 +5248,43 @@ out:
> >       return ret;
> >   }
> >
> > +static HANDLE
> > +service_open_tun_device(const HANDLE pipe, const char* device_guid)
> > +{
> > +    open_tun_device_result_message_t result_msg;
> > +    struct gc_arena gc = gc_new();
> > +    open_tun_device_message_t open_tun_device = {
> > +        .header = {
> > +            msg_open_tun_device,
> > +            sizeof(open_tun_device_message_t),
> > +            0
> > +        }
> > +    };
> > +    result_msg.handle = INVALID_HANDLE_VALUE;
> > +
> > +    strncpynt(open_tun_device.device_guid, device_guid,
> sizeof(open_tun_device.device_guid));
> > +
> > +    if (!send_msg_iservice_ex(pipe, &open_tun_device,
> sizeof(open_tun_device),
> > +        &result_msg, sizeof(result_msg), "Open_tun_device"))
> > +    {
> > +        goto out;
> > +    }
> > +
> > +    if (result_msg.error_number != NO_ERROR)
> > +    {
> > +        msg(D_TUNTAP_INFO, "TUN: opening tun handle using service
> failed: %s [status=%u device_path=%s]",
> > +            strerror_win32(result_msg.error_number, &gc),
> result_msg.error_number, device_guid);
> > +    }
> > +    else
> > +    {
> > +        msg(M_INFO, "Opened tun device %s using service", device_guid);
> > +    }
> > +
> > +out:
> > +    gc_free(&gc);
> > +    return result_msg.handle;
> > +}
> > +
> >   /*
> >    * Return a TAP name for netsh commands.
> >    */
> > @@ -5591,15 +5628,22 @@ open_tun(const char *dev, const char *dev_type,
> const char *dev_node, struct tun
> >                                device_guid,
> >                                TAP_WIN_SUFFIX);
> >
> > -            tt->hand = CreateFile(
> > -                device_path,
> > -                GENERIC_READ | GENERIC_WRITE,
> > -                0,                /* was: FILE_SHARE_READ */
> > -                0,
> > -                OPEN_EXISTING,
> > -                FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
> > -                0
> > +            if (tt->options.msg_channel)
> > +            {
> > +                tt->hand =
> service_open_tun_device(tt->options.msg_channel, device_guid);
> > +            }
> > +            else
> > +            {
> > +                tt->hand = CreateFile(
> > +                    device_path,
> > +                    GENERIC_READ | GENERIC_WRITE,
> > +                    0,                /* was: FILE_SHARE_READ */
> > +                    0,
> > +                    OPEN_EXISTING,
> > +                    FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
> > +                    0
> >                   );
> > +            }
> >
> >               if (tt->hand == INVALID_HANDLE_VALUE)
> >               {
> > @@ -5631,15 +5675,22 @@ open_tun(const char *dev, const char *dev_type,
> const char *dev_node, struct tun
> >                                    device_guid,
> >                                    TAP_WIN_SUFFIX);
> >
> > -                tt->hand = CreateFile(
> > -                    device_path,
> > -                    GENERIC_READ | GENERIC_WRITE,
> > -                    0,                /* was: FILE_SHARE_READ */
> > -                    0,
> > -                    OPEN_EXISTING,
> > -                    FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
> > -                    0
> > +                if (tt->options.msg_channel)
> > +                {
> > +                    tt->hand =
> service_open_tun_device(tt->options.msg_channel, device_guid);
> > +                }
> > +                else
> > +                {
> > +                    tt->hand = CreateFile(
> > +                        device_path,
> > +                        GENERIC_READ | GENERIC_WRITE,
> > +                        0,                /* was: FILE_SHARE_READ */
> > +                        0,
> > +                        OPEN_EXISTING,
> > +                        FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
> > +                        0
> >                       );
> > +                }
> >
> >                   if (tt->hand == INVALID_HANDLE_VALUE)
> >                   {
> > diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c
> > index eb4c030..039c1a4 100644
> > --- a/src/openvpn/win32.c
> > +++ b/src/openvpn/win32.c
> > @@ -1476,12 +1476,19 @@ bool
> >   send_msg_iservice(HANDLE pipe, const void *data, size_t size,
> >                     ack_message_t *ack, const char *context)
> >   {
> > +    return send_msg_iservice_ex(pipe, data, size, ack, sizeof(*ack),
> context);
> > +}
> > +
> > +bool
> > +send_msg_iservice_ex(HANDLE pipe, const void *data, size_t size,
> > +                     void *response, size_t response_size, const char
> *context)
> > +{
> >       struct gc_arena gc = gc_new();
> >       DWORD len;
> >       bool ret = true;
> >
> >       if (!WriteFile(pipe, data, size, &len, NULL)
> > -        || !ReadFile(pipe, ack, sizeof(*ack), &len, NULL))
> > +        || !ReadFile(pipe, response, response_size, &len, NULL))
> >       {
> >           msg(M_WARN, "%s: could not talk to service: %s [%lu]",
> >               context ? context : "Unknown",
> > diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h
> > index 4814bbc..eff4401 100644
> > --- a/src/openvpn/win32.h
> > +++ b/src/openvpn/win32.h
> > @@ -309,14 +309,36 @@ int win32_version_info(void);
> >    */
> >   const char *win32_version_string(struct gc_arena *gc, bool add_name);
> >
> > -/*
> > - * Send the |size| bytes in buffer |data| to the interactive service
> |pipe|
> > - * and read the result in |ack|. Returns false on communication error.
> > - * The string in |context| is used to prefix error messages.
> > +
> > +/**
> > + * Send data to interactive service and receive response of type
> ack_message_t.
> > + *
> > + * @param  pipe      The handle of communication pipe
> > + * @param  data      The data to send
> > + * @param  size      The size of data to send
> > + * @param  ack       The pointer to ack_message_t structure to where
> response is written
> > + * @param  context   The string used to prefix error messages
> > + *
> > + * @returns True on success, false on failure.
> >    */
> >   bool send_msg_iservice(HANDLE pipe, const void *data, size_t size,
> >                          ack_message_t *ack, const char *context);
> >
> > +/**
> > + * Send data to interactive service and receive response.
> > + *
> > + * @param  pipe           The handle of communication pipe
> > + * @param  data           The data to send
> > + * @param  size           The size of data to send
> > + * @param  response       The buffer to where response is written
> > + * @param  response_size  The size of response buffer
> > + * @param  context        The string used to prefix error messages
> > + *
> > + * @returns True on success, false on failure.
> > + */
> > +bool send_msg_iservice_ex(HANDLE pipe, const void *data, size_t size,
> > +                          void *response, size_t response_size, const
> char *context);
> > +
> >   /*
> >    * Attempt to simulate fork/execve on Windows
> >    */
> > diff --git a/src/openvpnserv/interactive.c
> b/src/openvpnserv/interactive.c
> > index 623c3ff..1b4a5e2 100644
> > --- a/src/openvpnserv/interactive.c
> > +++ b/src/openvpnserv/interactive.c
> > @@ -58,7 +58,6 @@ static settings_t settings;
> >   static HANDLE rdns_semaphore = NULL;
> >   #define RDNS_TIMEOUT 600  /* seconds to wait for the semaphore */
> >
> > -
> >   openvpn_service_t interactive_service = {
> >       interactive,
> >       TEXT(PACKAGE_NAME "ServiceInteractive"),
> > @@ -1198,8 +1197,62 @@ HandleEnableDHCPMessage(const
> enable_dhcp_message_t *dhcp)
> >       return err;
> >   }
> >
> > +static DWORD
> > +HandleOpenTunDeviceMessage(const open_tun_device_message_t *open_tun,
> HANDLE ovpn_proc, HANDLE *remote_handle)
> > +{
> > +    DWORD err = ERROR_SUCCESS;
> > +    HANDLE local_handle;
> > +    LPWSTR wguid = NULL;
> > +    WCHAR device_path[256] = {0};
> > +    const WCHAR prefix[] = L"\\\\.\\Global\\";
> > +    const WCHAR tap_suffix[] = L".tap";
> > +
> > +    *remote_handle = INVALID_HANDLE_VALUE;
> > +
> > +    wguid = utf8to16(open_tun->device_guid);
> > +    if (!wguid)
> > +    {
> > +        err = ERROR_OUTOFMEMORY;
> > +        goto out;
> > +    }
> > +
> > +    /* validate device guid */
> > +    const size_t guid_len = wcslen(wguid);
> > +    if (guid_len != 38 || wcsspn(wguid, L"0123456789ABCDEFabcdef-{}")
> != guid_len)
> > +    {
> > +        err = ERROR_MESSAGE_DATA;
> > +        MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Invalid device guild
> (%s)"), wguid);
>
> Invalid device "guild" ? I presume guid ..
>
>
> > +        goto out;
> > +    }
> > +
> > +    openvpn_swprintf(device_path, sizeof(device_path), L"%s%s%s",
> prefix, wguid, tap_suffix);
> > +
> > +    /* open tun device */
> > +    local_handle = CreateFileW(device_path, GENERIC_READ |
> GENERIC_WRITE, 0, 0,
> > +                               OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM |
> FILE_FLAG_OVERLAPPED, 0);
> > +    if (local_handle == INVALID_HANDLE_VALUE)
> > +    {
> > +        err = GetLastError();
> > +        MsgToEventLog(M_SYSERR, TEXT("Error opening tun device (%s)"),
> device_path);
> > +        goto out;
> > +    }
> > +
> > +    /* duplicate tun device handle to openvpn process */
> > +    if (!DuplicateHandle(GetCurrentProcess(), local_handle, ovpn_proc,
> remote_handle, 0, FALSE,
> > +                         DUPLICATE_CLOSE_SOURCE |
> DUPLICATE_SAME_ACCESS))
> > +    {
> > +        err = GetLastError();
> > +        MsgToEventLog(M_SYSERR, TEXT("Error duplicating tun device
> handle"));
> > +    }
> > +
> > +out:
> > +    free(wguid);
> > +
> > +    return err;
> > +}
> > +
> >   static VOID
> > -HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events,
> undo_lists_t *lists)
> > +HandleMessage(HANDLE pipe, HANDLE ovpn_proc, DWORD bytes, DWORD count,
> LPHANDLE events, undo_lists_t *lists)
> >   {
> >       DWORD read;
> >       union {
> > @@ -1210,6 +1263,7 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD
> count, LPHANDLE events, undo_lists
> >           block_dns_message_t block_dns;
> >           dns_cfg_message_t dns;
> >           enable_dhcp_message_t dhcp;
> > +        open_tun_device_message_t open_tun;
> >       } msg;
> >       ack_message_t ack = {
> >           .header = {
> > @@ -1277,6 +1331,24 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD
> count, LPHANDLE events, undo_lists
> >               }
> >               break;
> >
> > +        case msg_open_tun_device:
> > +            if (msg.header.size == sizeof(msg.open_tun))
> > +            {
> > +                open_tun_device_result_message_t res = {
> > +                    .header = {
> > +                        .type = msg_open_tun_device_result,
> > +                        .size = sizeof(res),
> > +                        .message_id = msg.header.message_id
> > +                    }
> > +                };
> > +                /* make sure that string passed from user process is
> null-terminated */
> > +
> msg.open_tun.device_guid[sizeof(msg.open_tun.device_guid) - 1] = '\0';
> > +                res.error_number =
> HandleOpenTunDeviceMessage(&msg.open_tun, ovpn_proc, &res.handle);
> > +                WritePipeAsync(pipe, &res, sizeof(res), count, events);
> > +                return;
> > +            }
> > +            break;
> > +
> >           default:
> >               ack.error_number = ERROR_MESSAGE_TYPE;
> >               MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type
> %d"), msg.header.type);
> > @@ -1611,7 +1683,7 @@ RunOpenvpn(LPVOID p)
> >               break;
> >           }
> >
> > -        HandleMessage(ovpn_pipe, bytes, 1, &exit_event, &undo_lists);
> > +        HandleMessage(ovpn_pipe, proc_info.hProcess, bytes, 1,
> &exit_event, &undo_lists);
> >       }
> >
> >       WaitForSingleObject(proc_info.hProcess, IO_TIMEOUT);
> >
>
>
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
>


-- 
-Lev
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to