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
518 if (siginfo_static.signal_received == SIGTERM)
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 }
769 return (siginfo_static.signal_received);
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
938{
939 semaphore_open(&netcmd_semaphore, PACKAGE "_netcmd");
940}
941
942void
947
948void
950{
951 const int timeout_seconds = 600;
952
953 if (!netcmd_semaphore.hand)
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
1045 if (a && a->argv[0])
1046 {
1047 if (openvpn_execve_allowed(flags))
1048 {
1049 struct gc_arena gc = gc_new();
1050 STARTUPINFOW start_info;
1051 PROCESS_INFORMATION proc_info;
1052
1053 char *env = env_block(es);
1054 WCHAR *cl = wide_cmd_line(a, &gc);
1055 WCHAR *cmd = wide_string(a->argv[0], &gc);
1056
1057 /* this allows console programs to run, and is ignored otherwise */
1058 DWORD proc_flags = CREATE_NO_WINDOW;
1059
1060 CLEAR(start_info);
1061 CLEAR(proc_info);
1062
1063 /* fill in STARTUPINFO struct */
1064 GetStartupInfoW(&start_info);
1065 start_info.cb = sizeof(start_info);
1066 start_info.dwFlags = STARTF_USESHOWWINDOW;
1067 start_info.wShowWindow = SW_HIDE;
1068
1069 if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info,
1070 &proc_info))
1071 {
1072 DWORD exit_status = 0;
1073 CloseHandle(proc_info.hThread);
1074 WaitForSingleObject(proc_info.hProcess, INFINITE);
1075 if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1076 {
1077 ret = (int)exit_status;
1078 }
1079 else
1080 {
1081 msg(M_WARN | M_ERRNO, "openvpn_execve: GetExitCodeProcess %ls failed", cmd);
1082 }
1083 CloseHandle(proc_info.hProcess);
1084 }
1085 else
1086 {
1087 msg(M_WARN | M_ERRNO, "openvpn_execve: CreateProcess %ls failed", cmd);
1088 }
1089 free(env);
1090 gc_free(&gc);
1091 }
1092 else
1093 {
1094 static bool exec_warn = false;
1095
1097 if (!exec_warn && (script_security() < SSEC_SCRIPTS))
1098 {
1100 exec_warn = true;
1101 }
1102 }
1103 }
1104 else
1105 {
1106 msg(M_WARN, "openvpn_execve: called with empty argv");
1107 }
1108 return ret;
1109}
1110
1111/*
1112 * call ourself in another process
1113 */
1114void
1115fork_to_self(const char *cmdline)
1116{
1117 STARTUPINFO start_info;
1118 PROCESS_INFORMATION proc_info;
1119 char self_exe[256];
1120 char *cl = string_alloc(cmdline, NULL);
1121 DWORD status;
1122
1123 CLEAR(start_info);
1124 CLEAR(proc_info);
1125 CLEAR(self_exe);
1126
1127 status = GetModuleFileName(NULL, self_exe, sizeof(self_exe));
1128 if (status == 0 || status == sizeof(self_exe))
1129 {
1130 msg(M_WARN | M_ERRNO,
1131 "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1132 goto done;
1133 }
1134
1135 /* fill in STARTUPINFO struct */
1136 GetStartupInfo(&start_info);
1137 start_info.cb = sizeof(start_info);
1138 start_info.dwFlags = STARTF_USESHOWWINDOW;
1139 start_info.wShowWindow = SW_HIDE;
1140
1141 if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1142 {
1143 CloseHandle(proc_info.hThread);
1144 CloseHandle(proc_info.hProcess);
1145 }
1146 else
1147 {
1148 msg(M_WARN | M_ERRNO, "fork_to_self: CreateProcess failed: %s", cmdline);
1149 }
1150
1151done:
1152 free(cl);
1153}
1154
1155char *
1157{
1159 return win_sys_path;
1160}
1161
1162void
1163set_win_sys_path(const char *newpath, struct env_set *es)
1164{
1165 free(win_sys_path);
1166 win_sys_path = string_alloc(newpath, NULL);
1167 setenv_str(es, SYS_PATH_ENV_VAR_NAME, win_sys_path); /* route.exe needs this */
1168}
1169
1170void
1172{
1173 char buf[256];
1174 DWORD status = GetEnvironmentVariable(SYS_PATH_ENV_VAR_NAME, buf, sizeof(buf));
1175 if (!status)
1176 {
1177 msg(M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1178 }
1179 if (status > sizeof(buf) - 1)
1180 {
1181 msg(M_FATAL, "String overflow attempting to read environmental variable %s",
1183 }
1184 set_win_sys_path(buf, es);
1185}
1186
1187static bool
1188win_get_exe_path(PWCHAR path, DWORD size)
1189{
1190 DWORD status = GetModuleFileNameW(NULL, path, size);
1191 if (status == 0 || status == size)
1192 {
1193 msg(M_WARN | M_ERRNO, "cannot get executable path");
1194 return false;
1195 }
1196 return true;
1197}
1198
1199static void
1200win_wfp_msg_handler(DWORD err, const char *msg)
1201{
1202 struct gc_arena gc = gc_new();
1203
1204 if (err == 0)
1205 {
1206 msg(M_INFO, "%s", msg);
1207 }
1208 else
1209 {
1210 msg(M_WARN, "Error in WFP: %s : %s [status=0x%lx]", msg, strerror_win32(err, &gc), err);
1211 }
1212
1213 gc_free(&gc);
1214}
1215
1216static bool
1217win_wfp_block_service(bool add, bool dns_only, int index, const HANDLE pipe)
1218{
1219 bool ret = false;
1220 ack_message_t ack;
1221 struct gc_arena gc = gc_new();
1222
1223 wfp_block_message_t data = { .header = { (add ? msg_add_wfp_block : msg_del_wfp_block),
1224 sizeof(wfp_block_message_t), 0 },
1225 .flags = dns_only ? wfp_block_dns : wfp_block_local,
1226 .iface = { .index = index, .name = "" } };
1227
1228 if (!send_msg_iservice(pipe, &data, sizeof(data), &ack, "WFP block"))
1229 {
1230 goto out;
1231 }
1232
1233 if (ack.error_number != NO_ERROR)
1234 {
1235 msg(M_WARN,
1236 "WFP block: %s block filters using service failed: %s [status=0x%x if_index=%lu]",
1237 (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), ack.error_number,
1238 data.iface.index);
1239 goto out;
1240 }
1241
1242 ret = true;
1243 msg(M_INFO, "%s WFP block filters using service succeeded.", (add ? "Adding" : "Deleting"));
1244out:
1245 gc_free(&gc);
1246 return ret;
1247}
1248
1249bool
1250win_wfp_block(const NET_IFINDEX index, const HANDLE msg_channel, BOOL dns_only)
1251{
1252 WCHAR openvpnpath[MAX_PATH];
1253 bool ret = false;
1254 DWORD status;
1255
1256 if (msg_channel)
1257 {
1258 dmsg(D_LOW, "Using service to add WFP block filters");
1259 ret = win_wfp_block_service(true, dns_only, index, msg_channel);
1260 goto out;
1261 }
1262
1263 ret = win_get_exe_path(openvpnpath, _countof(openvpnpath));
1264 if (ret == false)
1265 {
1266 goto out;
1267 }
1268
1269 status =
1270 add_wfp_block_filters(&m_hEngineHandle, index, openvpnpath, win_wfp_msg_handler, dns_only);
1271 if (status == 0)
1272 {
1273 int is_auto = 0;
1274 tap_metric_v4 = get_interface_metric(index, AF_INET, &is_auto);
1275 if (is_auto)
1276 {
1277 tap_metric_v4 = 0;
1278 }
1279 tap_metric_v6 = get_interface_metric(index, AF_INET6, &is_auto);
1280 if (is_auto)
1281 {
1282 tap_metric_v6 = 0;
1283 }
1285 if (!status)
1286 {
1288 }
1289 }
1290
1291 ret = (status == 0);
1292
1293out:
1294
1295 return ret;
1296}
1297
1298bool
1299win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
1300{
1301 dmsg(D_LOW, "Uninitializing WFP");
1302
1303 if (msg_channel)
1304 {
1305 msg(D_LOW, "Using service to delete WFP block filters");
1306 win_wfp_block_service(false, false, index, msg_channel);
1307 }
1308 else
1309 {
1311 m_hEngineHandle = NULL;
1312 if (tap_metric_v4 >= 0)
1313 {
1314 set_interface_metric(index, AF_INET, tap_metric_v4);
1315 }
1316 if (tap_metric_v6 >= 0)
1317 {
1318 set_interface_metric(index, AF_INET6, tap_metric_v6);
1319 }
1320 }
1321
1322 return true;
1323}
1324
1325typedef enum
1326{
1330 ARCH_NATIVE, /* means no emulation, makes sense for host arch */
1332} arch_t;
1333
1334static void
1335win32_get_arch(arch_t *process_arch, arch_t *host_arch)
1336{
1337 *process_arch = ARCH_UNKNOWN;
1338 *host_arch = ARCH_NATIVE;
1339
1340 typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
1341 is_wow64_process2_t is_wow64_process2 =
1342 (is_wow64_process2_t)GetProcAddress(GetModuleHandle("Kernel32.dll"), "IsWow64Process2");
1343
1344#ifdef _ARM64_
1345 *process_arch = ARCH_ARM64;
1346#elif defined(_WIN64)
1347 *process_arch = ARCH_AMD64;
1348 if (is_wow64_process2)
1349 {
1350 /* this could be amd64 on arm64 */
1351 USHORT process_machine = 0;
1352 USHORT native_machine = 0;
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 USHORT process_machine = 0;
1366 USHORT native_machine = 0;
1367 BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
1368 if (is_wow64)
1369 {
1370 switch (native_machine)
1371 {
1372 case IMAGE_FILE_MACHINE_ARM64:
1373 *host_arch = ARCH_ARM64;
1374 break;
1375
1376 case IMAGE_FILE_MACHINE_AMD64:
1377 *host_arch = ARCH_AMD64;
1378 break;
1379
1380 default:
1381 *host_arch = ARCH_UNKNOWN;
1382 break;
1383 }
1384 }
1385 }
1386 else
1387 {
1388 BOOL w64 = FALSE;
1389 BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
1390 if (is_wow64)
1391 {
1392 /* we are unable to differentiate between arm64 and amd64
1393 * machines here, so assume we are running on amd64 */
1394 *host_arch = ARCH_AMD64;
1395 }
1396 }
1397#endif /* _ARM64_ */
1398}
1399
1400static void
1402{
1403 switch (arch)
1404 {
1405 case ARCH_X86:
1406 buf_printf(out, "x86");
1407 break;
1408
1409 case ARCH_AMD64:
1410 buf_printf(out, "amd64");
1411 break;
1412
1413 case ARCH_ARM64:
1414 buf_printf(out, "arm64");
1415 break;
1416
1417 case ARCH_UNKNOWN:
1418 buf_printf(out, "(unknown)");
1419 break;
1420
1421 default:
1422 break;
1423 }
1424}
1425
1426typedef LONG(WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
1427
1428const char *
1430{
1431 HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
1432 if (!hMod)
1433 {
1434 return "N/A";
1435 }
1436
1437 RtlGetVersionPtr fn = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion");
1438 if (!fn)
1439 {
1440 return "N/A";
1441 }
1442
1443 RTL_OSVERSIONINFOW rovi = { 0 };
1444 rovi.dwOSVersionInfoSize = sizeof(rovi);
1445 if (fn(&rovi) != 0)
1446 {
1447 return "N/A";
1448 }
1449
1450 struct buffer out = alloc_buf_gc(256, gc);
1451
1452 buf_printf(&out, "%lu.%lu.%lu", rovi.dwMajorVersion, rovi.dwMinorVersion, rovi.dwBuildNumber);
1453
1454 buf_printf(&out, ",");
1455
1456 arch_t process_arch, host_arch;
1457 win32_get_arch(&process_arch, &host_arch);
1458 win32_print_arch(process_arch, &out);
1459
1460 if (host_arch != ARCH_NATIVE)
1461 {
1462 buf_printf(&out, " running on ");
1463 win32_print_arch(host_arch, &out);
1464 buf_printf(&out, " host");
1465 }
1466
1467 return (const char *)out.data;
1468}
1469
1470bool
1471send_msg_iservice(HANDLE pipe, const void *data, DWORD size, ack_message_t *ack,
1472 const char *context)
1473{
1474 struct gc_arena gc = gc_new();
1475 DWORD len;
1476 bool ret = true;
1477
1478 if (!WriteFile(pipe, data, size, &len, NULL) || !ReadFile(pipe, ack, sizeof(*ack), &len, NULL))
1479 {
1480 msg(M_WARN, "%s: could not talk to service: %s [%lu]", context ? context : "Unknown",
1481 strerror_win32(GetLastError(), &gc), GetLastError());
1482 ret = false;
1483 }
1484
1485 gc_free(&gc);
1486 return ret;
1487}
1488
1489bool
1490get_openvpn_reg_value(const WCHAR *key, WCHAR *value, DWORD size)
1491{
1492 WCHAR reg_path[256];
1493 HKEY hkey;
1494 swprintf(reg_path, _countof(reg_path), L"SOFTWARE\\" PACKAGE_NAME);
1495
1496 LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hkey);
1497 if (status != ERROR_SUCCESS)
1498 {
1499 return false;
1500 }
1501
1502 status = RegGetValueW(hkey, NULL, key, RRF_RT_REG_SZ, NULL, (LPBYTE)value, &size);
1503
1504 RegCloseKey(hkey);
1505
1506 return status == ERROR_SUCCESS;
1507}
1508
1509static void
1511{
1512 WCHAR install_path[MAX_PATH] = { 0 };
1513 if (!get_openvpn_reg_value(NULL, install_path, _countof(install_path)))
1514 {
1515 const WCHAR *ssl_fallback_dir = L"C:\\Windows\\System32";
1516 /* if we cannot find installation path from the registry,
1517 * use Windows directory as a fallback
1518 */
1519 swprintf(install_path, _countof(install_path), L"%ls", ssl_fallback_dir);
1520 }
1521
1522 if ((install_path[wcslen(install_path) - 1]) == L'\\')
1523 {
1524 install_path[wcslen(install_path) - 1] = L'\0';
1525 }
1526
1527 static struct
1528 {
1529 WCHAR *name;
1530 WCHAR *value;
1531 } ossl_env[] = { { L"OPENSSL_CONF", L"openssl.cnf" },
1532 { L"OPENSSL_ENGINES", L"engines" },
1533 { L"OPENSSL_MODULES", L"modules" } };
1534
1535 for (size_t i = 0; i < SIZE(ossl_env); ++i)
1536 {
1537 size_t size = 0;
1538
1539 _wgetenv_s(&size, NULL, 0, ossl_env[i].name);
1540 if (size == 0)
1541 {
1542 WCHAR val[MAX_PATH] = { 0 };
1543 swprintf(val, _countof(val), L"%ls\\ssl\\%ls", install_path, ossl_env[i].value);
1544 _wputenv_s(ossl_env[i].name, val);
1545 }
1546 }
1547}
1548
1549void
1550win32_sleep(const int n)
1551{
1552 if (n < 0)
1553 {
1554 return;
1555 }
1556
1557 /* Sleep() is not interruptible. Use a WAIT_OBJECT to catch signal */
1558
1560 {
1561 if (n > 0)
1562 {
1563 Sleep(n * 1000);
1564 }
1565 return;
1566 }
1567
1568 update_time();
1569 time_t expire = now + n;
1570
1571 while (expire >= now)
1572 {
1573 DWORD wait_ms = (DWORD)((expire - now) * 1000);
1574 DWORD status = WaitForSingleObject(win32_signal.in.read, wait_ms);
1575 if ((status == WAIT_OBJECT_0 && win32_signal_get(&win32_signal)) || status == WAIT_TIMEOUT)
1576 {
1577 return;
1578 }
1579
1580 update_time();
1581
1582 if (status != WAIT_OBJECT_0) /* wait failed or some unexpected error ? */
1583 {
1584 if (expire > now)
1585 {
1586 Sleep((DWORD)((expire - now) * 1000));
1587 }
1588 return;
1589 }
1590 }
1591}
1592
1593bool
1594plugin_in_trusted_dir(const WCHAR *plugin_path)
1595{
1596 /* UNC paths are not allowed */
1597 if (wcsncmp(plugin_path, L"\\\\", 2) == 0)
1598 {
1599 msg(M_WARN, "UNC paths for plugins are not allowed.");
1600 return false;
1601 }
1602
1603 WCHAR plugin_dir[MAX_PATH] = { 0 };
1604
1605 /* Attempt to retrieve the trusted plugin directory path from the registry,
1606 * using installation path as a fallback */
1607 if (!get_openvpn_reg_value(L"plugin_dir", plugin_dir, _countof(plugin_dir))
1608 && !get_openvpn_reg_value(NULL, plugin_dir, _countof(plugin_dir)))
1609 {
1610 msg(M_WARN, "Installation path could not be determined.");
1611 }
1612
1613 /* Get the system directory */
1614 WCHAR system_dir[MAX_PATH] = { 0 };
1615 if (GetSystemDirectoryW(system_dir, _countof(system_dir)) == 0)
1616 {
1617 msg(M_NONFATAL | M_ERRNO, "Failed to get system directory.");
1618 }
1619
1620 if ((wcslen(plugin_dir) == 0) && (wcslen(system_dir) == 0))
1621 {
1622 return false;
1623 }
1624
1625 WCHAR normalized_plugin_dir[MAX_PATH] = { 0 };
1626
1627 /* Normalize the plugin dir */
1628 if (wcslen(plugin_dir) > 0)
1629 {
1630 if (!GetFullPathNameW(plugin_dir, MAX_PATH, normalized_plugin_dir, NULL))
1631 {
1632 msg(M_NONFATAL | M_ERRNO, "Failed to normalize plugin dir.");
1633 return false;
1634 }
1635 }
1636
1637 /* Check if the plugin path resides within the plugin/install directory */
1638 if (win_path_in_dir(plugin_path, normalized_plugin_dir))
1639 {
1640 return true;
1641 }
1642
1643 /* Fallback to the system directory */
1644 return win_path_in_dir(plugin_path, system_dir);
1645}
1646
1647bool
1648protect_buffer_win32(char *buf, DWORD len)
1649{
1650 bool ret;
1651 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1652 {
1653 msg(M_NONFATAL, "Error: Unable to encrypt memory: buffer size not a multiple of %d",
1654 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1655 return false;
1656 }
1657 ret = CryptProtectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1658 if (!ret)
1659 {
1660 msg(M_NONFATAL | M_ERRNO, "Failed to encrypt memory.");
1661 }
1662 return ret;
1663}
1664
1665bool
1666unprotect_buffer_win32(char *buf, DWORD len)
1667{
1668 bool ret;
1669 if (len % CRYPTPROTECTMEMORY_BLOCK_SIZE)
1670 {
1671 msg(M_NONFATAL, "Error: Unable to decrypt memory: buffer size not a multiple of %d",
1672 CRYPTPROTECTMEMORY_BLOCK_SIZE);
1673 return false;
1674 }
1675 ret = CryptUnprotectMemory(buf, len, CRYPTPROTECTMEMORY_SAME_PROCESS);
1676 if (!ret)
1677 {
1678 msg(M_FATAL | M_ERRNO, "Failed to decrypt memory.");
1679 }
1680 return ret;
1681}
1682
1683#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:157
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
Definition buffer.h:2146
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1976
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1960
#define SCRIPT_SECURITY_WARNING
Definition common.h:99
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:305
bool env_allowed(const char *str)
Definition env_set.c:430
#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:164
#define M_ERR
Definition error.h:106
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:221
#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
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
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 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:249
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:1188
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:1250
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:1163
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:1490
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:1648
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:1594
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:1666
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:1299
void fork_to_self(const char *cmdline)
Definition win32.c:1115
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:1550
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:1217
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:1401
static void win32_get_arch(arch_t *process_arch, arch_t *host_arch)
Definition win32.c:1335
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:1171
static void set_openssl_env_vars(void)
Set OpenSSL environment variables to a safe directory.
Definition win32.c:1510
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:1156
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:1200
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:1429
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:1471
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:1326
@ ARCH_AMD64
Definition win32.c:1328
@ ARCH_NATIVE
Definition win32.c:1330
@ ARCH_X86
Definition win32.c:1327
@ ARCH_ARM64
Definition win32.c:1329
@ ARCH_UNKNOWN
Definition win32.c:1331
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:1426
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