openvpn 2.3.10
[tomato.git] / release / src / router / openvpn / src / openvpn / win32.c
blob6c6ac4c83a45205de08a1dd806b68684eed1704b
1 /*
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
6 * packet compression.
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.
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #elif defined(_MSC_VER)
33 #include "config-msvc.h"
34 #endif
36 #include "syshead.h"
38 #ifdef WIN32
40 #include "buffer.h"
41 #include "error.h"
42 #include "mtu.h"
43 #include "sig.h"
44 #include "win32.h"
45 #include "misc.h"
47 #include "memdbg.h"
49 #include "win32_wfp.h"
51 #ifdef HAVE_VERSIONHELPERS_H
52 #include <versionhelpers.h>
53 #else
54 #include "compat-versionhelpers.h"
55 #endif
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;
68 * WFP firewall name.
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
97 * it on exit.
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 */
113 void
114 init_win32 (void)
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 ();
125 void
126 uninit_win32 (void)
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);
135 win32_pause (&w);
136 win32_signal_close (&w);
138 else
139 win32_pause (&win32_signal);
141 window_title_restore (&window_title);
142 win32_signal_close (&win32_signal);
143 WSACleanup ();
144 free (win_sys_path);
147 void
148 set_pause_exit_win32 (void)
150 pause_exit_enabled = true;
153 bool
154 init_security_attributes_allow_all (struct security_attributes *obj)
156 CLEAR (*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))
162 return false;
163 if (!SetSecurityDescriptorDacl (&obj->sd, TRUE, NULL, FALSE))
164 return false;
165 return true;
168 void
169 overlapped_io_init (struct overlapped_io *o,
170 const struct frame *frame,
171 BOOL event_state,
172 bool tuntap_buffer) /* if true: tuntap buffer, if false: socket buffer */
174 CLEAR (*o);
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);
185 void
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);
196 char *
197 overlapped_io_state_ascii (const struct overlapped_io *o)
199 switch (o->iostate)
201 case IOSTATE_INITIAL:
202 return "0";
203 case IOSTATE_QUEUED:
204 return "Q";
205 case IOSTATE_IMMEDIATE_RETURN:
206 return "1";
208 return "?";
212 * Event-based notification of network events
215 void
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");
229 else
230 event->write = NULL;
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");
246 long
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 */
255 else
256 return wne.lNetworkEvents;
259 void
260 close_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
262 if (event->read)
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");
275 event->read = NULL;
279 if (event->write)
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");
287 event->write = NULL;
293 * struct net_event_win32
296 void
297 net_event_win32_init (struct net_event_win32 *ne)
299 CLEAR (*ne);
300 ne->sd = SOCKET_UNDEFINED;
303 void
304 net_event_win32_start (struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
306 ASSERT (!socket_defined (ne->sd));
307 ne->sd = sd;
308 ne->event_mask = 0;
309 init_net_event_win32 (&ne->handle, network_events, sd, NE32_PERSIST_EVENT|NE32_WRITE_EVENT);
312 void
313 net_event_win32_reset_write (struct net_event_win32 *ne)
315 BOOL status;
316 if (ne->event_mask & FD_WRITE)
317 status = SetEvent (ne->handle.write);
318 else
319 status = ResetEvent (ne->handle.write);
320 if (!status)
321 msg (M_WARN | M_ERRNO, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
324 void
325 net_event_win32_reset (struct net_event_win32 *ne)
327 ne->event_mask |= reset_net_event_win32 (&ne->handle, ne->sd);
330 void
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;
336 ne->event_mask = 0;
339 void
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.
350 * Two modes:
351 * (1) Console mode -- map keyboard function keys to signals
352 * (2) Service mode -- map Windows event object to SIGTERM
355 static void
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 */
362 DWORD tmp;
363 INPUT_RECORD ir;
364 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
366 CLEAR(ir);
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
377 static bool WINAPI
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)
383 return true;
385 switch (signum)
387 case CTRL_C_EVENT:
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);
392 return true;
393 break;
394 default:
395 msg(D_LOW, "win_ctrl_handler: signal (code=%lu) not handled", (unsigned long) signum);
396 break;
398 /* pass all other signals to the next handler */
399 return false;
402 void
403 win32_signal_clear (struct win32_signal *ws)
405 CLEAR (*ws);
408 void
409 win32_signal_open (struct win32_signal *ws,
410 int force,
411 const char *exit_event_name,
412 bool exit_event_initial_state)
414 CLEAR (*ws);
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
436 | ENABLE_LINE_INPUT
437 | ENABLE_ECHO_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;
448 else
449 ws->in.read = INVALID_HANDLE_VALUE; /* probably running as a service */
454 * If console open failed, assume we are running
455 * as a service.
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,
466 TRUE,
467 exit_event_initial_state ? TRUE : FALSE,
468 exit_event_name);
469 if (ws->in.read == NULL)
471 msg (M_WARN|M_ERRNO, "NOTE: CreateEvent '%s' failed", exit_event_name);
473 else
475 if (WaitForSingleObject (ws->in.read, 0) != WAIT_TIMEOUT)
476 msg (M_FATAL, "ERROR: Exit Event ('%s') is signaled", exit_event_name);
477 else
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");
486 static bool
487 keyboard_input_available (struct win32_signal *ws)
489 ASSERT (ws->mode == WSO_MODE_CONSOLE);
490 if (HANDLE_DEFINED (ws->in.read))
492 DWORD n;
493 if (GetNumberOfConsoleInputEvents (ws->in.read, &n))
494 return n > 0;
496 return false;
499 static unsigned int
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;
513 static unsigned int
514 win32_keyboard_get (struct win32_signal *ws)
516 ASSERT (ws->mode == WSO_MODE_CONSOLE);
517 if (HANDLE_DEFINED (ws->in.read))
519 INPUT_RECORD ir;
520 do {
521 DWORD n;
522 if (!keyboard_input_available (ws))
523 return 0;
524 if (!ReadConsoleInput (ws->in.read, &ir, 1, &n))
525 return 0;
526 } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
528 return keyboard_ir_to_key (&ir);
530 else
531 return 0;
534 void
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");
544 CLEAR (*ws);
548 * Return true if interrupt occurs in service mode.
550 bool
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)
557 return true;
559 return false;
563 win32_signal_get (struct win32_signal *ws)
565 int ret = 0;
566 if (siginfo_static.signal_received)
568 ret = siginfo_static.signal_received;
570 else
572 if (ws->mode == WSO_MODE_SERVICE)
574 if (win32_service_interrupt (ws))
575 ret = SIGTERM;
577 else if (ws->mode == WSO_MODE_CONSOLE)
579 switch (win32_keyboard_get (ws))
581 case 0x3B: /* F1 -> USR1 */
582 ret = SIGUSR1;
583 break;
584 case 0x3C: /* F2 -> USR2 */
585 ret = SIGUSR2;
586 break;
587 case 0x3D: /* F3 -> HUP */
588 ret = SIGHUP;
589 break;
590 case 0x3E: /* F4 -> TERM */
591 ret = SIGTERM;
592 break;
593 case 0x03: /* CTRL-C -> TERM */
594 ret = SIGTERM;
595 break;
598 if (ret)
600 siginfo_static.signal_received = ret;
601 siginfo_static.hard = true;
604 return ret;
607 void
608 win32_pause (struct win32_signal *ws)
610 if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED (ws->in.read))
612 int status;
613 msg (M_INFO|M_NOPREFIX, "Press any key to continue...");
614 do {
615 status = WaitForSingleObject (ws->in.read, INFINITE);
616 } while (!win32_keyboard_get (ws));
620 /* window functions */
622 void
623 window_title_clear (struct window_title *wt)
625 CLEAR (*wt);
628 void
629 window_title_save (struct window_title *wt)
631 if (!wt->saved)
633 if (!GetConsoleTitle (wt->old_window_title, sizeof (wt->old_window_title)))
635 wt->old_window_title[0] = 0;
636 wt->saved = false;
638 else
639 wt->saved = true;
643 void
644 window_title_restore (const struct window_title *wt)
646 if (wt->saved)
647 SetConsoleTitle (wt->old_window_title);
650 void
651 window_title_generate (const char *title)
653 struct gc_arena gc = gc_new ();
654 struct buffer out = alloc_buf_gc (256, &gc);
655 if (!title)
656 title = "";
657 buf_printf (&out, "[%s] " PACKAGE_NAME " " PACKAGE_VERSION " F4:EXIT F1:USR1 F2:USR2 F3:HUP", title);
658 SetConsoleTitle (BSTR (&out));
659 gc_free (&gc);
662 /* semaphore functions */
664 void
665 semaphore_clear (struct semaphore *s)
667 CLEAR (*s);
670 void
671 semaphore_open (struct semaphore *s, const char *name)
673 struct security_attributes sa;
675 s->locked = false;
676 s->name = name;
677 s->hand = NULL;
679 if (init_security_attributes_allow_all (&sa))
680 s->hand = CreateSemaphore(&sa.sa, 1, 1, name);
682 if (s->hand == NULL)
683 msg (M_WARN|M_ERRNO, "WARNING: Cannot create Win32 semaphore '%s'", name);
684 else
685 dmsg (D_SEMAPHORE, "Created Win32 semaphore '%s'", s->name);
688 bool
689 semaphore_lock (struct semaphore *s, int timeout_milliseconds)
691 bool ret = true;
693 if (s->hand)
695 DWORD status;
696 ASSERT (!s->locked);
698 dmsg (D_SEMAPHORE_LOW, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
699 s->name,
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;
705 if (ret)
707 dmsg (D_SEMAPHORE, "Locked Win32 semaphore '%s'", s->name);
708 s->locked = true;
710 else
712 dmsg (D_SEMAPHORE, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
713 s->name,
714 timeout_milliseconds);
717 return ret;
720 void
721 semaphore_release (struct semaphore *s)
723 if (s->hand)
725 ASSERT (s->locked);
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'",
729 s->name);
730 s->locked = false;
734 void
735 semaphore_close (struct semaphore *s)
737 if (s->hand)
739 if (s->locked)
740 semaphore_release (s);
741 dmsg (D_SEMAPHORE, "Closing Win32 semaphore '%s'", s->name);
742 CloseHandle (s->hand);
743 s->hand = NULL;
748 * Special global semaphore used to protect network
749 * shell commands from simultaneous instantiation.
752 void
753 netcmd_semaphore_init (void)
755 semaphore_open (&netcmd_semaphore, PACKAGE "_netcmd");
758 void
759 netcmd_semaphore_close (void)
761 semaphore_close (&netcmd_semaphore);
764 void
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");
772 void
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
789 static bool
790 cmp_prefix (const char *str, const bool n, const char *pre)
792 size_t i = 0;
794 if (!str)
795 return false;
797 while (true)
799 const int c1 = pre[i];
800 int c2 = str[i];
801 ++i;
802 if (c1 == '\0')
804 if (n)
806 if (isdigit (c2))
807 c2 = str[i];
808 else
809 return false;
811 return c2 == '\0' || c2 == '.';
813 else if (c2 == '\0')
814 return false;
815 if (c1 != tolower(c2))
816 return false;
820 bool
821 win_safe_filename (const char *fn)
823 if (cmp_prefix (fn, false, "con"))
824 return false;
825 if (cmp_prefix (fn, false, "prn"))
826 return false;
827 if (cmp_prefix (fn, false, "aux"))
828 return false;
829 if (cmp_prefix (fn, false, "nul"))
830 return false;
831 if (cmp_prefix (fn, true, "com"))
832 return false;
833 if (cmp_prefix (fn, true, "lpt"))
834 return false;
835 if (cmp_prefix (fn, false, "clock$"))
836 return false;
837 return true;
841 * Service functions for openvpn_execve
844 static char *
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);
854 if (es)
856 struct env_item *e;
857 char *ret;
858 char *p;
859 size_t nchars = 1;
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);
870 p = 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 )
879 path_seen = true;
882 /* make sure PATH is set */
883 if ( !path_seen )
885 msg( M_INFO, "env_block: add %s", force_path );
886 strcpy( p, force_path );
887 p += strlen(force_path) + 1;
890 *p = '\0';
891 return ret;
893 else
894 return NULL;
897 static WCHAR *
898 wide_cmd_line (const struct argv *a, struct gc_arena *gc)
900 size_t nchars = 1;
901 size_t maxlen = 0;
902 size_t i;
903 struct buffer buf;
904 char *work = NULL;
906 if (!a)
907 return NULL;
909 for (i = 0; i < a->argc; ++i)
911 const char *arg = a->argv[i];
912 const size_t len = strlen (arg);
913 nchars += len + 3;
914 if (len > maxlen)
915 maxlen = len;
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];
925 strcpy (work, arg);
926 string_mod (work, CC_PRINT, CC_DOUBLE_QUOTE|CC_CRLF, '_');
927 if (i)
928 buf_printf (&buf, " ");
929 if (string_class (work, CC_ANY, CC_SPACE))
930 buf_printf (&buf, "%s", work);
931 else
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)
944 int ret = -1;
945 static bool exec_warn = false;
947 if (a && a->argv[0])
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;
962 CLEAR (start_info);
963 CLEAR (proc_info);
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;
978 else
979 msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %S failed", cmd);
980 CloseHandle (proc_info.hProcess);
982 else
984 msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %S failed", cmd);
986 free (env);
987 gc_free (&gc);
989 else if (!exec_warn && (script_security < SSEC_SCRIPTS))
991 msg (M_WARN, SCRIPT_SECURITY_WARNING);
992 exec_warn = true;
995 else
997 msg (M_WARN, "openvpn_execve: called with empty argv");
999 return ret;
1002 WCHAR *
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);
1008 return ucs16;
1012 * call ourself in another process
1014 void
1015 fork_to_self (const char *cmdline)
1017 STARTUPINFO start_info;
1018 PROCESS_INFORMATION proc_info;
1019 char self_exe[256];
1020 char *cl = string_alloc (cmdline, NULL);
1021 DWORD status;
1023 CLEAR (start_info);
1024 CLEAR (proc_info);
1025 CLEAR (self_exe);
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");
1031 goto done;
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);
1045 else
1047 msg (M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: %s", cmdline);
1050 done:
1051 free (cl);
1054 char *
1055 get_win_sys_path (void)
1057 ASSERT (win_sys_path);
1058 return win_sys_path;
1061 void
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 */
1069 void
1070 set_win_sys_path_via_env (struct env_set *es)
1072 char buf[256];
1073 DWORD status = GetEnvironmentVariable (SYS_PATH_ENV_VAR_NAME, buf, sizeof(buf));
1074 if (!status)
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);
1082 const char *
1083 win_get_tempdir()
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
1091 * be unlikely.
1093 msg (M_WARN, "Could not find a suitable temporary directory."
1094 " (GetTempPath() failed). Consider using --tmp-dir");
1095 return NULL;
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");
1102 return NULL;
1105 WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, tmpdir, sizeof (tmpdir), NULL, NULL);
1106 return tmpdir;
1109 bool
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");
1120 return false;
1123 fwpuclntHandle = LoadLibrary("fwpuclnt.dll");
1124 if (fwpuclntHandle == NULL)
1126 msg (M_NONFATAL, "Can't load fwpuclnt.dll");
1127 return false;
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 ||
1140 !FwpmFilterAdd0 ||
1141 !FwpmEngineOpen0 ||
1142 !FwpmEngineClose0 ||
1143 !FwpmSubLayerAdd0 ||
1144 !FwpmSubLayerDeleteByKey0 ||
1145 !FwpmFreeMemory0 ||
1146 !FwpmGetAppIdFromFileName0)
1148 msg (M_NONFATAL, "Can't get address for all WFP-related procedures.");
1149 return false;
1152 return true;
1155 bool
1156 win_wfp_add_filter (HANDLE engineHandle,
1157 const FWPM_FILTER0 *filter,
1158 PSECURITY_DESCRIPTOR sd,
1159 UINT64 *id)
1161 if (FwpmFilterAdd0(engineHandle, filter, sd, id) != ERROR_SUCCESS)
1163 msg (M_NONFATAL, "Can't add WFP filter");
1164 return false;
1166 return true;
1169 bool
1170 win_wfp_block_dns (const NET_IFINDEX index)
1172 FWPM_SESSION0 session = {0};
1173 FWPM_SUBLAYER0 SubLayer = {0};
1174 NET_LUID tapluid;
1175 UINT64 filterid;
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");
1189 return false;
1192 if (UuidCreate(&SubLayer.subLayerKey) != NO_ERROR)
1193 return false;
1195 /* Populate packet filter layer information. */
1196 SubLayer.displayData.name = FIREWALL_NAME;
1197 SubLayer.displayData.description = FIREWALL_NAME;
1198 SubLayer.flags = 0;
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");
1206 return false;
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");
1213 return false;
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)
1221 return false;
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))
1246 goto err;
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))
1254 goto err;
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))
1268 goto err;
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))
1276 goto err;
1277 dmsg (D_LOW, "Filter (Permit IPv6 DNS queries from TAP) added with ID=%I64d", filterid);
1279 FwpmFreeMemory0((void **)&openvpnblob);
1280 return true;
1282 err:
1283 FwpmFreeMemory0((void **)&openvpnblob);
1284 return false;
1287 bool
1288 win_wfp_uninit()
1290 dmsg (D_LOW, "Uninitializing WFP");
1291 if (m_hEngineHandle) {
1292 FwpmEngineClose0(m_hEngineHandle);
1293 m_hEngineHandle = NULL;
1295 return true;
1299 win32_version_info()
1301 if (!IsWindowsXPOrGreater())
1303 msg (M_FATAL, "Error: Windows version must be XP or greater.");
1306 if (!IsWindowsVistaOrGreater())
1308 return WIN_XP;
1311 if (!IsWindows7OrGreater())
1313 return WIN_VISTA;
1316 if (!IsWindows8OrGreater())
1318 return WIN_7;
1320 else
1322 return WIN_8;
1326 const char *
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);
1332 switch (version)
1334 case WIN_XP:
1335 buf_printf (&out, "5.1%s", add_name ? " (Windows XP)" : "");
1336 break;
1337 case WIN_VISTA:
1338 buf_printf (&out, "6.0%s", add_name ? " (Windows Vista)" : "");
1339 break;
1340 case WIN_7:
1341 buf_printf (&out, "6.1%s", add_name ? " (Windows 7)" : "");
1342 break;
1343 case WIN_8:
1344 buf_printf (&out, "6.2%s", add_name ? " (Windows 8 or greater)" : "");
1345 break;
1346 default:
1347 msg (M_NONFATAL, "Unknown Windows version: %d", version);
1348 buf_printf (&out, "0.0%s", add_name ? " (unknown)" : "");
1349 break;
1352 return (const char *)out.data;
1355 #endif