2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Win32-specific OpenVPN code, targetted at the mingw
27 * development environment.
32 #elif defined(_MSC_VER)
33 #include "config-msvc.h"
49 #include "win32_wfp.h"
51 #ifdef HAVE_VERSIONHELPERS_H
52 #include <versionhelpers.h>
54 #include "compat-versionhelpers.h"
57 /* WFP function pointers. Initialized in win_wfp_init_funcs() */
58 func_ConvertInterfaceIndexToLuid ConvertInterfaceIndexToLuid
= NULL
;
59 func_FwpmEngineOpen0 FwpmEngineOpen0
= NULL
;
60 func_FwpmEngineClose0 FwpmEngineClose0
= NULL
;
61 func_FwpmFilterAdd0 FwpmFilterAdd0
= NULL
;
62 func_FwpmSubLayerAdd0 FwpmSubLayerAdd0
= NULL
;
63 func_FwpmSubLayerDeleteByKey0 FwpmSubLayerDeleteByKey0
= NULL
;
64 func_FwpmFreeMemory0 FwpmFreeMemory0
= NULL
;
65 func_FwpmGetAppIdFromFileName0 FwpmGetAppIdFromFileName0
= NULL
;
70 WCHAR
* FIREWALL_NAME
= L
"OpenVPN"; /* GLOBAL */
73 * WFP handle and GUID.
75 static HANDLE m_hEngineHandle
= NULL
; /* GLOBAL */
78 * Windows internal socket API state (opaque).
80 static struct WSAData wsa_state
; /* GLOBAL */
83 * Should we call win32_pause() on program exit?
85 static bool pause_exit_enabled
= false; /* GLOBAL */
88 * win32_signal is used to get input from the keyboard
89 * if we are running in a console, or get input from an
90 * event object if we are running as a service.
93 struct win32_signal win32_signal
; /* GLOBAL */
96 * Save our old window title so we can restore
99 struct window_title window_title
; /* GLOBAL*/
102 * Special global semaphore used to protect network
103 * shell commands from simultaneous instantiation.
106 struct semaphore netcmd_semaphore
; /* GLOBAL */
109 * Windows system pathname such as c:\windows
111 static char *win_sys_path
= NULL
; /* GLOBAL */
116 if (WSAStartup(0x0101, &wsa_state
))
118 msg (M_ERR
, "WSAStartup failed");
120 window_title_clear (&window_title
);
121 win32_signal_clear (&win32_signal
);
122 netcmd_semaphore_init ();
128 netcmd_semaphore_close ();
129 if (pause_exit_enabled
)
131 if (win32_signal
.mode
== WSO_MODE_UNDEF
)
133 struct win32_signal w
;
134 win32_signal_open (&w
, WSO_FORCE_CONSOLE
, NULL
, false);
136 win32_signal_close (&w
);
139 win32_pause (&win32_signal
);
141 window_title_restore (&window_title
);
142 win32_signal_close (&win32_signal
);
148 set_pause_exit_win32 (void)
150 pause_exit_enabled
= true;
154 init_security_attributes_allow_all (struct security_attributes
*obj
)
158 obj
->sa
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
159 obj
->sa
.lpSecurityDescriptor
= &obj
->sd
;
160 obj
->sa
.bInheritHandle
= FALSE
;
161 if (!InitializeSecurityDescriptor (&obj
->sd
, SECURITY_DESCRIPTOR_REVISION
))
163 if (!SetSecurityDescriptorDacl (&obj
->sd
, TRUE
, NULL
, FALSE
))
169 overlapped_io_init (struct overlapped_io
*o
,
170 const struct frame
*frame
,
172 bool tuntap_buffer
) /* if true: tuntap buffer, if false: socket buffer */
176 /* manual reset event, initially set according to event_state */
177 o
->overlapped
.hEvent
= CreateEvent (NULL
, TRUE
, event_state
, NULL
);
178 if (o
->overlapped
.hEvent
== NULL
)
179 msg (M_ERR
, "Error: overlapped_io_init: CreateEvent failed");
181 /* allocate buffer for overlapped I/O */
182 alloc_buf_sock_tun (&o
->buf_init
, frame
, tuntap_buffer
, 0);
186 overlapped_io_close (struct overlapped_io
*o
)
188 if (o
->overlapped
.hEvent
)
190 if (!CloseHandle (o
->overlapped
.hEvent
))
191 msg (M_WARN
| M_ERRNO
, "Warning: CloseHandle failed on overlapped I/O event object");
193 free_buf (&o
->buf_init
);
197 overlapped_io_state_ascii (const struct overlapped_io
*o
)
201 case IOSTATE_INITIAL
:
205 case IOSTATE_IMMEDIATE_RETURN
:
212 * Event-based notification of network events
216 init_net_event_win32 (struct rw_handle
*event
, long network_events
, socket_descriptor_t sd
, unsigned int flags
)
218 /* manual reset events, initially set to unsignaled */
220 /* initialize write event */
221 if (!(flags
& NE32_PERSIST_EVENT
) || !event
->write
)
223 if (flags
& NE32_WRITE_EVENT
)
225 event
->write
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
226 if (event
->write
== NULL
)
227 msg (M_ERR
, "Error: init_net_event_win32: CreateEvent (write) failed");
233 /* initialize read event */
234 if (!(flags
& NE32_PERSIST_EVENT
) || !event
->read
)
236 event
->read
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
237 if (event
->read
== NULL
)
238 msg (M_ERR
, "Error: init_net_event_win32: CreateEvent (read) failed");
241 /* setup network events to change read event state */
242 if (WSAEventSelect (sd
, event
->read
, network_events
) != 0)
243 msg (M_FATAL
| M_ERRNO
, "Error: init_net_event_win32: WSAEventSelect call failed");
247 reset_net_event_win32 (struct rw_handle
*event
, socket_descriptor_t sd
)
249 WSANETWORKEVENTS wne
;
250 if (WSAEnumNetworkEvents (sd
, event
->read
, &wne
) != 0)
252 msg (M_FATAL
| M_ERRNO
, "Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
253 return 0; /* NOTREACHED */
256 return wne
.lNetworkEvents
;
260 close_net_event_win32 (struct rw_handle
*event
, socket_descriptor_t sd
, unsigned int flags
)
264 if (socket_defined (sd
))
266 if (WSAEventSelect (sd
, event
->read
, 0) != 0)
267 msg (M_WARN
| M_ERRNO
, "Warning: close_net_event_win32: WSAEventSelect call failed");
269 if (!ResetEvent (event
->read
))
270 msg (M_WARN
| M_ERRNO
, "Warning: ResetEvent (read) failed in close_net_event_win32");
271 if (!(flags
& NE32_PERSIST_EVENT
))
273 if (!CloseHandle (event
->read
))
274 msg (M_WARN
| M_ERRNO
, "Warning: CloseHandle (read) failed in close_net_event_win32");
281 if (!ResetEvent (event
->write
))
282 msg (M_WARN
| M_ERRNO
, "Warning: ResetEvent (write) failed in close_net_event_win32");
283 if (!(flags
& NE32_PERSIST_EVENT
))
285 if (!CloseHandle (event
->write
))
286 msg (M_WARN
| M_ERRNO
, "Warning: CloseHandle (write) failed in close_net_event_win32");
293 * struct net_event_win32
297 net_event_win32_init (struct net_event_win32
*ne
)
300 ne
->sd
= SOCKET_UNDEFINED
;
304 net_event_win32_start (struct net_event_win32
*ne
, long network_events
, socket_descriptor_t sd
)
306 ASSERT (!socket_defined (ne
->sd
));
309 init_net_event_win32 (&ne
->handle
, network_events
, sd
, NE32_PERSIST_EVENT
|NE32_WRITE_EVENT
);
313 net_event_win32_reset_write (struct net_event_win32
*ne
)
316 if (ne
->event_mask
& FD_WRITE
)
317 status
= SetEvent (ne
->handle
.write
);
319 status
= ResetEvent (ne
->handle
.write
);
321 msg (M_WARN
| M_ERRNO
, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
325 net_event_win32_reset (struct net_event_win32
*ne
)
327 ne
->event_mask
|= reset_net_event_win32 (&ne
->handle
, ne
->sd
);
331 net_event_win32_stop (struct net_event_win32
*ne
)
333 if (net_event_win32_defined (ne
))
334 close_net_event_win32 (&ne
->handle
, ne
->sd
, NE32_PERSIST_EVENT
);
335 ne
->sd
= SOCKET_UNDEFINED
;
340 net_event_win32_close (struct net_event_win32
*ne
)
342 if (net_event_win32_defined (ne
))
343 close_net_event_win32 (&ne
->handle
, ne
->sd
, 0);
344 net_event_win32_init (ne
);
348 * Simulate *nix signals on Windows.
351 * (1) Console mode -- map keyboard function keys to signals
352 * (2) Service mode -- map Windows event object to SIGTERM
356 win_trigger_event(struct win32_signal
*ws
)
358 if (ws
->mode
== WSO_MODE_SERVICE
&& HANDLE_DEFINED(ws
->in
.read
))
359 SetEvent (ws
->in
.read
);
360 else /* generate a key-press event */
364 HANDLE stdin_handle
= GetStdHandle(STD_INPUT_HANDLE
);
367 ir
.EventType
= KEY_EVENT
;
368 ir
.Event
.KeyEvent
.bKeyDown
= true;
369 if (!stdin_handle
|| !WriteConsoleInput(stdin_handle
, &ir
, 1, &tmp
))
370 msg(M_WARN
|M_ERRNO
, "WARN: win_trigger_event: WriteConsoleInput");
375 * Callback to handle console ctrl events
378 win_ctrl_handler (DWORD signum
)
380 msg(D_LOW
, "win_ctrl_handler: signal received (code=%lu)", (unsigned long) signum
);
382 if (siginfo_static
.signal_received
== SIGTERM
)
388 case CTRL_BREAK_EVENT
:
389 throw_signal(SIGTERM
);
390 /* trigget the win32_signal to interrupt the event loop */
391 win_trigger_event(&win32_signal
);
395 msg(D_LOW
, "win_ctrl_handler: signal (code=%lu) not handled", (unsigned long) signum
);
398 /* pass all other signals to the next handler */
403 win32_signal_clear (struct win32_signal
*ws
)
409 win32_signal_open (struct win32_signal
*ws
,
411 const char *exit_event_name
,
412 bool exit_event_initial_state
)
416 ws
->mode
= WSO_MODE_UNDEF
;
417 ws
->in
.read
= INVALID_HANDLE_VALUE
;
418 ws
->in
.write
= INVALID_HANDLE_VALUE
;
419 ws
->console_mode_save
= 0;
420 ws
->console_mode_save_defined
= false;
422 if (force
== WSO_NOFORCE
|| force
== WSO_FORCE_CONSOLE
)
425 * Try to open console.
427 ws
->in
.read
= GetStdHandle (STD_INPUT_HANDLE
);
428 if (ws
->in
.read
!= INVALID_HANDLE_VALUE
)
430 if (GetConsoleMode (ws
->in
.read
, &ws
->console_mode_save
))
432 /* running on a console */
433 const DWORD new_console_mode
= ws
->console_mode_save
434 & ~(ENABLE_WINDOW_INPUT
435 | ENABLE_PROCESSED_INPUT
438 | ENABLE_MOUSE_INPUT
);
440 if (new_console_mode
!= ws
->console_mode_save
)
442 if (!SetConsoleMode (ws
->in
.read
, new_console_mode
))
443 msg (M_ERR
, "Error: win32_signal_open: SetConsoleMode failed");
444 ws
->console_mode_save_defined
= true;
446 ws
->mode
= WSO_MODE_CONSOLE
;
449 ws
->in
.read
= INVALID_HANDLE_VALUE
; /* probably running as a service */
454 * If console open failed, assume we are running
457 if ((force
== WSO_NOFORCE
|| force
== WSO_FORCE_SERVICE
)
458 && !HANDLE_DEFINED (ws
->in
.read
) && exit_event_name
)
460 struct security_attributes sa
;
462 if (!init_security_attributes_allow_all (&sa
))
463 msg (M_ERR
, "Error: win32_signal_open: init SA failed");
465 ws
->in
.read
= CreateEvent (&sa
.sa
,
467 exit_event_initial_state
? TRUE
: FALSE
,
469 if (ws
->in
.read
== NULL
)
471 msg (M_WARN
|M_ERRNO
, "NOTE: CreateEvent '%s' failed", exit_event_name
);
475 if (WaitForSingleObject (ws
->in
.read
, 0) != WAIT_TIMEOUT
)
476 msg (M_FATAL
, "ERROR: Exit Event ('%s') is signaled", exit_event_name
);
478 ws
->mode
= WSO_MODE_SERVICE
;
481 /* set the ctrl handler in both console and service modes */
482 if (!SetConsoleCtrlHandler ((PHANDLER_ROUTINE
) win_ctrl_handler
, true))
483 msg (M_WARN
|M_ERRNO
, "WARN: SetConsoleCtrlHandler failed");
487 keyboard_input_available (struct win32_signal
*ws
)
489 ASSERT (ws
->mode
== WSO_MODE_CONSOLE
);
490 if (HANDLE_DEFINED (ws
->in
.read
))
493 if (GetNumberOfConsoleInputEvents (ws
->in
.read
, &n
))
500 keyboard_ir_to_key (INPUT_RECORD
*ir
)
502 if (ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0)
503 return ir
->Event
.KeyEvent
.wVirtualScanCode
;
505 if ((ir
->Event
.KeyEvent
.dwControlKeyState
506 & (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
507 && (ir
->Event
.KeyEvent
.wVirtualKeyCode
!= 18))
508 return ir
->Event
.KeyEvent
.wVirtualScanCode
* 256;
510 return ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
514 win32_keyboard_get (struct win32_signal
*ws
)
516 ASSERT (ws
->mode
== WSO_MODE_CONSOLE
);
517 if (HANDLE_DEFINED (ws
->in
.read
))
522 if (!keyboard_input_available (ws
))
524 if (!ReadConsoleInput (ws
->in
.read
, &ir
, 1, &n
))
526 } while (ir
.EventType
!= KEY_EVENT
|| ir
.Event
.KeyEvent
.bKeyDown
!= TRUE
);
528 return keyboard_ir_to_key (&ir
);
535 win32_signal_close (struct win32_signal
*ws
)
537 if (ws
->mode
== WSO_MODE_SERVICE
&& HANDLE_DEFINED (ws
->in
.read
))
538 CloseHandle (ws
->in
.read
);
539 if (ws
->console_mode_save_defined
)
541 if (!SetConsoleMode (ws
->in
.read
, ws
->console_mode_save
))
542 msg (M_ERR
, "Error: win32_signal_close: SetConsoleMode failed");
548 * Return true if interrupt occurs in service mode.
551 win32_service_interrupt (struct win32_signal
*ws
)
553 if (ws
->mode
== WSO_MODE_SERVICE
)
555 if (HANDLE_DEFINED (ws
->in
.read
)
556 && WaitForSingleObject (ws
->in
.read
, 0) == WAIT_OBJECT_0
)
563 win32_signal_get (struct win32_signal
*ws
)
566 if (siginfo_static
.signal_received
)
568 ret
= siginfo_static
.signal_received
;
572 if (ws
->mode
== WSO_MODE_SERVICE
)
574 if (win32_service_interrupt (ws
))
577 else if (ws
->mode
== WSO_MODE_CONSOLE
)
579 switch (win32_keyboard_get (ws
))
581 case 0x3B: /* F1 -> USR1 */
584 case 0x3C: /* F2 -> USR2 */
587 case 0x3D: /* F3 -> HUP */
590 case 0x3E: /* F4 -> TERM */
593 case 0x03: /* CTRL-C -> TERM */
600 siginfo_static
.signal_received
= ret
;
601 siginfo_static
.hard
= true;
608 win32_pause (struct win32_signal
*ws
)
610 if (ws
->mode
== WSO_MODE_CONSOLE
&& HANDLE_DEFINED (ws
->in
.read
))
613 msg (M_INFO
|M_NOPREFIX
, "Press any key to continue...");
615 status
= WaitForSingleObject (ws
->in
.read
, INFINITE
);
616 } while (!win32_keyboard_get (ws
));
620 /* window functions */
623 window_title_clear (struct window_title
*wt
)
629 window_title_save (struct window_title
*wt
)
633 if (!GetConsoleTitle (wt
->old_window_title
, sizeof (wt
->old_window_title
)))
635 wt
->old_window_title
[0] = 0;
644 window_title_restore (const struct window_title
*wt
)
647 SetConsoleTitle (wt
->old_window_title
);
651 window_title_generate (const char *title
)
653 struct gc_arena gc
= gc_new ();
654 struct buffer out
= alloc_buf_gc (256, &gc
);
657 buf_printf (&out
, "[%s] " PACKAGE_NAME
" " PACKAGE_VERSION
" F4:EXIT F1:USR1 F2:USR2 F3:HUP", title
);
658 SetConsoleTitle (BSTR (&out
));
662 /* semaphore functions */
665 semaphore_clear (struct semaphore
*s
)
671 semaphore_open (struct semaphore
*s
, const char *name
)
673 struct security_attributes sa
;
679 if (init_security_attributes_allow_all (&sa
))
680 s
->hand
= CreateSemaphore(&sa
.sa
, 1, 1, name
);
683 msg (M_WARN
|M_ERRNO
, "WARNING: Cannot create Win32 semaphore '%s'", name
);
685 dmsg (D_SEMAPHORE
, "Created Win32 semaphore '%s'", s
->name
);
689 semaphore_lock (struct semaphore
*s
, int timeout_milliseconds
)
698 dmsg (D_SEMAPHORE_LOW
, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
700 timeout_milliseconds
/ 1000);
701 status
= WaitForSingleObject (s
->hand
, timeout_milliseconds
);
702 if (status
== WAIT_FAILED
)
703 msg (M_ERR
, "Wait failed on Win32 semaphore '%s'", s
->name
);
704 ret
= (status
== WAIT_TIMEOUT
) ? false : true;
707 dmsg (D_SEMAPHORE
, "Locked Win32 semaphore '%s'", s
->name
);
712 dmsg (D_SEMAPHORE
, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
714 timeout_milliseconds
);
721 semaphore_release (struct semaphore
*s
)
726 dmsg (D_SEMAPHORE
, "Releasing Win32 semaphore '%s'", s
->name
);
727 if (!ReleaseSemaphore(s
->hand
, 1, NULL
))
728 msg (M_WARN
| M_ERRNO
, "ReleaseSemaphore failed on Win32 semaphore '%s'",
735 semaphore_close (struct semaphore
*s
)
740 semaphore_release (s
);
741 dmsg (D_SEMAPHORE
, "Closing Win32 semaphore '%s'", s
->name
);
742 CloseHandle (s
->hand
);
748 * Special global semaphore used to protect network
749 * shell commands from simultaneous instantiation.
753 netcmd_semaphore_init (void)
755 semaphore_open (&netcmd_semaphore
, PACKAGE
"_netcmd");
759 netcmd_semaphore_close (void)
761 semaphore_close (&netcmd_semaphore
);
765 netcmd_semaphore_lock (void)
767 const int timeout_seconds
= 600;
768 if (!semaphore_lock (&netcmd_semaphore
, timeout_seconds
* 1000))
769 msg (M_FATAL
, "Cannot lock net command semaphore");
773 netcmd_semaphore_release (void)
775 semaphore_release (&netcmd_semaphore
);
779 * Return true if filename is safe to be used on Windows,
780 * by avoiding the following reserved names:
782 * CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9,
783 * LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, and CLOCK$
785 * See: http://msdn.microsoft.com/en-us/library/aa365247.aspx
786 * and http://msdn.microsoft.com/en-us/library/86k9f82k(VS.80).aspx
790 cmp_prefix (const char *str
, const bool n
, const char *pre
)
799 const int c1
= pre
[i
];
811 return c2
== '\0' || c2
== '.';
815 if (c1
!= tolower(c2
))
821 win_safe_filename (const char *fn
)
823 if (cmp_prefix (fn
, false, "con"))
825 if (cmp_prefix (fn
, false, "prn"))
827 if (cmp_prefix (fn
, false, "aux"))
829 if (cmp_prefix (fn
, false, "nul"))
831 if (cmp_prefix (fn
, true, "com"))
833 if (cmp_prefix (fn
, true, "lpt"))
835 if (cmp_prefix (fn
, false, "clock$"))
841 * Service functions for openvpn_execve
845 env_block (const struct env_set
*es
)
847 char force_path
[256];
848 char *sysroot
= get_win_sys_path();
850 if (!openvpn_snprintf(force_path
, sizeof(force_path
), "PATH=%s\\System32;%s;%s\\System32\\Wbem",
851 sysroot
, sysroot
, sysroot
))
852 msg(M_WARN
, "env_block: default path truncated to %s", force_path
);
860 bool path_seen
= false;
862 for (e
= es
->list
; e
!= NULL
; e
= e
->next
)
863 nchars
+= strlen (e
->string
) + 1;
865 nchars
+= strlen(force_path
)+1;
867 ret
= (char *) malloc (nchars
);
868 check_malloc_return (ret
);
871 for (e
= es
->list
; e
!= NULL
; e
= e
->next
)
873 if (env_allowed (e
->string
))
875 strcpy (p
, e
->string
);
876 p
+= strlen (e
->string
) + 1;
878 if ( strncmp(e
->string
, "PATH=", 5 ) == 0 )
882 /* make sure PATH is set */
885 msg( M_INFO
, "env_block: add %s", force_path
);
886 strcpy( p
, force_path
);
887 p
+= strlen(force_path
) + 1;
898 wide_cmd_line (const struct argv
*a
, struct gc_arena
*gc
)
909 for (i
= 0; i
< a
->argc
; ++i
)
911 const char *arg
= a
->argv
[i
];
912 const size_t len
= strlen (arg
);
918 work
= gc_malloc (maxlen
+ 1, false, gc
);
919 check_malloc_return (work
);
920 buf
= alloc_buf_gc (nchars
, gc
);
922 for (i
= 0; i
< a
->argc
; ++i
)
924 const char *arg
= a
->argv
[i
];
926 string_mod (work
, CC_PRINT
, CC_DOUBLE_QUOTE
|CC_CRLF
, '_');
928 buf_printf (&buf
, " ");
929 if (string_class (work
, CC_ANY
, CC_SPACE
))
930 buf_printf (&buf
, "%s", work
);
932 buf_printf (&buf
, "\"%s\"", work
);
935 return wide_string (BSTR (&buf
), gc
);
939 * Attempt to simulate fork/execve on Windows
942 openvpn_execve (const struct argv
*a
, const struct env_set
*es
, const unsigned int flags
)
945 static bool exec_warn
= false;
949 if (openvpn_execve_allowed (flags
))
951 struct gc_arena gc
= gc_new ();
952 STARTUPINFOW start_info
;
953 PROCESS_INFORMATION proc_info
;
955 char *env
= env_block (es
);
956 WCHAR
*cl
= wide_cmd_line (a
, &gc
);
957 WCHAR
*cmd
= wide_string (a
->argv
[0], &gc
);
959 /* this allows console programs to run, and is ignored otherwise */
960 DWORD proc_flags
= CREATE_NO_WINDOW
;
965 /* fill in STARTUPINFO struct */
966 GetStartupInfoW(&start_info
);
967 start_info
.cb
= sizeof(start_info
);
968 start_info
.dwFlags
= STARTF_USESHOWWINDOW
;
969 start_info
.wShowWindow
= SW_HIDE
;
971 if (CreateProcessW (cmd
, cl
, NULL
, NULL
, FALSE
, proc_flags
, env
, NULL
, &start_info
, &proc_info
))
973 DWORD exit_status
= 0;
974 CloseHandle (proc_info
.hThread
);
975 WaitForSingleObject (proc_info
.hProcess
, INFINITE
);
976 if (GetExitCodeProcess (proc_info
.hProcess
, &exit_status
))
977 ret
= (int)exit_status
;
979 msg (M_WARN
|M_ERRNO
, "openvpn_execve: GetExitCodeProcess %S failed", cmd
);
980 CloseHandle (proc_info
.hProcess
);
984 msg (M_WARN
|M_ERRNO
, "openvpn_execve: CreateProcess %S failed", cmd
);
989 else if (!exec_warn
&& (script_security
< SSEC_SCRIPTS
))
991 msg (M_WARN
, SCRIPT_SECURITY_WARNING
);
997 msg (M_WARN
, "openvpn_execve: called with empty argv");
1003 wide_string (const char* utf8
, struct gc_arena
*gc
)
1005 int n
= MultiByteToWideChar (CP_UTF8
, 0, utf8
, -1, NULL
, 0);
1006 WCHAR
*ucs16
= gc_malloc (n
* sizeof (WCHAR
), false, gc
);
1007 MultiByteToWideChar (CP_UTF8
, 0, utf8
, -1, ucs16
, n
);
1012 * call ourself in another process
1015 fork_to_self (const char *cmdline
)
1017 STARTUPINFO start_info
;
1018 PROCESS_INFORMATION proc_info
;
1020 char *cl
= string_alloc (cmdline
, NULL
);
1027 status
= GetModuleFileName (NULL
, self_exe
, sizeof(self_exe
));
1028 if (status
== 0 || status
== sizeof(self_exe
))
1030 msg (M_WARN
|M_ERRNO
, "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1034 /* fill in STARTUPINFO struct */
1035 GetStartupInfo(&start_info
);
1036 start_info
.cb
= sizeof(start_info
);
1037 start_info
.dwFlags
= STARTF_USESHOWWINDOW
;
1038 start_info
.wShowWindow
= SW_HIDE
;
1040 if (CreateProcess (self_exe
, cl
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &start_info
, &proc_info
))
1042 CloseHandle (proc_info
.hThread
);
1043 CloseHandle (proc_info
.hProcess
);
1047 msg (M_WARN
|M_ERRNO
, "fork_to_self: CreateProcess failed: %s", cmdline
);
1055 get_win_sys_path (void)
1057 ASSERT (win_sys_path
);
1058 return win_sys_path
;
1062 set_win_sys_path (const char *newpath
, struct env_set
*es
)
1064 free (win_sys_path
);
1065 win_sys_path
= string_alloc (newpath
, NULL
);
1066 setenv_str (es
, SYS_PATH_ENV_VAR_NAME
, win_sys_path
); /* route.exe needs this */
1070 set_win_sys_path_via_env (struct env_set
*es
)
1073 DWORD status
= GetEnvironmentVariable (SYS_PATH_ENV_VAR_NAME
, buf
, sizeof(buf
));
1075 msg (M_ERR
, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME
);
1076 if (status
> sizeof (buf
) - 1)
1077 msg (M_FATAL
, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME
);
1078 set_win_sys_path (buf
, es
);
1085 static char tmpdir
[MAX_PATH
];
1086 WCHAR wtmpdir
[MAX_PATH
];
1088 if (!GetTempPathW(_countof(wtmpdir
), wtmpdir
))
1090 /* Warn if we can't find a valid temporary directory, which should
1093 msg (M_WARN
, "Could not find a suitable temporary directory."
1094 " (GetTempPath() failed). Consider using --tmp-dir");
1098 if (WideCharToMultiByte (CP_UTF8
, 0, wtmpdir
, -1, NULL
, 0, NULL
, NULL
) > sizeof (tmpdir
))
1100 msg (M_WARN
, "Could not get temporary directory. Path is too long."
1101 " Consider using --tmp-dir");
1105 WideCharToMultiByte (CP_UTF8
, 0, wtmpdir
, -1, tmpdir
, sizeof (tmpdir
), NULL
, NULL
);
1110 win_wfp_init_funcs ()
1112 /* Initialize all WFP-related function pointers */
1113 HMODULE iphlpapiHandle
;
1114 HMODULE fwpuclntHandle
;
1116 iphlpapiHandle
= LoadLibrary("iphlpapi.dll");
1117 if (iphlpapiHandle
== NULL
)
1119 msg (M_NONFATAL
, "Can't load iphlpapi.dll");
1123 fwpuclntHandle
= LoadLibrary("fwpuclnt.dll");
1124 if (fwpuclntHandle
== NULL
)
1126 msg (M_NONFATAL
, "Can't load fwpuclnt.dll");
1130 ConvertInterfaceIndexToLuid
= (func_ConvertInterfaceIndexToLuid
)GetProcAddress(iphlpapiHandle
, "ConvertInterfaceIndexToLuid");
1131 FwpmFilterAdd0
= (func_FwpmFilterAdd0
)GetProcAddress(fwpuclntHandle
, "FwpmFilterAdd0");
1132 FwpmEngineOpen0
= (func_FwpmEngineOpen0
)GetProcAddress(fwpuclntHandle
, "FwpmEngineOpen0");
1133 FwpmEngineClose0
= (func_FwpmEngineClose0
)GetProcAddress(fwpuclntHandle
, "FwpmEngineClose0");
1134 FwpmSubLayerAdd0
= (func_FwpmSubLayerAdd0
)GetProcAddress(fwpuclntHandle
, "FwpmSubLayerAdd0");
1135 FwpmSubLayerDeleteByKey0
= (func_FwpmSubLayerDeleteByKey0
)GetProcAddress(fwpuclntHandle
, "FwpmSubLayerDeleteByKey0");
1136 FwpmFreeMemory0
= (func_FwpmFreeMemory0
)GetProcAddress(fwpuclntHandle
, "FwpmFreeMemory0");
1137 FwpmGetAppIdFromFileName0
= (func_FwpmGetAppIdFromFileName0
)GetProcAddress(fwpuclntHandle
, "FwpmGetAppIdFromFileName0");
1139 if (!ConvertInterfaceIndexToLuid
||
1142 !FwpmEngineClose0
||
1143 !FwpmSubLayerAdd0
||
1144 !FwpmSubLayerDeleteByKey0
||
1146 !FwpmGetAppIdFromFileName0
)
1148 msg (M_NONFATAL
, "Can't get address for all WFP-related procedures.");
1156 win_wfp_add_filter (HANDLE engineHandle
,
1157 const FWPM_FILTER0
*filter
,
1158 PSECURITY_DESCRIPTOR sd
,
1161 if (FwpmFilterAdd0(engineHandle
, filter
, sd
, id
) != ERROR_SUCCESS
)
1163 msg (M_NONFATAL
, "Can't add WFP filter");
1170 win_wfp_block_dns (const NET_IFINDEX index
)
1172 FWPM_SESSION0 session
= {0};
1173 FWPM_SUBLAYER0 SubLayer
= {0};
1176 WCHAR openvpnpath
[MAX_PATH
];
1177 FWP_BYTE_BLOB
*openvpnblob
= NULL
;
1178 FWPM_FILTER0 Filter
= {0};
1179 FWPM_FILTER_CONDITION0 Condition
[2] = {0};
1181 /* Add temporary filters which don't survive reboots or crashes. */
1182 session
.flags
= FWPM_SESSION_FLAG_DYNAMIC
;
1184 dmsg (D_LOW
, "Opening WFP engine");
1186 if (FwpmEngineOpen0(NULL
, RPC_C_AUTHN_WINNT
, NULL
, &session
, &m_hEngineHandle
) != ERROR_SUCCESS
)
1188 msg (M_NONFATAL
, "Can't open WFP engine");
1192 if (UuidCreate(&SubLayer
.subLayerKey
) != NO_ERROR
)
1195 /* Populate packet filter layer information. */
1196 SubLayer
.displayData
.name
= FIREWALL_NAME
;
1197 SubLayer
.displayData
.description
= FIREWALL_NAME
;
1199 SubLayer
.weight
= 0x100;
1201 /* Add packet filter to our interface. */
1202 dmsg (D_LOW
, "Adding WFP sublayer");
1203 if (FwpmSubLayerAdd0(m_hEngineHandle
, &SubLayer
, NULL
) != ERROR_SUCCESS
)
1205 msg (M_NONFATAL
, "Can't add WFP sublayer");
1209 dmsg (D_LOW
, "Blocking DNS using WFP");
1210 if (ConvertInterfaceIndexToLuid(index
, &tapluid
) != NO_ERROR
)
1212 msg (M_NONFATAL
, "Can't convert interface index to LUID");
1215 dmsg (D_LOW
, "Tap Luid: %I64d", tapluid
.Value
);
1217 /* Get OpenVPN path. */
1218 GetModuleFileNameW(NULL
, openvpnpath
, MAX_PATH
);
1220 if (FwpmGetAppIdFromFileName0(openvpnpath
, &openvpnblob
) != ERROR_SUCCESS
)
1223 /* Prepare filter. */
1224 Filter
.subLayerKey
= SubLayer
.subLayerKey
;
1225 Filter
.displayData
.name
= FIREWALL_NAME
;
1226 Filter
.weight
.type
= FWP_EMPTY
;
1227 Filter
.filterCondition
= Condition
;
1228 Filter
.numFilterConditions
= 2;
1230 /* First filter. Block IPv4 DNS queries except from OpenVPN itself. */
1231 Filter
.layerKey
= FWPM_LAYER_ALE_AUTH_CONNECT_V4
;
1232 Filter
.action
.type
= FWP_ACTION_BLOCK
;
1234 Condition
[0].fieldKey
= FWPM_CONDITION_IP_REMOTE_PORT
;
1235 Condition
[0].matchType
= FWP_MATCH_EQUAL
;
1236 Condition
[0].conditionValue
.type
= FWP_UINT16
;
1237 Condition
[0].conditionValue
.uint16
= 53;
1239 Condition
[1].fieldKey
= FWPM_CONDITION_ALE_APP_ID
;
1240 Condition
[1].matchType
= FWP_MATCH_NOT_EQUAL
;
1241 Condition
[1].conditionValue
.type
= FWP_BYTE_BLOB_TYPE
;
1242 Condition
[1].conditionValue
.byteBlob
= openvpnblob
;
1244 /* Add filter condition to our interface. */
1245 if (!win_wfp_add_filter(m_hEngineHandle
, &Filter
, NULL
, &filterid
))
1247 dmsg (D_LOW
, "Filter (Block IPv4 DNS) added with ID=%I64d", filterid
);
1249 /* Second filter. Block IPv6 DNS queries except from OpenVPN itself. */
1250 Filter
.layerKey
= FWPM_LAYER_ALE_AUTH_CONNECT_V6
;
1252 /* Add filter condition to our interface. */
1253 if (!win_wfp_add_filter(m_hEngineHandle
, &Filter
, NULL
, &filterid
))
1255 dmsg (D_LOW
, "Filter (Block IPv6 DNS) added with ID=%I64d", filterid
);
1257 /* Third filter. Permit IPv4 DNS queries from TAP. */
1258 Filter
.layerKey
= FWPM_LAYER_ALE_AUTH_CONNECT_V4
;
1259 Filter
.action
.type
= FWP_ACTION_PERMIT
;
1261 Condition
[1].fieldKey
= FWPM_CONDITION_IP_LOCAL_INTERFACE
;
1262 Condition
[1].matchType
= FWP_MATCH_EQUAL
;
1263 Condition
[1].conditionValue
.type
= FWP_UINT64
;
1264 Condition
[1].conditionValue
.uint64
= &tapluid
.Value
;
1266 /* Add filter condition to our interface. */
1267 if (!win_wfp_add_filter(m_hEngineHandle
, &Filter
, NULL
, &filterid
))
1269 dmsg (D_LOW
, "Filter (Permit IPv4 DNS queries from TAP) added with ID=%I64d", filterid
);
1271 /* Forth filter. Permit IPv6 DNS queries from TAP. */
1272 Filter
.layerKey
= FWPM_LAYER_ALE_AUTH_CONNECT_V6
;
1274 /* Add filter condition to our interface. */
1275 if (!win_wfp_add_filter(m_hEngineHandle
, &Filter
, NULL
, &filterid
))
1277 dmsg (D_LOW
, "Filter (Permit IPv6 DNS queries from TAP) added with ID=%I64d", filterid
);
1279 FwpmFreeMemory0((void **)&openvpnblob
);
1283 FwpmFreeMemory0((void **)&openvpnblob
);
1290 dmsg (D_LOW
, "Uninitializing WFP");
1291 if (m_hEngineHandle
) {
1292 FwpmEngineClose0(m_hEngineHandle
);
1293 m_hEngineHandle
= NULL
;
1299 win32_version_info()
1301 if (!IsWindowsXPOrGreater())
1303 msg (M_FATAL
, "Error: Windows version must be XP or greater.");
1306 if (!IsWindowsVistaOrGreater())
1311 if (!IsWindows7OrGreater())
1316 if (!IsWindows8OrGreater())
1327 win32_version_string(struct gc_arena
*gc
, bool add_name
)
1329 int version
= win32_version_info();
1330 struct buffer out
= alloc_buf_gc (256, gc
);
1335 buf_printf (&out
, "5.1%s", add_name
? " (Windows XP)" : "");
1338 buf_printf (&out
, "6.0%s", add_name
? " (Windows Vista)" : "");
1341 buf_printf (&out
, "6.1%s", add_name
? " (Windows 7)" : "");
1344 buf_printf (&out
, "6.2%s", add_name
? " (Windows 8 or greater)" : "");
1347 msg (M_NONFATAL
, "Unknown Windows version: %d", version
);
1348 buf_printf (&out
, "0.0%s", add_name
? " (unknown)" : "");
1352 return (const char *)out
.data
;