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