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