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-2018 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * Win32-specific OpenVPN code, targeted at the mingw
26  * development environment.
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #elif defined(_MSC_VER)
32 #include "config-msvc.h"
33 #endif
34 
35 #include "syshead.h"
36 
37 #ifdef _WIN32
38 
39 #include "buffer.h"
40 #include "error.h"
41 #include "mtu.h"
42 #include "run_command.h"
43 #include "sig.h"
44 #include "win32-util.h"
45 #include "win32.h"
46 #include "openvpn-msg.h"
47 
48 #include "memdbg.h"
49 
50 #ifdef HAVE_VERSIONHELPERS_H
51 #include <versionhelpers.h>
52 #else
53 #include "compat-versionhelpers.h"
54 #endif
55 
56 #include "block_dns.h"
57 
58 /*
59  * WFP handle
60  */
61 static HANDLE m_hEngineHandle = NULL; /* GLOBAL */
62 
63 /*
64  * TAP adapter original metric value
65  */
66 static int tap_metric_v4 = -1; /* GLOBAL */
67 static int tap_metric_v6 = -1; /* GLOBAL */
68 
69 /*
70  * Windows internal socket API state (opaque).
71  */
72 static struct WSAData wsa_state; /* GLOBAL */
73 
74 /*
75  * Should we call win32_pause() on program exit?
76  */
77 static bool pause_exit_enabled = false; /* GLOBAL */
78 
79 /*
80  * win32_signal is used to get input from the keyboard
81  * if we are running in a console, or get input from an
82  * event object if we are running as a service.
83  */
84 
85 struct win32_signal win32_signal; /* GLOBAL */
86 
87 /*
88  * Save our old window title so we can restore
89  * it on exit.
90  */
91 struct window_title window_title; /* GLOBAL*/
92 
93 /*
94  * Special global semaphore used to protect network
95  * shell commands from simultaneous instantiation.
96  */
97 
98 struct semaphore netcmd_semaphore; /* GLOBAL */
99 
100 /*
101  * Windows system pathname such as c:\windows
102  */
103 static char *win_sys_path = NULL; /* GLOBAL */
104 
105 void
107 {
108  if (WSAStartup(0x0101, &wsa_state))
109  {
110  msg(M_ERR, "WSAStartup failed");
111  }
114 }
115 
116 void
118 {
120  if (pause_exit_enabled)
121  {
123  {
124  struct win32_signal w;
125  win32_signal_open(&w, WSO_FORCE_CONSOLE, NULL, false);
126  win32_pause(&w);
127  win32_signal_close(&w);
128  }
129  else
130  {
132  }
133  }
136  WSACleanup();
138 }
139 
140 void
142 {
143  pause_exit_enabled = true;
144 }
145 
146 bool
148 {
149  CLEAR(*obj);
150 
151  obj->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
152  obj->sa.lpSecurityDescriptor = &obj->sd;
153  obj->sa.bInheritHandle = FALSE;
154  if (!InitializeSecurityDescriptor(&obj->sd, SECURITY_DESCRIPTOR_REVISION))
155  {
156  return false;
157  }
158  if (!SetSecurityDescriptorDacl(&obj->sd, TRUE, NULL, FALSE))
159  {
160  return false;
161  }
162  return true;
163 }
164 
165 void
167  const struct frame *frame,
168  BOOL event_state,
169  bool tuntap_buffer) /* if true: tuntap buffer, if false: socket buffer */
170 {
171  CLEAR(*o);
172 
173  /* manual reset event, initially set according to event_state */
174  o->overlapped.hEvent = CreateEvent(NULL, TRUE, event_state, NULL);
175  if (o->overlapped.hEvent == NULL)
176  {
177  msg(M_ERR, "Error: overlapped_io_init: CreateEvent failed");
178  }
179 
180  /* allocate buffer for overlapped I/O */
181  alloc_buf_sock_tun(&o->buf_init, frame, tuntap_buffer, 0);
182 }
183 
184 void
186 {
187  if (o->overlapped.hEvent)
188  {
189  if (!CloseHandle(o->overlapped.hEvent))
190  {
191  msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on overlapped I/O event object");
192  }
193  }
194  free_buf(&o->buf_init);
195 }
196 
197 char *
199 {
200  switch (o->iostate)
201  {
202  case IOSTATE_INITIAL:
203  return "0";
204 
205  case IOSTATE_QUEUED:
206  return "Q";
207 
209  return "1";
210  }
211  return "?";
212 }
213 
214 /*
215  * Event-based notification of network events
216  */
217 
218 void
219 init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
220 {
221  /* manual reset events, initially set to unsignaled */
222 
223  /* initialize write event */
224  if (!(flags & NE32_PERSIST_EVENT) || !event->write)
225  {
226  if (flags & NE32_WRITE_EVENT)
227  {
228  event->write = CreateEvent(NULL, TRUE, FALSE, NULL);
229  if (event->write == NULL)
230  {
231  msg(M_ERR, "Error: init_net_event_win32: CreateEvent (write) failed");
232  }
233  }
234  else
235  {
236  event->write = NULL;
237  }
238  }
239 
240  /* initialize read event */
241  if (!(flags & NE32_PERSIST_EVENT) || !event->read)
242  {
243  event->read = CreateEvent(NULL, TRUE, FALSE, NULL);
244  if (event->read == NULL)
245  {
246  msg(M_ERR, "Error: init_net_event_win32: CreateEvent (read) failed");
247  }
248  }
249 
250  /* setup network events to change read event state */
251  if (WSAEventSelect(sd, event->read, network_events) != 0)
252  {
253  msg(M_FATAL | M_ERRNO, "Error: init_net_event_win32: WSAEventSelect call failed");
254  }
255 }
256 
257 long
259 {
260  WSANETWORKEVENTS wne;
261  if (WSAEnumNetworkEvents(sd, event->read, &wne) != 0)
262  {
263  msg(M_FATAL | M_ERRNO, "Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
264  return 0; /* NOTREACHED */
265  }
266  else
267  {
268  return wne.lNetworkEvents;
269  }
270 }
271 
272 void
274 {
275  if (event->read)
276  {
277  if (socket_defined(sd))
278  {
279  if (WSAEventSelect(sd, event->read, 0) != 0)
280  {
281  msg(M_WARN | M_ERRNO, "Warning: close_net_event_win32: WSAEventSelect call failed");
282  }
283  }
284  if (!ResetEvent(event->read))
285  {
286  msg(M_WARN | M_ERRNO, "Warning: ResetEvent (read) failed in close_net_event_win32");
287  }
288  if (!(flags & NE32_PERSIST_EVENT))
289  {
290  if (!CloseHandle(event->read))
291  {
292  msg(M_WARN | M_ERRNO, "Warning: CloseHandle (read) failed in close_net_event_win32");
293  }
294  event->read = NULL;
295  }
296  }
297 
298  if (event->write)
299  {
300  if (!ResetEvent(event->write))
301  {
302  msg(M_WARN | M_ERRNO, "Warning: ResetEvent (write) failed in close_net_event_win32");
303  }
304  if (!(flags & NE32_PERSIST_EVENT))
305  {
306  if (!CloseHandle(event->write))
307  {
308  msg(M_WARN | M_ERRNO, "Warning: CloseHandle (write) failed in close_net_event_win32");
309  }
310  event->write = NULL;
311  }
312  }
313 }
314 
315 /*
316  * struct net_event_win32
317  */
318 
319 void
321 {
322  CLEAR(*ne);
323  ne->sd = SOCKET_UNDEFINED;
324 }
325 
326 void
327 net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
328 {
329  ASSERT(!socket_defined(ne->sd));
330  ne->sd = sd;
331  ne->event_mask = 0;
333 }
334 
335 void
337 {
338  BOOL status;
339  if (ne->event_mask & FD_WRITE)
340  {
341  status = SetEvent(ne->handle.write);
342  }
343  else
344  {
345  status = ResetEvent(ne->handle.write);
346  }
347  if (!status)
348  {
349  msg(M_WARN | M_ERRNO, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
350  }
351 }
352 
353 void
355 {
356  ne->event_mask |= reset_net_event_win32(&ne->handle, ne->sd);
357 }
358 
359 void
361 {
362  if (net_event_win32_defined(ne))
363  {
365  }
366  ne->sd = SOCKET_UNDEFINED;
367  ne->event_mask = 0;
368 }
369 
370 void
372 {
373  if (net_event_win32_defined(ne))
374  {
375  close_net_event_win32(&ne->handle, ne->sd, 0);
376  }
378 }
379 
380 /*
381  * Simulate *nix signals on Windows.
382  *
383  * Two modes:
384  * (1) Console mode -- map keyboard function keys to signals
385  * (2) Service mode -- map Windows event object to SIGTERM
386  */
387 
388 static void
390 {
391  if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read))
392  {
393  SetEvent(ws->in.read);
394  }
395  else /* generate a key-press event */
396  {
397  DWORD tmp;
398  INPUT_RECORD ir;
399  HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
400 
401  CLEAR(ir);
402  ir.EventType = KEY_EVENT;
403  ir.Event.KeyEvent.bKeyDown = true;
404  if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
405  {
406  msg(M_WARN|M_ERRNO, "WARN: win_trigger_event: WriteConsoleInput");
407  }
408  }
409 }
410 
411 /*
412  * Callback to handle console ctrl events
413  */
414 static bool WINAPI
415 win_ctrl_handler(DWORD signum)
416 {
417  msg(D_LOW, "win_ctrl_handler: signal received (code=%lu)", (unsigned long) signum);
418 
420  {
421  return true;
422  }
423 
424  switch (signum)
425  {
426  case CTRL_C_EVENT:
427  case CTRL_BREAK_EVENT:
429  /* trigget the win32_signal to interrupt the event loop */
431  return true;
432  break;
433 
434  default:
435  msg(D_LOW, "win_ctrl_handler: signal (code=%lu) not handled", (unsigned long) signum);
436  break;
437  }
438  /* pass all other signals to the next handler */
439  return false;
440 }
441 
442 void
444 {
445  CLEAR(*ws);
446 }
447 
448 void
450  int force,
451  const char *exit_event_name,
452  bool exit_event_initial_state)
453 {
454  CLEAR(*ws);
455 
456  ws->mode = WSO_MODE_UNDEF;
457  ws->in.read = INVALID_HANDLE_VALUE;
458  ws->in.write = INVALID_HANDLE_VALUE;
459  ws->console_mode_save = 0;
460  ws->console_mode_save_defined = false;
461 
462  if (force == WSO_NOFORCE || force == WSO_FORCE_CONSOLE)
463  {
464  /*
465  * Try to open console.
466  */
467  ws->in.read = GetStdHandle(STD_INPUT_HANDLE);
468  if (ws->in.read != INVALID_HANDLE_VALUE)
469  {
470  if (GetConsoleMode(ws->in.read, &ws->console_mode_save))
471  {
472  /* running on a console */
473  const DWORD new_console_mode = ws->console_mode_save
474  & ~(ENABLE_WINDOW_INPUT
475  | ENABLE_PROCESSED_INPUT
476  | ENABLE_LINE_INPUT
477  | ENABLE_ECHO_INPUT
478  | ENABLE_MOUSE_INPUT);
479 
480  if (new_console_mode != ws->console_mode_save)
481  {
482  if (!SetConsoleMode(ws->in.read, new_console_mode))
483  {
484  msg(M_ERR, "Error: win32_signal_open: SetConsoleMode failed");
485  }
486  ws->console_mode_save_defined = true;
487  }
488  ws->mode = WSO_MODE_CONSOLE;
489  }
490  else
491  {
492  ws->in.read = INVALID_HANDLE_VALUE; /* probably running as a service */
493  }
494  }
495  }
496 
497  /*
498  * If console open failed, assume we are running
499  * as a service.
500  */
501  if ((force == WSO_NOFORCE || force == WSO_FORCE_SERVICE)
502  && !HANDLE_DEFINED(ws->in.read) && exit_event_name)
503  {
504  struct security_attributes sa;
505 
507  {
508  msg(M_ERR, "Error: win32_signal_open: init SA failed");
509  }
510 
511  ws->in.read = CreateEvent(&sa.sa,
512  TRUE,
513  exit_event_initial_state ? TRUE : FALSE,
514  exit_event_name);
515  if (ws->in.read == NULL)
516  {
517  msg(M_WARN|M_ERRNO, "NOTE: CreateEvent '%s' failed", exit_event_name);
518  }
519  else
520  {
521  if (WaitForSingleObject(ws->in.read, 0) != WAIT_TIMEOUT)
522  {
523  msg(M_FATAL, "ERROR: Exit Event ('%s') is signaled", exit_event_name);
524  }
525  else
526  {
527  ws->mode = WSO_MODE_SERVICE;
528  }
529  }
530  }
531  /* set the ctrl handler in both console and service modes */
532  if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) win_ctrl_handler, true))
533  {
534  msg(M_WARN|M_ERRNO, "WARN: SetConsoleCtrlHandler failed");
535  }
536 }
537 
538 static bool
540 {
541  ASSERT(ws->mode == WSO_MODE_CONSOLE);
542  if (HANDLE_DEFINED(ws->in.read))
543  {
544  DWORD n;
545  if (GetNumberOfConsoleInputEvents(ws->in.read, &n))
546  {
547  return n > 0;
548  }
549  }
550  return false;
551 }
552 
553 static unsigned int
554 keyboard_ir_to_key(INPUT_RECORD *ir)
555 {
556  if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
557  {
558  return ir->Event.KeyEvent.wVirtualScanCode;
559  }
560 
561  if ((ir->Event.KeyEvent.dwControlKeyState
562  & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
563  && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
564  {
565  return ir->Event.KeyEvent.wVirtualScanCode * 256;
566  }
567 
568  return ir->Event.KeyEvent.uChar.AsciiChar;
569 }
570 
571 static unsigned int
573 {
574  ASSERT(ws->mode == WSO_MODE_CONSOLE);
575  if (HANDLE_DEFINED(ws->in.read))
576  {
577  INPUT_RECORD ir;
578  do
579  {
580  DWORD n;
581  if (!keyboard_input_available(ws))
582  {
583  return 0;
584  }
585  if (!ReadConsoleInput(ws->in.read, &ir, 1, &n))
586  {
587  return 0;
588  }
589  } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
590 
591  return keyboard_ir_to_key(&ir);
592  }
593  else
594  {
595  return 0;
596  }
597 }
598 
599 void
601 {
602  if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read))
603  {
604  CloseHandle(ws->in.read);
605  }
607  {
608  if (!SetConsoleMode(ws->in.read, ws->console_mode_save))
609  {
610  msg(M_ERR, "Error: win32_signal_close: SetConsoleMode failed");
611  }
612  }
613  CLEAR(*ws);
614 }
615 
616 /*
617  * Return true if interrupt occurs in service mode.
618  */
619 bool
621 {
622  if (ws->mode == WSO_MODE_SERVICE)
623  {
624  if (HANDLE_DEFINED(ws->in.read)
625  && WaitForSingleObject(ws->in.read, 0) == WAIT_OBJECT_0)
626  {
627  return true;
628  }
629  }
630  return false;
631 }
632 
633 int
635 {
636  int ret = 0;
638  {
640  }
641  else
642  {
643  if (ws->mode == WSO_MODE_SERVICE)
644  {
645  if (win32_service_interrupt(ws))
646  {
647  ret = SIGTERM;
648  }
649  }
650  else if (ws->mode == WSO_MODE_CONSOLE)
651  {
652  switch (win32_keyboard_get(ws))
653  {
654  case 0x3B: /* F1 -> USR1 */
655  ret = SIGUSR1;
656  break;
657 
658  case 0x3C: /* F2 -> USR2 */
659  ret = SIGUSR2;
660  break;
661 
662  case 0x3D: /* F3 -> HUP */
663  ret = SIGHUP;
664  break;
665 
666  case 0x3E: /* F4 -> TERM */
667  ret = SIGTERM;
668  break;
669 
670  case 0x03: /* CTRL-C -> TERM */
671  ret = SIGTERM;
672  break;
673  }
674  }
675  if (ret)
676  {
679  }
680  }
681  return ret;
682 }
683 
684 void
686 {
687  if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED(ws->in.read))
688  {
689  msg(M_INFO|M_NOPREFIX, "Press any key to continue...");
690  do
691  {
692  WaitForSingleObject(ws->in.read, INFINITE);
693  } while (!win32_keyboard_get(ws));
694  }
695 }
696 
697 /* window functions */
698 
699 void
701 {
702  CLEAR(*wt);
703 }
704 
705 void
707 {
708  if (!wt->saved)
709  {
710  if (!GetConsoleTitle(wt->old_window_title, sizeof(wt->old_window_title)))
711  {
712  wt->old_window_title[0] = 0;
713  wt->saved = false;
714  }
715  else
716  {
717  wt->saved = true;
718  }
719  }
720 }
721 
722 void
724 {
725  if (wt->saved)
726  {
727  SetConsoleTitle(wt->old_window_title);
728  }
729 }
730 
731 void
732 window_title_generate(const char *title)
733 {
734  struct gc_arena gc = gc_new();
735  struct buffer out = alloc_buf_gc(256, &gc);
736  if (!title)
737  {
738  title = "";
739  }
740  buf_printf(&out, "[%s] " PACKAGE_NAME " " PACKAGE_VERSION " F4:EXIT F1:USR1 F2:USR2 F3:HUP", title);
741  SetConsoleTitle(BSTR(&out));
742  gc_free(&gc);
743 }
744 
745 /* semaphore functions */
746 
747 void
749 {
750  CLEAR(*s);
751 }
752 
753 void
754 semaphore_open(struct semaphore *s, const char *name)
755 {
756  struct security_attributes sa;
757 
758  s->locked = false;
759  s->name = name;
760  s->hand = NULL;
761 
763  {
764  s->hand = CreateSemaphore(&sa.sa, 1, 1, name);
765  }
766 
767  if (s->hand == NULL)
768  {
769  msg(M_WARN|M_ERRNO, "WARNING: Cannot create Win32 semaphore '%s'", name);
770  }
771  else
772  {
773  dmsg(D_SEMAPHORE, "Created Win32 semaphore '%s'", s->name);
774  }
775 }
776 
777 bool
778 semaphore_lock(struct semaphore *s, int timeout_milliseconds)
779 {
780  bool ret = true;
781 
782  if (s->hand)
783  {
784  DWORD status;
785  ASSERT(!s->locked);
786 
787  dmsg(D_SEMAPHORE_LOW, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
788  s->name,
789  timeout_milliseconds / 1000);
790  status = WaitForSingleObject(s->hand, timeout_milliseconds);
791  if (status == WAIT_FAILED)
792  {
793  msg(M_ERR, "Wait failed on Win32 semaphore '%s'", s->name);
794  }
795  ret = (status == WAIT_TIMEOUT) ? false : true;
796  if (ret)
797  {
798  dmsg(D_SEMAPHORE, "Locked Win32 semaphore '%s'", s->name);
799  s->locked = true;
800  }
801  else
802  {
803  dmsg(D_SEMAPHORE, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
804  s->name,
805  timeout_milliseconds);
806  }
807  }
808  return ret;
809 }
810 
811 void
813 {
814  if (s->hand)
815  {
816  ASSERT(s->locked);
817  dmsg(D_SEMAPHORE, "Releasing Win32 semaphore '%s'", s->name);
818  if (!ReleaseSemaphore(s->hand, 1, NULL))
819  {
820  msg(M_WARN | M_ERRNO, "ReleaseSemaphore failed on Win32 semaphore '%s'",
821  s->name);
822  }
823  s->locked = false;
824  }
825 }
826 
827 void
829 {
830  if (s->hand)
831  {
832  if (s->locked)
833  {
835  }
836  dmsg(D_SEMAPHORE, "Closing Win32 semaphore '%s'", s->name);
837  CloseHandle(s->hand);
838  s->hand = NULL;
839  }
840 }
841 
842 /*
843  * Special global semaphore used to protect network
844  * shell commands from simultaneous instantiation.
845  */
846 
847 void
849 {
851 }
852 
853 void
855 {
857 }
858 
859 void
861 {
862  const int timeout_seconds = 600;
863 
864  if (!netcmd_semaphore.hand)
865  {
867  }
868 
869  if (!semaphore_lock(&netcmd_semaphore, timeout_seconds * 1000))
870  {
871  msg(M_FATAL, "Cannot lock net command semaphore");
872  }
873 }
874 
875 void
877 {
879  /* netcmd_semaphore has max count of 1 - safe to close after release */
881 }
882 
883 /*
884  * Service functions for openvpn_execve
885  */
886 
887 static char *
888 env_block(const struct env_set *es)
889 {
890  char force_path[256];
891  char *sysroot = get_win_sys_path();
892 
893  if (!openvpn_snprintf(force_path, sizeof(force_path), "PATH=%s\\System32;%s;%s\\System32\\Wbem",
894  sysroot, sysroot, sysroot))
895  {
896  msg(M_WARN, "env_block: default path truncated to %s", force_path);
897  }
898 
899  if (es)
900  {
901  struct env_item *e;
902  char *ret;
903  char *p;
904  size_t nchars = 1;
905  bool path_seen = false;
906 
907  for (e = es->list; e != NULL; e = e->next)
908  {
909  nchars += strlen(e->string) + 1;
910  }
911 
912  nchars += strlen(force_path)+1;
913 
914  ret = (char *) malloc(nchars);
915  check_malloc_return(ret);
916 
917  p = ret;
918  for (e = es->list; e != NULL; e = e->next)
919  {
920  if (env_allowed(e->string))
921  {
922  strcpy(p, e->string);
923  p += strlen(e->string) + 1;
924  }
925  if (strncmp(e->string, "PATH=", 5 ) == 0)
926  {
927  path_seen = true;
928  }
929  }
930 
931  /* make sure PATH is set */
932  if (!path_seen)
933  {
934  msg( M_INFO, "env_block: add %s", force_path );
935  strcpy( p, force_path );
936  p += strlen(force_path) + 1;
937  }
938 
939  *p = '\0';
940  return ret;
941  }
942  else
943  {
944  return NULL;
945  }
946 }
947 
948 static WCHAR *
949 wide_cmd_line(const struct argv *a, struct gc_arena *gc)
950 {
951  size_t nchars = 1;
952  size_t maxlen = 0;
953  size_t i;
954  struct buffer buf;
955  char *work = NULL;
956 
957  if (!a)
958  {
959  return NULL;
960  }
961 
962  for (i = 0; i < a->argc; ++i)
963  {
964  const char *arg = a->argv[i];
965  const size_t len = strlen(arg);
966  nchars += len + 3;
967  if (len > maxlen)
968  {
969  maxlen = len;
970  }
971  }
972 
973  work = gc_malloc(maxlen + 1, false, gc);
974  check_malloc_return(work);
975  buf = alloc_buf_gc(nchars, gc);
976 
977  for (i = 0; i < a->argc; ++i)
978  {
979  const char *arg = a->argv[i];
980  strcpy(work, arg);
982  if (i)
983  {
984  buf_printf(&buf, " ");
985  }
986  if (string_class(work, CC_ANY, CC_SPACE))
987  {
988  buf_printf(&buf, "%s", work);
989  }
990  else
991  {
992  buf_printf(&buf, "\"%s\"", work);
993  }
994  }
995 
996  return wide_string(BSTR(&buf), gc);
997 }
998 
999 /*
1000  * Attempt to simulate fork/execve on Windows
1001  */
1002 int
1003 openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
1004 {
1005  int ret = OPENVPN_EXECVE_ERROR;
1006  static bool exec_warn = false;
1007 
1008  if (a && a->argv[0])
1009  {
1010  if (openvpn_execve_allowed(flags))
1011  {
1012  struct gc_arena gc = gc_new();
1013  STARTUPINFOW start_info;
1014  PROCESS_INFORMATION proc_info;
1015 
1016  char *env = env_block(es);
1017  WCHAR *cl = wide_cmd_line(a, &gc);
1018  WCHAR *cmd = wide_string(a->argv[0], &gc);
1019 
1020  /* this allows console programs to run, and is ignored otherwise */
1021  DWORD proc_flags = CREATE_NO_WINDOW;
1022 
1023  CLEAR(start_info);
1024  CLEAR(proc_info);
1025 
1026  /* fill in STARTUPINFO struct */
1027  GetStartupInfoW(&start_info);
1028  start_info.cb = sizeof(start_info);
1029  start_info.dwFlags = STARTF_USESHOWWINDOW;
1030  start_info.wShowWindow = SW_HIDE;
1031 
1032  if (CreateProcessW(cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))
1033  {
1034  DWORD exit_status = 0;
1035  CloseHandle(proc_info.hThread);
1036  WaitForSingleObject(proc_info.hProcess, INFINITE);
1037  if (GetExitCodeProcess(proc_info.hProcess, &exit_status))
1038  {
1039  ret = (int)exit_status;
1040  }
1041  else
1042  {
1043  msg(M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %S failed", cmd);
1044  }
1045  CloseHandle(proc_info.hProcess);
1046  }
1047  else
1048  {
1049  msg(M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %S failed", cmd);
1050  }
1051  free(env);
1052  gc_free(&gc);
1053  }
1054  else
1055  {
1057  if (!exec_warn && (script_security() < SSEC_SCRIPTS))
1058  {
1060  exec_warn = true;
1061  }
1062  }
1063  }
1064  else
1065  {
1066  msg(M_WARN, "openvpn_execve: called with empty argv");
1067  }
1068  return ret;
1069 }
1070 
1071 /*
1072  * call ourself in another process
1073  */
1074 void
1075 fork_to_self(const char *cmdline)
1076 {
1077  STARTUPINFO start_info;
1078  PROCESS_INFORMATION proc_info;
1079  char self_exe[256];
1080  char *cl = string_alloc(cmdline, NULL);
1081  DWORD status;
1082 
1083  CLEAR(start_info);
1084  CLEAR(proc_info);
1085  CLEAR(self_exe);
1086 
1087  status = GetModuleFileName(NULL, self_exe, sizeof(self_exe));
1088  if (status == 0 || status == sizeof(self_exe))
1089  {
1090  msg(M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1091  goto done;
1092  }
1093 
1094  /* fill in STARTUPINFO struct */
1095  GetStartupInfo(&start_info);
1096  start_info.cb = sizeof(start_info);
1097  start_info.dwFlags = STARTF_USESHOWWINDOW;
1098  start_info.wShowWindow = SW_HIDE;
1099 
1100  if (CreateProcess(self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1101  {
1102  CloseHandle(proc_info.hThread);
1103  CloseHandle(proc_info.hProcess);
1104  }
1105  else
1106  {
1107  msg(M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: %s", cmdline);
1108  }
1109 
1110 done:
1111  free(cl);
1112 }
1113 
1114 char *
1116 {
1118  return win_sys_path;
1119 }
1120 
1121 void
1122 set_win_sys_path(const char *newpath, struct env_set *es)
1123 {
1124  free(win_sys_path);
1125  win_sys_path = string_alloc(newpath, NULL);
1126  setenv_str(es, SYS_PATH_ENV_VAR_NAME, win_sys_path); /* route.exe needs this */
1127 }
1128 
1129 void
1131 {
1132  char buf[256];
1133  DWORD status = GetEnvironmentVariable(SYS_PATH_ENV_VAR_NAME, buf, sizeof(buf));
1134  if (!status)
1135  {
1136  msg(M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1137  }
1138  if (status > sizeof(buf) - 1)
1139  {
1140  msg(M_FATAL, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1141  }
1142  set_win_sys_path(buf, es);
1143 }
1144 
1145 
1146 const char *
1148 {
1149  static char tmpdir[MAX_PATH];
1150  WCHAR wtmpdir[MAX_PATH];
1151 
1152  if (!GetTempPathW(_countof(wtmpdir), wtmpdir))
1153  {
1154  /* Warn if we can't find a valid temporary directory, which should
1155  * be unlikely.
1156  */
1157  msg(M_WARN, "Could not find a suitable temporary directory."
1158  " (GetTempPath() failed). Consider using --tmp-dir");
1159  return NULL;
1160  }
1161 
1162  if (WideCharToMultiByte(CP_UTF8, 0, wtmpdir, -1, NULL, 0, NULL, NULL) > sizeof(tmpdir))
1163  {
1164  msg(M_WARN, "Could not get temporary directory. Path is too long."
1165  " Consider using --tmp-dir");
1166  return NULL;
1167  }
1168 
1169  WideCharToMultiByte(CP_UTF8, 0, wtmpdir, -1, tmpdir, sizeof(tmpdir), NULL, NULL);
1170  return tmpdir;
1171 }
1172 
1173 static bool
1174 win_block_dns_service(bool add, int index, const HANDLE pipe)
1175 {
1176  bool ret = false;
1177  ack_message_t ack;
1178  struct gc_arena gc = gc_new();
1179 
1180  block_dns_message_t data = {
1181  .header = {
1183  sizeof(block_dns_message_t),
1184  0
1185  },
1186  .iface = { .index = index, .name = "" }
1187  };
1188 
1189  if (!send_msg_iservice(pipe, &data, sizeof(data), &ack, "Block_DNS"))
1190  {
1191  goto out;
1192  }
1193 
1194  if (ack.error_number != NO_ERROR)
1195  {
1196  msg(M_WARN, "Block_DNS: %s block dns filters using service failed: %s [status=0x%x if_index=%d]",
1197  (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc),
1198  ack.error_number, data.iface.index);
1199  goto out;
1200  }
1201 
1202  ret = true;
1203  msg(M_INFO, "%s outside dns using service succeeded.", (add ? "Blocking" : "Unblocking"));
1204 out:
1205  gc_free(&gc);
1206  return ret;
1207 }
1208 
1209 static void
1210 block_dns_msg_handler(DWORD err, const char *msg)
1211 {
1212  struct gc_arena gc = gc_new();
1213 
1214  if (err == 0)
1215  {
1216  msg(M_INFO, "%s", msg);
1217  }
1218  else
1219  {
1220  msg(M_WARN, "Error in add_block_dns_filters(): %s : %s [status=0x%lx]",
1221  msg, strerror_win32(err, &gc), err);
1222  }
1223 
1224  gc_free(&gc);
1225 }
1226 
1227 bool
1228 win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel)
1229 {
1230  WCHAR openvpnpath[MAX_PATH];
1231  bool ret = false;
1232  DWORD status;
1233 
1234  if (msg_channel)
1235  {
1236  dmsg(D_LOW, "Using service to add block dns filters");
1237  ret = win_block_dns_service(true, index, msg_channel);
1238  goto out;
1239  }
1240 
1241  status = GetModuleFileNameW(NULL, openvpnpath, _countof(openvpnpath));
1242  if (status == 0 || status == _countof(openvpnpath))
1243  {
1244  msg(M_WARN|M_ERRNO, "block_dns: cannot get executable path");
1245  goto out;
1246  }
1247 
1248  status = add_block_dns_filters(&m_hEngineHandle, index, openvpnpath,
1250  if (status == 0)
1251  {
1252  int is_auto = 0;
1253  tap_metric_v4 = get_interface_metric(index, AF_INET, &is_auto);
1254  if (is_auto)
1255  {
1256  tap_metric_v4 = 0;
1257  }
1258  tap_metric_v6 = get_interface_metric(index, AF_INET6, &is_auto);
1259  if (is_auto)
1260  {
1261  tap_metric_v6 = 0;
1262  }
1263  status = set_interface_metric(index, AF_INET, BLOCK_DNS_IFACE_METRIC);
1264  if (!status)
1265  {
1266  set_interface_metric(index, AF_INET6, BLOCK_DNS_IFACE_METRIC);
1267  }
1268  }
1269 
1270  ret = (status == 0);
1271 
1272 out:
1273 
1274  return ret;
1275 }
1276 
1277 bool
1278 win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
1279 {
1280  dmsg(D_LOW, "Uninitializing WFP");
1281 
1282  if (msg_channel)
1283  {
1284  msg(D_LOW, "Using service to delete block dns filters");
1285  win_block_dns_service(false, index, msg_channel);
1286  }
1287  else
1288  {
1290  m_hEngineHandle = NULL;
1291  if (tap_metric_v4 >= 0)
1292  {
1293  set_interface_metric(index, AF_INET, tap_metric_v4);
1294  }
1295  if (tap_metric_v6 >= 0)
1296  {
1297  set_interface_metric(index, AF_INET6, tap_metric_v6);
1298  }
1299  }
1300 
1301  return true;
1302 }
1303 
1304 int
1306 {
1307  if (!IsWindowsXPOrGreater())
1308  {
1309  msg(M_FATAL, "Error: Windows version must be XP or greater.");
1310  }
1311 
1312  if (!IsWindowsVistaOrGreater())
1313  {
1314  return WIN_XP;
1315  }
1316 
1317  if (!IsWindows7OrGreater())
1318  {
1319  return WIN_VISTA;
1320  }
1321 
1322  if (!IsWindows8OrGreater())
1323  {
1324  return WIN_7;
1325  }
1326 
1327  if (!IsWindows8Point1OrGreater())
1328  {
1329  return WIN_8;
1330  }
1331 
1332  if (!IsWindows10OrGreater())
1333  {
1334  return WIN_8_1;
1335  }
1336 
1337  return WIN_10;
1338 }
1339 
1340 bool
1342 {
1343 #if defined(_WIN64)
1344  return true; /* 64-bit programs run only on Win64 */
1345 #elif defined(_WIN32)
1346  /* 32-bit programs run on both 32-bit and 64-bit Windows */
1347  BOOL f64 = FALSE;
1348  return IsWow64Process(GetCurrentProcess(), &f64) && f64;
1349 #else /* if defined(_WIN64) */
1350  return false; /* Win64 does not support Win16 */
1351 #endif
1352 }
1353 
1354 const char *
1355 win32_version_string(struct gc_arena *gc, bool add_name)
1356 {
1357  int version = win32_version_info();
1358  struct buffer out = alloc_buf_gc(256, gc);
1359 
1360  switch (version)
1361  {
1362  case WIN_XP:
1363  buf_printf(&out, "5.1%s", add_name ? " (Windows XP)" : "");
1364  break;
1365 
1366  case WIN_VISTA:
1367  buf_printf(&out, "6.0%s", add_name ? " (Windows Vista)" : "");
1368  break;
1369 
1370  case WIN_7:
1371  buf_printf(&out, "6.1%s", add_name ? " (Windows 7)" : "");
1372  break;
1373 
1374  case WIN_8:
1375  buf_printf(&out, "6.2%s", add_name ? " (Windows 8)" : "");
1376  break;
1377 
1378  case WIN_8_1:
1379  buf_printf(&out, "6.3%s", add_name ? " (Windows 8.1)" : "");
1380  break;
1381 
1382  case WIN_10:
1383  buf_printf(&out, "10.0%s", add_name ? " (Windows 10 or greater)" : "");
1384  break;
1385 
1386  default:
1387  msg(M_NONFATAL, "Unknown Windows version: %d", version);
1388  buf_printf(&out, "0.0%s", add_name ? " (unknown)" : "");
1389  break;
1390  }
1391 
1392  buf_printf(&out, win32_is_64bit() ? " 64bit" : " 32bit");
1393 
1394  return (const char *)out.data;
1395 }
1396 
1397 bool
1398 send_msg_iservice(HANDLE pipe, const void *data, size_t size,
1399  ack_message_t *ack, const char *context)
1400 {
1401  struct gc_arena gc = gc_new();
1402  DWORD len;
1403  bool ret = true;
1404 
1405  if (!WriteFile(pipe, data, size, &len, NULL)
1406  || !ReadFile(pipe, ack, sizeof(*ack), &len, NULL))
1407  {
1408  msg(M_WARN, "%s: could not talk to service: %s [%lu]",
1409  context ? context : "Unknown",
1410  strerror_win32(GetLastError(), &gc), GetLastError());
1411  ret = false;
1412  }
1413 
1414  gc_free(&gc);
1415  return ret;
1416 }
1417 
1418 #endif /* ifdef _WIN32 */
struct signal_info siginfo_static
Definition: sig.c:46
#define M_NONFATAL
Definition: error.h:99
void uninit_win32(void)
Definition: win32.c:117
static bool pause_exit_enabled
Definition: win32.c:77
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1058
static int tap_metric_v6
Definition: win32.c:67
static bool WINAPI win_ctrl_handler(DWORD signum)
Definition: win32.c:415
void netcmd_semaphore_close(void)
Definition: win32.c:854
const char * win_get_tempdir(void)
Definition: win32.c:1147
static int tap_metric_v4
Definition: win32.c:66
struct buffer buf_init
Definition: win32.h:213
#define WSO_NOFORCE
Definition: win32.h:165
#define M_NOPREFIX
Definition: error.h:106
void free_buf(struct buffer *buf)
Definition: buffer.c:185
HANDLE read
Definition: win32.h:76
void init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
Definition: win32.c:219
static bool win_block_dns_service(bool add, int index, const HANDLE pipe)
Definition: win32.c:1174
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:685
static void win_trigger_event(struct win32_signal *ws)
Definition: win32.c:389
#define WSO_FORCE_SERVICE
Definition: win32.h:166
#define M_INFO
Definition: errlevel.h:55
Contains all state information for one tunnel.
Definition: openvpn.h:463
Packet geometry parameters.
Definition: mtu.h:93
void window_title_clear(struct window_title *wt)
Definition: win32.c:700
void semaphore_open(struct semaphore *s, const char *name)
Definition: win32.c:754
#define D_SEMAPHORE_LOW
Definition: errlevel.h:133
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state, bool tuntap_buffer)
Definition: win32.c:166
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
OVERLAPPED overlapped
Definition: win32.h:203
int script_security(void)
Definition: run_command.c:45
DWORD delete_block_dns_filters(HANDLE engine_handle)
Definition: block_dns.c:330
#define CC_PRINT
Definition: buffer.h:915
#define SIGUSR1
Definition: config-msvc.h:115
struct semaphore netcmd_semaphore
Definition: win32.c:98
void semaphore_close(struct semaphore *s)
Definition: win32.c:828
#define WIN_VISTA
Definition: win32.h:296
bool win32_service_interrupt(struct win32_signal *ws)
Definition: win32.c:620
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition: env_set.c:285
bool openvpn_execve_allowed(const unsigned int flags)
Definition: run_command.c:112
const char * win32_version_string(struct gc_arena *gc, bool add_name)
Definition: win32.c:1355
#define dmsg(flags,...)
Definition: error.h:157
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
Definition: win32-util.c:43
#define WIN_7
Definition: win32.h:297
void window_title_restore(const struct window_title *wt)
Definition: win32.c:723
#define SIGTERM
Definition: config-msvc.h:117
#define SIGHUP
Definition: config-msvc.h:113
#define WIN_XP
Definition: win32.h:295
#define ASSERT(x)
Definition: error.h:204
static unsigned int win32_keyboard_get(struct win32_signal *ws)
Definition: win32.c:572
#define D_LOW
Definition: errlevel.h:98
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
Definition: win32.c:273
#define OPENVPN_EXECVE_ERROR
Definition: run_command.h:36
static char * env_block(const struct env_set *es)
Definition: win32.c:888
#define SYS_PATH_ENV_VAR_NAME
Definition: win32.h:35
void netcmd_semaphore_lock(void)
Definition: win32.c:860
#define BLOCK_DNS_IFACE_METRIC
Definition: block_dns.h:30
int add(int a, int b)
list flags
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds)
Definition: win32.c:778
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
void set_win_sys_path(const char *newpath, struct env_set *es)
Definition: win32.c:1122
static HANDLE m_hEngineHandle
Definition: win32.c:61
int iostate
Definition: win32.h:202
#define WSO_FORCE_CONSOLE
Definition: win32.h:167
#define WSO_MODE_CONSOLE
Definition: win32.h:152
#define CLEAR(x)
Definition: basic.h:33
void net_event_win32_stop(struct net_event_win32 *ne)
Definition: win32.c:360
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
Definition: buffer.c:296
static struct WSAData wsa_state
Definition: win32.c:72
bool console_mode_save_defined
Definition: win32.h:156
#define SSEC_SCRIPTS
Definition: run_command.h:33
struct env_item * list
Definition: env_set.h:44
#define NE32_WRITE_EVENT
Definition: win32.h:85
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: block_dns.c:355
void set_win_sys_path_via_env(struct env_set *es)
Definition: win32.c:1130
void win32_signal_clear(struct win32_signal *ws)
Definition: win32.c:443
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
#define IOSTATE_IMMEDIATE_RETURN
Definition: win32.h:201
static unsigned int keyboard_ir_to_key(INPUT_RECORD *ir)
Definition: win32.c:554
#define malloc
Definition: cmocka.c:1795
char ** argv
Definition: argv.h:39
#define WSO_MODE_UNDEF
Definition: win32.h:150
#define PACKAGE_NAME
Definition: config.h:730
void init_win32(void)
Definition: win32.c:106
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:405
void semaphore_clear(struct semaphore *s)
Definition: win32.c:748
#define IOSTATE_QUEUED
Definition: win32.h:200
SECURITY_ATTRIBUTES sa
Definition: win32.h:60
static int socket_defined(const socket_descriptor_t sd)
Definition: syshead.h:452
void overlapped_io_close(struct overlapped_io *o)
Definition: win32.c:185
void net_event_win32_reset(struct net_event_win32 *ne)
Definition: win32.c:354
#define SIG_SOURCE_HARD
Definition: sig.h:33
void net_event_win32_init(struct net_event_win32 *ne)
Definition: win32.c:320
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
Definition: win32.c:1398
void net_event_win32_close(struct net_event_win32 *ne)
Definition: win32.c:371
struct env_item * next
Definition: env_set.h:39
DWORD add_block_dns_filters(HANDLE *engine_handle, int index, const WCHAR *exe_path, block_dns_msg_handler_t msg_handler)
Definition: block_dns.c:179
#define M_ERRNO
Definition: error.h:103
char * string
Definition: env_set.h:38
long event_mask
Definition: win32.h:107
char * get_win_sys_path(void)
Definition: win32.c:1115
void win32_signal_open(struct win32_signal *ws, int force, const char *exit_event_name, bool exit_event_initial_state)
Definition: win32.c:449
static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc)
Definition: win32.c:949
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
struct rw_handle in
Definition: win32.h:154
#define SOCKET_UNDEFINED
Definition: syshead.h:444
#define WIN_8_1
Definition: win32.h:299
#define NE32_PERSIST_EVENT
Definition: win32.h:84
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition: error.c:816
char * overlapped_io_state_ascii(const struct overlapped_io *o)
Definition: win32.c:198
struct rw_handle handle
Definition: win32.h:105
bool win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel)
Definition: win32.c:1228
volatile int source
Definition: sig.h:46
void window_title_save(struct window_title *wt)
Definition: win32.c:706
size_t argc
Definition: argv.h:38
SECURITY_DESCRIPTOR sd
Definition: win32.h:61
void win32_signal_close(struct win32_signal *ws)
Definition: win32.c:600
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame, const bool tuntap_buffer, const unsigned int align_mask)
Definition: mtu.c:43
#define msg(flags,...)
Definition: error.h:153
bool locked
Definition: win32.h:241
bool init_security_attributes_allow_all(struct security_attributes *obj)
Definition: win32.c:147
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
Definition: win32.c:327
void fork_to_self(const char *cmdline)
Definition: win32.c:1075
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Definition: buffer.c:1077
void set_pause_exit_win32(void)
Definition: win32.c:141
HANDLE write
Definition: win32.h:77
#define D_SEMAPHORE
Definition: errlevel.h:134
volatile int signal_received
Definition: sig.h:45
#define M_ERR
Definition: error.h:114
#define SIGUSR2
Definition: config-msvc.h:116
static void check_malloc_return(const void *p)
Definition: buffer.h:1093
#define WIN_10
Definition: win32.h:300
void semaphore_release(struct semaphore *s)
Definition: win32.c:812
int mode
Definition: win32.h:153
SOCKET socket_descriptor_t
Definition: syshead.h:445
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
Definition: win32.c:1003
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd)
Definition: win32.c:258
static bool net_event_win32_defined(const struct net_event_win32 *ne)
Definition: win32.h:123
DWORD set_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, const ULONG metric)
Sets interface metric value for specified interface index.
Definition: block_dns.c:394
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
#define M_FATAL
Definition: error.h:98
#define SCRIPT_SECURITY_WARNING
Definition: common.h:85
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
Definition: win32.c:1278
DWORD console_mode_save
Definition: win32.h:155
int win32_version_info(void)
Definition: win32.c:1305
#define WSO_MODE_SERVICE
Definition: win32.h:151
void netcmd_semaphore_release(void)
Definition: win32.c:876
#define IOSTATE_INITIAL
Definition: win32.h:199
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
const char * name
Definition: win32.h:240
HANDLE hand
Definition: win32.h:242
#define M_WARN
Definition: error.h:100
#define PACKAGE_VERSION
Definition: config.h:742
void win32_pause(struct win32_signal *ws)
Definition: win32.c:685
void throw_signal(const int signum)
Definition: sig.c:104
#define free
Definition: cmocka.c:1850
#define CC_SPACE
Definition: buffer.h:917
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
static char * win_sys_path
Definition: win32.c:103
void net_event_win32_reset_write(struct net_event_win32 *ne)
Definition: win32.c:336
#define BSTR(buf)
Definition: buffer.h:129
#define OPENVPN_EXECVE_NOT_ALLOWED
Definition: run_command.h:37
#define PACKAGE
Definition: config.h:724
message_header_t header
Definition: openvpn-msg.h:113
int win32_signal_get(struct win32_signal *ws)
Definition: win32.c:634
#define WIN_8
Definition: win32.h:298
Definition: argv.h:35
bool win32_is_64bit(void)
Definition: win32.c:1341
char old_window_title[256]
Definition: win32.h:72
#define CC_CRLF
Definition: buffer.h:944
static SERVICE_STATUS status
Definition: interactive.c:56
void window_title_generate(const char *title)
Definition: win32.c:732
interface_t iface
Definition: openvpn-msg.h:114
#define CC_ANY
Definition: buffer.h:907
static bool keyboard_input_available(struct win32_signal *ws)
Definition: win32.c:539
static void block_dns_msg_handler(DWORD err, const char *msg)
Definition: win32.c:1210
bool env_allowed(const char *str)
Definition: env_set.c:415
socket_descriptor_t sd
Definition: win32.h:106
bool saved
Definition: win32.h:71
#define CC_DOUBLE_QUOTE
Definition: buffer.h:932
void netcmd_semaphore_init(void)
Definition: win32.c:848
#define HANDLE_DEFINED(h)
Definition: win32.h:64