summaryrefslogtreecommitdiff
path: root/src/openvpnserv
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpnserv')
-rw-r--r--src/openvpnserv/Makefile.am5
-rw-r--r--src/openvpnserv/Makefile.in17
-rw-r--r--src/openvpnserv/automatic.c25
-rw-r--r--src/openvpnserv/common.c36
-rw-r--r--src/openvpnserv/interactive.c395
-rw-r--r--src/openvpnserv/openvpnserv.vcxproj186
-rw-r--r--src/openvpnserv/openvpnserv.vcxproj.filters25
-rw-r--r--src/openvpnserv/service.c4
-rw-r--r--src/openvpnserv/service.h11
-rw-r--r--src/openvpnserv/validate.c13
-rw-r--r--src/openvpnserv/validate.h2
11 files changed, 560 insertions, 159 deletions
diff --git a/src/openvpnserv/Makefile.am b/src/openvpnserv/Makefile.am
index bc65070..b067fb9 100644
--- a/src/openvpnserv/Makefile.am
+++ b/src/openvpnserv/Makefile.am
@@ -5,7 +5,7 @@
# packet encryption, packet authentication, and
# packet compression.
#
-# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
+# Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
# Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com>
#
@@ -36,4 +36,5 @@ openvpnserv_SOURCES = \
service.c service.h \
validate.c validate.h \
$(top_srcdir)/src/openvpn/block_dns.c $(top_srcdir)/src/openvpn/block_dns.h \
- openvpnserv_resources.rc
+ openvpnserv_resources.rc \
+ $(top_srcdir)/src/openvpn/ring_buffer.h
diff --git a/src/openvpnserv/Makefile.in b/src/openvpnserv/Makefile.in
index 90a9abe..18eb55e 100644
--- a/src/openvpnserv/Makefile.in
+++ b/src/openvpnserv/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -21,7 +21,7 @@
# packet encryption, packet authentication, and
# packet compression.
#
-# Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
+# Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
# Copyright (C) 2006-2012 Alon Bar-Lev <alon.barlev@gmail.com>
#
@@ -226,7 +226,8 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
-CMAKE = @CMAKE@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -240,6 +241,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLE_UNITTESTS = @ENABLE_UNITTESTS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GIT = @GIT@
@@ -267,7 +269,6 @@ LZ4_LIBS = @LZ4_LIBS@
LZO_CFLAGS = @LZO_CFLAGS@
LZO_LIBS = @LZO_LIBS@
MAKEINFO = @MAKEINFO@
-MAN2HTML = @MAN2HTML@
MANIFEST_TOOL = @MANIFEST_TOOL@
MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@
MBEDTLS_LIBS = @MBEDTLS_LIBS@
@@ -318,6 +319,8 @@ PLUGIN_AUTH_PAM_LIBS = @PLUGIN_AUTH_PAM_LIBS@
RANLIB = @RANLIB@
RC = @RC@
ROUTE = @ROUTE@
+RST2HTML = @RST2HTML@
+RST2MAN = @RST2MAN@
SED = @SED@
SELINUX_LIBS = @SELINUX_LIBS@
SET_MAKE = @SET_MAKE@
@@ -381,6 +384,7 @@ plugindir = @plugindir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sampledir = @sampledir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
@@ -417,7 +421,8 @@ openvpnserv_SOURCES = \
service.c service.h \
validate.c validate.h \
$(top_srcdir)/src/openvpn/block_dns.c $(top_srcdir)/src/openvpn/block_dns.h \
- openvpnserv_resources.rc
+ openvpnserv_resources.rc \
+ $(top_srcdir)/src/openvpn/ring_buffer.h
all: all-am
diff --git a/src/openvpnserv/automatic.c b/src/openvpnserv/automatic.c
index 5569ce9..3f2ca34 100644
--- a/src/openvpnserv/automatic.c
+++ b/src/openvpnserv/automatic.c
@@ -36,13 +36,9 @@
#include <stdio.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <process.h>
-/* bool definitions */
-#define bool int
-#define true 1
-#define false 0
-
static SERVICE_STATUS_HANDLE service;
static SERVICE_STATUS status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
@@ -115,41 +111,36 @@ close_if_open(HANDLE h)
static bool
match(const WIN32_FIND_DATA *find, LPCTSTR ext)
{
- int i;
-
if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
return false;
}
- if (!_tcslen(ext))
+ if (*ext == TEXT('\0'))
{
return true;
}
- i = _tcslen(find->cFileName) - _tcslen(ext) - 1;
- if (i < 1)
- {
- return false;
- }
+ /* find the pointer to that last '.' in filename and match ext against the rest */
- return find->cFileName[i] == '.' && !_tcsicmp(find->cFileName + i + 1, ext);
+ const TCHAR *p = _tcsrchr(find->cFileName, TEXT('.'));
+ return p && p != find->cFileName && _tcsicmp(p + 1, ext) == 0;
}
/*
* Modify the extension on a filename.
*/
static bool
-modext(LPTSTR dest, int size, LPCTSTR src, LPCTSTR newext)
+modext(LPTSTR dest, size_t size, LPCTSTR src, LPCTSTR newext)
{
- int i;
+ size_t i;
if (size > 0 && (_tcslen(src) + 1) <= size)
{
_tcscpy(dest, src);
dest [size - 1] = TEXT('\0');
i = _tcslen(dest);
- while (--i >= 0)
+ while (i-- > 0)
{
if (dest[i] == TEXT('\\'))
{
diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c
index eb718d4..f7b061c 100644
--- a/src/openvpnserv/common.c
+++ b/src/openvpnserv/common.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2011-2018 Heiko Hund <heiko.hund@sophos.com>
+ * Copyright (C) 2011-2021 Heiko Hund <heiko.hund@sophos.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -31,7 +31,7 @@ static wchar_t win_sys_path[MAX_PATH];
* These are necessary due to certain buggy implementations of (v)snprintf,
* that don't guarantee null termination for size > 0.
*/
-int
+BOOL
openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist)
{
int len = -1;
@@ -40,20 +40,36 @@ openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist)
len = _vsntprintf(str, size, format, arglist);
str[size - 1] = 0;
}
- return (len >= 0 && len < size);
+ return (len >= 0 && (size_t)len < size);
}
-int
+
+BOOL
openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...)
{
va_list arglist;
+ BOOL res = FALSE;
+ if (size > 0)
+ {
+ va_start(arglist, format);
+ res = openvpn_vsntprintf(str, size, format, arglist);
+ va_end(arglist);
+ }
+ return res;
+}
+
+BOOL
+openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...)
+{
+ va_list arglist;
int len = -1;
if (size > 0)
{
va_start(arglist, format);
- len = openvpn_vsntprintf(str, size, format, arglist);
+ len = vswprintf(str, size, format, arglist);
va_end(arglist);
+ str[size - 1] = L'\0';
}
- return len;
+ return (len >= 0 && len < size);
}
static DWORD
@@ -65,7 +81,7 @@ GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size, LPCTSTR default_v
if (status == ERROR_FILE_NOT_FOUND && default_value)
{
size_t len = size/sizeof(data[0]);
- if (openvpn_sntprintf(data, len, default_value) > 0)
+ if (openvpn_sntprintf(data, len, default_value))
{
status = ERROR_SUCCESS;
}
@@ -212,12 +228,14 @@ out:
LPCTSTR
GetLastErrorText()
{
+ DWORD error;
static TCHAR buf[256];
DWORD len;
LPTSTR tmp = NULL;
+ error = GetLastError();
len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&tmp, 0, NULL);
+ NULL, error, LANG_NEUTRAL, (LPTSTR)&tmp, 0, NULL);
if (len == 0 || (long) _countof(buf) < (long) len + 14)
{
@@ -226,7 +244,7 @@ GetLastErrorText()
else
{
tmp[_tcslen(tmp) - 2] = TEXT('\0'); /* remove CR/LF characters */
- openvpn_sntprintf(buf, _countof(buf), TEXT("%s (0x%x)"), tmp, GetLastError());
+ openvpn_sntprintf(buf, _countof(buf), TEXT("%s (0x%x)"), tmp, error);
}
if (tmp)
diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c
index aecbd84..de36e85 100644
--- a/src/openvpnserv/interactive.c
+++ b/src/openvpnserv/interactive.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2012-2018 Heiko Hund <heiko.hund@sophos.com>
+ * Copyright (C) 2012-2021 Heiko Hund <heiko.hund@sophos.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -24,7 +24,6 @@
#include "service.h"
-#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <userenv.h>
@@ -44,13 +43,14 @@
#include "openvpn-msg.h"
#include "validate.h"
#include "block_dns.h"
+#include "ring_buffer.h"
#define IO_TIMEOUT 2000 /*ms*/
-#define ERROR_OPENVPN_STARTUP 0x20000000
-#define ERROR_STARTUP_DATA 0x20000001
-#define ERROR_MESSAGE_DATA 0x20000002
-#define ERROR_MESSAGE_TYPE 0x20000003
+#define ERROR_OPENVPN_STARTUP 0x20000000
+#define ERROR_STARTUP_DATA 0x20000001
+#define ERROR_MESSAGE_DATA 0x20000002
+#define ERROR_MESSAGE_TYPE 0x20000003
static SERVICE_STATUS_HANDLE service;
static SERVICE_STATUS status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
@@ -59,6 +59,7 @@ static settings_t settings;
static HANDLE rdns_semaphore = NULL;
#define RDNS_TIMEOUT 600 /* seconds to wait for the semaphore */
+#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
openvpn_service_t interactive_service = {
interactive,
@@ -90,6 +91,7 @@ typedef enum {
block_dns,
undo_dns4,
undo_dns6,
+ undo_domain,
_undo_type_max
} undo_type_t;
typedef list_item_t *undo_lists_t[_undo_type_max];
@@ -101,6 +103,14 @@ typedef struct {
int metric_v6;
} block_dns_data_t;
+typedef struct {
+ HANDLE send_ring_handle;
+ HANDLE receive_ring_handle;
+ HANDLE send_tail_moved;
+ HANDLE receive_tail_moved;
+ HANDLE device;
+} ring_buffer_handles_t;
+
static DWORD
AddListItem(list_item_t **pfirst, LPVOID data)
@@ -155,6 +165,26 @@ CloseHandleEx(LPHANDLE handle)
return INVALID_HANDLE_VALUE;
}
+static HANDLE
+OvpnUnmapViewOfFile(LPHANDLE handle)
+{
+ if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
+ {
+ UnmapViewOfFile(*handle);
+ *handle = INVALID_HANDLE_VALUE;
+ }
+ return INVALID_HANDLE_VALUE;
+}
+
+static void
+CloseRingBufferHandles(ring_buffer_handles_t *ring_buffer_handles)
+{
+ CloseHandleEx(&ring_buffer_handles->device);
+ CloseHandleEx(&ring_buffer_handles->receive_tail_moved);
+ CloseHandleEx(&ring_buffer_handles->send_tail_moved);
+ OvpnUnmapViewOfFile(&ring_buffer_handles->send_ring_handle);
+ OvpnUnmapViewOfFile(&ring_buffer_handles->receive_ring_handle);
+}
static HANDLE
InitOverlapped(LPOVERLAPPED overlapped)
@@ -188,7 +218,7 @@ typedef enum {
static DWORD
AsyncPipeOp(async_op_t op, HANDLE pipe, LPVOID buffer, DWORD size, DWORD count, LPHANDLE events)
{
- int i;
+ DWORD i;
BOOL success;
HANDLE io_event;
DWORD res, bytes = 0;
@@ -277,10 +307,9 @@ ReturnProcessId(HANDLE pipe, DWORD pid, DWORD count, LPHANDLE events)
* Same format as error messages (3 line string) with error = 0 in
* 0x%08x format, PID on line 2 and a description "Process ID" on line 3
*/
- swprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg);
- buf[_countof(buf) - 1] = '\0';
+ openvpn_swprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg);
- WritePipeAsync(pipe, buf, wcslen(buf) * 2, count, events);
+ WritePipeAsync(pipe, buf, (DWORD)(wcslen(buf) * 2), count, events);
}
static VOID
@@ -308,7 +337,7 @@ ReturnError(HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events
L"0x%1!08x!\n%2!s!\n%3!s!", 0, 0,
(LPWSTR) &result, 0, (va_list *) args);
- WritePipeAsync(pipe, result, wcslen(result) * 2, count, events);
+ WritePipeAsync(pipe, result, (DWORD)(wcslen(result) * 2), count, events);
#ifdef UNICODE
MsgToEventLog(MSG_FLAGS_ERROR, result);
#else
@@ -332,31 +361,6 @@ ReturnLastError(HANDLE pipe, LPCWSTR func)
ReturnError(pipe, GetLastError(), func, 1, &exit_event);
}
-
-static VOID
-ReturnOpenvpnOutput(HANDLE pipe, HANDLE ovpn_output, DWORD count, LPHANDLE events)
-{
- WCHAR *wide_output = NULL;
- CHAR output[512];
- DWORD size;
-
- ReadFile(ovpn_output, output, sizeof(output), &size, NULL);
- if (size == 0)
- {
- return;
- }
-
- wide_output = malloc((size) * sizeof(WCHAR));
- if (wide_output)
- {
- MultiByteToWideChar(CP_UTF8, 0, output, size, wide_output, size);
- wide_output[size - 1] = 0;
- }
-
- ReturnError(pipe, ERROR_OPENVPN_STARTUP, wide_output, count, events);
- free(wide_output);
-}
-
/*
* Validate options against a white list. Also check the config_file is
* inside the config_dir. The white list is defined in validate.c
@@ -381,10 +385,9 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options, WCHAR *
if (!argv)
{
- swprintf(errmsg, capacity,
- L"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x",
- GetLastError());
- errmsg[capacity-1] = L'\0';
+ openvpn_swprintf(errmsg, capacity,
+ L"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x",
+ GetLastError());
goto out;
}
@@ -404,9 +407,8 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options, WCHAR *
if (!CheckOption(workdir, 2, argv_tmp, &settings))
{
- swprintf(errmsg, capacity, msg1, argv[0], workdir,
- settings.ovpn_admin_group);
- errmsg[capacity-1] = L'\0';
+ openvpn_swprintf(errmsg, capacity, msg1, argv[0], workdir,
+ settings.ovpn_admin_group);
}
goto out;
}
@@ -422,15 +424,14 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options, WCHAR *
{
if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1)
{
- swprintf(errmsg, capacity, msg1, argv[i+1], workdir,
- settings.ovpn_admin_group);
+ openvpn_swprintf(errmsg, capacity, msg1, argv[i+1], workdir,
+ settings.ovpn_admin_group);
}
else
{
- swprintf(errmsg, capacity, msg2, argv[i],
- settings.ovpn_admin_group);
+ openvpn_swprintf(errmsg, capacity, msg2, argv[i],
+ settings.ovpn_admin_group);
}
- errmsg[capacity-1] = L'\0';
goto out;
}
}
@@ -449,9 +450,9 @@ out:
static BOOL
GetStartupData(HANDLE pipe, STARTUP_DATA *sud)
{
- size_t len;
+ size_t size, len;
WCHAR *data = NULL;
- DWORD size, bytes, read;
+ DWORD bytes, read;
bytes = PeekNamedPipeAsync(pipe, 1, &exit_event);
if (bytes == 0)
@@ -516,7 +517,7 @@ GetStartupData(HANDLE pipe, STARTUP_DATA *sud)
return TRUE;
err:
- sud->directory = NULL; /* caller must not free() */
+ sud->directory = NULL; /* caller must not free() */
free(data);
return FALSE;
}
@@ -564,6 +565,24 @@ InterfaceLuid(const char *iface_name, PNET_LUID luid)
return status;
}
+static DWORD
+ConvertInterfaceNameToIndex(const wchar_t *ifname, NET_IFINDEX *index)
+{
+ NET_LUID luid;
+ DWORD err;
+
+ err = ConvertInterfaceAliasToLuid(ifname, &luid);
+ if (err == ERROR_SUCCESS)
+ {
+ err = ConvertInterfaceLuidToIndex(&luid, index);
+ }
+ if (err != ERROR_SUCCESS)
+ {
+ MsgToEventLog(M_ERR, L"Failed to find interface index for <%s>", ifname);
+ }
+ return err;
+}
+
static BOOL
CmpAddress(LPVOID item, LPVOID address)
{
@@ -930,7 +949,7 @@ static DWORD WINAPI
RegisterDNS(LPVOID unused)
{
DWORD err;
- DWORD i;
+ size_t i;
DWORD timeout = RDNS_TIMEOUT * 1000; /* in milliseconds */
/* path of ipconfig command */
@@ -945,17 +964,15 @@ RegisterDNS(LPVOID unused)
{ ipcfg, L"ipconfig /flushdns", timeout },
{ ipcfg, L"ipconfig /registerdns", timeout },
};
- int ncmds = sizeof(cmds) / sizeof(cmds[0]);
HANDLE wait_handles[2] = {rdns_semaphore, exit_event};
- swprintf(ipcfg, _countof(ipcfg), L"%s\\%s", get_win_sys_path(), L"ipconfig.exe");
- ipcfg[_countof(ipcfg) - 1] = L'\0';
+ openvpn_swprintf(ipcfg, MAX_PATH, L"%s\\%s", get_win_sys_path(), L"ipconfig.exe");
if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0)
{
/* Semaphore locked */
- for (i = 0; i < ncmds; ++i)
+ for (i = 0; i < _countof(cmds); ++i)
{
ExecCommand(cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout);
}
@@ -1038,7 +1055,7 @@ netsh_dns_cmd(const wchar_t *action, const wchar_t *proto, const wchar_t *if_nam
const wchar_t *fmt = L"netsh interface %s %s dns \"%s\" %s";
/* max cmdline length in wchars -- include room for worst case and some */
- int ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1;
+ size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1;
cmdline = malloc(ncmdline*sizeof(wchar_t));
if (!cmdline)
{
@@ -1059,6 +1076,53 @@ out:
return err;
}
+/**
+ * Run command: wmic nicconfig (InterfaceIndex=$if_index) call $action ($data)
+ * @param if_index "index of interface"
+ * @param action e.g., "SetDNSDomain"
+ * @param data data if required for action
+ * - a single word for SetDNSDomain, empty or NULL to delete
+ * - comma separated values for a list
+ */
+static DWORD
+wmic_nicconfig_cmd(const wchar_t *action, const NET_IFINDEX if_index,
+ const wchar_t *data)
+{
+ DWORD err = 0;
+ wchar_t argv0[MAX_PATH];
+ wchar_t *cmdline = NULL;
+ int timeout = 10000; /* in msec */
+
+ swprintf(argv0, _countof(argv0), L"%s\\%s", get_win_sys_path(), L"wbem\\wmic.exe");
+ argv0[_countof(argv0) - 1] = L'\0';
+
+ const wchar_t *fmt;
+ /* comma separated list must be enclosed in parenthesis */
+ if (data && wcschr(data, L','))
+ {
+ fmt = L"wmic nicconfig where (InterfaceIndex=%ld) call %s (%s)";
+ }
+ else
+ {
+ fmt = L"wmic nicconfig where (InterfaceIndex=%ld) call %s \"%s\"";
+ }
+
+ size_t ncmdline = wcslen(fmt) + 20 + wcslen(action) /* max 20 for ifindex */
+ + (data ? wcslen(data) + 1 : 1);
+ cmdline = malloc(ncmdline*sizeof(wchar_t));
+ if (!cmdline)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ openvpn_sntprintf(cmdline, ncmdline, fmt, if_index, action,
+ data? data : L"");
+ err = ExecCommand(argv0, cmdline, timeout);
+
+ free(cmdline);
+ return err;
+}
+
/* Delete all IPv4 or IPv6 dns servers for an interface */
static DWORD
DeleteDNS(short family, wchar_t *if_name)
@@ -1081,6 +1145,54 @@ CmpWString(LPVOID item, LPVOID str)
return (wcscmp(item, str) == 0) ? TRUE : FALSE;
}
+/**
+ * Set interface specific DNS domain suffix
+ * @param if_name name of the the interface
+ * @param domain a single domain name
+ * @param lists pointer to the undo lists. If NULL
+ * undo lists are not altered.
+ * Will delete the currently set value if domain is empty.
+ */
+static DWORD
+SetDNSDomain(const wchar_t *if_name, const char *domain, undo_lists_t *lists)
+{
+ NET_IFINDEX if_index;
+
+ DWORD err = ConvertInterfaceNameToIndex(if_name, &if_index);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ wchar_t *wdomain = utf8to16(domain); /* utf8 to wide-char */
+ if (!wdomain)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ /* free undo list if previously set */
+ if (lists)
+ {
+ free(RemoveListItem(&(*lists)[undo_domain], CmpWString, (void *)if_name));
+ }
+
+ err = wmic_nicconfig_cmd(L"SetDNSDomain", if_index, wdomain);
+
+ /* Add to undo list if domain is non-empty */
+ if (err == 0 && wdomain[0] && lists)
+ {
+ wchar_t *tmp_name = wcsdup(if_name);
+ if (!tmp_name || AddListItem(&(*lists)[undo_domain], tmp_name))
+ {
+ free(tmp_name);
+ err = ERROR_OUTOFMEMORY;
+ }
+ }
+
+ free(wdomain);
+ return err;
+}
+
static DWORD
HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
{
@@ -1100,6 +1212,13 @@ HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
return ERROR_MESSAGE_DATA;
}
+ /* use a non-const reference with limited scope to enforce null-termination of strings from client */
+ {
+ dns_cfg_message_t *msgptr = (dns_cfg_message_t *) msg;
+ msgptr->iface.name[_countof(msg->iface.name)-1] = '\0';
+ msgptr->domains[_countof(msg->domains)-1] = '\0';
+ }
+
wchar_t *wide_name = utf8to16(msg->iface.name); /* utf8 to wide-char */
if (!wide_name)
{
@@ -1119,9 +1238,14 @@ HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
free(RemoveListItem(&(*lists)[undo_type], CmpWString, wide_name));
}
- if (msg->header.type == msg_del_dns_cfg) /* job done */
+ if (msg->header.type == msg_del_dns_cfg)
{
- goto out;
+ if (msg->domains[0])
+ {
+ /* setting an empty domain removes any previous value */
+ err = SetDNSDomain(wide_name, "", lists);
+ }
+ goto out; /* job done */
}
for (int i = 0; i < addr_len; ++i)
@@ -1144,6 +1268,8 @@ HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
*/
}
+ err = 0;
+
if (msg->addr_len > 0)
{
wchar_t *tmp_name = wcsdup(wide_name);
@@ -1156,7 +1282,10 @@ HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
}
}
- err = 0;
+ if (msg->domains[0])
+ {
+ err = SetDNSDomain(wide_name, msg->domains, lists);
+ }
out:
free(wide_name);
@@ -1202,8 +1331,118 @@ HandleEnableDHCPMessage(const enable_dhcp_message_t *dhcp)
return err;
}
+static DWORD
+OvpnDuplicateHandle(HANDLE ovpn_proc, HANDLE orig_handle, HANDLE* new_handle)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ if (!DuplicateHandle(ovpn_proc, orig_handle, GetCurrentProcess(), new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ err = GetLastError();
+ MsgToEventLog(M_SYSERR, TEXT("Could not duplicate handle"));
+ return err;
+ }
+
+ return err;
+}
+
+static DWORD
+DuplicateAndMapRing(HANDLE ovpn_proc, HANDLE orig_handle, HANDLE *new_handle, struct tun_ring **ring)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ err = OvpnDuplicateHandle(ovpn_proc, orig_handle, new_handle);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+ *ring = (struct tun_ring *)MapViewOfFile(*new_handle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(struct tun_ring));
+ if (*ring == NULL)
+ {
+ err = GetLastError();
+ MsgToEventLog(M_SYSERR, TEXT("Could not map shared memory"));
+ return err;
+ }
+
+ return err;
+}
+
+static DWORD
+HandleRegisterRingBuffers(const register_ring_buffers_message_t *rrb, HANDLE ovpn_proc,
+ ring_buffer_handles_t *ring_buffer_handles)
+{
+ DWORD err = 0;
+ struct tun_ring *send_ring;
+ struct tun_ring *receive_ring;
+
+ CloseRingBufferHandles(ring_buffer_handles);
+
+ err = OvpnDuplicateHandle(ovpn_proc, rrb->device, &ring_buffer_handles->device);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ err = DuplicateAndMapRing(ovpn_proc, rrb->send_ring_handle, &ring_buffer_handles->send_ring_handle, &send_ring);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ err = DuplicateAndMapRing(ovpn_proc, rrb->receive_ring_handle, &ring_buffer_handles->receive_ring_handle, &receive_ring);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ err = OvpnDuplicateHandle(ovpn_proc, rrb->send_tail_moved, &ring_buffer_handles->send_tail_moved);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ err = OvpnDuplicateHandle(ovpn_proc, rrb->receive_tail_moved, &ring_buffer_handles->receive_tail_moved);
+ if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ if (!register_ring_buffers(ring_buffer_handles->device, send_ring, receive_ring,
+ ring_buffer_handles->send_tail_moved, ring_buffer_handles->receive_tail_moved))
+ {
+ err = GetLastError();
+ MsgToEventLog(M_SYSERR, TEXT("Could not register ring buffers"));
+ }
+
+ return err;
+}
+
+static DWORD
+HandleMTUMessage(const set_mtu_message_t *mtu)
+{
+ DWORD err = 0;
+ MIB_IPINTERFACE_ROW ipiface;
+ InitializeIpInterfaceEntry(&ipiface);
+ ipiface.Family = mtu->family;
+ ipiface.InterfaceIndex = mtu->iface.index;
+ err = GetIpInterfaceEntry(&ipiface);
+ if (err != NO_ERROR)
+ {
+ return err;
+ }
+ if (mtu->family == AF_INET)
+ {
+ ipiface.SitePrefixLength = 0;
+ }
+ ipiface.NlMtu = mtu->mtu;
+
+ err = SetIpInterfaceEntry(&ipiface);
+ return err;
+}
+
static VOID
-HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists)
+HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_handles,
+ DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists)
{
DWORD read;
union {
@@ -1214,6 +1453,8 @@ 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;
+ register_ring_buffers_message_t rrb;
+ set_mtu_message_t mtu;
} msg;
ack_message_t ack = {
.header = {
@@ -1281,6 +1522,20 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists
}
break;
+ case msg_register_ring_buffers:
+ if (msg.header.size == sizeof(msg.rrb))
+ {
+ ack.error_number = HandleRegisterRingBuffers(&msg.rrb, ovpn_proc, ring_buffer_handles);
+ }
+ break;
+
+ case msg_set_mtu:
+ if (msg.header.size == sizeof(msg.mtu))
+ {
+ ack.error_number = HandleMTUMessage(&msg.mtu);
+ }
+ break;
+
default:
ack.error_number = ERROR_MESSAGE_TYPE;
MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type %d"), msg.header.type);
@@ -1321,8 +1576,12 @@ Undo(undo_lists_t *lists)
DeleteDNS(AF_INET6, item->data);
break;
+ case undo_domain:
+ SetDNSDomain(item->data, "", NULL);
+ break;
+
case block_dns:
- interface_data = (block_dns_data_t*)(item->data);
+ interface_data = (block_dns_data_t *)(item->data);
delete_block_dns_filters(interface_data->engine);
if (interface_data->metric_v4 >= 0)
{
@@ -1364,6 +1623,7 @@ RunOpenvpn(LPVOID p)
WCHAR *cmdline = NULL;
size_t cmdline_size;
undo_lists_t undo_lists;
+ ring_buffer_handles_t ring_buffer_handles;
WCHAR errmsg[512] = L"";
SECURITY_ATTRIBUTES inheritable = {
@@ -1385,6 +1645,7 @@ RunOpenvpn(LPVOID p)
ZeroMemory(&startup_info, sizeof(startup_info));
ZeroMemory(&undo_lists, sizeof(undo_lists));
ZeroMemory(&proc_info, sizeof(proc_info));
+ ZeroMemory(&ring_buffer_handles, sizeof(ring_buffer_handles));
if (!GetStartupData(pipe, &sud))
{
@@ -1611,7 +1872,7 @@ RunOpenvpn(LPVOID p)
{
DWORD written;
WideCharToMultiByte(CP_UTF8, 0, sud.std_input, -1, input, input_size, NULL, NULL);
- WriteFile(stdin_write, input, strlen(input), &written, NULL);
+ WriteFile(stdin_write, input, (DWORD)strlen(input), &written, NULL);
free(input);
}
@@ -1623,7 +1884,7 @@ RunOpenvpn(LPVOID p)
break;
}
- HandleMessage(ovpn_pipe, bytes, 1, &exit_event, &undo_lists);
+ HandleMessage(ovpn_pipe, proc_info.hProcess, &ring_buffer_handles, bytes, 1, &exit_event, &undo_lists);
}
WaitForSingleObject(proc_info.hProcess, IO_TIMEOUT);
@@ -1635,9 +1896,8 @@ RunOpenvpn(LPVOID p)
else if (exit_code != 0)
{
WCHAR buf[256];
- swprintf(buf, _countof(buf),
- L"OpenVPN exited with error: exit code = %lu", exit_code);
- buf[_countof(buf) - 1] = L'\0';
+ openvpn_swprintf(buf, _countof(buf),
+ L"OpenVPN exited with error: exit code = %lu", exit_code);
ReturnError(pipe, ERROR_OPENVPN_STARTUP, buf, 1, &exit_event);
}
Undo(&undo_lists);
@@ -1651,6 +1911,7 @@ out:
free(cmdline);
DestroyEnvironmentBlock(user_env);
FreeStartupData(&sud);
+ CloseRingBufferHandles(&ring_buffer_handles);
CloseHandleEx(&proc_info.hProcess);
CloseHandleEx(&proc_info.hThread);
CloseHandleEx(&stdin_read);
diff --git a/src/openvpnserv/openvpnserv.vcxproj b/src/openvpnserv/openvpnserv.vcxproj
index c6760da..bcf9d25 100644
--- a/src/openvpnserv/openvpnserv.vcxproj
+++ b/src/openvpnserv/openvpnserv.vcxproj
@@ -1,103 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9C91EE0B-817D-420A-A1E6-15A5A9D98BAD}</ProjectGuid>
<RootNamespace>openvpnserv</RootNamespace>
<Keyword>Win32Proj</Keyword>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Release.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Release.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\compat\Debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)-Output\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)-Output\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <VcpkgEnabled>true</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <VcpkgEnabled>true</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgEnabled>true</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgEnabled>true</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgEnabled>true</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgEnabled>true</VcpkgEnabled>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;$(CPPFLAGS);%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile />
+ <Link>
+ <AdditionalDependencies>Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile />
+ <Link>
+ <AdditionalDependencies>legacy_stdio_definitions.lib;Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
- <ResourceCompile>
- <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
+ <ResourceCompile />
<Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>legacy_stdio_definitions.lib;Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
- <TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;$(CPPFLAGS);%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile />
+ <Link>
+ <AdditionalDependencies>Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile />
+ <Link>
+ <AdditionalDependencies>legacy_stdio_definitions.lib;Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\openvpn;..\compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
- <ResourceCompile>
- <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
+ <ResourceCompile />
<Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>legacy_stdio_definitions.lib;Userenv.lib;Iphlpapi.lib;ntdll.lib;Fwpuclnt.lib;Netapi32.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="openvpnserv.c" />
+ <ClCompile Include="automatic.c" />
+ <ClCompile Include="common.c" />
+ <ClCompile Include="interactive.c" />
<ClCompile Include="service.c" />
+ <ClCompile Include="validate.c" />
+ <ClCompile Include="..\openvpn\block_dns.c" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="..\openvpn\ring_buffer.h" />
<ClInclude Include="service.h" />
+ <ClInclude Include="validate.h" />
+ <ClInclude Include="..\openvpn\block_dns.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="openvpnserv_resources.rc" />
@@ -111,4 +207,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/openvpnserv/openvpnserv.vcxproj.filters b/src/openvpnserv/openvpnserv.vcxproj.filters
index 0c89b4f..41ad3e8 100644
--- a/src/openvpnserv/openvpnserv.vcxproj.filters
+++ b/src/openvpnserv/openvpnserv.vcxproj.filters
@@ -15,10 +15,22 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="openvpnserv.c">
+ <ClCompile Include="service.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="service.c">
+ <ClCompile Include="automatic.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="common.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="interactive.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="validate.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\openvpn\block_dns.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -26,6 +38,15 @@
<ClInclude Include="service.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="validate.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\openvpn\block_dns.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\openvpn\ring_buffer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="openvpnserv_resources.rc">
diff --git a/src/openvpnserv/service.c b/src/openvpnserv/service.c
index 7157bea..8efe25f 100644
--- a/src/openvpnserv/service.c
+++ b/src/openvpnserv/service.c
@@ -270,8 +270,8 @@ _tmain(int argc, TCHAR *argv[])
else if (argc > i + 2 && _tcsicmp(TEXT("instance"), argv[i] + 1) == 0)
{
dispatchTable = _tcsicmp(TEXT("interactive"), argv[i + 1]) != 0 ?
- dispatchTable_automatic :
- dispatchTable_interactive;
+ dispatchTable_automatic :
+ dispatchTable_interactive;
service_instance = argv[i + 2];
i += 2;
diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h
index 23b105f..500f390 100644
--- a/src/openvpnserv/service.h
+++ b/src/openvpnserv/service.h
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2013-2018 Heiko Hund <heiko.hund@sophos.com>
+ * Copyright (C) 2013-2021 Heiko Hund <heiko.hund@sophos.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -30,6 +30,7 @@
#include "config-msvc.h"
#endif
+#include <winsock2.h>
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
@@ -76,14 +77,18 @@ extern openvpn_service_t interactive_service;
extern LPCTSTR service_instance;
VOID WINAPI ServiceStartAutomaticOwn(DWORD argc, LPTSTR *argv);
+
VOID WINAPI ServiceStartAutomatic(DWORD argc, LPTSTR *argv);
VOID WINAPI ServiceStartInteractiveOwn(DWORD argc, LPTSTR *argv);
+
VOID WINAPI ServiceStartInteractive(DWORD argc, LPTSTR *argv);
-int openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist);
+BOOL openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist);
+
+BOOL openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...);
-int openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...);
+BOOL openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...);
DWORD GetOpenvpnSettings(settings_t *s);
diff --git a/src/openvpnserv/validate.c b/src/openvpnserv/validate.c
index d35938c..93f92e3 100644
--- a/src/openvpnserv/validate.c
+++ b/src/openvpnserv/validate.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2016 Selva Nair <selva.nair@gmail.com>
+ * Copyright (C) 2016-2021 Selva Nair <selva.nair@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -51,6 +51,7 @@ static const WCHAR *white_list[] =
};
static BOOL IsUserInGroup(PSID sid, const PTOKEN_GROUPS groups, const WCHAR *group_name);
+
static PTOKEN_GROUPS GetTokenGroups(const HANDLE token);
/*
@@ -63,12 +64,14 @@ CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s)
WCHAR tmp[MAX_PATH];
const WCHAR *config_file = NULL;
const WCHAR *config_dir = NULL;
+#ifndef UNICODE
+ WCHAR widepath[MAX_PATH];
+#endif
/* convert fname to full path */
if (PathIsRelativeW(fname) )
{
- swprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname);
- tmp[_countof(tmp)-1] = L'\0';
+ openvpn_swprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname);
config_file = tmp;
}
else
@@ -300,12 +303,12 @@ IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_nam
break;
}
/* If a match is already found, ret == TRUE and the loop is skipped */
- for (int i = 0; i < nread && !ret; ++i)
+ for (DWORD i = 0; i < nread && !ret; ++i)
{
ret = EqualSid(members[i].lgrmi0_sid, sid);
}
NetApiBufferFree(members);
- /* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */
+ /* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */
} while (err == ERROR_MORE_DATA && nloop++ < 100);
if (err != NERR_Success && err != NERR_GroupNotFound)
diff --git a/src/openvpnserv/validate.h b/src/openvpnserv/validate.h
index cc443e6..710e136 100644
--- a/src/openvpnserv/validate.h
+++ b/src/openvpnserv/validate.h
@@ -6,7 +6,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2016 Selva Nair <selva.nair@gmail.com>
+ * Copyright (C) 2016-2021 Selva Nair <selva.nair@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2