50#include <versionhelpers.h>
154 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
155 obj->
sa.lpSecurityDescriptor = &obj->
sd;
156 obj->
sa.bInheritHandle = FALSE;
157 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
161 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
174 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
177 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
191 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle failed on overlapped I/O event object");
229 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
230 if (event->
write == NULL)
232 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (write) failed");
244 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
245 if (event->
read == NULL)
247 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (read) failed");
252 if (WSAEventSelect(sd, event->
read, network_events) != 0)
254 msg(
M_FATAL |
M_ERRNO,
"Error: init_net_event_win32: WSAEventSelect call failed");
261 WSANETWORKEVENTS wne;
262 if (WSAEnumNetworkEvents(sd, event->
read, &wne) != 0)
264 msg(
M_FATAL |
M_ERRNO,
"Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
269 return wne.lNetworkEvents;
280 if (WSAEventSelect(sd, event->
read, 0) != 0)
282 msg(
M_WARN |
M_ERRNO,
"Warning: close_net_event_win32: WSAEventSelect call failed");
285 if (!ResetEvent(event->
read))
287 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (read) failed in close_net_event_win32");
291 if (!CloseHandle(event->
read))
294 "Warning: CloseHandle (read) failed in close_net_event_win32");
302 if (!ResetEvent(event->
write))
304 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
308 if (!CloseHandle(event->
write))
311 "Warning: CloseHandle (write) failed in close_net_event_win32");
352 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
402 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
405 ir.EventType = KEY_EVENT;
406 ir.Event.KeyEvent.bKeyDown =
true;
407 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
420 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long)signum);
430 case CTRL_BREAK_EVENT:
438 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long)signum);
453 bool exit_event_initial_state)
458 ws->
in.
read = INVALID_HANDLE_VALUE;
459 ws->
in.
write = INVALID_HANDLE_VALUE;
468 ws->
in.
read = GetStdHandle(STD_INPUT_HANDLE);
469 if (ws->
in.
read != INVALID_HANDLE_VALUE)
474 const DWORD new_console_mode =
476 & ~(ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT
477 | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT);
481 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
483 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
491 ws->
in.
read = INVALID_HANDLE_VALUE;
505 const wchar_t *exit_event_nameW =
wide_string(exit_event_name, &
gc);
509 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
513 CreateEventW(&sa.
sa, TRUE, exit_event_initial_state ? TRUE : FALSE, exit_event_nameW);
520 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
522 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
545 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
556 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
558 return ir->Event.KeyEvent.wVirtualScanCode;
561 if ((ir->Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
562 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
564 return ir->Event.KeyEvent.wVirtualScanCode * 256;
567 return ir->Event.KeyEvent.uChar.AsciiChar;
584 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
588 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
609 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
683 WaitForSingleObject(ws->
in.
read, INFINITE);
756 s->
hand = CreateSemaphore(&
sa.sa, 1, 1, name);
781 "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
782 s->
name, timeout_milliseconds / 1000);
783 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
784 if (
status == WAIT_FAILED)
786 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
788 ret = (
status == WAIT_TIMEOUT) ?
false :
true;
796 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
797 s->
name, timeout_milliseconds);
810 if (!ReleaseSemaphore(s->
hand, 1, NULL))
828 CloseHandle(s->
hand);
853 const int timeout_seconds = 600;
862 msg(
M_FATAL,
"Cannot lock net command semaphore");
881 char force_path[256];
884 if (snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
885 sysroot, sysroot, sysroot)
886 >=
sizeof(force_path))
888 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
897 bool path_seen =
false;
901 nchars += strlen(e->
string) + 1;
904 nchars += strlen(force_path) + 1;
906 ret = (
char *)malloc(nchars);
915 p += strlen(e->
string) + 1;
917 if (strncmp(e->
string,
"PATH=", 5) == 0)
926 msg(
M_INFO,
"env_block: add %s", force_path);
927 strcpy(p, force_path);
928 p += strlen(force_path) + 1;
954 for (
i = 0;
i <
a->argc; ++
i)
956 const char *arg =
a->argv[
i];
969 for (
i = 0;
i <
a->argc; ++
i)
971 const char *arg =
a->argv[
i];
1000 if (
a &&
a->argv[0])
1005 STARTUPINFOW start_info;
1006 PROCESS_INFORMATION proc_info;
1013 DWORD proc_flags = CREATE_NO_WINDOW;
1019 GetStartupInfoW(&start_info);
1020 start_info.cb =
sizeof(start_info);
1021 start_info.dwFlags = STARTF_USESHOWWINDOW;
1022 start_info.wShowWindow = SW_HIDE;
1024 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info,
1027 DWORD exit_status = 0;
1028 CloseHandle(proc_info.hThread);
1029 WaitForSingleObject(proc_info.hProcess, INFINITE);
1030 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1032 ret = (int)exit_status;
1036 msg(
M_WARN |
M_ERRNO,
"openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1038 CloseHandle(proc_info.hProcess);
1059 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1070 STARTUPINFO start_info;
1071 PROCESS_INFORMATION proc_info;
1080 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1084 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1089 GetStartupInfo(&start_info);
1090 start_info.cb =
sizeof(start_info);
1091 start_info.dwFlags = STARTF_USESHOWWINDOW;
1092 start_info.wShowWindow = SW_HIDE;
1094 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1096 CloseHandle(proc_info.hThread);
1097 CloseHandle(proc_info.hProcess);
1132 if (
status >
sizeof(buf) - 1)
1134 msg(
M_FATAL,
"String overflow attempting to read environmental variable %s",
1143 DWORD
status = GetModuleFileNameW(NULL, path, size);
1179 .iface = { .index = index, .name =
"" } };
1189 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%d]",
1196 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1205 WCHAR openvpnpath[MAX_PATH];
1211 dmsg(
D_LOW,
"Using service to add WFP block filters");
1258 msg(
D_LOW,
"Using service to delete WFP block filters");
1293 typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1294 is_wow64_process2_t is_wow64_process2 =
1295 (is_wow64_process2_t)GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1297 USHORT process_machine = 0;
1298 USHORT native_machine = 0;
1302#elif defined(_WIN64)
1304 if (is_wow64_process2)
1307 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1308 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1313#elif defined(_WIN32)
1316 if (is_wow64_process2)
1319 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1322 switch (native_machine)
1324 case IMAGE_FILE_MACHINE_ARM64:
1328 case IMAGE_FILE_MACHINE_AMD64:
1341 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1383 HMODULE hMod = GetModuleHandleW(L
"ntdll.dll");
1395 RTL_OSVERSIONINFOW rovi = { 0 };
1396 rovi.dwOSVersionInfoSize =
sizeof(rovi);
1419 return (
const char *)out.
data;
1430 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1444 WCHAR reg_path[256];
1446 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1448 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1449 if (
status != ERROR_SUCCESS)
1454 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1458 return status == ERROR_SUCCESS;
1464 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1466 WCHAR install_path[MAX_PATH] = { 0 };
1472 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1475 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1477 install_path[wcslen(install_path) - 1] = L
'\0';
1484 } ossl_env[] = { { L
"OPENSSL_CONF", L
"openssl.cnf" },
1485 { L
"OPENSSL_ENGINES", L
"engines" },
1486 { L
"OPENSSL_MODULES", L
"modules" } };
1488 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1492 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1495 WCHAR val[MAX_PATH] = { 0 };
1496 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1497 _wputenv_s(ossl_env[i].name, val);
1522 time_t expire =
now + n;
1524 while (expire >=
now)
1526 DWORD wait_ms = (DWORD)((expire -
now) * 1000);
1535 if (
status != WAIT_OBJECT_0)
1539 Sleep((DWORD)((expire -
now) * 1000));
1550 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1552 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1556 WCHAR plugin_dir[MAX_PATH] = { 0 };
1563 msg(
M_WARN,
"Installation path could not be determined.");
1567 WCHAR system_dir[MAX_PATH] = { 0 };
1568 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1573 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1578 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1581 if (wcslen(plugin_dir) > 0)
1583 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1591 if ((wcslen(normalized_plugin_dir) > 0)
1592 && (wcsnicmp(normalized_plugin_dir, plugin_path, wcslen(normalized_plugin_dir)) == 0))
1598 return wcsnicmp(system_dir, plugin_path, wcslen(system_dir)) == 0;
1605 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1607 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1608 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1611 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1623 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1625 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1626 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1629 ret = CryptUnprotectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
void free_buf(struct buffer *buf)
bool buf_printf(struct buffer *buf, const char *format,...)
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
char * string_alloc(const char *str, struct gc_arena *gc)
#define CC_DOUBLE_QUOTE
double quote
#define CC_ANY
any character
#define CC_CRLF
carriage return or newline
#define CC_SPACE
whitespace isspace()
static void check_malloc_return(void *p)
static void gc_free(struct gc_arena *a)
#define CC_PRINT
printable (>= 32, != 127)
static struct gc_arena gc_new(void)
#define SCRIPT_SECURITY_WARNING
void setenv_str(struct env_set *es, const char *name, const char *value)
bool env_allowed(const char *str)
static SERVICE_STATUS status
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame)
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
static void update_time(void)
bool openvpn_execve_allowed(const unsigned int flags)
int script_security(void)
#define SSEC_SCRIPTS
allow calling of built-in programs and user-defined scripts
#define OPENVPN_EXECVE_ERROR
#define OPENVPN_EXECVE_NOT_ALLOWED
void throw_signal(const int signum)
Throw a hard signal.
struct signal_info siginfo_static
Wrapper structure for dynamically allocated memory.
uint8_t * data
Pointer to the allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Contains all state information for one tunnel.
Packet geometry parameters.
Garbage collection arena used to keep track of dynamically allocated memory.
Container for unidirectional cipher and HMAC key material.
volatile int signal_received
bool console_mode_save_defined
char old_window_title[256]
SOCKET socket_descriptor_t
static int socket_defined(const socket_descriptor_t sd)
int get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto)
Return interface metric value for the specified interface index.
DWORD set_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, const ULONG metric)
Sets interface metric value for specified interface index.
DWORD delete_wfp_block_filters(HANDLE engine_handle)
DWORD add_wfp_block_filters(HANDLE *engine_handle, int index, const WCHAR *exe_path, wfp_block_msg_handler_t msg_handler, BOOL dns_only)
#define WFP_BLOCK_IFACE_METRIC
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc)
static unsigned int keyboard_ir_to_key(INPUT_RECORD *ir)
void init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
static bool win_get_exe_path(PWCHAR path, DWORD size)
void net_event_win32_init(struct net_event_win32 *ne)
void net_event_win32_close(struct net_event_win32 *ne)
void win32_signal_open(struct win32_signal *ws, int force, const char *exit_event_name, bool exit_event_initial_state)
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state)
bool win_wfp_block(const NET_IFINDEX index, const HANDLE msg_channel, BOOL dns_only)
void window_title_generate(const char *title)
void set_win_sys_path(const char *newpath, struct env_set *es)
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
void window_title_clear(struct window_title *wt)
static unsigned int win32_keyboard_get(struct win32_signal *ws)
bool get_openvpn_reg_value(const WCHAR *key, WCHAR *value, DWORD size)
Fetches a registry value for OpenVPN registry key.
static bool pause_exit_enabled
void window_title_save(struct window_title *wt)
bool protect_buffer_win32(char *buf, DWORD len)
Encrypt a region of memory using CryptProtectMemory() with access restricted to the current process.
void semaphore_clear(struct semaphore *s)
bool plugin_in_trusted_dir(const WCHAR *plugin_path)
Checks if a plugin is located in a trusted directory.
void semaphore_close(struct semaphore *s)
static bool keyboard_input_available(struct win32_signal *ws)
bool unprotect_buffer_win32(char *buf, DWORD len)
Decrypt a previously encrypted region of memory using CryptUnProtectMemory() with access restricted t...
void net_event_win32_reset_write(struct net_event_win32 *ne)
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds)
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
void fork_to_self(const char *cmdline)
static char * env_block(const struct env_set *es)
static void win_trigger_event(struct win32_signal *ws)
char * overlapped_io_state_ascii(const struct overlapped_io *o)
void overlapped_io_close(struct overlapped_io *o)
void netcmd_semaphore_release(void)
void win32_sleep(const int n)
static char * win_sys_path
static bool win_wfp_block_service(bool add, bool dns_only, int index, const HANDLE pipe)
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
static void win32_print_arch(arch_t arch, struct buffer *out)
static void win32_get_arch(arch_t *process_arch, arch_t *host_arch)
void semaphore_release(struct semaphore *s)
static HANDLE m_hEngineHandle
void set_win_sys_path_via_env(struct env_set *es)
static void set_openssl_env_vars(void)
Set OpenSSL environment variables to a safe directory.
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd)
static bool WINAPI win_ctrl_handler(DWORD signum)
void window_title_restore(const struct window_title *wt)
struct semaphore netcmd_semaphore
char * get_win_sys_path(void)
bool win32_service_interrupt(struct win32_signal *ws)
void win32_pause(struct win32_signal *ws)
static void win_wfp_msg_handler(DWORD err, const char *msg)
static struct WSAData wsa_state
void netcmd_semaphore_init(void)
void netcmd_semaphore_lock(void)
void win32_signal_close(struct win32_signal *ws)
const char * win32_version_string(struct gc_arena *gc)
Get Windows version string with architecture info.
void win32_signal_clear(struct win32_signal *ws)
bool send_msg_iservice(HANDLE pipe, const void *data, DWORD size, ack_message_t *ack, const char *context)
Send the size bytes in buffer data to the interactive service pipe and read the result in ack.
int win32_signal_get(struct win32_signal *ws)
void net_event_win32_reset(struct net_event_win32 *ne)
void netcmd_semaphore_close(void)
void set_pause_exit_win32(void)
bool init_security_attributes_allow_all(struct security_attributes *obj)
void semaphore_open(struct semaphore *s, const char *name)
void net_event_win32_stop(struct net_event_win32 *ne)
LONG(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW)
static bool net_event_win32_defined(const struct net_event_win32 *ne)
#define SYS_PATH_ENV_VAR_NAME
#define NE32_PERSIST_EVENT
#define IOSTATE_IMMEDIATE_RETURN
#define WSO_FORCE_SERVICE
#define WSO_FORCE_CONSOLE
#define HANDLE_DEFINED(h)