31 #elif defined(_MSC_VER) 49 #ifdef HAVE_VERSIONHELPERS_H 50 #include <versionhelpers.h> 150 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
151 obj->
sa.lpSecurityDescriptor = &obj->
sd;
152 obj->
sa.bInheritHandle = FALSE;
153 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
157 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
173 o->
overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
176 msg(
M_ERR,
"Error: overlapped_io_init: CreateEvent failed");
190 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle failed on overlapped I/O event object");
227 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
228 if (event->
write == NULL)
230 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (write) failed");
240 if (!(flags & NE32_PERSIST_EVENT) || !event->
read)
242 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
243 if (event->
read == NULL)
245 msg(
M_ERR,
"Error: init_net_event_win32: CreateEvent (read) failed");
250 if (WSAEventSelect(sd, event->
read, network_events) != 0)
252 msg(
M_FATAL |
M_ERRNO,
"Error: init_net_event_win32: WSAEventSelect call failed");
259 WSANETWORKEVENTS wne;
260 if (WSAEnumNetworkEvents(sd, event->
read, &wne) != 0)
262 msg(
M_FATAL |
M_ERRNO,
"Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
267 return wne.lNetworkEvents;
278 if (WSAEventSelect(sd, event->
read, 0) != 0)
280 msg(
M_WARN |
M_ERRNO,
"Warning: close_net_event_win32: WSAEventSelect call failed");
283 if (!ResetEvent(event->
read))
285 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (read) failed in close_net_event_win32");
289 if (!CloseHandle(event->
read))
291 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (read) failed in close_net_event_win32");
299 if (!ResetEvent(event->
write))
301 msg(
M_WARN |
M_ERRNO,
"Warning: ResetEvent (write) failed in close_net_event_win32");
305 if (!CloseHandle(event->
write))
307 msg(
M_WARN |
M_ERRNO,
"Warning: CloseHandle (write) failed in close_net_event_win32");
348 msg(
M_WARN |
M_ERRNO,
"Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
398 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
401 ir.EventType = KEY_EVENT;
402 ir.Event.KeyEvent.bKeyDown =
true;
403 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
416 msg(
D_LOW,
"win_ctrl_handler: signal received (code=%lu)", (
unsigned long) signum);
426 case CTRL_BREAK_EVENT:
434 msg(
D_LOW,
"win_ctrl_handler: signal (code=%lu) not handled", (
unsigned long) signum);
450 const char *exit_event_name,
451 bool exit_event_initial_state)
456 ws->
in.
read = INVALID_HANDLE_VALUE;
457 ws->
in.
write = INVALID_HANDLE_VALUE;
466 ws->
in.
read = GetStdHandle(STD_INPUT_HANDLE);
467 if (ws->
in.
read != INVALID_HANDLE_VALUE)
473 & ~(ENABLE_WINDOW_INPUT
474 | ENABLE_PROCESSED_INPUT
477 | ENABLE_MOUSE_INPUT);
481 if (!SetConsoleMode(ws->
in.
read, new_console_mode))
483 msg(
M_ERR,
"Error: win32_signal_open: SetConsoleMode failed");
491 ws->
in.
read = INVALID_HANDLE_VALUE;
507 msg(
M_ERR,
"Error: win32_signal_open: init SA failed");
512 exit_event_initial_state ? TRUE : FALSE,
520 if (WaitForSingleObject(ws->
in.
read, 0) != WAIT_TIMEOUT)
522 msg(
M_FATAL,
"ERROR: Exit Event ('%s') is signaled", exit_event_name);
544 if (GetNumberOfConsoleInputEvents(ws->
in.
read, &n))
555 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
557 return ir->Event.KeyEvent.wVirtualScanCode;
560 if ((ir->Event.KeyEvent.dwControlKeyState
561 & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
562 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
564 return ir->Event.KeyEvent.wVirtualScanCode * 256;
567 return ir->Event.KeyEvent.uChar.AsciiChar;
584 if (!ReadConsoleInput(ws->
in.
read, &ir, 1, &n))
588 }
while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
609 msg(
M_ERR,
"Error: win32_signal_close: SetConsoleMode failed");
624 && WaitForSingleObject(ws->
in.
read, 0) == WAIT_OBJECT_0)
691 WaitForSingleObject(ws->
in.
read, INFINITE);
740 SetConsoleTitle(
BSTR(&out));
763 s->
hand = CreateSemaphore(&sa.
sa, 1, 1, name);
786 dmsg(
D_SEMAPHORE_LOW,
"Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
788 timeout_milliseconds / 1000);
789 status = WaitForSingleObject(s->
hand, timeout_milliseconds);
790 if (status == WAIT_FAILED)
792 msg(
M_ERR,
"Wait failed on Win32 semaphore '%s'", s->
name);
794 ret = (status == WAIT_TIMEOUT) ?
false :
true;
802 dmsg(
D_SEMAPHORE,
"Wait on Win32 semaphore '%s' timed out after %d milliseconds",
804 timeout_milliseconds);
817 if (!ReleaseSemaphore(s->
hand, 1, NULL))
836 CloseHandle(s->
hand);
861 const int timeout_seconds = 600;
870 msg(
M_FATAL,
"Cannot lock net command semaphore");
905 const int c1 = pre[i];
921 return c2 ==
'\0' || c2 ==
'.';
927 if (c1 != tolower(c2))
975 char force_path[256];
978 if (!
openvpn_snprintf(force_path,
sizeof(force_path),
"PATH=%s\\System32;%s;%s\\System32\\Wbem",
979 sysroot, sysroot, sysroot))
981 msg(
M_WARN,
"env_block: default path truncated to %s", force_path);
990 bool path_seen =
false;
992 for (e = es->
list; e != NULL; e = e->
next)
994 nchars += strlen(e->
string) + 1;
997 nchars += strlen(force_path)+1;
999 ret = (
char *)
malloc(nchars);
1003 for (e = es->
list; e != NULL; e = e->
next)
1008 p += strlen(e->
string) + 1;
1010 if (strncmp(e->
string,
"PATH=", 5 ) == 0)
1019 msg(
M_INFO,
"env_block: add %s", force_path );
1020 strcpy( p, force_path );
1021 p += strlen(force_path) + 1;
1047 for (i = 0; i < a->
argc; ++i)
1049 const char *arg = a->
argv[i];
1050 const size_t len = strlen(arg);
1058 work =
gc_malloc(maxlen + 1,
false, gc);
1062 for (i = 0; i < a->
argc; ++i)
1064 const char *arg = a->
argv[i];
1091 static bool exec_warn =
false;
1093 if (a && a->
argv[0])
1098 STARTUPINFOW start_info;
1099 PROCESS_INFORMATION proc_info;
1106 DWORD proc_flags = CREATE_NO_WINDOW;
1112 GetStartupInfoW(&start_info);
1113 start_info.cb =
sizeof(start_info);
1114 start_info.dwFlags = STARTF_USESHOWWINDOW;
1115 start_info.wShowWindow = SW_HIDE;
1117 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))
1119 DWORD exit_status = 0;
1120 CloseHandle(proc_info.hThread);
1121 WaitForSingleObject(proc_info.hProcess, INFINITE);
1122 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1124 ret = (int)exit_status;
1130 CloseHandle(proc_info.hProcess);
1151 msg(
M_WARN,
"openvpn_execve: called with empty argv");
1159 int n = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
1160 WCHAR *ucs16 =
gc_malloc(n *
sizeof(WCHAR),
false, gc);
1161 MultiByteToWideChar(CP_UTF8, 0, utf8, -1, ucs16, n);
1171 STARTUPINFO start_info;
1172 PROCESS_INFORMATION proc_info;
1181 status = GetModuleFileName(NULL, self_exe,
sizeof(self_exe));
1182 if (status == 0 || status ==
sizeof(self_exe))
1184 msg(
M_WARN|
M_ERRNO,
"fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1189 GetStartupInfo(&start_info);
1190 start_info.cb =
sizeof(start_info);
1191 start_info.dwFlags = STARTF_USESHOWWINDOW;
1192 start_info.wShowWindow = SW_HIDE;
1194 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1196 CloseHandle(proc_info.hThread);
1197 CloseHandle(proc_info.hProcess);
1232 if (status >
sizeof(buf) - 1)
1243 static char tmpdir[MAX_PATH];
1244 WCHAR wtmpdir[MAX_PATH];
1246 if (!GetTempPathW(_countof(wtmpdir), wtmpdir))
1251 msg(
M_WARN,
"Could not find a suitable temporary directory." 1252 " (GetTempPath() failed). Consider using --tmp-dir");
1256 if (WideCharToMultiByte(CP_UTF8, 0, wtmpdir, -1, NULL, 0, NULL, NULL) >
sizeof(tmpdir))
1258 msg(
M_WARN,
"Could not get temporary directory. Path is too long." 1259 " Consider using --tmp-dir");
1263 WideCharToMultiByte(CP_UTF8, 0, wtmpdir, -1, tmpdir,
sizeof(tmpdir), NULL, NULL);
1280 .iface = { .index = index, .name =
"" }
1290 msg(
M_WARN,
"Block_DNS: %s block dns filters using service failed: %s [status=0x%x if_index=%d]",
1297 msg(
M_INFO,
"%s outside dns using service succeeded.", (add ?
"Blocking" :
"Unblocking"));
1314 msg(
M_WARN,
"Error in add_block_dns_filters(): %s : %s [status=0x%lx]",
1324 WCHAR openvpnpath[MAX_PATH];
1330 dmsg(
D_LOW,
"Using service to add block dns filters");
1335 status = GetModuleFileNameW(NULL, openvpnpath, _countof(openvpnpath));
1336 if (status == 0 || status == _countof(openvpnpath))
1364 ret = (status == 0);
1378 msg(
D_LOW,
"Using service to delete block dns filters");
1401 if (!IsWindowsXPOrGreater())
1403 msg(
M_FATAL,
"Error: Windows version must be XP or greater.");
1406 if (!IsWindowsVistaOrGreater())
1411 if (!IsWindows7OrGreater())
1416 if (!IsWindows8OrGreater())
1421 if (!IsWindows8Point1OrGreater())
1426 if (!IsWindows10OrGreater())
1439 #elif defined(_WIN32) 1442 return IsWow64Process(GetCurrentProcess(), &f64) && f64;
1457 buf_printf(&out,
"5.1%s", add_name ?
" (Windows XP)" :
"");
1461 buf_printf(&out,
"6.0%s", add_name ?
" (Windows Vista)" :
"");
1465 buf_printf(&out,
"6.1%s", add_name ?
" (Windows 7)" :
"");
1469 buf_printf(&out,
"6.2%s", add_name ?
" (Windows 8)" :
"");
1473 buf_printf(&out,
"6.3%s", add_name ?
" (Windows 8.1)" :
"");
1477 buf_printf(&out,
"10.0%s", add_name ?
" (Windows 10 or greater)" :
"");
1482 buf_printf(&out,
"0.0%s", add_name ?
" (unknown)" :
"");
1488 return (
const char *)out.
data;
1499 if (!WriteFile(pipe, data, size, &len, NULL)
1500 || !ReadFile(pipe, ack,
sizeof(*ack), &len, NULL))
1502 msg(
M_WARN,
"%s: could not talk to service: %s [%lu]",
1503 context ? context :
"Unknown",
struct signal_info siginfo_static
static bool pause_exit_enabled
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
static bool WINAPI win_ctrl_handler(DWORD signum)
void netcmd_semaphore_close(void)
const char * win_get_tempdir(void)
void free_buf(struct buffer *buf)
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)
char * string_alloc(const char *str, struct gc_arena *gc)
static void win_trigger_event(struct win32_signal *ws)
#define WSO_FORCE_SERVICE
Contains all state information for one tunnel.
Packet geometry parameters.
void window_title_clear(struct window_title *wt)
void semaphore_open(struct semaphore *s, const char *name)
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state, bool tuntap_buffer)
static void gc_free(struct gc_arena *a)
int script_security(void)
DWORD delete_block_dns_filters(HANDLE engine_handle)
struct semaphore netcmd_semaphore
void semaphore_close(struct semaphore *s)
bool win32_service_interrupt(struct win32_signal *ws)
bool buf_printf(struct buffer *buf, const char *format,...)
void setenv_str(struct env_set *es, const char *name, const char *value)
bool openvpn_execve_allowed(const unsigned int flags)
const char * win32_version_string(struct gc_arena *gc, bool add_name)
void window_title_restore(const struct window_title *wt)
static unsigned int win32_keyboard_get(struct win32_signal *ws)
static bool cmp_prefix(const char *str, const bool n, const char *pre)
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
#define OPENVPN_EXECVE_ERROR
static char * env_block(const struct env_set *es)
#define SYS_PATH_ENV_VAR_NAME
void netcmd_semaphore_lock(void)
#define BLOCK_DNS_IFACE_METRIC
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds)
int len
Length in bytes of the actual content within the allocated memory.
void set_win_sys_path(const char *newpath, struct env_set *es)
static HANDLE m_hEngineHandle
#define WSO_FORCE_CONSOLE
void net_event_win32_stop(struct net_event_win32 *ne)
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
static struct WSAData wsa_state
bool console_mode_save_defined
int get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto)
Return interface metric value for the specified interface index.
void set_win_sys_path_via_env(struct env_set *es)
void win32_signal_clear(struct win32_signal *ws)
static struct gc_arena gc_new(void)
#define IOSTATE_IMMEDIATE_RETURN
static unsigned int keyboard_ir_to_key(INPUT_RECORD *ir)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
void semaphore_clear(struct semaphore *s)
static int socket_defined(const socket_descriptor_t sd)
void overlapped_io_close(struct overlapped_io *o)
static SERVICE_STATUS status
void net_event_win32_reset(struct net_event_win32 *ne)
void net_event_win32_init(struct net_event_win32 *ne)
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
void net_event_win32_close(struct net_event_win32 *ne)
DWORD add_block_dns_filters(HANDLE *engine_handle, int index, const WCHAR *exe_path, block_dns_msg_handler_t msg_handler)
char * get_win_sys_path(void)
void win32_signal_open(struct win32_signal *ws, int force, const char *exit_event_name, bool exit_event_initial_state)
static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc)
uint8_t * data
Pointer to the allocated memory.
#define NE32_PERSIST_EVENT
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
char * overlapped_io_state_ascii(const struct overlapped_io *o)
bool win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel)
void window_title_save(struct window_title *wt)
void win32_signal_close(struct win32_signal *ws)
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame, const bool tuntap_buffer, const unsigned int align_mask)
bool init_security_attributes_allow_all(struct security_attributes *obj)
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
void fork_to_self(const char *cmdline)
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
void set_pause_exit_win32(void)
volatile int signal_received
static void check_malloc_return(const void *p)
void semaphore_release(struct semaphore *s)
SOCKET socket_descriptor_t
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd)
static bool net_event_win32_defined(const struct net_event_win32 *ne)
DWORD set_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, const ULONG metric)
Sets interface metric value for specified interface index.
Wrapper structure for dynamically allocated memory.
#define SCRIPT_SECURITY_WARNING
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
int win32_version_info(void)
void netcmd_semaphore_release(void)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
void win32_pause(struct win32_signal *ws)
void throw_signal(const int signum)
Garbage collection arena used to keep track of dynamically allocated memory.
static char * win_sys_path
void net_event_win32_reset_write(struct net_event_win32 *ne)
#define OPENVPN_EXECVE_NOT_ALLOWED
int win32_signal_get(struct win32_signal *ws)
bool win32_is_64bit(void)
char old_window_title[256]
void window_title_generate(const char *title)
static bool keyboard_input_available(struct win32_signal *ws)
static void block_dns_msg_handler(DWORD err, const char *msg)
bool env_allowed(const char *str)
bool win_safe_filename(const char *fn)
void netcmd_semaphore_init(void)
#define HANDLE_DEFINED(h)