OpenVPN
win32.c
Go to the documentation of this file.
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.
7 *
8 * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9 *
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.
13 *
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.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24/*
25 * Win32-specific OpenVPN code, targeted at the mingw
26 * development environment.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "syshead.h"
34
35#ifdef _WIN32
36
37#include <minwindef.h>
38#include <winsock2.h>
39
40#include "buffer.h"
41#include "error.h"
42#include "mtu.h"
43#include "run_command.h"
44#include "sig.h"
45#include "win32-util.h"
46#include "win32.h"
47#include "openvpn-msg.h"
48
49#include "memdbg.h"
50
51#include <versionhelpers.h>
52
53#include "wfp_block.h"
54
55/*
56 * WFP handle
57 */
58static HANDLE m_hEngineHandle = NULL; /* GLOBAL */
59
60/*
61 * TAP adapter original metric value
62 */
63static int tap_metric_v4 = -1; /* GLOBAL */
64static int tap_metric_v6 = -1; /* GLOBAL */
65
66/*
67 * Windows internal socket API state (opaque).
68 */
69static struct WSAData wsa_state; /* GLOBAL */
70
71/*
72 * Should we call win32_pause() on program exit?
73 */
74static bool pause_exit_enabled = false; /* GLOBAL */
75
76/*
77 * win32_signal is used to get input from the keyboard
78 * if we are running in a console, or get input from an
79 * event object if we are running as a service.
80 */
81
82struct win32_signal win32_signal; /* GLOBAL */
83
84/*
85 * Save our old window title so we can restore
86 * it on exit.
87 */
88struct window_title window_title; /* GLOBAL*/
89
90/*
91 * Special global semaphore used to protect network
92 * shell commands from simultaneous instantiation.
93 */
94
95struct semaphore netcmd_semaphore; /* GLOBAL */
96
97/*
98 * Windows system pathname such as c:\windows
99 */
100static char *win_sys_path = NULL; /* GLOBAL */
101
105static void
107
108void
110{
111 if (WSAStartup(0x0101, &wsa_state))
112 {
113 msg(M_ERR, "WSAStartup failed");
114 }
117
119}
120
121void
123{
126 {
128 {
129 struct win32_signal w;
130 win32_signal_open(&w, WSO_FORCE_CONSOLE, NULL, false);
131 win32_pause(&w);
133 }
134 else
135 {
137 }
138 }
141 WSACleanup();
142 free(win_sys_path);
143}
144
145void
147{
148 pause_exit_enabled = true;
149}
150
151bool
153{
154 CLEAR(*obj);
155
156 obj->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
157 obj->sa.lpSecurityDescriptor = &obj->sd;
158 obj->sa.bInheritHandle = FALSE;
159 if (!InitializeSecurityDescriptor(&obj->sd, SECURITY_DESCRIPTOR_REVISION))
160 {
161 return false;
162 }
163 if (!SetSecurityDescriptorDacl(&obj->sd, TRUE, NULL, FALSE))
164 {
165 return false;
166 }
167 return true;
168}
169
170void
172 const struct frame *frame,
173 BOOL event_state)
174{
175 CLEAR(*o);
176
177 /* manual reset event, initially set according to event_state */
178 o->overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
179 if (o->overlapped.hEvent == NULL)
180 {
181 msg(M_ERR, "Error: overlapped_io_init: CreateEvent failed");
182 }
183
184 /* allocate buffer for overlapped I/O */
186}
187
188void
190{
191 if (o->overlapped.hEvent)
192 {
193 if (!CloseHandle(o->overlapped.hEvent))
194 {
195 msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on overlapped I/O event object");
196 }
197 }
198 free_buf(&o->buf_init);
199}
200
201char *
203{
204 switch (o->iostate)
205 {
206 case IOSTATE_INITIAL:
207 return "0";
208
209 case IOSTATE_QUEUED:
210 return "Q";
211
213 return "1";
214 }
215 return "?";
216}
217
218/*
219 * Event-based notification of network events
220 */
221
222void
223init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
224{
225 /* manual reset events, initially set to unsignaled */
226
227 /* initialize write event */
228 if (!(flags & NE32_PERSIST_EVENT) || !event->write)
229 {
230 if (flags & NE32_WRITE_EVENT)
231 {
232 event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
233 if (event->write == NULL)
234 {
235 msg(M_ERR, "Error: init_net_event_win32: CreateEvent (write) failed");
236 }
237 }
238 else
239 {
240 event->write = NULL;
241 }
242 }
243
244 /* initialize read event */
245 if (!(flags & NE32_PERSIST_EVENT) || !event->read)
246 {
247 event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
248 if (event->read == NULL)
249 {
250 msg(M_ERR, "Error: init_net_event_win32: CreateEvent (read) failed");
251 }
252 }
253
254 /* setup network events to change read event state */
255 if (WSAEventSelect(sd, event->read, network_events) != 0)
256 {
257 msg(M_FATAL | M_ERRNO, "Error: init_net_event_win32: WSAEventSelect call failed");
258 }
259}
260
261long
263{
264 WSANETWORKEVENTS wne;
265 if (WSAEnumNetworkEvents(sd, event->read, &wne) != 0)
266 {
267 msg(M_FATAL | M_ERRNO, "Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
268 return 0; /* NOTREACHED */
269 }
270 else
271 {
272 return wne.lNetworkEvents;
273 }
274}
275
276void
277close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
278{
279 if (event->read)
280 {
281 if (socket_defined(sd))
282 {
283 if (WSAEventSelect(sd, event->read, 0) != 0)
284 {
285 msg(M_WARN | M_ERRNO, "Warning: close_net_event_win32: WSAEventSelect call failed");
286 }
287 }
288 if (!ResetEvent(event->read))
289 {
290 msg(M_WARN | M_ERRNO, "Warning: ResetEvent (read) failed in close_net_event_win32");
291 }
292 if (!(flags & NE32_PERSIST_EVENT))
293 {
294 if (!CloseHandle(event->read))
295 {
296 msg(M_WARN | M_ERRNO, "Warning: CloseHandle (read) failed in close_net_event_win32");
297 }
298 event->read = NULL;
299 }
300 }
301
302 if (event->write)
303 {
304 if (!ResetEvent(event->write))
305 {
306 msg(M_WARN | M_ERRNO, "Warning: ResetEvent (write) failed in close_net_event_win32");
307 }
308 if (!(flags & NE32_PERSIST_EVENT))
309 {
310 if (!CloseHandle(event->write))
311 {
312 msg(M_WARN | M_ERRNO, "Warning: CloseHandle (write) failed in close_net_event_win32");
313 }
314 event->write = NULL;
315 }
316 }
317}
318
319/*
320 * struct net_event_win32
321 */
322
323void
325{
326 CLEAR(*ne);
327 ne->sd = SOCKET_UNDEFINED;
328}
329
330void
332{
333 ASSERT(!socket_defined(ne->sd));
334 ne->sd = sd;
335 ne->event_mask = 0;
337}
338
339void
341{
342 BOOL status;
343 if (ne->event_mask & FD_WRITE)
344 {
345 status = SetEvent(ne->handle.write);
346 }
347 else
348 {
349 status = ResetEvent(ne->handle.write);
350 }
351 if (!status)
352 {
353 msg(M_WARN | M_ERRNO, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
354 }
355}
356
357void
362
363void
365{
367 {
369 }
370 ne->sd = SOCKET_UNDEFINED;
371 ne->event_mask = 0;
372}
373
374void
376{
378 {
379 close_net_event_win32(&ne->handle, ne->sd, 0);
380 }
382}
383
384/*
385 * Simulate *nix signals on Windows.
386 *
387 * Two modes:
388 * (1) Console mode -- map keyboard function keys to signals
389 * (2) Service mode -- map Windows event object to SIGTERM
390 */
391
392static void
394{
395 if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read))
396 {
397 SetEvent(ws->in.read);
398 }
399 else /* generate a key-press event */
400 {
401 DWORD tmp;
402 INPUT_RECORD ir;
403 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
404
405 CLEAR(ir);
406 ir.EventType = KEY_EVENT;
407 ir.Event.KeyEvent.bKeyDown = true;
408 if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
409 {
410 msg(M_WARN|M_ERRNO, "WARN: win_trigger_event: WriteConsoleInput");
411 }
412 }
413}
414
415/*
416 * Callback to handle console ctrl events
417 */
418static bool WINAPI
419win_ctrl_handler(DWORD signum)
420{
421 msg(D_LOW, "win_ctrl_handler: signal received (code=%lu)", (unsigned long) signum);
422
423 if (siginfo_static.signal_received == SIGTERM)
424 {
425 return true;
426 }
427
428 switch (signum)
429 {
430 case CTRL_C_EVENT:
431 case CTRL_BREAK_EVENT:
432 throw_signal(SIGTERM);
433 /* trigget the win32_signal to interrupt the event loop */
435 return true;
436 break;
437
438 default:
439 msg(D_LOW, "win_ctrl_handler: signal (code=%lu) not handled", (unsigned long) signum);
440 break;
441 }
442 /* pass all other signals to the next handler */
443 return false;
444}
445
446void
448{
449 CLEAR(*ws);
450}
451
452void
454 int force,
455 const char *exit_event_name,
456 bool exit_event_initial_state)
457{
458 CLEAR(*ws);
459
460 ws->mode = WSO_MODE_UNDEF;
461 ws->in.read = INVALID_HANDLE_VALUE;
462 ws->in.write = INVALID_HANDLE_VALUE;
463 ws->console_mode_save = 0;
464 ws->console_mode_save_defined = false;
465
466 if (force == WSO_NOFORCE || force == WSO_FORCE_CONSOLE)
467 {
468 /*
469 * Try to open console.
470 */
471 ws->in.read = GetStdHandle(STD_INPUT_HANDLE);
472 if (ws->in.read != INVALID_HANDLE_VALUE)
473 {
474 if (GetConsoleMode(ws->in.read, &ws->console_mode_save))
475 {
476 /* running on a console */
477 const DWORD new_console_mode = ws->console_mode_save
478 & ~(ENABLE_WINDOW_INPUT
479 | ENABLE_PROCESSED_INPUT
480 | ENABLE_LINE_INPUT
481 | ENABLE_ECHO_INPUT
482 | ENABLE_MOUSE_INPUT);
483
484 if (new_console_mode != ws->console_mode_save)
485 {
486 if (!SetConsoleMode(ws->in.read, new_console_mode))
487 {
488 msg(M_ERR, "Error: win32_signal_open: SetConsoleMode failed");
489 }
490 ws->console_mode_save_defined = true;
491 }
493 }
494 else
495 {
496 ws->in.read = INVALID_HANDLE_VALUE; /* probably running as a service */
497 }
498 }
499 }
500
501 /*
502 * If console open failed, assume we are running
503 * as a service.
504 */
505 if ((force == WSO_NOFORCE || force == WSO_FORCE_SERVICE)
506 && !HANDLE_DEFINED(ws->in.read) && exit_event_name)
507 {
508 struct security_attributes sa;
509 struct gc_arena gc = gc_new();
510 const wchar_t *exit_event_nameW = wide_string(exit_event_name, &gc);
511
513 {
514 msg(M_ERR, "Error: win32_signal_open: init SA failed");
515 }
516
517 ws->in.read = CreateEventW(&sa.sa, TRUE, exit_event_initial_state ? TRUE : FALSE,
518 exit_event_nameW);
519 if (ws->in.read == NULL)
520 {
521 msg(M_WARN|M_ERRNO, "NOTE: CreateEventW '%s' failed", exit_event_name);
522 }
523 else
524 {
525 if (WaitForSingleObject(ws->in.read, 0) != WAIT_TIMEOUT)
526 {
527 msg(M_FATAL, "ERROR: Exit Event ('%s') is signaled", exit_event_name);
528 }
529 else
530 {
532 }
533 }
534 gc_free(&gc);
535 }
536 /* set the ctrl handler in both console and service modes */
537 if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) win_ctrl_handler, true))
538 {
539 msg(M_WARN|M_ERRNO, "WARN: SetConsoleCtrlHandler failed");
540 }
541}
542
543static bool
545{
547 if (HANDLE_DEFINED(ws->in.read))
548 {
549 DWORD n;
550 if (GetNumberOfConsoleInputEvents(ws->in.read, &n))
551 {
552 return n > 0;
553 }
554 }
555 return false;
556}
557
558static unsigned int
559keyboard_ir_to_key(INPUT_RECORD *ir)
560{
561 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
562 {
563 return ir->Event.KeyEvent.wVirtualScanCode;
564 }
565
566 if ((ir->Event.KeyEvent.dwControlKeyState
567 & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
568 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
569 {
570 return ir->Event.KeyEvent.wVirtualScanCode * 256;
571 }
572
573 return ir->Event.KeyEvent.uChar.AsciiChar;
574}
575
576static unsigned int
578{
580 if (HANDLE_DEFINED(ws->in.read))
581 {
582 INPUT_RECORD ir;
583 do
584 {
585 DWORD n;
587 {
588 return 0;
589 }
590 if (!ReadConsoleInput(ws->in.read, &ir, 1, &n))
591 {
592 return 0;
593 }
594 } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
595
596 return keyboard_ir_to_key(&ir);
597 }
598 else
599 {
600 return 0;
601 }
602}
603
604void
606{
607 if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read))
608 {
609 CloseHandle(ws->in.read);
610 }
612 {
613 if (!SetConsoleMode(ws->in.read, ws->console_mode_save))
614 {
615 msg(M_ERR, "Error: win32_signal_close: SetConsoleMode failed");
616 }
617 }
618 CLEAR(*ws);
619}
620
621/*
622 * Return true if interrupt occurs in service mode.
623 */
624bool
626{
627 if (ws->mode == WSO_MODE_SERVICE)
628 {
629 if (HANDLE_DEFINED(ws->in.read)
630 && WaitForSingleObject(ws->in.read, 0) == WAIT_OBJECT_0)
631 {
632 return true;
633 }
634 }
635 return false;
636}
637
638int
640{
641 int ret = 0;
642
643 if (ws->mode == WSO_MODE_SERVICE)
644 {
646 {
647 ret = SIGTERM;
648 }
649 }
650 else if (ws->mode == WSO_MODE_CONSOLE)
651 {
652 switch (win32_keyboard_get(ws))
653 {
654 case 0x3B: /* F1 -> USR1 */
655 ret = SIGUSR1;
656 break;
657
658 case 0x3C: /* F2 -> USR2 */
659 ret = SIGUSR2;
660 break;
661
662 case 0x3D: /* F3 -> HUP */
663 ret = SIGHUP;
664 break;
665
666 case 0x3E: /* F4 -> TERM */
667 ret = SIGTERM;
668 break;
669
670 case 0x03: /* CTRL-C -> TERM */
671 ret = SIGTERM;
672 break;
673 }
674 }
675 if (ret)
676 {
677 throw_signal(ret); /* this will update siginfo_static.signal received */
678 }
680}
681
682void
684{
685 if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED(ws->in.read))
686 {
687 msg(M_INFO|M_NOPREFIX, "Press any key to continue...");
688 do
689 {
690 WaitForSingleObject(ws->in.read, INFINITE);
691 } while (!win32_keyboard_get(ws));
692 }
693}
694
695/* window functions */
696
697void
699{
700 CLEAR(*wt);
701}
702
703void
705{
706 if (!wt->saved)
707 {
708 if (!GetConsoleTitle(wt->old_window_title, sizeof(wt->old_window_title)))
709 {
710 wt->old_window_title[0] = 0;
711 wt->saved = false;
712 }
713 else
714 {
715 wt->saved = true;
716 }
717 }
718}
719
720void
722{
723 if (wt->saved)
724 {
725 SetConsoleTitle(wt->old_window_title);
726 }
727}
728
729void
730window_title_generate(const char *title)
731{
732 struct gc_arena gc = gc_new();
733 struct buffer out = alloc_buf_gc(256, &gc);
734 if (!title)
735 {
736 title = "";
737 }
738 buf_printf(&out, "[%s] " PACKAGE_NAME " " PACKAGE_VERSION " F4:EXIT F1:USR1 F2:USR2 F3:HUP", title);
739 SetConsoleTitle(BSTR(&out));
740 gc_free(&gc);
741}
742
743/* semaphore functions */
744
745void
747{
748 CLEAR(*s);
749}
750
751void
752semaphore_open(struct semaphore *s, const char *name)
753{
754 struct security_attributes sa;
755
756 s->locked = false;
757 s->name = name;
758 s->hand = NULL;
759
761 {
762 s->hand = CreateSemaphore(&sa.sa, 1, 1, name);
763 }
764
765 if (s->hand == NULL)
766 {
767 msg(M_WARN|M_ERRNO, "WARNING: Cannot create Win32 semaphore '%s'", name);
768 }
769 else
770 {
771 dmsg(D_SEMAPHORE, "Created Win32 semaphore '%s'", s->name);
772 }
773}
774
775bool
776semaphore_lock(struct semaphore *s, int timeout_milliseconds)
777{
778 bool ret = true;
779
780 if (s->hand)
781 {
782 DWORD status;
783 ASSERT(!s->locked);
784
785 dmsg(D_SEMAPHORE_LOW, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
786 s->name,
787 timeout_milliseconds / 1000);
788 status = WaitForSingleObject(s->hand, timeout_milliseconds);
789 if (status == WAIT_FAILED)
790 {
791 msg(M_ERR, "Wait failed on Win32 semaphore '%s'", s->name);
792 }
793 ret = (status == WAIT_TIMEOUT) ? false : true;
794 if (ret)
795 {
796 dmsg(D_SEMAPHORE, "Locked Win32 semaphore '%s'", s->name);
797 s->locked = true;
798 }
799 else
800 {
801 dmsg(D_SEMAPHORE, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
802 s->name,
803 timeout_milliseconds);
804 }
805 }
806 return ret;
807}
808
809void
811{
812 if (s->hand)
813 {
814 ASSERT(s->locked);
815 dmsg(D_SEMAPHORE, "Releasing Win32 semaphore '%s'", s->name);
816 if (!ReleaseSemaphore(s->hand, 1, NULL))
817 {
818 msg(M_WARN | M_ERRNO, "ReleaseSemaphore failed on Win32 semaphore '%s'",
819 s->name);
820 }
821 s->locked = false;
822 }
823}
824
825void
827{
828 if (s->hand)
829 {
830 if (s->locked)
831 {
833 }
834 dmsg(D_SEMAPHORE, "Closing Win32 semaphore '%s'", s->name);
835 CloseHandle(s->hand);
836 s->hand = NULL;
837 }
838}
839
840/*
841 * Special global semaphore used to protect network
842 * shell commands from simultaneous instantiation.
843 */
844
845void
847{
848 semaphore_open(&netcmd_semaphore, PACKAGE "_netcmd");
849}
850
851void
856
857void
859{
860 const int timeout_seconds = 600;
861
863 {
865 }
866
867 if (!semaphore_lock(&netcmd_semaphore, timeout_seconds * 1000))
868 {
869 msg(M_FATAL, "Cannot lock net command semaphore");
870 }
871}
872
873void
875{
877 /* netcmd_semaphore has max count of 1 - safe to close after release */
879}
880
881/*
882 * Service functions for openvpn_execve
883 */
884
885static char *
886env_block(const struct env_set *es)
887{
888 char force_path[256];
889 char *sysroot = get_win_sys_path();
890
891 if (!snprintf(force_path, sizeof(force_path), "PATH=%s\\System32;%s;%s\\System32\\Wbem",
892 sysroot, sysroot, sysroot))
893 {
894 msg(M_WARN, "env_block: default path truncated to %s", force_path);
895 }
896
897 if (es)
898 {
899 struct env_item *e;
900 char *ret;
901 char *p;
902 size_t nchars = 1;
903 bool path_seen = false;
904
905 for (e = es->list; e != NULL; e = e->next)
906 {
907 nchars += strlen(e->string) + 1;
908 }
909
910 nchars += strlen(force_path)+1;
911
912 ret = (char *) malloc(nchars);
914
915 p = ret;
916 for (e = es->list; e != NULL; e = e->next)
917 {
918 if (env_allowed(e->string))
919 {
920 strcpy(p, e->string);
921 p += strlen(e->string) + 1;
922 }
923 if (strncmp(e->string, "PATH=", 5 ) == 0)
924 {
925 path_seen = true;
926 }
927 }
928
929 /* make sure PATH is set */
930 if (!path_seen)
931 {
932 msg( M_INFO, "env_block: add %s", force_path );
933 strcpy( p, force_path );
934 p += strlen(force_path) + 1;
935 }
936
937 *p = '\0';
938 return ret;
939 }
940 else
941 {
942 return NULL;
943 }
944}
945
946static WCHAR *
947wide_cmd_line(const struct argv *a, struct gc_arena *gc)
948{
949 size_t nchars = 1;
950 size_t maxlen = 0;
951 size_t i;
952 struct buffer buf;
953 char *work = NULL;
954
955 if (!a)
956 {
957 return NULL;
958 }
959
960 for (i = 0; i < a->argc; ++i)
961 {
962 const char *arg = a->argv[i];
963 const size_t len = strlen(arg);
964 nchars += len + 3;
965 if (len > maxlen)
966 {
967 maxlen = len;
968 }
969 }
970
971 work = gc_malloc(maxlen + 1, false, gc);
973 buf = alloc_buf_gc(nchars, gc);
974
975 for (i = 0; i < a->argc; ++i)
976 {
977 const char *arg = a->argv[i];
978 strcpy(work, arg);
980 if (i)
981 {
982 buf_printf(&buf, " ");
983 }
984 if (string_class(work, CC_ANY, CC_SPACE))
985 {
986 buf_printf(&buf, "%s", work);
987 }
988 else
989 {
990 buf_printf(&buf, "\"%s\"", work);
991 }
992 }
993
994 return wide_string(BSTR(&buf), gc);
995}
996
997/*
998 * Attempt to simulate fork/execve on Windows
999 */
1000int
1001openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
1002{
1003 int ret = OPENVPN_EXECVE_ERROR;
1004 static bool exec_warn = false;
1005
1006 if (a && a->argv[0])
1007 {
1008 if (openvpn_execve_allowed(flags))
1009 {
1010 struct gc_arena gc = gc_new();
1011 STARTUPINFOW start_info;
1012 PROCESS_INFORMATION proc_info;
1013
1014 char *env = env_block(es);
1015 WCHAR *cl = wide_cmd_line(a, &gc);
1016 WCHAR *cmd = wide_string(a->argv[0], &gc);
1017
1018 /* this allows console programs to run, and is ignored otherwise */
1019 DWORD proc_flags = CREATE_NO_WINDOW;
1020
1021 CLEAR(start_info);
1022 CLEAR(proc_info);
1023
1024 /* fill in STARTUPINFO struct */
1025 GetStartupInfoW(&start_info);
1026 start_info.cb = sizeof(start_info);
1027 start_info.dwFlags = STARTF_USESHOWWINDOW;
1028 start_info.wShowWindow = SW_HIDE;
1029
1030 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))
1031 {
1032 DWORD exit_status = 0;
1033 CloseHandle(proc_info.hThread);
1034 WaitForSingleObject(proc_info.hProcess, INFINITE);
1035 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1036 {
1037 ret = (int)exit_status;
1038 }
1039 else
1040 {
1041 msg(M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1042 }
1043 CloseHandle(proc_info.hProcess);
1044 }
1045 else
1046 {
1047 msg(M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %ls failed", cmd);
1048 }
1049 free(env);
1050 gc_free(&gc);
1051 }
1052 else
1053 {
1055 if (!exec_warn && (script_security() < SSEC_SCRIPTS))
1056 {
1058 exec_warn = true;
1059 }
1060 }
1061 }
1062 else
1063 {
1064 msg(M_WARN, "openvpn_execve: called with empty argv");
1065 }
1066 return ret;
1067}
1068
1069/*
1070 * call ourself in another process
1071 */
1072void
1073fork_to_self(const char *cmdline)
1074{
1075 STARTUPINFO start_info;
1076 PROCESS_INFORMATION proc_info;
1077 char self_exe[256];
1078 char *cl = string_alloc(cmdline, NULL);
1079 DWORD status;
1080
1081 CLEAR(start_info);
1082 CLEAR(proc_info);
1083 CLEAR(self_exe);
1084
1085 status = GetModuleFileName(NULL, self_exe, sizeof(self_exe));
1086 if (status == 0 || status == sizeof(self_exe))
1087 {
1088 msg(M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1089 goto done;
1090 }
1091
1092 /* fill in STARTUPINFO struct */
1093 GetStartupInfo(&start_info);
1094 start_info.cb = sizeof(start_info);
1095 start_info.dwFlags = STARTF_USESHOWWINDOW;
1096 start_info.wShowWindow = SW_HIDE;
1097
1098 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1099 {
1100 CloseHandle(proc_info.hThread);
1101 CloseHandle(proc_info.hProcess);
1102 }
1103 else
1104 {
1105 msg(M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: %s", cmdline);
1106 }
1107
1108done:
1109 free(cl);
1110}
1111
1112char *
1114{
1116 return win_sys_path;
1117}
1118
1119void
1120set_win_sys_path(const char *newpath, struct env_set *es)
1121{
1122 free(win_sys_path);
1123 win_sys_path = string_alloc(newpath, NULL);
1124 setenv_str(es, SYS_PATH_ENV_VAR_NAME, win_sys_path); /* route.exe needs this */
1125}
1126
1127void
1129{
1130 char buf[256];
1131 DWORD status = GetEnvironmentVariable(SYS_PATH_ENV_VAR_NAME, buf, sizeof(buf));
1132 if (!status)
1133 {
1134 msg(M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1135 }
1136 if (status > sizeof(buf) - 1)
1137 {
1138 msg(M_FATAL, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1139 }
1140 set_win_sys_path(buf, es);
1141}
1142
1143static bool
1144win_get_exe_path(PWCHAR path, DWORD size)
1145{
1146 DWORD status = GetModuleFileNameW(NULL, path, size);
1147 if (status == 0 || status == size)
1148 {
1149 msg(M_WARN|M_ERRNO, "cannot get executable path");
1150 return false;
1151 }
1152 return true;
1153}
1154
1155static void
1156win_wfp_msg_handler(DWORD err, const char *msg)
1157{
1158 struct gc_arena gc = gc_new();
1159
1160 if (err == 0)
1161 {
1162 msg(M_INFO, "%s", msg);
1163 }
1164 else
1165 {
1166 msg(M_WARN, "Error in WFP: %s : %s [status=0x%lx]",
1167 msg, strerror_win32(err, &gc), err);
1168 }
1169
1170 gc_free(&gc);
1171}
1172
1173static bool
1174win_wfp_block_service(bool add, bool dns_only, int index, const HANDLE pipe)
1175{
1176 bool ret = false;
1177 ack_message_t ack;
1178 struct gc_arena gc = gc_new();
1179
1180 wfp_block_message_t data = {
1181 .header = {
1183 sizeof(wfp_block_message_t),
1184 0
1185 },
1186 .flags = dns_only ? wfp_block_dns : wfp_block_local,
1187 .iface = { .index = index, .name = "" }
1188 };
1189
1190 if (!send_msg_iservice(pipe, &data, sizeof(data), &ack, "WFP block"))
1191 {
1192 goto out;
1193 }
1194
1195 if (ack.error_number != NO_ERROR)
1196 {
1197 msg(M_WARN, "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%d]",
1198 (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc),
1199 ack.error_number, data.iface.index);
1200 goto out;
1201 }
1202
1203 ret = true;
1204 msg(M_INFO, "%s WFP block filters using service succeeded.", (add ? "Adding" : "Deleting"));
1205out:
1206 gc_free(&gc);
1207 return ret;
1208}
1209
1210bool
1211win_wfp_block(const NET_IFINDEX index, const HANDLE msg_channel, BOOL dns_only)
1212{
1213 WCHAR openvpnpath[MAX_PATH];
1214 bool ret = false;
1215 DWORD status;
1216
1217 if (msg_channel)
1218 {
1219 dmsg(D_LOW, "Using service to add WFP block filters");
1220 ret = win_wfp_block_service(true, dns_only, index, msg_channel);
1221 goto out;
1222 }
1223
1224 ret = win_get_exe_path(openvpnpath, _countof(openvpnpath));
1225 if (ret == false)
1226 {
1227 goto out;
1228 }
1229
1230 status = add_wfp_block_filters(&m_hEngineHandle, index, openvpnpath,
1231 win_wfp_msg_handler, dns_only);
1232 if (status == 0)
1233 {
1234 int is_auto = 0;
1235 tap_metric_v4 = get_interface_metric(index, AF_INET, &is_auto);
1236 if (is_auto)
1237 {
1238 tap_metric_v4 = 0;
1239 }
1240 tap_metric_v6 = get_interface_metric(index, AF_INET6, &is_auto);
1241 if (is_auto)
1242 {
1243 tap_metric_v6 = 0;
1244 }
1246 if (!status)
1247 {
1249 }
1250 }
1251
1252 ret = (status == 0);
1253
1254out:
1255
1256 return ret;
1257}
1258
1259bool
1260win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
1261{
1262 dmsg(D_LOW, "Uninitializing WFP");
1263
1264 if (msg_channel)
1265 {
1266 msg(D_LOW, "Using service to delete WFP block filters");
1267 win_wfp_block_service(false, false, index, msg_channel);
1268 }
1269 else
1270 {
1272 m_hEngineHandle = NULL;
1273 if (tap_metric_v4 >= 0)
1274 {
1275 set_interface_metric(index, AF_INET, tap_metric_v4);
1276 }
1277 if (tap_metric_v6 >= 0)
1278 {
1279 set_interface_metric(index, AF_INET6, tap_metric_v6);
1280 }
1281 }
1282
1283 return true;
1284}
1285
1286int
1288{
1289 if (!IsWindowsXPOrGreater())
1290 {
1291 msg(M_FATAL, "Error: Windows version must be XP or greater.");
1292 }
1293
1294 if (!IsWindowsVistaOrGreater())
1295 {
1296 return WIN_XP;
1297 }
1298
1299 if (!IsWindows7OrGreater())
1300 {
1301 return WIN_VISTA;
1302 }
1303
1304 if (!IsWindows8OrGreater())
1305 {
1306 return WIN_7;
1307 }
1308
1309 if (!IsWindows8Point1OrGreater())
1310 {
1311 return WIN_8;
1312 }
1313
1314 if (!IsWindows10OrGreater())
1315 {
1316 return WIN_8_1;
1317 }
1318
1319 return WIN_10;
1320}
1321
1322typedef enum {
1326 ARCH_NATIVE, /* means no emulation, makes sense for host arch */
1329
1330static void
1331win32_get_arch(arch_t *process_arch, arch_t *host_arch)
1332{
1333 *process_arch = ARCH_UNKNOWN;
1334 *host_arch = ARCH_NATIVE;
1335
1336 typedef BOOL (WINAPI *is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1337 is_wow64_process2_t is_wow64_process2 = (is_wow64_process2_t)
1338 GetProcAddress(GetModuleHandle("Kernel32.dll"), "IsWow64Process2");
1339
1340 USHORT process_machine = 0;
1341 USHORT native_machine = 0;
1342
1343#ifdef _ARM64_
1344 *process_arch = ARCH_ARM64;
1345#elif defined(_WIN64)
1346 *process_arch = ARCH_AMD64;
1347 if (is_wow64_process2)
1348 {
1349 /* this could be amd64 on arm64 */
1350 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1351 &process_machine, &native_machine);
1352 if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
1353 {
1354 *host_arch = ARCH_ARM64;
1355 }
1356 }
1357#elif defined(_WIN32)
1358 *process_arch = ARCH_X86;
1359
1360 if (is_wow64_process2)
1361 {
1362 /* check if we're running on arm64 or amd64 machine */
1363 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(),
1364 &process_machine, &native_machine);
1365 if (is_wow64)
1366 {
1367 switch (native_machine)
1368 {
1369 case IMAGE_FILE_MACHINE_ARM64:
1370 *host_arch = ARCH_ARM64;
1371 break;
1372
1373 case IMAGE_FILE_MACHINE_AMD64:
1374 *host_arch = ARCH_AMD64;
1375 break;
1376
1377 default:
1378 *host_arch = ARCH_UNKNOWN;
1379 break;
1380 }
1381 }
1382 }
1383 else
1384 {
1385 BOOL w64 = FALSE;
1386 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1387 if (is_wow64)
1388 {
1389 /* we are unable to differentiate between arm64 and amd64
1390 * machines here, so assume we are running on amd64 */
1391 *host_arch = ARCH_AMD64;
1392 }
1393 }
1394#endif /* _ARM64_ */
1395}
1396
1397static void
1399{
1400 switch (arch)
1401 {
1402 case ARCH_X86:
1403 buf_printf(out, "x86");
1404 break;
1405
1406 case ARCH_AMD64:
1407 buf_printf(out, "amd64");
1408 break;
1409
1410 case ARCH_ARM64:
1411 buf_printf(out, "arm64");
1412 break;
1413
1414 case ARCH_UNKNOWN:
1415 buf_printf(out, "(unknown)");
1416 break;
1417
1418 default:
1419 break;
1420 }
1421}
1422
1423const char *
1424win32_version_string(struct gc_arena *gc, bool add_name)
1425{
1426 int version = win32_version_info();
1427 struct buffer out = alloc_buf_gc(256, gc);
1428
1429 switch (version)
1430 {
1431 case WIN_XP:
1432 buf_printf(&out, "5.1%s", add_name ? " (Windows XP)" : "");
1433 break;
1434
1435 case WIN_VISTA:
1436 buf_printf(&out, "6.0%s", add_name ? " (Windows Vista)" : "");
1437 break;
1438
1439 case WIN_7:
1440 buf_printf(&out, "6.1%s", add_name ? " (Windows 7)" : "");
1441 break;
1442
1443 case WIN_8:
1444 buf_printf(&out, "6.2%s", add_name ? " (Windows 8)" : "");
1445 break;
1446
1447 case WIN_8_1:
1448 buf_printf(&out, "6.3%s", add_name ? " (Windows 8.1)" : "");
1449 break;
1450
1451 case WIN_10:
1452 buf_printf(&out, "10.0%s", add_name ? " (Windows 10 or greater)" : "");
1453 break;
1454
1455 default:
1456 msg(M_NONFATAL, "Unknown Windows version: %d", version);
1457 buf_printf(&out, "0.0%s", add_name ? " (unknown)" : "");
1458 break;
1459 }
1460
1461 buf_printf(&out, ", ");
1462
1466
1467 buf_printf(&out, " executable");
1468
1469 if (host_arch != ARCH_NATIVE)
1470 {
1471 buf_printf(&out, " running on ");
1473 buf_printf(&out, " host");
1474 }
1475
1476 return (const char *)out.data;
1477}
1478
1479bool
1480send_msg_iservice(HANDLE pipe, const void *data, size_t size,
1481 ack_message_t *ack, const char *context)
1482{
1483 struct gc_arena gc = gc_new();
1484 DWORD len;
1485 bool ret = true;
1486
1487 if (!WriteFile(pipe, data, size, &len, NULL)
1488 || !ReadFile(pipe, ack, sizeof(*ack), &len, NULL))
1489 {
1490 msg(M_WARN, "%s: could not talk to service: %s [%lu]",
1491 context ? context : "Unknown",
1492 strerror_win32(GetLastError(), &gc), GetLastError());
1493 ret = false;
1494 }
1495
1496 gc_free(&gc);
1497 return ret;
1498}
1499
1500bool
1501get_openvpn_reg_value(const WCHAR *key, WCHAR *value, DWORD size)
1502{
1503 WCHAR reg_path[256];
1504 HKEY hkey;
1505 swprintf(reg_path, _countof(reg_path), L"SOFTWARE\\" PACKAGE_NAME);
1506
1507 LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1508 if (status != ERROR_SUCCESS)
1509 {
1510 return false;
1511 }
1512
1513 status = RegGetValueW(hkey, NULL, key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1514
1515 RegCloseKey(hkey);
1516
1517 return status == ERROR_SUCCESS;
1518}
1519
1520static void
1522{
1523 const WCHAR *ssl_fallback_dir = L"C:\\Windows\\System32";
1524
1525 WCHAR install_path[MAX_PATH] = { 0 };
1526 if (!get_openvpn_reg_value(NULL, install_path, _countof(install_path)))
1527 {
1528 /* if we cannot find installation path from the registry,
1529 * use Windows directory as a fallback
1530 */
1531 swprintf(install_path, _countof(install_path), L"%ls", ssl_fallback_dir);
1532 }
1533
1534 if ((install_path[wcslen(install_path) - 1]) == L'\\')
1535 {
1536 install_path[wcslen(install_path) - 1] = L'\0';
1537 }
1538
1539 static struct {
1540 WCHAR *name;
1541 WCHAR *value;
1542 } ossl_env[] = {
1543 {L"OPENSSL_CONF", L"openssl.cnf"},
1544 {L"OPENSSL_ENGINES", L"engines"},
1545 {L"OPENSSL_MODULES", L"modules"}
1546 };
1547
1548 for (size_t i = 0; i < SIZE(ossl_env); ++i)
1549 {
1550 size_t size = 0;
1551
1552 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1553 if (size == 0)
1554 {
1555 WCHAR val[MAX_PATH] = {0};
1556 swprintf(val, _countof(val), L"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1557 _wputenv_s(ossl_env[i].name, val);
1558 }
1559 }
1560}
1561
1562void
1563win32_sleep(const int n)
1564{
1565 if (n < 0)
1566 {
1567 return;
1568 }
1569
1570 /* Sleep() is not interruptible. Use a WAIT_OBJECT to catch signal */
1571
1573 {
1574 if (n > 0)
1575 {
1576 Sleep(n*1000);
1577 }
1578 return;
1579 }
1580
1581 update_time();
1582 time_t expire = now + n;
1583
1584 while (expire >= now)
1585 {
1586 DWORD status = WaitForSingleObject(win32_signal.in.read, (expire-now)*1000);
1587 if ((status == WAIT_OBJECT_0 && win32_signal_get(&win32_signal))
1588 || status == WAIT_TIMEOUT)
1589 {
1590 return;
1591 }
1592
1593 update_time();
1594
1595 if (status != WAIT_OBJECT_0) /* wait failed or some unexpected error ? */
1596 {
1597 if (expire > now)
1598 {
1599 Sleep((expire-now)*1000);
1600 }
1601 return;
1602 }
1603 }
1604}
1605
1606bool
1607plugin_in_trusted_dir(const WCHAR *plugin_path)
1608{
1609 /* UNC paths are not allowed */
1610 if (wcsncmp(plugin_path, L"\\\\", 2) == 0)
1611 {
1612 msg(M_WARN, "UNC paths for plugins are not allowed.");
1613 return false;
1614 }
1615
1616 WCHAR plugin_dir[MAX_PATH] = { 0 };
1617
1618 /* Attempt to retrieve the trusted plugin directory path from the registry,
1619 * using installation path as a fallback */
1620 if (!get_openvpn_reg_value(L"plugin_dir", plugin_dir, _countof(plugin_dir))
1621 && !get_openvpn_reg_value(NULL, plugin_dir, _countof(plugin_dir)))
1622 {
1623 msg(M_WARN, "Installation path could not be determined.");
1624 }
1625
1626 /* Get the system directory */
1627 WCHAR system_dir[MAX_PATH] = { 0 };
1628 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1629 {
1630 msg(M_NONFATAL | M_ERRNO, "Failed to get system directory.");
1631 }
1632
1633 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1634 {
1635 return false;
1636 }
1637
1638 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1639
1640 /* Normalize the plugin dir */
1641 if (wcslen(plugin_dir) > 0)
1642 {
1643 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1644 {
1645 msg(M_NONFATAL | M_ERRNO, "Failed to normalize plugin dir.");
1646 return false;
1647 }
1648 }
1649
1650 /* Check if the plugin path resides within the plugin/install directory */
1651 if ((wcslen(normalized_plugin_dir) > 0) && (wcsnicmp(normalized_plugin_dir,
1652 plugin_path, wcslen(normalized_plugin_dir)) == 0))
1653 {
1654 return true;
1655 }
1656
1657 /* Fallback to the system directory */
1658 return wcsnicmp(system_dir, plugin_path, wcslen(system_dir)) == 0;
1659}
1660
1661bool
1662protect_buffer_win32(char *buf, size_t len)
1663{
1664 bool ret;
1665 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1666 {
1667 msg(M_NONFATAL, "Error: Unable to encrypt memory: buffer size not a multiple of %d",
1668 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1669 return false;
1670 }
1671 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1672 if (!ret)
1673 {
1674 msg(M_NONFATAL | M_ERRNO, "Failed to encrypt memory.");
1675 }
1676 return ret;
1677}
1678
1679bool
1680unprotect_buffer_win32(char *buf, size_t len)
1681{
1682 bool ret;
1683 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1684 {
1685 msg(M_NONFATAL, "Error: Unable to decrypt memory: buffer size not a multiple of %d",
1686 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1687 return false;
1688 }
1689 ret = CryptUnprotectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1690 if (!ret)
1691 {
1692 msg(M_FATAL | M_ERRNO, "Failed to decrypt memory.");
1693 }
1694 return ret;
1695}
1696
1697#endif /* ifdef _WIN32 */
void free_buf(struct buffer *buf)
Definition buffer.c:183
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:240
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Definition buffer.c:1022
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:88
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...
Definition buffer.c:1041
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:649
#define CC_DOUBLE_QUOTE
double quote
Definition buffer.h:908
#define BSTR(buf)
Definition buffer.h:129
#define CC_ANY
any character
Definition buffer.h:883
#define CC_CRLF
carriage return or newline
Definition buffer.h:920
#define CC_SPACE
whitespace isspace()
Definition buffer.h:893
static void check_malloc_return(void *p)
Definition buffer.h:1103
static void gc_free(struct gc_arena *a)
Definition buffer.h:1033
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:891
static struct gc_arena gc_new(void)
Definition buffer.h:1025
#define SCRIPT_SECURITY_WARNING
Definition common.h:98
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:283
bool env_allowed(const char *str)
Definition env_set.c:413
#define D_SEMAPHORE_LOW
Definition errlevel.h:135
#define D_SEMAPHORE
Definition errlevel.h:136
#define D_LOW
Definition errlevel.h:97
#define M_INFO
Definition errlevel.h:55
static SERVICE_STATUS status
Definition interactive.c:53
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame)
Definition mtu.c:42
@ wfp_block_local
Definition openvpn-msg.h:68
@ wfp_block_dns
Definition openvpn-msg.h:69
@ msg_del_wfp_block
Definition openvpn-msg.h:42
@ msg_add_wfp_block
Definition openvpn-msg.h:41
#define CLEAR(x)
Definition basic.h:33
#define SIZE(x)
Definition basic.h:30
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition error.c:812
#define M_NOPREFIX
Definition error.h:97
#define M_FATAL
Definition error.h:89
#define M_NONFATAL
Definition error.h:90
#define dmsg(flags,...)
Definition error.h:148
#define M_ERR
Definition error.h:105
#define msg(flags,...)
Definition error.h:144
#define ASSERT(x)
Definition error.h:195
#define M_WARN
Definition error.h:91
#define M_ERRNO
Definition error.h:94
time_t now
Definition otime.c:34
static void update_time(void)
Definition otime.h:77
bool openvpn_execve_allowed(const unsigned int flags)
int script_security(void)
Definition run_command.c:43
#define SSEC_SCRIPTS
Definition run_command.h:33
#define OPENVPN_EXECVE_ERROR
Definition run_command.h:36
#define OPENVPN_EXECVE_NOT_ALLOWED
Definition run_command.h:37
void throw_signal(const int signum)
Throw a hard signal.
Definition sig.c:177
struct signal_info siginfo_static
Definition sig.c:45
Definition argv.h:35
char ** argv
Definition argv.h:39
Wrapper structure for dynamically allocated memory.
Definition buffer.h:61
uint8_t * data
Pointer to the allocated memory.
Definition buffer.h:68
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:66
Contains all state information for one tunnel.
Definition openvpn.h:474
char * string
Definition env_set.h:38
struct env_item * next
Definition env_set.h:39
struct env_item * list
Definition env_set.h:44
Packet geometry parameters.
Definition mtu.h:98
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:117
Container for unidirectional cipher and HMAC key material.
Definition crypto.h:152
socket_descriptor_t sd
Definition win32.h:110
long event_mask
Definition win32.h:111
struct rw_handle handle
Definition win32.h:109
OVERLAPPED overlapped
Definition win32.h:207
struct buffer buf_init
Definition win32.h:217
int iostate
Definition win32.h:206
HANDLE write
Definition win32.h:81
HANDLE read
Definition win32.h:80
SECURITY_ATTRIBUTES sa
Definition win32.h:64
SECURITY_DESCRIPTOR sd
Definition win32.h:65
const char * name
Definition win32.h:243
bool locked
Definition win32.h:244
HANDLE hand
Definition win32.h:245
volatile int signal_received
Definition sig.h:43
message_header_t header
DWORD console_mode_save
Definition win32.h:159
struct rw_handle in
Definition win32.h:158
bool console_mode_save_defined
Definition win32.h:160
bool saved
Definition win32.h:75
char old_window_title[256]
Definition win32.h:76
#define SOCKET_UNDEFINED
Definition syshead.h:437
SOCKET socket_descriptor_t
Definition syshead.h:439
static int socket_defined(const socket_descriptor_t sd)
Definition syshead.h:447
struct env_set * es
struct gc_arena gc
Definition test_ssl.c:155
int get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto)
Return interface metric value for the specified interface index.
Definition wfp_block.c:404
DWORD set_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, const ULONG metric)
Sets interface metric value for specified interface index.
Definition wfp_block.c:443
DWORD delete_wfp_block_filters(HANDLE engine_handle)
Definition wfp_block.c:379
DWORD add_wfp_block_filters(HANDLE *engine_handle, int index, const WCHAR *exe_path, wfp_block_msg_handler_t msg_handler, BOOL dns_only)
Definition wfp_block.c:185
#define WFP_BLOCK_IFACE_METRIC
Definition wfp_block.h:34
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
Definition win32-util.c:41
static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc)
Definition win32.c:947
static unsigned int keyboard_ir_to_key(INPUT_RECORD *ir)
Definition win32.c:559
void init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
Definition win32.c:223
static bool win_get_exe_path(PWCHAR path, DWORD size)
Definition win32.c:1144
void net_event_win32_init(struct net_event_win32 *ne)
Definition win32.c:324
void net_event_win32_close(struct net_event_win32 *ne)
Definition win32.c:375
void win32_signal_open(struct win32_signal *ws, int force, const char *exit_event_name, bool exit_event_initial_state)
Definition win32.c:453
void uninit_win32(void)
Definition win32.c:122
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state)
Definition win32.c:171
bool win_wfp_block(const NET_IFINDEX index, const HANDLE msg_channel, BOOL dns_only)
Definition win32.c:1211
void window_title_generate(const char *title)
Definition win32.c:730
void set_win_sys_path(const char *newpath, struct env_set *es)
Definition win32.c:1120
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
Definition win32.c:277
void window_title_clear(struct window_title *wt)
Definition win32.c:698
static unsigned int win32_keyboard_get(struct win32_signal *ws)
Definition win32.c:577
bool get_openvpn_reg_value(const WCHAR *key, WCHAR *value, DWORD size)
Fetches a registry value for OpenVPN registry key.
Definition win32.c:1501
static bool pause_exit_enabled
Definition win32.c:74
void window_title_save(struct window_title *wt)
Definition win32.c:704
void semaphore_clear(struct semaphore *s)
Definition win32.c:746
int win32_version_info(void)
Definition win32.c:1287
bool unprotect_buffer_win32(char *buf, size_t len)
Decrypt a previously encrypted region of memory using CryptUnProtectMemory() with access restricted t...
Definition win32.c:1680
bool protect_buffer_win32(char *buf, size_t len)
Encrypt a region of memory using CryptProtectMemory() with access restricted to the current process.
Definition win32.c:1662
bool plugin_in_trusted_dir(const WCHAR *plugin_path)
Checks if a plugin is located in a trusted directory.
Definition win32.c:1607
const char * win32_version_string(struct gc_arena *gc, bool add_name)
Definition win32.c:1424
void semaphore_close(struct semaphore *s)
Definition win32.c:826
static bool keyboard_input_available(struct win32_signal *ws)
Definition win32.c:544
void net_event_win32_reset_write(struct net_event_win32 *ne)
Definition win32.c:340
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds)
Definition win32.c:776
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
Definition win32.c:331
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
Definition win32.c:1260
void fork_to_self(const char *cmdline)
Definition win32.c:1073
static char * env_block(const struct env_set *es)
Definition win32.c:886
static void win_trigger_event(struct win32_signal *ws)
Definition win32.c:393
char * overlapped_io_state_ascii(const struct overlapped_io *o)
Definition win32.c:202
static int tap_metric_v4
Definition win32.c:63
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
Definition win32.c:1480
void overlapped_io_close(struct overlapped_io *o)
Definition win32.c:189
void netcmd_semaphore_release(void)
Definition win32.c:874
void win32_sleep(const int n)
Definition win32.c:1563
static char * win_sys_path
Definition win32.c:100
static bool win_wfp_block_service(bool add, bool dns_only, int index, const HANDLE pipe)
Definition win32.c:1174
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
Definition win32.c:1001
static void win32_print_arch(arch_t arch, struct buffer *out)
Definition win32.c:1398
static void win32_get_arch(arch_t *process_arch, arch_t *host_arch)
Definition win32.c:1331
void semaphore_release(struct semaphore *s)
Definition win32.c:810
void init_win32(void)
Definition win32.c:109
static HANDLE m_hEngineHandle
Definition win32.c:58
void set_win_sys_path_via_env(struct env_set *es)
Definition win32.c:1128
static void set_openssl_env_vars(void)
Set OpenSSL environment variables to a safe directory.
Definition win32.c:1521
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd)
Definition win32.c:262
static bool WINAPI win_ctrl_handler(DWORD signum)
Definition win32.c:419
void window_title_restore(const struct window_title *wt)
Definition win32.c:721
struct semaphore netcmd_semaphore
Definition win32.c:95
char * get_win_sys_path(void)
Definition win32.c:1113
bool win32_service_interrupt(struct win32_signal *ws)
Definition win32.c:625
static int tap_metric_v6
Definition win32.c:64
void win32_pause(struct win32_signal *ws)
Definition win32.c:683
static void win_wfp_msg_handler(DWORD err, const char *msg)
Definition win32.c:1156
static struct WSAData wsa_state
Definition win32.c:69
void netcmd_semaphore_init(void)
Definition win32.c:846
void netcmd_semaphore_lock(void)
Definition win32.c:858
void win32_signal_close(struct win32_signal *ws)
Definition win32.c:605
void win32_signal_clear(struct win32_signal *ws)
Definition win32.c:447
int win32_signal_get(struct win32_signal *ws)
Definition win32.c:639
void net_event_win32_reset(struct net_event_win32 *ne)
Definition win32.c:358
void netcmd_semaphore_close(void)
Definition win32.c:852
void set_pause_exit_win32(void)
Definition win32.c:146
arch_t
Definition win32.c:1322
@ ARCH_AMD64
Definition win32.c:1324
@ ARCH_NATIVE
Definition win32.c:1326
@ ARCH_X86
Definition win32.c:1323
@ ARCH_ARM64
Definition win32.c:1325
@ ARCH_UNKNOWN
Definition win32.c:1327
bool init_security_attributes_allow_all(struct security_attributes *obj)
Definition win32.c:152
void semaphore_open(struct semaphore *s, const char *name)
Definition win32.c:752
void net_event_win32_stop(struct net_event_win32 *ne)
Definition win32.c:364
static bool net_event_win32_defined(const struct net_event_win32 *ne)
Definition win32.h:127
#define WIN_8_1
Definition win32.h:299
#define SYS_PATH_ENV_VAR_NAME
Definition win32.h:38
#define WSO_MODE_UNDEF
Definition win32.h:154
#define NE32_PERSIST_EVENT
Definition win32.h:88
#define IOSTATE_IMMEDIATE_RETURN
Definition win32.h:205
#define WSO_MODE_SERVICE
Definition win32.h:155
#define WSO_MODE_CONSOLE
Definition win32.h:156
#define IOSTATE_INITIAL
Definition win32.h:203
#define IOSTATE_QUEUED
Definition win32.h:204
#define NE32_WRITE_EVENT
Definition win32.h:89
#define WSO_FORCE_SERVICE
Definition win32.h:170
#define WIN_10
Definition win32.h:300
#define WIN_7
Definition win32.h:297
#define WIN_XP
Definition win32.h:295
#define WSO_FORCE_CONSOLE
Definition win32.h:171
#define WSO_NOFORCE
Definition win32.h:169
#define WIN_VISTA
Definition win32.h:296
#define WIN_8
Definition win32.h:298
#define HANDLE_DEFINED(h)
Definition win32.h:68