40#include <wow64apiset.h>
53#include <versionhelpers.h>
164 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
165 obj->
sa.lpSecurityDescriptor = &obj->
sd;
166 obj->
sa.bInheritHandle = FALSE;
167 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
171 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
197 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
198 obj->
sa.lpSecurityDescriptor = &obj->
sd;
199 obj->
sa.bInheritHandle = FALSE;
201 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
207 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
212 PTOKEN_USER info = NULL;
214 if (!GetTokenInformation(token, TokenUser, info, info_len, &info_len)
215 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
220 info = malloc(info_len);
221 if (!info || !GetTokenInformation(token, TokenUser, info, info_len, &info_len))
226 EXPLICIT_ACCESS ea = { 0 };
227 ea.grfAccessPermissions = GENERIC_ALL;
228 ea.grfAccessMode = SET_ACCESS;
229 ea.grfInheritance = NO_INHERITANCE;
230 ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
231 ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
232 ea.Trustee.ptstrName = (LPTSTR)info->User.Sid;
234 if (SetEntriesInAcl(1, &ea, NULL, &obj->
dacl) != ERROR_SUCCESS)
239 if (SetSecurityDescriptorDacl(&obj->
sd, TRUE, obj->
dacl, FALSE))
260 LocalFree(obj->
dacl);
271 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
274 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
288 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle failed on overlapped I/O event object");
326 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
327 if (event->
write == NULL)
329 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (write) failed");
341 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
342 if (event->
read == NULL)
344 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (read) failed");
349 if (WSAEventSelect(sd, event->
read, network_events) != 0)
351 msg(
M_FATAL |
M_ERRNO,
"Error: init_net_event_win32: WSAEventSelect call failed");
358 WSANETWORKEVENTS wne;
359 if (WSAEnumNetworkEvents(sd, event->
read, &wne) != 0)
361 msg(
M_FATAL |
M_ERRNO,
"Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
366 return wne.lNetworkEvents;
377 if (WSAEventSelect(sd, event->
read, 0) != 0)
379 msg(
M_WARN |
M_ERRNO,
"Warning: close_net_event_win32: WSAEventSelect call failed");
382 if (!ResetEvent(event->
read))
384 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (read) failed in close_net_event_win32");
388 if (!CloseHandle(event->
read))
391 "Warning: CloseHandle (read) failed in close_net_event_win32");
399 if (!ResetEvent(event->
write))
401 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
405 if (!CloseHandle(event->
write))
408 "Warning: CloseHandle (write) failed in close_net_event_win32");
449 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
499 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
502 ir.EventType = KEY_EVENT;
503 ir.Event.KeyEvent.bKeyDown =
true;
504 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
517 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long)signum);
527 case CTRL_BREAK_EVENT:
535 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long)signum);
550 bool exit_event_initial_state)
555 ws->
in.
read = INVALID_HANDLE_VALUE;
556 ws->
in.
write = INVALID_HANDLE_VALUE;
565 ws->
in.
read = GetStdHandle(STD_INPUT_HANDLE);
566 if (ws->
in.
read != INVALID_HANDLE_VALUE)
571 const DWORD new_console_mode =
573 & ~(ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT
574 | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT);
578 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
580 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
588 ws->
in.
read = INVALID_HANDLE_VALUE;
602 const wchar_t *exit_event_nameW =
wide_string(exit_event_name, &
gc);
606 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
610 CreateEventW(&sa.
sa, TRUE, exit_event_initial_state ? TRUE : FALSE, exit_event_nameW);
617 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
619 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
643 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
654 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
656 return ir->Event.KeyEvent.wVirtualScanCode;
659 if ((ir->Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
660 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
662 return ir->Event.KeyEvent.wVirtualScanCode * 256;
665 return ir->Event.KeyEvent.uChar.AsciiChar;
682 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
686 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
707 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
781 WaitForSingleObject(ws->
in.
read, INFINITE);
854 s->
hand = CreateSemaphore(&
sa.sa, 1, 1, name);
860 msg(
M_ERR,
"Cannot create Win32 semaphore '%s'", name);
880 "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
881 s->
name, timeout_milliseconds / 1000);
882 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
883 if (
status == WAIT_FAILED)
885 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
887 ret = (
status == WAIT_TIMEOUT) ?
false :
true;
895 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
896 s->
name, timeout_milliseconds);
909 if (!ReleaseSemaphore(s->
hand, 1, NULL))
927 CloseHandle(s->
hand);
952 const int timeout_seconds = 600;
961 msg(
M_FATAL,
"Cannot lock net command semaphore");
980 char force_path[256];
983 if (!
checked_snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
984 sysroot, sysroot, sysroot))
986 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
995 bool path_seen =
false;
997 for (e = es->
list; e != NULL; e = e->
next)
999 nchars += strlen(e->
string) + 1;
1002 nchars += strlen(force_path) + 1;
1004 ret = (
char *)malloc(nchars);
1008 for (e = es->
list; e != NULL; e = e->
next)
1013 p += strlen(e->
string) + 1;
1015 if (strncmp(e->
string,
"PATH=", 5) == 0)
1024 msg(
M_INFO,
"env_block: add %s", force_path);
1025 strcpy(p, force_path);
1026 p += strlen(force_path) + 1;
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);
1095 static bool exec_warn =
false;
1107 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1118 STARTUPINFO start_info;
1119 PROCESS_INFORMATION proc_info;
1128 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1132 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1137 GetStartupInfo(&start_info);
1138 start_info.cb =
sizeof(start_info);
1139 start_info.dwFlags = STARTF_USESHOWWINDOW;
1140 start_info.wShowWindow = SW_HIDE;
1142 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1144 CloseHandle(proc_info.hThread);
1145 CloseHandle(proc_info.hProcess);
1180 if (
status >
sizeof(buf) - 1)
1182 msg(
M_FATAL,
"String overflow attempting to read environmental variable %s",
1191 DWORD
status = GetModuleFileNameW(NULL, path, size);
1227 .iface = { .index = index, .name =
"" } };
1237 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%lu]",
1244 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1253 WCHAR openvpnpath[MAX_PATH];
1259 dmsg(
D_LOW,
"Using service to add WFP block filters");
1306 msg(
D_LOW,
"Using service to delete WFP block filters");
1340#elif defined(_WIN64)
1348 USHORT process_machine = 0;
1349 USHORT native_machine = 0;
1351 if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine))
1356 switch (native_machine)
1358 case IMAGE_FILE_MACHINE_ARM64:
1362 case IMAGE_FILE_MACHINE_AMD64:
1366 case IMAGE_FILE_MACHINE_I386:
1375 if (*host_arch == *process_arch)
1412 HMODULE hMod = GetModuleHandleW(L
"ntdll.dll");
1424 RTL_OSVERSIONINFOW rovi = { 0 };
1425 rovi.dwOSVersionInfoSize =
sizeof(rovi);
1448 return (
const char *)out.
data;
1459 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1473 WCHAR reg_path[256];
1475 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1477 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1478 if (
status != ERROR_SUCCESS)
1483 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1487 return status == ERROR_SUCCESS;
1493 WCHAR install_path[MAX_PATH] = { 0 };
1496 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1500 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1503 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1505 install_path[wcslen(install_path) - 1] = L
'\0';
1512 } ossl_env[] = { { L
"OPENSSL_CONF", L
"openssl.cnf" },
1513 { L
"OPENSSL_ENGINES", L
"engines" },
1514 { L
"OPENSSL_MODULES", L
"modules" } };
1516 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1520 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1523 WCHAR val[MAX_PATH] = { 0 };
1524 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1525 _wputenv_s(ossl_env[i].name, val);
1550 time_t expire =
now + n;
1552 while (expire >=
now)
1554 DWORD wait_ms = (DWORD)((expire -
now) * 1000);
1563 if (
status != WAIT_OBJECT_0)
1567 Sleep((DWORD)((expire -
now) * 1000));
1578 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1580 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1584 WCHAR plugin_dir[MAX_PATH] = { 0 };
1591 msg(
M_WARN,
"Installation path could not be determined.");
1595 WCHAR system_dir[MAX_PATH] = { 0 };
1596 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1601 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1606 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1609 if (wcslen(plugin_dir) > 0)
1611 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1632 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1634 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1635 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1638 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1650 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1652 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1653 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1656 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)