Go to the documentation of this file.
48 #include <versionhelpers.h>
153 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
154 obj->
sa.lpSecurityDescriptor = &obj->
sd;
155 obj->
sa.bInheritHandle = FALSE;
156 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
160 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
175 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
178 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
192 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))
293 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (read) failed in close_net_event_win32");
301 if (!ResetEvent(event->
write))
303 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
307 if (!CloseHandle(event->
write))
309 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (write) failed in close_net_event_win32");
350 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
400 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
403 ir.EventType = KEY_EVENT;
404 ir.Event.KeyEvent.bKeyDown =
true;
405 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
418 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long) signum);
428 case CTRL_BREAK_EVENT:
436 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long) signum);
452 const char *exit_event_name,
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)
475 & ~(ENABLE_WINDOW_INPUT
476 | ENABLE_PROCESSED_INPUT
479 | ENABLE_MOUSE_INPUT);
483 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
485 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
493 ws->
in.
read = INVALID_HANDLE_VALUE;
507 const wchar_t *exit_event_nameW =
wide_string(exit_event_name, &gc);
511 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
514 ws->
in.
read = CreateEventW(&sa.
sa, TRUE, exit_event_initial_state ? TRUE : FALSE,
522 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
524 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
547 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
558 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
560 return ir->Event.KeyEvent.wVirtualScanCode;
563 if ((ir->Event.KeyEvent.dwControlKeyState
564 & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
565 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
567 return ir->Event.KeyEvent.wVirtualScanCode * 256;
570 return ir->Event.KeyEvent.uChar.AsciiChar;
587 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
591 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
612 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
627 && WaitForSingleObject(ws->
in.
read, 0) == WAIT_OBJECT_0)
687 WaitForSingleObject(ws->
in.
read, INFINITE);
736 SetConsoleTitle(
BSTR(&out));
759 s->
hand = CreateSemaphore(&
sa.sa, 1, 1, name);
782 dmsg(
D_SEMAPHORE_LOW,
"Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
784 timeout_milliseconds / 1000);
785 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
786 if (
status == WAIT_FAILED)
788 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
790 ret = (
status == WAIT_TIMEOUT) ?
false :
true;
798 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
800 timeout_milliseconds);
813 if (!ReleaseSemaphore(s->
hand, 1, NULL))
832 CloseHandle(s->
hand);
857 const int timeout_seconds = 600;
866 msg(
M_FATAL,
"Cannot lock net command semaphore");
885 char force_path[256];
888 if (!
openvpn_snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
889 sysroot, sysroot, sysroot))
891 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
900 bool path_seen =
false;
904 nchars += strlen(e->
string) + 1;
907 nchars += strlen(force_path)+1;
909 ret = (
char *) malloc(nchars);
918 p += strlen(e->
string) + 1;
920 if (strncmp(e->
string,
"PATH=", 5 ) == 0)
929 msg(
M_INFO,
"env_block: add %s", force_path );
930 strcpy( p, force_path );
931 p += strlen(force_path) + 1;
957 for (i = 0; i < a->
argc; ++i)
959 const char *arg = a->
argv[i];
960 const size_t len = strlen(arg);
972 for (i = 0; i < a->
argc; ++i)
974 const char *arg = a->
argv[i];
1001 static bool exec_warn =
false;
1003 if (a && a->
argv[0])
1008 STARTUPINFOW start_info;
1009 PROCESS_INFORMATION proc_info;
1016 DWORD proc_flags = CREATE_NO_WINDOW;
1022 GetStartupInfoW(&start_info);
1023 start_info.cb =
sizeof(start_info);
1024 start_info.dwFlags = STARTF_USESHOWWINDOW;
1025 start_info.wShowWindow = SW_HIDE;
1027 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))
1029 DWORD exit_status = 0;
1030 CloseHandle(proc_info.hThread);
1031 WaitForSingleObject(proc_info.hProcess, INFINITE);
1032 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1034 ret = (int)exit_status;
1040 CloseHandle(proc_info.hProcess);
1061 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1072 STARTUPINFO start_info;
1073 PROCESS_INFORMATION proc_info;
1082 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1085 msg(
M_WARN|
M_ERRNO,
"fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1090 GetStartupInfo(&start_info);
1091 start_info.cb =
sizeof(start_info);
1092 start_info.dwFlags = STARTF_USESHOWWINDOW;
1093 start_info.wShowWindow = SW_HIDE;
1095 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1097 CloseHandle(proc_info.hThread);
1098 CloseHandle(proc_info.hProcess);
1133 if (
status >
sizeof(buf) - 1)
1153 .iface = { .index = index, .name =
"" }
1163 msg(
M_WARN,
"Block_DNS: %s block dns filters using service failed: %s [status=0x%x if_index=%d]",
1170 msg(
M_INFO,
"%s outside dns using service succeeded.", (add ?
"Blocking" :
"Unblocking"));
1187 msg(
M_WARN,
"Error in add_block_dns_filters(): %s : %s [status=0x%lx]",
1197 WCHAR openvpnpath[MAX_PATH];
1203 dmsg(
D_LOW,
"Using service to add block dns filters");
1208 status = GetModuleFileNameW(NULL, openvpnpath, _countof(openvpnpath));
1251 msg(
D_LOW,
"Using service to delete block dns filters");
1274 if (!IsWindowsXPOrGreater())
1276 msg(
M_FATAL,
"Error: Windows version must be XP or greater.");
1279 if (!IsWindowsVistaOrGreater())
1284 if (!IsWindows7OrGreater())
1289 if (!IsWindows8OrGreater())
1294 if (!IsWindows8Point1OrGreater())
1299 if (!IsWindows10OrGreater())
1321 typedef BOOL (WINAPI *is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1322 is_wow64_process2_t is_wow64_process2 = (is_wow64_process2_t)
1323 GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
"IsWow64Process2");
1325 USHORT process_machine = 0;
1326 USHORT native_machine = 0;
1330 #elif defined(_WIN64)
1332 if (is_wow64_process2)
1335 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1336 &process_machine, &native_machine);
1337 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1342 #elif defined(_WIN32)
1345 if (is_wow64_process2)
1348 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1349 &process_machine, &native_machine);
1352 switch (native_machine)
1354 case IMAGE_FILE_MACHINE_ARM64:
1358 case IMAGE_FILE_MACHINE_AMD64:
1371 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1417 buf_printf(&out,
"5.1%s", add_name ?
" (Windows XP)" :
"");
1421 buf_printf(&out,
"6.0%s", add_name ?
" (Windows Vista)" :
"");
1425 buf_printf(&out,
"6.1%s", add_name ?
" (Windows 7)" :
"");
1429 buf_printf(&out,
"6.2%s", add_name ?
" (Windows 8)" :
"");
1433 buf_printf(&out,
"6.3%s", add_name ?
" (Windows 8.1)" :
"");
1437 buf_printf(&out,
"10.0%s", add_name ?
" (Windows 10 or greater)" :
"");
1442 buf_printf(&out,
"0.0%s", add_name ?
" (unknown)" :
"");
1448 arch_t process_arch, host_arch;
1461 return (
const char *)out.
data;
1472 if (!WriteFile(pipe, data, size, &len, NULL)
1473 || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1475 msg(
M_WARN,
"%s: could not talk to service: %s [%lu]",
1492 va_start(arglist, format);
1493 len = vswprintf(str, size, format, arglist);
1495 str[size - 1] = L
'\0';
1497 return (len >= 0 && len < size);
1503 WCHAR reg_path[256];
1508 LONG
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &
key);
1509 if (
status != ERROR_SUCCESS)
1515 status = RegGetValueW(
key, NULL, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)path, &size);
1516 res =
status == ERROR_SUCCESS;
1526 const WCHAR *ssl_fallback_dir = L
"C:\\Windows\\System32";
1528 WCHAR install_path[MAX_PATH] = { 0 };
1534 openvpn_swprintf(install_path, _countof(install_path), L
"%ls", ssl_fallback_dir);
1537 if ((install_path[wcslen(install_path) - 1]) == L
'\\')
1539 install_path[wcslen(install_path) - 1] = L
'\0';
1546 {L
"OPENSSL_CONF", L
"openssl.cnf"},
1547 {L
"OPENSSL_ENGINES", L
"engines"},
1548 {L
"OPENSSL_MODULES", L
"modules"}
1551 for (
size_t i = 0; i <
SIZE(ossl_env); ++i)
1555 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1558 WCHAR val[MAX_PATH] = {0};
1559 openvpn_swprintf(val, _countof(val), L
"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1560 _wputenv_s(ossl_env[i].name, val);
1585 time_t expire =
now + n;
1587 while (expire >=
now)
1591 ||
status == WAIT_TIMEOUT)
1598 if (
status != WAIT_OBJECT_0)
1602 Sleep((expire-
now)*1000);
char * overlapped_io_state_ascii(const struct overlapped_io *o)
void set_win_sys_path(const char *newpath, struct env_set *es)
volatile int signal_received
void fork_to_self(const char *cmdline)
static struct WSAData wsa_state
void semaphore_close(struct semaphore *s)
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds)
static struct gc_arena gc_new(void)
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
static void block_dns_msg_handler(DWORD err, const char *msg)
int len
Length in bytes of the actual content within the allocated memory.
void netcmd_semaphore_lock(void)
Contains all state information for one tunnel.
#define OPENVPN_EXECVE_ERROR
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
#define BLOCK_DNS_IFACE_METRIC
#define CC_CRLF
carriage return or newline
#define HANDLE_DEFINED(h)
void net_event_win32_reset(struct net_event_win32 *ne)
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
void window_title_save(struct window_title *wt)
#define NE32_PERSIST_EVENT
static HANDLE m_hEngineHandle
Packet geometry parameters.
struct semaphore netcmd_semaphore
#define IOSTATE_IMMEDIATE_RETURN
static bool net_event_win32_defined(const struct net_event_win32 *ne)
static void win_trigger_event(struct win32_signal *ws)
Container for unidirectional cipher and HMAC key material.
static void win32_get_arch(arch_t *process_arch, arch_t *host_arch)
void net_event_win32_stop(struct net_event_win32 *ne)
#define CC_DOUBLE_QUOTE
double quote
void win32_signal_clear(struct win32_signal *ws)
char * string_alloc(const char *str, struct gc_arena *gc)
char old_window_title[256]
void overlapped_io_close(struct overlapped_io *o)
static bool WINAPI win_ctrl_handler(DWORD signum)
#define SYS_PATH_ENV_VAR_NAME
static unsigned int win32_keyboard_get(struct win32_signal *ws)
void init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
static bool win_block_dns_service(bool add, int index, const HANDLE pipe)
#define OPENVPN_EXECVE_NOT_ALLOWED
#define CC_PRINT
printable (>= 32, != 127)
static void update_time(void)
bool win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel)
void netcmd_semaphore_release(void)
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...
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
void window_title_clear(struct window_title *wt)
bool env_allowed(const char *str)
void netcmd_semaphore_init(void)
void throw_signal(const int signum)
Throw a hard signal.
DWORD set_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, const ULONG metric)
Sets interface metric value for specified interface index.
void set_win_sys_path_via_env(struct env_set *es)
void semaphore_release(struct semaphore *s)
void win32_sleep(const int n)
void set_pause_exit_win32(void)
bool openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format,...)
Wrapper structure for dynamically allocated memory.
static BOOL get_install_path(WCHAR *path, DWORD size)
static bool pause_exit_enabled
#define WSO_FORCE_CONSOLE
static int socket_defined(const socket_descriptor_t sd)
void window_title_generate(const char *title)
#define CC_SPACE
whitespace isspace()
#define CC_ANY
any character
static void win32_print_arch(arch_t arch, struct buffer *out)
Garbage collection arena used to keep track of dynamically allocated memory.
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame)
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
void setenv_str(struct env_set *es, const char *name, const char *value)
int get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto)
Return interface metric value for the specified interface index.
static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc)
const char * win32_version_string(struct gc_arena *gc, bool add_name)
static bool keyboard_input_available(struct win32_signal *ws)
bool openvpn_execve_allowed(const unsigned int flags)
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd)
int win32_signal_get(struct win32_signal *ws)
DWORD add_block_dns_filters(HANDLE *engine_handle, int index, const WCHAR *exe_path, block_dns_msg_handler_t msg_handler)
void free_buf(struct buffer *buf)
SOCKET socket_descriptor_t
void net_event_win32_reset_write(struct net_event_win32 *ne)
static unsigned int keyboard_ir_to_key(INPUT_RECORD *ir)
static char * win_sys_path
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
void win32_signal_close(struct win32_signal *ws)
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state)
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
static SERVICE_STATUS status
static void gc_free(struct gc_arena *a)
#define WSO_FORCE_SERVICE
bool init_security_attributes_allow_all(struct security_attributes *obj)
void semaphore_open(struct semaphore *s, const char *name)
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
static void set_openssl_env_vars()
Set OpenSSL environment variables to a safe directory.
void net_event_win32_close(struct net_event_win32 *ne)
static void check_malloc_return(void *p)
bool win32_service_interrupt(struct win32_signal *ws)
char * get_win_sys_path(void)
void net_event_win32_init(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)
#define SCRIPT_SECURITY_WARNING
void netcmd_semaphore_close(void)
int win32_version_info(void)
void window_title_restore(const struct window_title *wt)
static char * env_block(const struct env_set *es)
void semaphore_clear(struct semaphore *s)
struct signal_info siginfo_static
bool buf_printf(struct buffer *buf, const char *format,...)
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
int script_security(void)
bool console_mode_save_defined
void win32_pause(struct win32_signal *ws)
DWORD delete_block_dns_filters(HANDLE engine_handle)
uint8_t * data
Pointer to the allocated memory.