diff options
author | Jörg Frings-Fürst <debian@jff.email> | 2021-11-29 20:51:58 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff.email> | 2021-11-29 20:51:58 +0100 |
commit | 6e3e95a9da9458ddf0874b4bd1c8ce6b47fcef27 (patch) | |
tree | 6e3667709d99f857d90b9831426f6a32ee70d113 /src/openvpnserv | |
parent | b29f419d68b26b75a44e3ac00748875f1003b900 (diff) | |
parent | f2b3dda12a731c2e0971cb7889728edaf23f6cb0 (diff) |
Merge branch 'upstream' into develop
Diffstat (limited to 'src/openvpnserv')
-rw-r--r-- | src/openvpnserv/Makefile.am | 5 | ||||
-rw-r--r-- | src/openvpnserv/Makefile.in | 17 | ||||
-rw-r--r-- | src/openvpnserv/automatic.c | 25 | ||||
-rw-r--r-- | src/openvpnserv/common.c | 36 | ||||
-rw-r--r-- | src/openvpnserv/interactive.c | 395 | ||||
-rw-r--r-- | src/openvpnserv/openvpnserv.vcxproj | 186 | ||||
-rw-r--r-- | src/openvpnserv/openvpnserv.vcxproj.filters | 25 | ||||
-rw-r--r-- | src/openvpnserv/service.c | 4 | ||||
-rw-r--r-- | src/openvpnserv/service.h | 11 | ||||
-rw-r--r-- | src/openvpnserv/validate.c | 13 | ||||
-rw-r--r-- | src/openvpnserv/validate.h | 2 |
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 |