From patchwork Tue Jun 25 23:51:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lev Stipakov X-Patchwork-Id: 765 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id iPCcDYxAE10QNAAAIUCqbw for ; Wed, 26 Jun 2019 05:53:16 -0400 Received: from proxy18.mail.iad3b.rsapps.net ([172.31.255.6]) by director8.mail.ord1d.rsapps.net with LMTP id oH5tCoxAE13cZgAAfY0hYg ; Wed, 26 Jun 2019 05:53:16 -0400 Received: from smtp30.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy18.mail.iad3b.rsapps.net with LMTP id mOqhA4xAE11fRgAA3NpJmQ ; Wed, 26 Jun 2019 05:53:16 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp30.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Suspicious-Flag: YES X-Classification-ID: 37899e66-97f8-11e9-ac19-525400502618-1-1 Received: from [216.105.38.7] ([216.105.38.7:50668] helo=lists.sourceforge.net) by smtp30.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 75/40-30814-B80431D5; Wed, 26 Jun 2019 05:53:15 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1hg4al-0007Rz-5d; Wed, 26 Jun 2019 09:51:51 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1hg4aj-0007Rl-Or for openvpn-devel@lists.sourceforge.net; Wed, 26 Jun 2019 09:51:49 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Qf8BVfZ1HNSpLwEF+OvPPjLbaqyJWjKxrXEwmo6X7ao=; b=TBJq1u8pAZl2TJskNX3q+C/iyh K/6sJcxVhj152G0mCauq1Jlu/AHhBdau05j9jVBAV7v1oWt9hqFGYMiknGT41goIw2aahU2iCdOi1 /K76Zpfo5Odjjdv5kyUfuJpIBQef6/7zPWOKwXbbjSD+VM2TcHEqSxxGHVXRd2o3T5Kk=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Qf8BVfZ1HNSpLwEF+OvPPjLbaqyJWjKxrXEwmo6X7ao=; b=AuPbbGd+kHZ92rw3LSz7ePJzLp Wfqw6iKVQsHQNjYRN7qorSqXK2zbu9fNUIRyYoArbcilQYtaW8BbMUzCJ3VqziVqrQ9gPXxgSlnuC ladKlDzEvvpMyoYp5NALLiWJtk9C3wfDZYPR+SOBsanFL6xqy73z5dttsNHfjM7L0NGA=; Received: from mail-lj1-f195.google.com ([209.85.208.195]) by sfi-mx-4.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.90_1) id 1hg4aq-00ECcX-N6 for openvpn-devel@lists.sourceforge.net; Wed, 26 Jun 2019 09:51:58 +0000 Received: by mail-lj1-f195.google.com with SMTP id p17so1536006ljg.1 for ; Wed, 26 Jun 2019 02:51:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=Qf8BVfZ1HNSpLwEF+OvPPjLbaqyJWjKxrXEwmo6X7ao=; b=NVxD7kpVi7gBRVOqJCWfPoqb4rwnxCRIdwfvA9tAmGDoueZ/0ql49PtNi2y6MvAkGn uTeAUIRTULHO+ej+EsNomenOKyVjiUIV/loLaT1ZvEDzeIkv7lCeaNs8wIWRE10RFY0k kAGg5GQ9ayfGedmRDDXGn1f6Strjg5AJpSofY6wNVUQa+5mRBHi8NLeLOTL/kD1UFvk9 iOmIfOnWuPQ2VSPp9PkGATVJof8ErcQqavhcr1cqDSHHcwxz34PpxZ6GkEjpL4tMF8dH 3U+/Yff3IXZcP7q9HpsY4L6YHO6fhHBA2jm6/MovDaeSFJnQ7DEQJYqV0BKwNl/jugQD cK2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=Qf8BVfZ1HNSpLwEF+OvPPjLbaqyJWjKxrXEwmo6X7ao=; b=h0PJjK+o/1ZYJvlejX8dbhJfA49FIKHd5a00UJfClL4vHo96raYT16WlloWJsc6K+Q q7pChg7fq4aSKp9KDAaZ39HTnP3vY8SaxWBEPQNWJRboCdcEcyKs+dLjbTIJ19ksRBeW gDinGELDMBBN1UN35yF01lGDIOwFACNtTbgRqWv7toWnEXkwthwCzE1F76K65pJxmUek d5vle203bFW29pfMwI8+hqXUG5SwXaKM4jlSBUam+i4MFosJsbu0MQZuFwVOOtuIOtU6 9UNstdTbnPiFzKuC+5SE3UnYT6pQkG5Gbn27WYnjQunI8nRg3+nntkFN3SHshyDV3YIH OqcQ== X-Gm-Message-State: APjAAAVI8VY9lX1NEAoeKAOyS/1S4l7W7DUj/D4WWF7nOWqvKAKgT29b DOv3AZ4TMdU0L3i/+3vvYATY0aKo12+EbA== X-Google-Smtp-Source: APXvYqwUoStUDxq70tbdPb8BRWSSU1jWdazcziboNWuzhgWwoYzctYhgbEC3uSJ82Qat3GqxviCrWw== X-Received: by 2002:a2e:635d:: with SMTP id x90mr2349737ljb.140.1561542709343; Wed, 26 Jun 2019 02:51:49 -0700 (PDT) Received: from stipakov.fi (stipakov.fi. [128.199.52.117]) by smtp.gmail.com with ESMTPSA id n7sm2354487lfi.68.2019.06.26.02.51.48 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 26 Jun 2019 02:51:48 -0700 (PDT) From: Lev Stipakov To: openvpn-devel@lists.sourceforge.net Date: Wed, 26 Jun 2019 12:51:30 +0300 Message-Id: <1561542690-17559-1-git-send-email-lstipakov@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.208.195 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (lstipakov[at]gmail.com) 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: openvpn.net] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.208.195 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1hg4aq-00ECcX-N6 Subject: [Openvpn-devel] [PATCH v2] openvpnserv: enable interactive service to open tun X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Lev Stipakov 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 --- 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 | 60 +++++++++++++++++++++++++++++++++++++------ src/openvpn/win32.c | 9 ++++++- src/openvpn/win32.h | 30 +++++++++++++++++++--- src/openvpnserv/interactive.c | 57 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 154 insertions(+), 14 deletions(-) diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h index 66177a2..273d9a6 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_path[512]; +} open_tun_device_message_t; + +typedef struct { + message_header_t header; + HANDLE handle; + int error_number; +} 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..6caba50 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_path) +{ + 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_path, device_path, sizeof(open_tun_device.device_path)); + + 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_path); + } + else + { + msg(M_INFO, "Opened tun device %s using service", device_path); + } + +out: + gc_free(&gc); + return result_msg.handle; +} + /* * Return a TAP name for netsh commands. */ @@ -5631,15 +5668,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_path); + } + 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..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 + * @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..81d556b 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -57,7 +57,7 @@ static HANDLE exit_event = NULL; static settings_t settings; static HANDLE rdns_semaphore = NULL; #define RDNS_TIMEOUT 600 /* seconds to wait for the semaphore */ - +static HANDLE ovpn_process = NULL; /* used by DuplicateHandle() when passing tun device handle to openvpn process */ openvpn_service_t interactive_service = { interactive, @@ -1198,6 +1198,42 @@ HandleEnableDHCPMessage(const enable_dhcp_message_t *dhcp) return err; } +static DWORD +HandleOpenTunDeviceMessage(const open_tun_device_message_t *open_tun, HANDLE *remote_handle) +{ + DWORD err = 0; + + *remote_handle = INVALID_HANDLE_VALUE; + + LPWSTR device_path = utf8to16(open_tun->device_path); + if (!device_path) + { + err = ERROR_OUTOFMEMORY; + goto out; + } + + HANDLE 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) + { + MsgToEventLog(M_SYSERR, TEXT("Error opening tun device (%s)"), device_path); + goto out; + } + + if (!DuplicateHandle(GetCurrentProcess(), local_handle, ovpn_process, remote_handle, 0, FALSE, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) + { + err = GetLastError(); + MsgToEventLog(M_SYSERR, TEXT("Error duplicating tun device handle")); + } + +out: + free(device_path); + + return err; +} + static VOID HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) { @@ -1210,6 +1246,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 +1314,22 @@ 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 + } + }; + res.error_number = HandleOpenTunDeviceMessage(&msg.open_tun, &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); @@ -1603,6 +1656,8 @@ RunOpenvpn(LPVOID p) free(input); } + ovpn_process = proc_info.hProcess; + while (TRUE) { DWORD bytes = PeekNamedPipeAsync(ovpn_pipe, 1, &exit_event);