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