52#include <versionhelpers.h>
163 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
164 obj->
sa.lpSecurityDescriptor = &obj->
sd;
165 obj->
sa.bInheritHandle = FALSE;
166 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
170 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
196 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
197 obj->
sa.lpSecurityDescriptor = &obj->
sd;
198 obj->
sa.bInheritHandle = FALSE;
200 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
206 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
211 PTOKEN_USER info = NULL;
213 if (!GetTokenInformation(token, TokenUser, info, info_len, &info_len)
214 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
219 info = malloc(info_len);
220 if (!info || !GetTokenInformation(token, TokenUser, info, info_len, &info_len))
225 EXPLICIT_ACCESS ea = { 0 };
226 ea.grfAccessPermissions = GENERIC_ALL;
227 ea.grfAccessMode = SET_ACCESS;
228 ea.grfInheritance = NO_INHERITANCE;
229 ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
230 ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
231 ea.Trustee.ptstrName = (LPTSTR)info->User.Sid;
233 if (SetEntriesInAcl(1, &ea, NULL, &obj->
dacl) != ERROR_SUCCESS)
238 if (SetSecurityDescriptorDacl(&obj->
sd, TRUE, obj->
dacl, FALSE))
259 LocalFree(obj->
dacl);
270 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
273 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
287 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle failed on overlapped I/O event object");
325 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
326 if (event->
write == NULL)
328 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (write) failed");
340 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
341 if (event->
read == NULL)
343 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (read) failed");
348 if (WSAEventSelect(sd, event->
read, network_events) != 0)
350 msg(
M_FATAL |
M_ERRNO,
"Error: init_net_event_win32: WSAEventSelect call failed");
357 WSANETWORKEVENTS wne;
358 if (WSAEnumNetworkEvents(sd, event->
read, &wne) != 0)
360 msg(
M_FATAL |
M_ERRNO,
"Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
365 return wne.lNetworkEvents;
376 if (WSAEventSelect(sd, event->
read, 0) != 0)
378 msg(
M_WARN |
M_ERRNO,
"Warning: close_net_event_win32: WSAEventSelect call failed");
381 if (!ResetEvent(event->
read))
383 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (read) failed in close_net_event_win32");
387 if (!CloseHandle(event->
read))
390 "Warning: CloseHandle (read) failed in close_net_event_win32");
398 if (!ResetEvent(event->
write))
400 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
404 if (!CloseHandle(event->
write))
407 "Warning: CloseHandle (write) failed in close_net_event_win32");
448 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
498 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
501 ir.EventType = KEY_EVENT;
502 ir.Event.KeyEvent.bKeyDown =
true;
503 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
516 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long)signum);
526 case CTRL_BREAK_EVENT:
534 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long)signum);
549 bool exit_event_initial_state)
554 ws->
in.
read = INVALID_HANDLE_VALUE;
555 ws->
in.
write = INVALID_HANDLE_VALUE;
564 ws->
in.
read = GetStdHandle(STD_INPUT_HANDLE);
565 if (ws->
in.
read != INVALID_HANDLE_VALUE)
570 const DWORD new_console_mode =
572 & ~(ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT
573 | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT);
577 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
579 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
587 ws->
in.
read = INVALID_HANDLE_VALUE;
601 const wchar_t *exit_event_nameW =
wide_string(exit_event_name, &
gc);
605 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
609 CreateEventW(&sa.
sa, TRUE, exit_event_initial_state ? TRUE : FALSE, exit_event_nameW);
616 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
618 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
642 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
653 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
655 return ir->Event.KeyEvent.wVirtualScanCode;
658 if ((ir->Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
659 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
661 return ir->Event.KeyEvent.wVirtualScanCode * 256;
664 return ir->Event.KeyEvent.uChar.AsciiChar;
681 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
685 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
706 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
780 WaitForSingleObject(ws->
in.
read, INFINITE);
853 s->
hand = CreateSemaphore(&
sa.sa, 1, 1, name);
859 msg(
M_ERR,
"Cannot create Win32 semaphore '%s'", name);
879 "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
880 s->
name, timeout_milliseconds / 1000);
881 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
882 if (
status == WAIT_FAILED)
884 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
886 ret = (
status == WAIT_TIMEOUT) ?
false :
true;
894 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
895 s->
name, timeout_milliseconds);
908 if (!ReleaseSemaphore(s->
hand, 1, NULL))
926 CloseHandle(s->
hand);
951 const int timeout_seconds = 600;
960 msg(
M_FATAL,
"Cannot lock net command semaphore");
979 char force_path[256];
982 if (!
checked_snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
983 sysroot, sysroot, sysroot))
985 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
994 bool path_seen =
false;
998 nchars += strlen(e->
string) + 1;
1001 nchars += strlen(force_path) + 1;
1003 ret = (
char *)malloc(nchars);
1012 p += strlen(e->
string) + 1;
1014 if (strncmp(e->
string,
"PATH=", 5) == 0)
1023 msg(
M_INFO,
"env_block: add %s", force_path);
1024 strcpy(p, force_path);
1025 p += strlen(force_path) + 1;
1044 static bool exec_warn =
false;
1046 if (a && a->
argv[0])
1051 STARTUPINFOW start_info;
1052 PROCESS_INFORMATION proc_info;
1059 DWORD proc_flags = CREATE_NO_WINDOW;
1065 GetStartupInfoW(&start_info);
1066 start_info.cb =
sizeof(start_info);
1067 start_info.dwFlags = STARTF_USESHOWWINDOW;
1068 start_info.wShowWindow = SW_HIDE;
1070 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info,
1073 DWORD exit_status = 0;
1074 CloseHandle(proc_info.hThread);
1075 WaitForSingleObject(proc_info.hProcess, INFINITE);
1076 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1078 ret = (int)exit_status;
1082 msg(
M_WARN |
M_ERRNO,
"openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1084 CloseHandle(proc_info.hProcess);
1105 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1116 STARTUPINFO start_info;
1117 PROCESS_INFORMATION proc_info;
1126 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1130 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1135 GetStartupInfo(&start_info);
1136 start_info.cb =
sizeof(start_info);
1137 start_info.dwFlags = STARTF_USESHOWWINDOW;
1138 start_info.wShowWindow = SW_HIDE;
1140 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1142 CloseHandle(proc_info.hThread);
1143 CloseHandle(proc_info.hProcess);
1178 if (
status >
sizeof(buf) - 1)
1180 msg(
M_FATAL,
"String overflow attempting to read environmental variable %s",
1189 DWORD
status = GetModuleFileNameW(NULL, path, size);
1225 .iface = { .index = index, .name =
"" } };
1235 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%lu]",
1242 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1251 WCHAR openvpnpath[MAX_PATH];
1257 dmsg(
D_LOW,
"Using service to add WFP block filters");
1304 msg(
D_LOW,
"Using service to delete WFP block filters");
1339 typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1340 is_wow64_process2_t is_wow64_process2 =
1341 (is_wow64_process2_t)GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1343 USHORT process_machine = 0;
1344 USHORT native_machine = 0;
1348#elif defined(_WIN64)
1350 if (is_wow64_process2)
1353 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1354 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1359#elif defined(_WIN32)
1362 if (is_wow64_process2)
1365 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1368 switch (native_machine)
1370 case IMAGE_FILE_MACHINE_ARM64:
1374 case IMAGE_FILE_MACHINE_AMD64:
1387 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1429 HMODULE hMod = GetModuleHandleW(L
"ntdll.dll");
1441 RTL_OSVERSIONINFOW rovi = { 0 };
1442 rovi.dwOSVersionInfoSize =
sizeof(rovi);
1465 return (
const char *)out.
data;
1476 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1490 WCHAR reg_path[256];
1492 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1494 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1495 if (
status != ERROR_SUCCESS)
1500 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1504 return status == ERROR_SUCCESS;
1510 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1512 WCHAR install_path[MAX_PATH] = { 0 };
1518 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1521 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1523 install_path[wcslen(install_path) - 1] = L
'\0';
1530 } ossl_env[] = { { L
"OPENSSL_CONF", L
"openssl.cnf" },
1531 { L
"OPENSSL_ENGINES", L
"engines" },
1532 { L
"OPENSSL_MODULES", L
"modules" } };
1534 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1538 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1541 WCHAR val[MAX_PATH] = { 0 };
1542 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1543 _wputenv_s(ossl_env[i].name, val);
1568 time_t expire =
now + n;
1570 while (expire >=
now)
1572 DWORD wait_ms = (DWORD)((expire -
now) * 1000);
1581 if (
status != WAIT_OBJECT_0)
1585 Sleep((DWORD)((expire -
now) * 1000));
1596 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1598 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1602 WCHAR plugin_dir[MAX_PATH] = { 0 };
1609 msg(
M_WARN,
"Installation path could not be determined.");
1613 WCHAR system_dir[MAX_PATH] = { 0 };
1614 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1619 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1624 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1627 if (wcslen(plugin_dir) > 0)
1629 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1650 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1652 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1653 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1656 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1668 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1670 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1671 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1674 ret = CryptUnprotectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
#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
bool win_path_in_dir(const WCHAR *path, const WCHAR *dir)
Check whether path resides within directory dir.
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
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)
static bool init_security_attributes_allow_user(struct security_attributes *obj)
Initializes security attributes with a DACL restricted to the current process user.
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)
static void free_security_attributes(struct security_attributes *obj)
Releases resources allocated by init_security_attributes_allow_user().
bool init_security_attributes_allow_all(struct security_attributes *obj)
Initializes security attributes with a NULL DACL, allowing unrestricted access to the resulting objec...
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)