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);
828 buf_printf(&out,
"[%s] " PACKAGE_NAME
" " PACKAGE_VERSION
" F4:EXIT F1:USR1 F2:USR2 F3:HUP",
830 SetConsoleTitle(
BSTR(&out));
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;
996 for (e = es->
list; e != NULL; e = e->
next)
998 nchars += strlen(e->
string) + 1;
1001 nchars += strlen(force_path) + 1;
1003 ret = (
char *)malloc(nchars);
1007 for (e = es->
list; e != NULL; e = e->
next)
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;
1045 if (a && a->
argv[0])
1050 STARTUPINFOW start_info;
1051 PROCESS_INFORMATION proc_info;
1058 DWORD proc_flags = CREATE_NO_WINDOW;
1064 GetStartupInfoW(&start_info);
1065 start_info.cb =
sizeof(start_info);
1066 start_info.dwFlags = STARTF_USESHOWWINDOW;
1067 start_info.wShowWindow = SW_HIDE;
1069 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info,
1072 DWORD exit_status = 0;
1073 CloseHandle(proc_info.hThread);
1074 WaitForSingleObject(proc_info.hProcess, INFINITE);
1075 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1077 ret = (int)exit_status;
1081 msg(
M_WARN |
M_ERRNO,
"openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1083 CloseHandle(proc_info.hProcess);
1094 static bool exec_warn =
false;
1106 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1117 STARTUPINFO start_info;
1118 PROCESS_INFORMATION proc_info;
1127 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1131 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1136 GetStartupInfo(&start_info);
1137 start_info.cb =
sizeof(start_info);
1138 start_info.dwFlags = STARTF_USESHOWWINDOW;
1139 start_info.wShowWindow = SW_HIDE;
1141 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1143 CloseHandle(proc_info.hThread);
1144 CloseHandle(proc_info.hProcess);
1179 if (
status >
sizeof(buf) - 1)
1181 msg(
M_FATAL,
"String overflow attempting to read environmental variable %s",
1190 DWORD
status = GetModuleFileNameW(NULL, path, size);
1226 .iface = { .index = index, .name =
"" } };
1236 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%lu]",
1243 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1252 WCHAR openvpnpath[MAX_PATH];
1258 dmsg(
D_LOW,
"Using service to add WFP block filters");
1305 msg(
D_LOW,
"Using service to delete WFP block filters");
1340 typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1341 is_wow64_process2_t is_wow64_process2 =
1342 (is_wow64_process2_t)GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1346#elif defined(_WIN64)
1348 if (is_wow64_process2)
1351 USHORT process_machine = 0;
1352 USHORT native_machine = 0;
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 USHORT process_machine = 0;
1366 USHORT native_machine = 0;
1367 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1370 switch (native_machine)
1372 case IMAGE_FILE_MACHINE_ARM64:
1376 case IMAGE_FILE_MACHINE_AMD64:
1389 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1431 HMODULE hMod = GetModuleHandleW(L
"ntdll.dll");
1443 RTL_OSVERSIONINFOW rovi = { 0 };
1444 rovi.dwOSVersionInfoSize =
sizeof(rovi);
1452 buf_printf(&out,
"%lu.%lu.%lu", rovi.dwMajorVersion, rovi.dwMinorVersion, rovi.dwBuildNumber);
1456 arch_t process_arch, host_arch;
1467 return (
const char *)out.
data;
1478 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1492 WCHAR reg_path[256];
1494 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1496 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1497 if (
status != ERROR_SUCCESS)
1502 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1506 return status == ERROR_SUCCESS;
1512 WCHAR install_path[MAX_PATH] = { 0 };
1515 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1519 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1522 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1524 install_path[wcslen(install_path) - 1] = L
'\0';
1531 } ossl_env[] = { { L
"OPENSSL_CONF", L
"openssl.cnf" },
1532 { L
"OPENSSL_ENGINES", L
"engines" },
1533 { L
"OPENSSL_MODULES", L
"modules" } };
1535 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1539 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1542 WCHAR val[MAX_PATH] = { 0 };
1543 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1544 _wputenv_s(ossl_env[i].name, val);
1569 time_t expire =
now + n;
1571 while (expire >=
now)
1573 DWORD wait_ms = (DWORD)((expire -
now) * 1000);
1582 if (
status != WAIT_OBJECT_0)
1586 Sleep((DWORD)((expire -
now) * 1000));
1597 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1599 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1603 WCHAR plugin_dir[MAX_PATH] = { 0 };
1610 msg(
M_WARN,
"Installation path could not be determined.");
1614 WCHAR system_dir[MAX_PATH] = { 0 };
1615 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1620 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1625 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1628 if (wcslen(plugin_dir) > 0)
1630 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1651 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1653 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1654 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1657 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1669 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1671 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1672 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1675 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.
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.
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)