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))
887 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
896 bool path_seen =
false;
900 nchars += strlen(e->
string) + 1;
903 nchars += strlen(force_path) + 1;
905 ret = (
char *)malloc(nchars);
914 p += strlen(e->
string) + 1;
916 if (strncmp(e->
string,
"PATH=", 5) == 0)
925 msg(
M_INFO,
"env_block: add %s", force_path);
926 strcpy(p, force_path);
927 p += strlen(force_path) + 1;
953 for (
i = 0;
i <
a->argc; ++
i)
955 const char *arg =
a->argv[
i];
968 for (
i = 0;
i <
a->argc; ++
i)
970 const char *arg =
a->argv[
i];
1004 STARTUPINFOW start_info;
1005 PROCESS_INFORMATION proc_info;
1012 DWORD proc_flags = CREATE_NO_WINDOW;
1018 GetStartupInfoW(&start_info);
1019 start_info.cb =
sizeof(start_info);
1020 start_info.dwFlags = STARTF_USESHOWWINDOW;
1021 start_info.wShowWindow = SW_HIDE;
1023 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info,
1026 DWORD exit_status = 0;
1027 CloseHandle(proc_info.hThread);
1028 WaitForSingleObject(proc_info.hProcess, INFINITE);
1029 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1031 ret = (int)exit_status;
1035 msg(
M_WARN |
M_ERRNO,
"openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1037 CloseHandle(proc_info.hProcess);
1058 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1069 STARTUPINFO start_info;
1070 PROCESS_INFORMATION proc_info;
1079 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1083 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1088 GetStartupInfo(&start_info);
1089 start_info.cb =
sizeof(start_info);
1090 start_info.dwFlags = STARTF_USESHOWWINDOW;
1091 start_info.wShowWindow = SW_HIDE;
1093 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1095 CloseHandle(proc_info.hThread);
1096 CloseHandle(proc_info.hProcess);
1131 if (
status >
sizeof(buf) - 1)
1133 msg(
M_FATAL,
"String overflow attempting to read environmental variable %s",
1142 DWORD
status = GetModuleFileNameW(NULL, path, size);
1178 .iface = { .index = index, .name =
"" } };
1188 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%d]",
1195 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1204 WCHAR openvpnpath[MAX_PATH];
1210 dmsg(
D_LOW,
"Using service to add WFP block filters");
1257 msg(
D_LOW,
"Using service to delete WFP block filters");
1292 typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1293 is_wow64_process2_t is_wow64_process2 =
1294 (is_wow64_process2_t)GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1296 USHORT process_machine = 0;
1297 USHORT native_machine = 0;
1301#elif defined(_WIN64)
1303 if (is_wow64_process2)
1306 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1307 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1312#elif defined(_WIN32)
1315 if (is_wow64_process2)
1318 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1321 switch (native_machine)
1323 case IMAGE_FILE_MACHINE_ARM64:
1327 case IMAGE_FILE_MACHINE_AMD64:
1340 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1382 HMODULE hMod = GetModuleHandleW(L
"ntdll.dll");
1394 RTL_OSVERSIONINFOW rovi = { 0 };
1395 rovi.dwOSVersionInfoSize =
sizeof(rovi);
1418 return (
const char *)out.
data;
1429 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1443 WCHAR reg_path[256];
1445 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1447 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1448 if (
status != ERROR_SUCCESS)
1453 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1457 return status == ERROR_SUCCESS;
1463 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1465 WCHAR install_path[MAX_PATH] = { 0 };
1471 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1474 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1476 install_path[wcslen(install_path) - 1] = L
'\0';
1483 } ossl_env[] = { { L
"OPENSSL_CONF", L
"openssl.cnf" },
1484 { L
"OPENSSL_ENGINES", L
"engines" },
1485 { L
"OPENSSL_MODULES", L
"modules" } };
1487 for (
size_t i = 0;
i <
SIZE(ossl_env); ++
i)
1491 _wgetenv_s(&size, NULL, 0, ossl_env[
i].name);
1494 WCHAR val[MAX_PATH] = { 0 };
1495 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[
i].value);
1496 _wputenv_s(ossl_env[
i].name, val);
1521 time_t expire =
now + n;
1523 while (expire >=
now)
1533 if (
status != WAIT_OBJECT_0)
1537 Sleep((expire -
now) * 1000);
1548 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1550 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1554 WCHAR plugin_dir[MAX_PATH] = { 0 };
1561 msg(
M_WARN,
"Installation path could not be determined.");
1565 WCHAR system_dir[MAX_PATH] = { 0 };
1566 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1571 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1576 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1579 if (wcslen(plugin_dir) > 0)
1581 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1589 if ((wcslen(normalized_plugin_dir) > 0)
1590 && (wcsnicmp(normalized_plugin_dir, plugin_path, wcslen(normalized_plugin_dir)) == 0))
1596 return wcsnicmp(system_dir, plugin_path, wcslen(system_dir)) == 0;
1603 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1605 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1606 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1609 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1621 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1623 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1624 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1627 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)
void semaphore_clear(struct semaphore *s)
bool unprotect_buffer_win32(char *buf, size_t len)
Decrypt a previously encrypted region of memory using CryptUnProtectMemory() with access restricted t...
bool protect_buffer_win32(char *buf, size_t len)
Encrypt a region of memory using CryptProtectMemory() with access restricted to the current process.
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)
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)
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
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)
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)