svn cleanup
[anytun.git] / openvpn / win32.c
blobf9a80fc2715747d2079ec6c038845a7de840e683
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.
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
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.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Win32-specific OpenVPN code, targetted at the mingw
27 * development environment.
30 #ifdef WIN32
32 #include "config-win32.h"
34 #include "syshead.h"
35 #include "buffer.h"
36 #include "error.h"
37 #include "mtu.h"
38 #include "sig.h"
39 #include "win32.h"
41 #include "memdbg.h"
44 * Windows internal socket API state (opaque).
46 static struct WSAData wsa_state; /* GLOBAL */
49 * Should we call win32_pause() on program exit?
51 static bool pause_exit_enabled = false; /* GLOBAL */
54 * win32_signal is used to get input from the keyboard
55 * if we are running in a console, or get input from an
56 * event object if we are running as a service.
59 struct win32_signal win32_signal; /* GLOBAL */
62 * Save our old window title so we can restore
63 * it on exit.
65 struct window_title window_title; /* GLOBAL*/
68 * Special global semaphore used to protect network
69 * shell commands from simultaneous instantiation.
72 struct semaphore netcmd_semaphore; /* GLOBAL */
74 void
75 init_win32 (void)
77 if (WSAStartup(0x0101, &wsa_state))
79 msg (M_ERR, "WSAStartup failed");
81 window_title_clear (&window_title);
82 win32_signal_clear (&win32_signal);
83 netcmd_semaphore_init ();
86 void
87 uninit_win32 (void)
89 netcmd_semaphore_close ();
90 if (pause_exit_enabled)
92 if (win32_signal.mode == WSO_MODE_UNDEF)
94 struct win32_signal w;
95 win32_signal_open (&w, WSO_FORCE_CONSOLE, NULL, false);
96 win32_pause (&w);
97 win32_signal_close (&w);
99 else
100 win32_pause (&win32_signal);
102 window_title_restore (&window_title);
103 win32_signal_close (&win32_signal);
104 WSACleanup ();
107 void
108 set_pause_exit_win32 (void)
110 pause_exit_enabled = true;
113 bool
114 init_security_attributes_allow_all (struct security_attributes *obj)
116 CLEAR (*obj);
118 obj->sa.nLength = sizeof (SECURITY_ATTRIBUTES);
119 obj->sa.lpSecurityDescriptor = &obj->sd;
120 obj->sa.bInheritHandle = FALSE;
121 if (!InitializeSecurityDescriptor (&obj->sd, SECURITY_DESCRIPTOR_REVISION))
122 return false;
123 if (!SetSecurityDescriptorDacl (&obj->sd, TRUE, NULL, FALSE))
124 return false;
125 return true;
128 void
129 overlapped_io_init (struct overlapped_io *o,
130 const struct frame *frame,
131 BOOL event_state,
132 bool tuntap_buffer) /* if true: tuntap buffer, if false: socket buffer */
134 CLEAR (*o);
136 /* manual reset event, initially set according to event_state */
137 o->overlapped.hEvent = CreateEvent (NULL, TRUE, event_state, NULL);
138 if (o->overlapped.hEvent == NULL)
139 msg (M_ERR, "Error: overlapped_io_init: CreateEvent failed");
141 /* allocate buffer for overlapped I/O */
142 alloc_buf_sock_tun (&o->buf_init, frame, tuntap_buffer, 0);
145 void
146 overlapped_io_close (struct overlapped_io *o)
148 if (o->overlapped.hEvent)
150 if (!CloseHandle (o->overlapped.hEvent))
151 msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on overlapped I/O event object");
153 free_buf (&o->buf_init);
156 char *
157 overlapped_io_state_ascii (const struct overlapped_io *o)
159 switch (o->iostate)
161 case IOSTATE_INITIAL:
162 return "0";
163 case IOSTATE_QUEUED:
164 return "Q";
165 case IOSTATE_IMMEDIATE_RETURN:
166 return "1";
168 return "?";
172 * Event-based notification of network events
175 void
176 init_net_event_win32 (struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
178 /* manual reset events, initially set to unsignaled */
180 /* initialize write event */
181 if (!(flags & NE32_PERSIST_EVENT) || !event->write)
183 if (flags & NE32_WRITE_EVENT)
185 event->write = CreateEvent (NULL, TRUE, FALSE, NULL);
186 if (event->write == NULL)
187 msg (M_ERR, "Error: init_net_event_win32: CreateEvent (write) failed");
189 else
190 event->write = NULL;
193 /* initialize read event */
194 if (!(flags & NE32_PERSIST_EVENT) || !event->read)
196 event->read = CreateEvent (NULL, TRUE, FALSE, NULL);
197 if (event->read == NULL)
198 msg (M_ERR, "Error: init_net_event_win32: CreateEvent (read) failed");
201 /* setup network events to change read event state */
202 if (WSAEventSelect (sd, event->read, network_events) != 0)
203 msg (M_FATAL | M_ERRNO_SOCK, "Error: init_net_event_win32: WSAEventSelect call failed");
206 long
207 reset_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd)
209 WSANETWORKEVENTS wne;
210 if (WSAEnumNetworkEvents (sd, event->read, &wne) != 0)
212 msg (M_FATAL | M_ERRNO_SOCK, "Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
213 return 0; /* NOTREACHED */
215 else
216 return wne.lNetworkEvents;
219 void
220 close_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
222 if (event->read)
224 if (socket_defined (sd))
226 if (WSAEventSelect (sd, event->read, 0) != 0)
227 msg (M_WARN | M_ERRNO_SOCK, "Warning: close_net_event_win32: WSAEventSelect call failed");
229 if (!ResetEvent (event->read))
230 msg (M_WARN | M_ERRNO, "Warning: ResetEvent (read) failed in close_net_event_win32");
231 if (!(flags & NE32_PERSIST_EVENT))
233 if (!CloseHandle (event->read))
234 msg (M_WARN | M_ERRNO, "Warning: CloseHandle (read) failed in close_net_event_win32");
235 event->read = NULL;
239 if (event->write)
241 if (!ResetEvent (event->write))
242 msg (M_WARN | M_ERRNO, "Warning: ResetEvent (write) failed in close_net_event_win32");
243 if (!(flags & NE32_PERSIST_EVENT))
245 if (!CloseHandle (event->write))
246 msg (M_WARN | M_ERRNO, "Warning: CloseHandle (write) failed in close_net_event_win32");
247 event->write = NULL;
253 * struct net_event_win32
256 void
257 net_event_win32_init (struct net_event_win32 *ne)
259 CLEAR (*ne);
260 ne->sd = SOCKET_UNDEFINED;
263 void
264 net_event_win32_start (struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
266 ASSERT (!socket_defined (ne->sd));
267 ne->sd = sd;
268 ne->event_mask = 0;
269 init_net_event_win32 (&ne->handle, network_events, sd, NE32_PERSIST_EVENT|NE32_WRITE_EVENT);
272 void
273 net_event_win32_reset_write (struct net_event_win32 *ne)
275 BOOL status;
276 if (ne->event_mask & FD_WRITE)
277 status = SetEvent (ne->handle.write);
278 else
279 status = ResetEvent (ne->handle.write);
280 if (!status)
281 msg (M_WARN | M_ERRNO, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
284 void
285 net_event_win32_reset (struct net_event_win32 *ne)
287 ne->event_mask |= reset_net_event_win32 (&ne->handle, ne->sd);
290 void
291 net_event_win32_stop (struct net_event_win32 *ne)
293 if (net_event_win32_defined (ne))
294 close_net_event_win32 (&ne->handle, ne->sd, NE32_PERSIST_EVENT);
295 ne->sd = SOCKET_UNDEFINED;
296 ne->event_mask = 0;
299 void
300 net_event_win32_close (struct net_event_win32 *ne)
302 if (net_event_win32_defined (ne))
303 close_net_event_win32 (&ne->handle, ne->sd, 0);
304 net_event_win32_init (ne);
308 * Simulate *nix signals on Windows.
310 * Two modes:
311 * (1) Console mode -- map keyboard function keys to signals
312 * (2) Service mode -- map Windows event object to SIGTERM
315 void
316 win32_signal_clear (struct win32_signal *ws)
318 CLEAR (*ws);
321 void
322 win32_signal_open (struct win32_signal *ws,
323 int force,
324 const char *exit_event_name,
325 bool exit_event_initial_state)
327 CLEAR (*ws);
329 ws->mode = WSO_MODE_UNDEF;
330 ws->in.read = INVALID_HANDLE_VALUE;
331 ws->in.write = INVALID_HANDLE_VALUE;
332 ws->console_mode_save = 0;
333 ws->console_mode_save_defined = false;
335 if (force == WSO_NOFORCE || force == WSO_FORCE_CONSOLE)
338 * Try to open console.
340 ws->in.read = GetStdHandle (STD_INPUT_HANDLE);
341 if (ws->in.read != INVALID_HANDLE_VALUE)
343 if (GetConsoleMode (ws->in.read, &ws->console_mode_save))
345 /* running on a console */
346 const DWORD new_console_mode = ws->console_mode_save
347 & ~(ENABLE_WINDOW_INPUT
348 | ENABLE_PROCESSED_INPUT
349 | ENABLE_LINE_INPUT
350 | ENABLE_ECHO_INPUT
351 | ENABLE_MOUSE_INPUT);
353 if (new_console_mode != ws->console_mode_save)
355 if (!SetConsoleMode (ws->in.read, new_console_mode))
356 msg (M_ERR, "Error: win32_signal_open: SetConsoleMode failed");
357 ws->console_mode_save_defined = true;
359 ws->mode = WSO_MODE_CONSOLE;
361 else
362 ws->in.read = INVALID_HANDLE_VALUE; /* probably running as a service */
367 * If console open failed, assume we are running
368 * as a service.
370 if ((force == WSO_NOFORCE || force == WSO_FORCE_SERVICE)
371 && !HANDLE_DEFINED (ws->in.read) && exit_event_name)
373 struct security_attributes sa;
375 if (!init_security_attributes_allow_all (&sa))
376 msg (M_ERR, "Error: win32_signal_open: init SA failed");
378 ws->in.read = CreateEvent (&sa.sa,
379 TRUE,
380 exit_event_initial_state ? TRUE : FALSE,
381 exit_event_name);
382 if (ws->in.read == NULL)
384 msg (M_WARN|M_ERRNO, "NOTE: CreateEvent '%s' failed", exit_event_name);
386 else
388 if (WaitForSingleObject (ws->in.read, 0) != WAIT_TIMEOUT)
389 msg (M_FATAL, "ERROR: Exit Event ('%s') is signaled", exit_event_name);
390 else
391 ws->mode = WSO_MODE_SERVICE;
396 static bool
397 keyboard_input_available (struct win32_signal *ws)
399 ASSERT (ws->mode == WSO_MODE_CONSOLE);
400 if (HANDLE_DEFINED (ws->in.read))
402 DWORD n;
403 if (GetNumberOfConsoleInputEvents (ws->in.read, &n))
404 return n > 0;
406 return false;
409 static unsigned int
410 keyboard_ir_to_key (INPUT_RECORD *ir)
412 if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
413 return ir->Event.KeyEvent.wVirtualScanCode;
415 if ((ir->Event.KeyEvent.dwControlKeyState
416 & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
417 && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
418 return ir->Event.KeyEvent.wVirtualScanCode * 256;
420 return ir->Event.KeyEvent.uChar.AsciiChar;
423 static unsigned int
424 win32_keyboard_get (struct win32_signal *ws)
426 ASSERT (ws->mode == WSO_MODE_CONSOLE);
427 if (HANDLE_DEFINED (ws->in.read))
429 INPUT_RECORD ir;
430 do {
431 DWORD n;
432 if (!keyboard_input_available (ws))
433 return 0;
434 if (!ReadConsoleInput (ws->in.read, &ir, 1, &n))
435 return 0;
436 } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
438 return keyboard_ir_to_key (&ir);
440 else
441 return 0;
444 void
445 win32_signal_close (struct win32_signal *ws)
447 if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED (ws->in.read))
448 CloseHandle (ws->in.read);
449 if (ws->console_mode_save_defined)
451 if (!SetConsoleMode (ws->in.read, ws->console_mode_save))
452 msg (M_ERR, "Error: win32_signal_close: SetConsoleMode failed");
454 CLEAR (*ws);
458 * Return true if interrupt occurs in service mode.
460 static bool
461 win32_service_interrupt (struct win32_signal *ws)
463 if (ws->mode == WSO_MODE_SERVICE)
465 if (HANDLE_DEFINED (ws->in.read)
466 && WaitForSingleObject (ws->in.read, 0) == WAIT_OBJECT_0)
467 return true;
469 return false;
473 win32_signal_get (struct win32_signal *ws)
475 int ret = 0;
476 if (siginfo_static.signal_received)
478 ret = siginfo_static.signal_received;
480 else
482 if (ws->mode == WSO_MODE_SERVICE)
484 if (win32_service_interrupt (ws))
485 ret = SIGTERM;
487 else if (ws->mode == WSO_MODE_CONSOLE)
489 switch (win32_keyboard_get (ws))
491 case 0x3B: /* F1 -> USR1 */
492 ret = SIGUSR1;
493 break;
494 case 0x3C: /* F2 -> USR2 */
495 ret = SIGUSR2;
496 break;
497 case 0x3D: /* F3 -> HUP */
498 ret = SIGHUP;
499 break;
500 case 0x3E: /* F4 -> TERM */
501 ret = SIGTERM;
502 break;
505 if (ret)
507 siginfo_static.signal_received = ret;
508 siginfo_static.hard = true;
511 return ret;
514 void
515 win32_pause (struct win32_signal *ws)
517 if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED (ws->in.read))
519 int status;
520 msg (M_INFO|M_NOPREFIX, "Press any key to continue...");
521 do {
522 status = WaitForSingleObject (ws->in.read, INFINITE);
523 } while (!win32_keyboard_get (ws));
527 /* window functions */
529 void
530 window_title_clear (struct window_title *wt)
532 CLEAR (*wt);
535 void
536 window_title_save (struct window_title *wt)
538 if (!wt->saved)
540 if (!GetConsoleTitle (wt->old_window_title, sizeof (wt->old_window_title)))
542 wt->old_window_title[0] = 0;
543 wt->saved = false;
545 else
546 wt->saved = true;
550 void
551 window_title_restore (const struct window_title *wt)
553 if (wt->saved)
554 SetConsoleTitle (wt->old_window_title);
557 void
558 window_title_generate (const char *title)
560 struct gc_arena gc = gc_new ();
561 struct buffer out = alloc_buf_gc (256, &gc);
562 if (!title)
563 title = "";
564 buf_printf (&out, "[%s] " PACKAGE_NAME " " VERSION " F4:EXIT F1:USR1 F2:USR2 F3:HUP", title);
565 SetConsoleTitle (BSTR (&out));
566 gc_free (&gc);
569 /* semaphore functions */
571 void
572 semaphore_clear (struct semaphore *s)
574 CLEAR (*s);
577 void
578 semaphore_open (struct semaphore *s, const char *name)
580 struct security_attributes sa;
582 s->locked = false;
583 s->name = name;
584 s->hand = NULL;
586 if (init_security_attributes_allow_all (&sa))
587 s->hand = CreateSemaphore(&sa.sa, 1, 1, name);
589 if (s->hand == NULL)
590 msg (M_WARN|M_ERRNO, "WARNING: Cannot create Win32 semaphore '%s'", name);
591 else
592 dmsg (D_SEMAPHORE, "Created Win32 semaphore '%s'", s->name);
595 bool
596 semaphore_lock (struct semaphore *s, int timeout_milliseconds)
598 bool ret = true;
600 if (s->hand)
602 DWORD status;
603 ASSERT (!s->locked);
605 dmsg (D_SEMAPHORE_LOW, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
606 s->name,
607 timeout_milliseconds / 1000);
608 status = WaitForSingleObject (s->hand, timeout_milliseconds);
609 if (status == WAIT_FAILED)
610 msg (M_ERR, "Wait failed on Win32 semaphore '%s'", s->name);
611 ret = (status == WAIT_TIMEOUT) ? false : true;
612 if (ret)
614 dmsg (D_SEMAPHORE, "Locked Win32 semaphore '%s'", s->name);
615 s->locked = true;
617 else
619 dmsg (D_SEMAPHORE, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
620 s->name,
621 timeout_milliseconds);
624 return ret;
627 void
628 semaphore_release (struct semaphore *s)
630 if (s->hand)
632 ASSERT (s->locked);
633 dmsg (D_SEMAPHORE, "Releasing Win32 semaphore '%s'", s->name);
634 if (!ReleaseSemaphore(s->hand, 1, NULL))
635 msg (M_WARN | M_ERRNO, "ReleaseSemaphore failed on Win32 semaphore '%s'",
636 s->name);
637 s->locked = false;
641 void
642 semaphore_close (struct semaphore *s)
644 if (s->hand)
646 if (s->locked)
647 semaphore_release (s);
648 dmsg (D_SEMAPHORE, "Closing Win32 semaphore '%s'", s->name);
649 CloseHandle (s->hand);
650 s->hand = NULL;
655 * Special global semaphore used to protect network
656 * shell commands from simultaneous instantiation.
659 void
660 netcmd_semaphore_init (void)
662 semaphore_open (&netcmd_semaphore, PACKAGE "_netcmd");
665 void
666 netcmd_semaphore_close (void)
668 semaphore_close (&netcmd_semaphore);
671 void
672 netcmd_semaphore_lock (void)
674 const int timeout_seconds = 600;
675 if (!semaphore_lock (&netcmd_semaphore, timeout_seconds * 1000))
676 msg (M_FATAL, "Cannot lock net command semaphore");
679 void
680 netcmd_semaphore_release (void)
682 semaphore_release (&netcmd_semaphore);
686 * Get input from console.
688 * Return false on input error, or if service
689 * exit event is signaled.
692 bool
693 get_console_input_win32 (const char *prompt, const bool echo, char *input, const int capacity)
695 HANDLE in = INVALID_HANDLE_VALUE;
696 HANDLE err = INVALID_HANDLE_VALUE;
697 DWORD len = 0;
699 ASSERT (prompt);
700 ASSERT (input);
701 ASSERT (capacity > 0);
703 input[0] = '\0';
705 in = GetStdHandle (STD_INPUT_HANDLE);
706 err = get_orig_stderr ();
708 if (in != INVALID_HANDLE_VALUE
709 && err != INVALID_HANDLE_VALUE
710 && !win32_service_interrupt (&win32_signal)
711 && WriteFile (err, prompt, strlen (prompt), &len, NULL))
713 bool is_console = (GetFileType (in) == FILE_TYPE_CHAR);
714 DWORD flags_save = 0;
715 int status = 0;
717 if (is_console)
719 if (GetConsoleMode (in, &flags_save))
721 DWORD flags = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
722 if (echo)
723 flags |= ENABLE_ECHO_INPUT;
724 SetConsoleMode (in, flags);
726 else
727 is_console = 0;
730 status = ReadFile (in, input, capacity, &len, NULL);
732 string_null_terminate (input, (int)len, capacity);
733 chomp (input);
735 if (!echo)
736 WriteFile (err, "\r\n", 2, &len, NULL);
737 if (is_console)
738 SetConsoleMode (in, flags_save);
739 if (status && !win32_service_interrupt (&win32_signal))
740 return true;
743 return false;
746 /* get password from console */
748 char *
749 getpass (const char *prompt)
751 static char line[256];
752 if (get_console_input_win32 (prompt, false, line, sizeof (line)))
753 return line;
754 else
755 return NULL;
758 #endif