51#include <versionhelpers.h>
156 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
157 obj->
sa.lpSecurityDescriptor = &obj->
sd;
158 obj->
sa.bInheritHandle = FALSE;
159 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
163 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
178 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
181 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
195 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle failed on overlapped I/O event object");
232 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
233 if (event->
write == NULL)
235 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (write) failed");
247 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
248 if (event->
read == NULL)
250 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (read) failed");
255 if (WSAEventSelect(sd, event->
read, network_events) != 0)
257 msg(
M_FATAL |
M_ERRNO,
"Error: init_net_event_win32: WSAEventSelect call failed");
264 WSANETWORKEVENTS wne;
265 if (WSAEnumNetworkEvents(sd, event->
read, &wne) != 0)
267 msg(
M_FATAL |
M_ERRNO,
"Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
272 return wne.lNetworkEvents;
283 if (WSAEventSelect(sd, event->
read, 0) != 0)
285 msg(
M_WARN |
M_ERRNO,
"Warning: close_net_event_win32: WSAEventSelect call failed");
288 if (!ResetEvent(event->
read))
290 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (read) failed in close_net_event_win32");
294 if (!CloseHandle(event->
read))
296 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (read) failed in close_net_event_win32");
304 if (!ResetEvent(event->
write))
306 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
310 if (!CloseHandle(event->
write))
312 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (write) failed in close_net_event_win32");
353 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
403 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
406 ir.EventType = KEY_EVENT;
407 ir.Event.KeyEvent.bKeyDown =
true;
408 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
421 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long) signum);
431 case CTRL_BREAK_EVENT:
439 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long) signum);
455 const char *exit_event_name,
456 bool exit_event_initial_state)
461 ws->
in.
read = INVALID_HANDLE_VALUE;
462 ws->
in.
write = INVALID_HANDLE_VALUE;
471 ws->
in.
read = GetStdHandle(STD_INPUT_HANDLE);
472 if (ws->
in.
read != INVALID_HANDLE_VALUE)
478 & ~(ENABLE_WINDOW_INPUT
479 | ENABLE_PROCESSED_INPUT
482 | ENABLE_MOUSE_INPUT);
486 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
488 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
496 ws->
in.
read = INVALID_HANDLE_VALUE;
510 const wchar_t *exit_event_nameW =
wide_string(exit_event_name, &
gc);
514 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
517 ws->
in.
read = CreateEventW(&sa.
sa, TRUE, exit_event_initial_state ? TRUE : FALSE,
525 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
527 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
550 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
561 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
563 return ir->Event.KeyEvent.wVirtualScanCode;
566 if ((ir->Event.KeyEvent.dwControlKeyState
567 & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
568 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
570 return ir->Event.KeyEvent.wVirtualScanCode * 256;
573 return ir->Event.KeyEvent.uChar.AsciiChar;
590 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
594 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
615 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
630 && WaitForSingleObject(ws->
in.
read, 0) == WAIT_OBJECT_0)
690 WaitForSingleObject(ws->
in.
read, INFINITE);
762 s->
hand = CreateSemaphore(&
sa.sa, 1, 1, name);
785 dmsg(
D_SEMAPHORE_LOW,
"Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
787 timeout_milliseconds / 1000);
788 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
789 if (
status == WAIT_FAILED)
791 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
793 ret = (
status == WAIT_TIMEOUT) ?
false :
true;
801 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
803 timeout_milliseconds);
816 if (!ReleaseSemaphore(s->
hand, 1, NULL))
835 CloseHandle(s->
hand);
860 const int timeout_seconds = 600;
869 msg(
M_FATAL,
"Cannot lock net command semaphore");
888 char force_path[256];
891 if (!snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
892 sysroot, sysroot, sysroot))
894 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
903 bool path_seen =
false;
907 nchars += strlen(e->
string) + 1;
910 nchars += strlen(force_path)+1;
912 ret = (
char *) malloc(nchars);
921 p += strlen(e->
string) + 1;
923 if (strncmp(e->
string,
"PATH=", 5 ) == 0)
932 msg(
M_INFO,
"env_block: add %s", force_path );
933 strcpy( p, force_path );
934 p += strlen(force_path) + 1;
960 for (
i = 0;
i <
a->argc; ++
i)
962 const char *arg =
a->argv[
i];
975 for (
i = 0;
i <
a->argc; ++
i)
977 const char *arg =
a->argv[
i];
1006 if (
a &&
a->argv[0])
1011 STARTUPINFOW start_info;
1012 PROCESS_INFORMATION proc_info;
1019 DWORD proc_flags = CREATE_NO_WINDOW;
1025 GetStartupInfoW(&start_info);
1026 start_info.cb =
sizeof(start_info);
1027 start_info.dwFlags = STARTF_USESHOWWINDOW;
1028 start_info.wShowWindow = SW_HIDE;
1030 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))
1032 DWORD exit_status = 0;
1033 CloseHandle(proc_info.hThread);
1034 WaitForSingleObject(proc_info.hProcess, INFINITE);
1035 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1037 ret = (int)exit_status;
1043 CloseHandle(proc_info.hProcess);
1064 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1075 STARTUPINFO start_info;
1076 PROCESS_INFORMATION proc_info;
1085 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1088 msg(
M_WARN|
M_ERRNO,
"fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1093 GetStartupInfo(&start_info);
1094 start_info.cb =
sizeof(start_info);
1095 start_info.dwFlags = STARTF_USESHOWWINDOW;
1096 start_info.wShowWindow = SW_HIDE;
1098 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1100 CloseHandle(proc_info.hThread);
1101 CloseHandle(proc_info.hProcess);
1136 if (
status >
sizeof(buf) - 1)
1146 DWORD
status = GetModuleFileNameW(NULL, path, size);
1166 msg(
M_WARN,
"Error in WFP: %s : %s [status=0x%lx]",
1187 .iface = { .index = index, .name =
"" }
1197 msg(
M_WARN,
"WFP block: %s block filters using service failed: %s [status=0x%x if_index=%d]",
1204 msg(
M_INFO,
"%s WFP block filters using service succeeded.", (add ?
"Adding" :
"Deleting"));
1213 WCHAR openvpnpath[MAX_PATH];
1219 dmsg(
D_LOW,
"Using service to add WFP block filters");
1266 msg(
D_LOW,
"Using service to delete WFP block filters");
1289 if (!IsWindowsXPOrGreater())
1291 msg(
M_FATAL,
"Error: Windows version must be XP or greater.");
1294 if (!IsWindowsVistaOrGreater())
1299 if (!IsWindows7OrGreater())
1304 if (!IsWindows8OrGreater())
1309 if (!IsWindows8Point1OrGreater())
1314 if (!IsWindows10OrGreater())
1336 typedef BOOL (WINAPI *is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1337 is_wow64_process2_t is_wow64_process2 = (is_wow64_process2_t)
1338 GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1340 USHORT process_machine = 0;
1341 USHORT native_machine = 0;
1345#elif defined(_WIN64)
1347 if (is_wow64_process2)
1350 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1351 &process_machine, &native_machine);
1352 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1357#elif defined(_WIN32)
1360 if (is_wow64_process2)
1363 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1364 &process_machine, &native_machine);
1367 switch (native_machine)
1369 case IMAGE_FILE_MACHINE_ARM64:
1373 case IMAGE_FILE_MACHINE_AMD64:
1386 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1476 return (
const char *)out.
data;
1487 if (!WriteFile(pipe, data, size, &len, NULL)
1488 || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1490 msg(
M_WARN,
"%s: could not talk to service: %s [%lu]",
1503 WCHAR reg_path[256];
1505 swprintf(reg_path, _countof(reg_path), L
"SOFTWARE\\" PACKAGE_NAME);
1507 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1508 if (
status != ERROR_SUCCESS)
1513 status = RegGetValueW(hkey, NULL,
key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1517 return status == ERROR_SUCCESS;
1523 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1525 WCHAR install_path[MAX_PATH] = { 0 };
1531 swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1534 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1536 install_path[wcslen(install_path) - 1] = L
'\0';
1543 {L
"OPENSSL_CONF", L
"openssl.cnf"},
1544 {L
"OPENSSL_ENGINES", L
"engines"},
1545 {L
"OPENSSL_MODULES", L
"modules"}
1548 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1552 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1555 WCHAR val[MAX_PATH] = {0};
1556 swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1557 _wputenv_s(ossl_env[i].name, val);
1582 time_t expire =
now + n;
1584 while (expire >=
now)
1588 ||
status == WAIT_TIMEOUT)
1595 if (
status != WAIT_OBJECT_0)
1599 Sleep((expire-
now)*1000);
1610 if (wcsncmp(plugin_path, L
"\\\\", 2) == 0)
1612 msg(
M_WARN,
"UNC paths for plugins are not allowed.");
1616 WCHAR plugin_dir[MAX_PATH] = { 0 };
1623 msg(
M_WARN,
"Installation path could not be determined.");
1627 WCHAR system_dir[MAX_PATH] = { 0 };
1628 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1633 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1638 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1641 if (wcslen(plugin_dir) > 0)
1643 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1651 if ((wcslen(normalized_plugin_dir) > 0) && (wcsnicmp(normalized_plugin_dir,
1652 plugin_path, wcslen(normalized_plugin_dir)) == 0))
1658 return wcsnicmp(system_dir, plugin_path, wcslen(system_dir)) == 0;
1665 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1667 msg(
M_NONFATAL,
"Error: Unable to encrypt memory: buffer size not a multiple of %d",
1668 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1671 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1683 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1685 msg(
M_NONFATAL,
"Error: Unable to decrypt memory: buffer size not a multiple of %d",
1686 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1689 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 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)
int win32_version_info(void)
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.
const char * win32_version_string(struct gc_arena *gc, bool add_name)
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)
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)
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)