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
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.
32 #include "config-win32.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
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 */
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 ();
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);
97 win32_signal_close (&w
);
100 win32_pause (&win32_signal
);
102 window_title_restore (&window_title
);
103 win32_signal_close (&win32_signal
);
108 set_pause_exit_win32 (void)
110 pause_exit_enabled
= true;
114 init_security_attributes_allow_all (struct security_attributes
*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
))
123 if (!SetSecurityDescriptorDacl (&obj
->sd
, TRUE
, NULL
, FALSE
))
129 overlapped_io_init (struct overlapped_io
*o
,
130 const struct frame
*frame
,
132 bool tuntap_buffer
) /* if true: tuntap buffer, if false: socket buffer */
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);
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
);
157 overlapped_io_state_ascii (const struct overlapped_io
*o
)
161 case IOSTATE_INITIAL
:
165 case IOSTATE_IMMEDIATE_RETURN
:
172 * Event-based notification of network events
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");
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");
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 */
216 return wne
.lNetworkEvents
;
220 close_net_event_win32 (struct rw_handle
*event
, socket_descriptor_t sd
, unsigned int flags
)
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");
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");
253 * struct net_event_win32
257 net_event_win32_init (struct net_event_win32
*ne
)
260 ne
->sd
= SOCKET_UNDEFINED
;
264 net_event_win32_start (struct net_event_win32
*ne
, long network_events
, socket_descriptor_t sd
)
266 ASSERT (!socket_defined (ne
->sd
));
269 init_net_event_win32 (&ne
->handle
, network_events
, sd
, NE32_PERSIST_EVENT
|NE32_WRITE_EVENT
);
273 net_event_win32_reset_write (struct net_event_win32
*ne
)
276 if (ne
->event_mask
& FD_WRITE
)
277 status
= SetEvent (ne
->handle
.write
);
279 status
= ResetEvent (ne
->handle
.write
);
281 msg (M_WARN
| M_ERRNO
, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
285 net_event_win32_reset (struct net_event_win32
*ne
)
287 ne
->event_mask
|= reset_net_event_win32 (&ne
->handle
, ne
->sd
);
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
;
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.
311 * (1) Console mode -- map keyboard function keys to signals
312 * (2) Service mode -- map Windows event object to SIGTERM
316 win32_signal_clear (struct win32_signal
*ws
)
322 win32_signal_open (struct win32_signal
*ws
,
324 const char *exit_event_name
,
325 bool exit_event_initial_state
)
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
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
;
362 ws
->in
.read
= INVALID_HANDLE_VALUE
; /* probably running as a service */
367 * If console open failed, assume we are running
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
,
380 exit_event_initial_state
? TRUE
: FALSE
,
382 if (ws
->in
.read
== NULL
)
384 msg (M_WARN
|M_ERRNO
, "NOTE: CreateEvent '%s' failed", exit_event_name
);
388 if (WaitForSingleObject (ws
->in
.read
, 0) != WAIT_TIMEOUT
)
389 msg (M_FATAL
, "ERROR: Exit Event ('%s') is signaled", exit_event_name
);
391 ws
->mode
= WSO_MODE_SERVICE
;
397 keyboard_input_available (struct win32_signal
*ws
)
399 ASSERT (ws
->mode
== WSO_MODE_CONSOLE
);
400 if (HANDLE_DEFINED (ws
->in
.read
))
403 if (GetNumberOfConsoleInputEvents (ws
->in
.read
, &n
))
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
;
424 win32_keyboard_get (struct win32_signal
*ws
)
426 ASSERT (ws
->mode
== WSO_MODE_CONSOLE
);
427 if (HANDLE_DEFINED (ws
->in
.read
))
432 if (!keyboard_input_available (ws
))
434 if (!ReadConsoleInput (ws
->in
.read
, &ir
, 1, &n
))
436 } while (ir
.EventType
!= KEY_EVENT
|| ir
.Event
.KeyEvent
.bKeyDown
!= TRUE
);
438 return keyboard_ir_to_key (&ir
);
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");
458 * Return true if interrupt occurs in service mode.
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
)
473 win32_signal_get (struct win32_signal
*ws
)
476 if (siginfo_static
.signal_received
)
478 ret
= siginfo_static
.signal_received
;
482 if (ws
->mode
== WSO_MODE_SERVICE
)
484 if (win32_service_interrupt (ws
))
487 else if (ws
->mode
== WSO_MODE_CONSOLE
)
489 switch (win32_keyboard_get (ws
))
491 case 0x3B: /* F1 -> USR1 */
494 case 0x3C: /* F2 -> USR2 */
497 case 0x3D: /* F3 -> HUP */
500 case 0x3E: /* F4 -> TERM */
507 siginfo_static
.signal_received
= ret
;
508 siginfo_static
.hard
= true;
515 win32_pause (struct win32_signal
*ws
)
517 if (ws
->mode
== WSO_MODE_CONSOLE
&& HANDLE_DEFINED (ws
->in
.read
))
520 msg (M_INFO
|M_NOPREFIX
, "Press any key to continue...");
522 status
= WaitForSingleObject (ws
->in
.read
, INFINITE
);
523 } while (!win32_keyboard_get (ws
));
527 /* window functions */
530 window_title_clear (struct window_title
*wt
)
536 window_title_save (struct window_title
*wt
)
540 if (!GetConsoleTitle (wt
->old_window_title
, sizeof (wt
->old_window_title
)))
542 wt
->old_window_title
[0] = 0;
551 window_title_restore (const struct window_title
*wt
)
554 SetConsoleTitle (wt
->old_window_title
);
558 window_title_generate (const char *title
)
560 struct gc_arena gc
= gc_new ();
561 struct buffer out
= alloc_buf_gc (256, &gc
);
564 buf_printf (&out
, "[%s] " PACKAGE_NAME
" " VERSION
" F4:EXIT F1:USR1 F2:USR2 F3:HUP", title
);
565 SetConsoleTitle (BSTR (&out
));
569 /* semaphore functions */
572 semaphore_clear (struct semaphore
*s
)
578 semaphore_open (struct semaphore
*s
, const char *name
)
580 struct security_attributes sa
;
586 if (init_security_attributes_allow_all (&sa
))
587 s
->hand
= CreateSemaphore(&sa
.sa
, 1, 1, name
);
590 msg (M_WARN
|M_ERRNO
, "WARNING: Cannot create Win32 semaphore '%s'", name
);
592 dmsg (D_SEMAPHORE
, "Created Win32 semaphore '%s'", s
->name
);
596 semaphore_lock (struct semaphore
*s
, int timeout_milliseconds
)
605 dmsg (D_SEMAPHORE_LOW
, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
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;
614 dmsg (D_SEMAPHORE
, "Locked Win32 semaphore '%s'", s
->name
);
619 dmsg (D_SEMAPHORE
, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
621 timeout_milliseconds
);
628 semaphore_release (struct semaphore
*s
)
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'",
642 semaphore_close (struct semaphore
*s
)
647 semaphore_release (s
);
648 dmsg (D_SEMAPHORE
, "Closing Win32 semaphore '%s'", s
->name
);
649 CloseHandle (s
->hand
);
655 * Special global semaphore used to protect network
656 * shell commands from simultaneous instantiation.
660 netcmd_semaphore_init (void)
662 semaphore_open (&netcmd_semaphore
, PACKAGE
"_netcmd");
666 netcmd_semaphore_close (void)
668 semaphore_close (&netcmd_semaphore
);
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");
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.
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
;
701 ASSERT (capacity
> 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;
719 if (GetConsoleMode (in
, &flags_save
))
721 DWORD flags
= ENABLE_LINE_INPUT
| ENABLE_PROCESSED_INPUT
;
723 flags
|= ENABLE_ECHO_INPUT
;
724 SetConsoleMode (in
, flags
);
730 status
= ReadFile (in
, input
, capacity
, &len
, NULL
);
732 string_null_terminate (input
, (int)len
, capacity
);
736 WriteFile (err
, "\r\n", 2, &len
, NULL
);
738 SetConsoleMode (in
, flags_save
);
739 if (status
&& !win32_service_interrupt (&win32_signal
))
746 /* get password from console */
749 getpass (const char *prompt
)
751 static char line
[256];
752 if (get_console_input_win32 (prompt
, false, line
, sizeof (line
)))