Hi,

On Thu, Jul 18, 2019 at 7:42 AM Lev Stipakov <lstipa...@gmail.com> 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>
> ---
>  v5:
>   - futher strengthen security by passing only device guid from client
> process
>

"further"


>   to service, validating guid and contructing device path on service side
>

"constructing"


>
>  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 | 83
> +++++++++++++++++++++++++++++++++++++++++--
>  5 files changed, 193 insertions(+), 24 deletions(-)



diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h
> index 4814bbc..8ccddc0 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  response  The pointer to ack_message_t structure to where
> response is written
>

That would be "@param ack"


> + * @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);
>
>


>
> diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c
> index 623c3ff..782c04d 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,67 @@ 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);
> +    for (int i = 0; i < guid_len; ++i)
> +    {
> +        const WCHAR ch = wguid[i];
> +
> +        if (!(iswalnum(ch)) && (ch != L'-') && (ch != L'{') && (ch !=
> L'}'))
> +        {
> +            err = ERROR_MESSAGE_DATA;
> +            MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Invalid device guild
> (%s)"), wguid);
> +            goto out;
> +        }
> +    }
>

I think the check could be made tighter than alpha numerics (only hex
digits need be allowed) and simpler like:

if (guid_len != 38 || wcspn(wguid, L"0123456789ABCDEFabcdef-{}") !=
guid_len)
{
    <handle the error and goto out>
}

I would have preferred to do a GUID parsing to validate it, but may be this
is good enough?

+
> +    openvpn_swprintf(device_path, sizeof(device_path), L"%s%s%s", prefix,
> wguid, tap_suffix);
> +
> +    /* open tun device */
> +
>

...

Thanks,

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

Reply via email to