~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/ipv6-payload.patch/win32.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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-2010 OpenVPN Technologies, 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
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
23
 
 */
24
 
 
25
 
/*
26
 
 * Win32-specific OpenVPN code, targetted at the mingw
27
 
 * development environment.
28
 
 */
29
 
#include "syshead.h"
30
 
 
31
 
#ifdef WIN32
32
 
 
33
 
#include "buffer.h"
34
 
#include "error.h"
35
 
#include "mtu.h"
36
 
#include "sig.h"
37
 
#include "win32.h"
38
 
#include "misc.h"
39
 
 
40
 
#include "memdbg.h"
41
 
 
42
 
/*
43
 
 * Windows internal socket API state (opaque).
44
 
 */
45
 
static struct WSAData wsa_state; /* GLOBAL */
46
 
 
47
 
/*
48
 
 * Should we call win32_pause() on program exit?
49
 
 */
50
 
static bool pause_exit_enabled = false; /* GLOBAL */
51
 
 
52
 
/*
53
 
 * win32_signal is used to get input from the keyboard
54
 
 * if we are running in a console, or get input from an
55
 
 * event object if we are running as a service.
56
 
 */
57
 
 
58
 
struct win32_signal win32_signal; /* GLOBAL */
59
 
 
60
 
/*
61
 
 * Save our old window title so we can restore
62
 
 * it on exit.
63
 
 */
64
 
struct window_title window_title; /* GLOBAL*/
65
 
 
66
 
/*
67
 
 * Special global semaphore used to protect network
68
 
 * shell commands from simultaneous instantiation.
69
 
 */
70
 
 
71
 
struct semaphore netcmd_semaphore; /* GLOBAL */
72
 
 
73
 
/*
74
 
 * Windows system pathname such as c:\windows
75
 
 */
76
 
static char *win_sys_path = NULL; /* GLOBAL */
77
 
 
78
 
/*
79
 
 * Configure PATH.  On Windows, sometimes PATH is not set correctly
80
 
 * by default.
81
 
 */
82
 
static void
83
 
configure_win_path (void)
84
 
{
85
 
  static bool done = false; /* GLOBAL */
86
 
  if (!done)
87
 
    {
88
 
      FILE *fp;
89
 
      fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
90
 
      if (fp)
91
 
        {
92
 
          const int bufsiz = 4096;
93
 
          struct gc_arena gc = gc_new ();
94
 
          struct buffer oldpath = alloc_buf_gc (bufsiz, &gc);
95
 
          struct buffer newpath = alloc_buf_gc (bufsiz, &gc);
96
 
          const char* delim = ";";
97
 
          DWORD status;
98
 
          fclose (fp);
99
 
          status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
100
 
#if 0
101
 
          status = 0;
102
 
#endif
103
 
          if (!status)
104
 
            {
105
 
              *BPTR(&oldpath) = '\0';
106
 
              delim = "";
107
 
            }
108
 
          buf_printf (&newpath, "C:\\WINDOWS\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem%s%s",
109
 
                      delim,
110
 
                      BSTR(&oldpath));
111
 
          SetEnvironmentVariable ("PATH", BSTR(&newpath));
112
 
#if 0
113
 
          status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
114
 
          if (status > 0)
115
 
            printf ("PATH: %s\n", BSTR(&oldpath));
116
 
#endif
117
 
          gc_free (&gc);
118
 
          done = true;
119
 
        }
120
 
    }
121
 
}
122
 
 
123
 
void
124
 
init_win32 (void)
125
 
{
126
 
  if (WSAStartup(0x0101, &wsa_state))
127
 
    {
128
 
      msg (M_ERR, "WSAStartup failed");
129
 
    }
130
 
  window_title_clear (&window_title);
131
 
  win32_signal_clear (&win32_signal);
132
 
  netcmd_semaphore_init ();
133
 
}
134
 
 
135
 
void
136
 
uninit_win32 (void)
137
 
{
138
 
  netcmd_semaphore_close ();
139
 
  if (pause_exit_enabled)
140
 
    {
141
 
      if (win32_signal.mode == WSO_MODE_UNDEF)
142
 
        {
143
 
          struct win32_signal w;
144
 
          win32_signal_open (&w, WSO_FORCE_CONSOLE, NULL, false);
145
 
          win32_pause (&w);
146
 
          win32_signal_close (&w);
147
 
        }
148
 
      else
149
 
        win32_pause (&win32_signal);
150
 
    }
151
 
  window_title_restore (&window_title);
152
 
  win32_signal_close (&win32_signal);
153
 
  WSACleanup ();
154
 
  free (win_sys_path);
155
 
}
156
 
 
157
 
void
158
 
set_pause_exit_win32 (void)
159
 
{
160
 
  pause_exit_enabled = true;
161
 
}
162
 
 
163
 
bool
164
 
init_security_attributes_allow_all (struct security_attributes *obj)
165
 
{
166
 
  CLEAR (*obj);
167
 
 
168
 
  obj->sa.nLength = sizeof (SECURITY_ATTRIBUTES);
169
 
  obj->sa.lpSecurityDescriptor = &obj->sd;
170
 
  obj->sa.bInheritHandle = FALSE;
171
 
  if (!InitializeSecurityDescriptor (&obj->sd, SECURITY_DESCRIPTOR_REVISION))
172
 
    return false;
173
 
  if (!SetSecurityDescriptorDacl (&obj->sd, TRUE, NULL, FALSE))
174
 
    return false;
175
 
  return true;
176
 
}
177
 
 
178
 
void
179
 
overlapped_io_init (struct overlapped_io *o,
180
 
                    const struct frame *frame,
181
 
                    BOOL event_state,
182
 
                    bool tuntap_buffer) /* if true: tuntap buffer, if false: socket buffer */
183
 
{
184
 
  CLEAR (*o);
185
 
 
186
 
  /* manual reset event, initially set according to event_state */
187
 
  o->overlapped.hEvent = CreateEvent (NULL, TRUE, event_state, NULL);
188
 
  if (o->overlapped.hEvent == NULL)
189
 
    msg (M_ERR, "Error: overlapped_io_init: CreateEvent failed");
190
 
 
191
 
  /* allocate buffer for overlapped I/O */
192
 
  alloc_buf_sock_tun (&o->buf_init, frame, tuntap_buffer, 0);
193
 
}
194
 
 
195
 
void
196
 
overlapped_io_close (struct overlapped_io *o)
197
 
{
198
 
  if (o->overlapped.hEvent)
199
 
    {
200
 
      if (!CloseHandle (o->overlapped.hEvent))
201
 
        msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on overlapped I/O event object");
202
 
    }
203
 
  free_buf (&o->buf_init);
204
 
}
205
 
 
206
 
char *
207
 
overlapped_io_state_ascii (const struct overlapped_io *o)
208
 
{
209
 
  switch (o->iostate)
210
 
    {
211
 
    case IOSTATE_INITIAL:
212
 
      return "0";
213
 
    case IOSTATE_QUEUED:
214
 
      return "Q";
215
 
    case IOSTATE_IMMEDIATE_RETURN:
216
 
      return "1";
217
 
    }
218
 
  return "?";
219
 
}
220
 
 
221
 
/*
222
 
 * Event-based notification of network events
223
 
 */
224
 
 
225
 
void
226
 
init_net_event_win32 (struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags)
227
 
{
228
 
  /* manual reset events, initially set to unsignaled */
229
 
 
230
 
  /* initialize write event */
231
 
  if (!(flags & NE32_PERSIST_EVENT) || !event->write)
232
 
    {
233
 
      if (flags & NE32_WRITE_EVENT)
234
 
        {
235
 
          event->write = CreateEvent (NULL, TRUE, FALSE, NULL);
236
 
          if (event->write == NULL)
237
 
            msg (M_ERR, "Error: init_net_event_win32: CreateEvent (write) failed");
238
 
        }
239
 
      else
240
 
        event->write = NULL;
241
 
    }
242
 
 
243
 
  /* initialize read event */
244
 
  if (!(flags & NE32_PERSIST_EVENT) || !event->read)
245
 
    {
246
 
      event->read = CreateEvent (NULL, TRUE, FALSE, NULL);
247
 
      if (event->read == NULL)
248
 
        msg (M_ERR, "Error: init_net_event_win32: CreateEvent (read) failed");
249
 
    }
250
 
  
251
 
  /* setup network events to change read event state */
252
 
  if (WSAEventSelect (sd, event->read, network_events) != 0)
253
 
    msg (M_FATAL | M_ERRNO_SOCK, "Error: init_net_event_win32: WSAEventSelect call failed");
254
 
}
255
 
 
256
 
long
257
 
reset_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd)
258
 
{
259
 
  WSANETWORKEVENTS wne;  
260
 
  if (WSAEnumNetworkEvents (sd, event->read, &wne) != 0)
261
 
    {
262
 
      msg (M_FATAL | M_ERRNO_SOCK, "Error: reset_net_event_win32: WSAEnumNetworkEvents call failed");
263
 
      return 0; /* NOTREACHED */
264
 
    }
265
 
  else
266
 
    return wne.lNetworkEvents;
267
 
}
268
 
 
269
 
void
270
 
close_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd, unsigned int flags)
271
 
{
272
 
  if (event->read)
273
 
    {
274
 
      if (socket_defined (sd))
275
 
        {
276
 
          if (WSAEventSelect (sd, event->read, 0) != 0)
277
 
            msg (M_WARN | M_ERRNO_SOCK, "Warning: close_net_event_win32: WSAEventSelect call failed");
278
 
        }
279
 
      if (!ResetEvent (event->read))
280
 
        msg (M_WARN | M_ERRNO, "Warning: ResetEvent (read) failed in close_net_event_win32");
281
 
      if (!(flags & NE32_PERSIST_EVENT))
282
 
        {
283
 
          if (!CloseHandle (event->read))
284
 
            msg (M_WARN | M_ERRNO, "Warning: CloseHandle (read) failed in close_net_event_win32");
285
 
          event->read = NULL;
286
 
        }
287
 
    }
288
 
 
289
 
  if (event->write)
290
 
    {
291
 
      if (!ResetEvent (event->write))
292
 
        msg (M_WARN | M_ERRNO, "Warning: ResetEvent (write) failed in close_net_event_win32");
293
 
      if (!(flags & NE32_PERSIST_EVENT))
294
 
        {
295
 
          if (!CloseHandle (event->write))
296
 
            msg (M_WARN | M_ERRNO, "Warning: CloseHandle (write) failed in close_net_event_win32");
297
 
          event->write = NULL;
298
 
        }
299
 
    }
300
 
}
301
 
 
302
 
/*
303
 
 * struct net_event_win32
304
 
 */
305
 
 
306
 
void
307
 
net_event_win32_init (struct net_event_win32 *ne)
308
 
{
309
 
  CLEAR (*ne);
310
 
  ne->sd = SOCKET_UNDEFINED;
311
 
}
312
 
 
313
 
void
314
 
net_event_win32_start (struct net_event_win32 *ne, long network_events, socket_descriptor_t sd)
315
 
{
316
 
  ASSERT (!socket_defined (ne->sd));
317
 
  ne->sd = sd;
318
 
  ne->event_mask = 0;
319
 
  init_net_event_win32 (&ne->handle, network_events, sd, NE32_PERSIST_EVENT|NE32_WRITE_EVENT);
320
 
}
321
 
 
322
 
void
323
 
net_event_win32_reset_write (struct net_event_win32 *ne)
324
 
{
325
 
  BOOL status;
326
 
  if (ne->event_mask & FD_WRITE)
327
 
    status = SetEvent (ne->handle.write);
328
 
  else
329
 
    status = ResetEvent (ne->handle.write);
330
 
  if (!status)
331
 
    msg (M_WARN | M_ERRNO, "Warning: SetEvent/ResetEvent failed in net_event_win32_reset_write");
332
 
}
333
 
 
334
 
void
335
 
net_event_win32_reset (struct net_event_win32 *ne)
336
 
{
337
 
  ne->event_mask |= reset_net_event_win32 (&ne->handle, ne->sd);
338
 
}
339
 
 
340
 
void
341
 
net_event_win32_stop (struct net_event_win32 *ne)
342
 
{
343
 
  if (net_event_win32_defined (ne))
344
 
    close_net_event_win32 (&ne->handle, ne->sd, NE32_PERSIST_EVENT);
345
 
  ne->sd = SOCKET_UNDEFINED;
346
 
  ne->event_mask = 0;
347
 
}
348
 
 
349
 
void
350
 
net_event_win32_close (struct net_event_win32 *ne)
351
 
{
352
 
  if (net_event_win32_defined (ne))
353
 
    close_net_event_win32 (&ne->handle, ne->sd, 0);
354
 
  net_event_win32_init (ne);
355
 
}
356
 
 
357
 
/*
358
 
 * Simulate *nix signals on Windows.
359
 
 *
360
 
 * Two modes:
361
 
 * (1) Console mode -- map keyboard function keys to signals
362
 
 * (2) Service mode -- map Windows event object to SIGTERM
363
 
 */
364
 
 
365
 
void
366
 
win32_signal_clear (struct win32_signal *ws)
367
 
{
368
 
  CLEAR (*ws);
369
 
}
370
 
 
371
 
void
372
 
win32_signal_open (struct win32_signal *ws,
373
 
                   int force,
374
 
                   const char *exit_event_name,
375
 
                   bool exit_event_initial_state)
376
 
{
377
 
  CLEAR (*ws);
378
 
 
379
 
  ws->mode = WSO_MODE_UNDEF;
380
 
  ws->in.read = INVALID_HANDLE_VALUE;
381
 
  ws->in.write = INVALID_HANDLE_VALUE;
382
 
  ws->console_mode_save = 0;
383
 
  ws->console_mode_save_defined = false;
384
 
 
385
 
  if (force == WSO_NOFORCE || force == WSO_FORCE_CONSOLE)
386
 
    {
387
 
      /*
388
 
       * Try to open console.
389
 
       */
390
 
      ws->in.read = GetStdHandle (STD_INPUT_HANDLE);
391
 
      if (ws->in.read != INVALID_HANDLE_VALUE)
392
 
        {
393
 
          if (GetConsoleMode (ws->in.read, &ws->console_mode_save))
394
 
            {
395
 
              /* running on a console */
396
 
              const DWORD new_console_mode = ws->console_mode_save
397
 
                & ~(ENABLE_WINDOW_INPUT
398
 
                    | ENABLE_PROCESSED_INPUT
399
 
                    | ENABLE_LINE_INPUT
400
 
                    | ENABLE_ECHO_INPUT 
401
 
                    | ENABLE_MOUSE_INPUT);
402
 
 
403
 
              if (new_console_mode != ws->console_mode_save)
404
 
                {
405
 
                  if (!SetConsoleMode (ws->in.read, new_console_mode))
406
 
                    msg (M_ERR, "Error: win32_signal_open: SetConsoleMode failed");
407
 
                  ws->console_mode_save_defined = true;
408
 
                }
409
 
              ws->mode = WSO_MODE_CONSOLE;
410
 
            }
411
 
          else
412
 
            ws->in.read = INVALID_HANDLE_VALUE; /* probably running as a service */
413
 
        }
414
 
    }
415
 
 
416
 
  /*
417
 
   * If console open failed, assume we are running
418
 
   * as a service.
419
 
   */
420
 
  if ((force == WSO_NOFORCE || force == WSO_FORCE_SERVICE)
421
 
      && !HANDLE_DEFINED (ws->in.read) && exit_event_name)
422
 
    {
423
 
      struct security_attributes sa;
424
 
 
425
 
      if (!init_security_attributes_allow_all (&sa))
426
 
        msg (M_ERR, "Error: win32_signal_open: init SA failed");
427
 
 
428
 
      ws->in.read = CreateEvent (&sa.sa,
429
 
                                 TRUE,
430
 
                                 exit_event_initial_state ? TRUE : FALSE,
431
 
                                 exit_event_name);
432
 
      if (ws->in.read == NULL)
433
 
        {
434
 
          msg (M_WARN|M_ERRNO, "NOTE: CreateEvent '%s' failed", exit_event_name);
435
 
        }
436
 
      else
437
 
        {
438
 
          if (WaitForSingleObject (ws->in.read, 0) != WAIT_TIMEOUT)
439
 
            msg (M_FATAL, "ERROR: Exit Event ('%s') is signaled", exit_event_name);
440
 
          else
441
 
            ws->mode = WSO_MODE_SERVICE;
442
 
        }
443
 
    }
444
 
}
445
 
 
446
 
static bool
447
 
keyboard_input_available (struct win32_signal *ws)
448
 
{
449
 
  ASSERT (ws->mode == WSO_MODE_CONSOLE);
450
 
  if (HANDLE_DEFINED (ws->in.read))
451
 
    {
452
 
      DWORD n;
453
 
      if (GetNumberOfConsoleInputEvents (ws->in.read, &n))
454
 
        return n > 0;
455
 
    }
456
 
  return false;
457
 
}
458
 
 
459
 
static unsigned int
460
 
keyboard_ir_to_key (INPUT_RECORD *ir)
461
 
{
462
 
  if (ir->Event.KeyEvent.uChar.AsciiChar == 0)
463
 
    return ir->Event.KeyEvent.wVirtualScanCode;
464
 
 
465
 
  if ((ir->Event.KeyEvent.dwControlKeyState
466
 
       & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
467
 
      && (ir->Event.KeyEvent.wVirtualKeyCode != 18))
468
 
    return ir->Event.KeyEvent.wVirtualScanCode * 256;
469
 
 
470
 
  return ir->Event.KeyEvent.uChar.AsciiChar;
471
 
}
472
 
 
473
 
static unsigned int
474
 
win32_keyboard_get (struct win32_signal *ws)
475
 
{
476
 
  ASSERT (ws->mode == WSO_MODE_CONSOLE);
477
 
  if (HANDLE_DEFINED (ws->in.read))
478
 
    {
479
 
      INPUT_RECORD ir;
480
 
      do {
481
 
        DWORD n;
482
 
        if (!keyboard_input_available (ws))
483
 
          return 0;
484
 
        if (!ReadConsoleInput (ws->in.read, &ir, 1, &n))
485
 
          return 0;
486
 
      } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE);
487
 
 
488
 
      return keyboard_ir_to_key (&ir);
489
 
    }
490
 
  else
491
 
    return 0;
492
 
}
493
 
 
494
 
void
495
 
win32_signal_close (struct win32_signal *ws)
496
 
{
497
 
  if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED (ws->in.read))
498
 
    CloseHandle (ws->in.read);
499
 
  if (ws->console_mode_save_defined)
500
 
    {
501
 
      if (!SetConsoleMode (ws->in.read, ws->console_mode_save))
502
 
        msg (M_ERR, "Error: win32_signal_close: SetConsoleMode failed");
503
 
    }
504
 
  CLEAR (*ws);
505
 
}
506
 
 
507
 
/*
508
 
 * Return true if interrupt occurs in service mode.
509
 
 */
510
 
static bool
511
 
win32_service_interrupt (struct win32_signal *ws)
512
 
{
513
 
  if (ws->mode == WSO_MODE_SERVICE)
514
 
    {
515
 
      if (HANDLE_DEFINED (ws->in.read)
516
 
          && WaitForSingleObject (ws->in.read, 0) == WAIT_OBJECT_0)
517
 
        return true;
518
 
    }
519
 
  return false;
520
 
}
521
 
 
522
 
int
523
 
win32_signal_get (struct win32_signal *ws)
524
 
{
525
 
  int ret = 0;
526
 
  if (siginfo_static.signal_received)
527
 
    {
528
 
      ret = siginfo_static.signal_received;
529
 
    }
530
 
  else
531
 
    {
532
 
      if (ws->mode == WSO_MODE_SERVICE)
533
 
        {
534
 
          if (win32_service_interrupt (ws))
535
 
            ret = SIGTERM;
536
 
        }
537
 
      else if (ws->mode == WSO_MODE_CONSOLE)
538
 
        {
539
 
          switch (win32_keyboard_get (ws))
540
 
            {
541
 
            case 0x3B: /* F1 -> USR1 */
542
 
              ret = SIGUSR1;
543
 
              break;
544
 
            case 0x3C: /* F2 -> USR2 */
545
 
              ret = SIGUSR2;
546
 
              break;
547
 
            case 0x3D: /* F3 -> HUP */
548
 
              ret = SIGHUP;
549
 
              break;
550
 
            case 0x3E: /* F4 -> TERM */
551
 
              ret = SIGTERM;
552
 
              break;
553
 
            }
554
 
        }
555
 
      if (ret)
556
 
        {
557
 
          siginfo_static.signal_received = ret;
558
 
          siginfo_static.hard = true;
559
 
        }
560
 
    }
561
 
  return ret;
562
 
}
563
 
 
564
 
void
565
 
win32_pause (struct win32_signal *ws)
566
 
{
567
 
  if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED (ws->in.read))
568
 
    {
569
 
      int status;
570
 
      msg (M_INFO|M_NOPREFIX, "Press any key to continue...");
571
 
      do {
572
 
        status = WaitForSingleObject (ws->in.read, INFINITE);
573
 
      } while (!win32_keyboard_get (ws));
574
 
    }
575
 
}
576
 
 
577
 
/* window functions */
578
 
 
579
 
void
580
 
window_title_clear (struct window_title *wt)
581
 
{
582
 
  CLEAR (*wt);
583
 
}
584
 
 
585
 
void
586
 
window_title_save (struct window_title *wt)
587
 
{
588
 
  if (!wt->saved)
589
 
    {
590
 
      if (!GetConsoleTitle (wt->old_window_title, sizeof (wt->old_window_title)))
591
 
        {
592
 
          wt->old_window_title[0] = 0;
593
 
          wt->saved = false;
594
 
        }
595
 
      else
596
 
        wt->saved = true;
597
 
    }
598
 
}
599
 
 
600
 
void
601
 
window_title_restore (const struct window_title *wt)
602
 
{
603
 
  if (wt->saved)
604
 
    SetConsoleTitle (wt->old_window_title);
605
 
}
606
 
 
607
 
void
608
 
window_title_generate (const char *title)
609
 
{
610
 
  struct gc_arena gc = gc_new ();
611
 
  struct buffer out = alloc_buf_gc (256, &gc);
612
 
  if (!title)
613
 
    title = "";
614
 
  buf_printf (&out, "[%s] " PACKAGE_NAME " " VERSION " F4:EXIT F1:USR1 F2:USR2 F3:HUP", title);
615
 
  SetConsoleTitle (BSTR (&out));
616
 
  gc_free (&gc);
617
 
}
618
 
 
619
 
/* semaphore functions */
620
 
 
621
 
void
622
 
semaphore_clear (struct semaphore *s)
623
 
{
624
 
  CLEAR (*s);
625
 
}
626
 
 
627
 
void
628
 
semaphore_open (struct semaphore *s, const char *name)
629
 
{
630
 
  struct security_attributes sa;
631
 
 
632
 
  s->locked = false;
633
 
  s->name = name;
634
 
  s->hand = NULL;
635
 
 
636
 
  if (init_security_attributes_allow_all (&sa))
637
 
    s->hand = CreateSemaphore(&sa.sa, 1, 1, name);
638
 
 
639
 
  if (s->hand == NULL)
640
 
    msg (M_WARN|M_ERRNO, "WARNING: Cannot create Win32 semaphore '%s'", name);
641
 
  else
642
 
    dmsg (D_SEMAPHORE, "Created Win32 semaphore '%s'", s->name);
643
 
}
644
 
 
645
 
bool
646
 
semaphore_lock (struct semaphore *s, int timeout_milliseconds)
647
 
{
648
 
  bool ret = true;
649
 
 
650
 
  if (s->hand)
651
 
    {
652
 
      DWORD status;
653
 
      ASSERT (!s->locked);
654
 
 
655
 
      dmsg (D_SEMAPHORE_LOW, "Attempting to lock Win32 semaphore '%s' prior to net shell command (timeout = %d sec)",
656
 
           s->name,
657
 
           timeout_milliseconds / 1000);
658
 
      status = WaitForSingleObject (s->hand, timeout_milliseconds);
659
 
      if (status == WAIT_FAILED)
660
 
        msg (M_ERR, "Wait failed on Win32 semaphore '%s'", s->name);
661
 
      ret = (status == WAIT_TIMEOUT) ? false : true;
662
 
      if (ret)
663
 
        {
664
 
          dmsg (D_SEMAPHORE, "Locked Win32 semaphore '%s'", s->name);
665
 
          s->locked = true;
666
 
        }
667
 
      else
668
 
        {
669
 
          dmsg (D_SEMAPHORE, "Wait on Win32 semaphore '%s' timed out after %d milliseconds",
670
 
               s->name,
671
 
               timeout_milliseconds);
672
 
        }
673
 
    }
674
 
  return ret;
675
 
}
676
 
 
677
 
void
678
 
semaphore_release (struct semaphore *s)
679
 
{
680
 
  if (s->hand)
681
 
    {
682
 
      ASSERT (s->locked);
683
 
      dmsg (D_SEMAPHORE, "Releasing Win32 semaphore '%s'", s->name);
684
 
      if (!ReleaseSemaphore(s->hand, 1, NULL))
685
 
        msg (M_WARN | M_ERRNO, "ReleaseSemaphore failed on Win32 semaphore '%s'",
686
 
             s->name);
687
 
      s->locked = false;
688
 
    }
689
 
}
690
 
 
691
 
void
692
 
semaphore_close (struct semaphore *s)
693
 
{
694
 
  if (s->hand)
695
 
    {
696
 
      if (s->locked)
697
 
        semaphore_release (s);
698
 
      dmsg (D_SEMAPHORE, "Closing Win32 semaphore '%s'", s->name);
699
 
      CloseHandle (s->hand);
700
 
      s->hand = NULL;
701
 
    }
702
 
}
703
 
 
704
 
/*
705
 
 * Special global semaphore used to protect network
706
 
 * shell commands from simultaneous instantiation.
707
 
 */
708
 
 
709
 
void
710
 
netcmd_semaphore_init (void)
711
 
{
712
 
  semaphore_open (&netcmd_semaphore, PACKAGE "_netcmd");
713
 
}
714
 
 
715
 
void
716
 
netcmd_semaphore_close (void)
717
 
{
718
 
  semaphore_close (&netcmd_semaphore);
719
 
}
720
 
 
721
 
void
722
 
netcmd_semaphore_lock (void)
723
 
{
724
 
  const int timeout_seconds = 600;
725
 
  if (!semaphore_lock (&netcmd_semaphore, timeout_seconds * 1000))
726
 
    msg (M_FATAL, "Cannot lock net command semaphore"); 
727
 
}
728
 
 
729
 
void
730
 
netcmd_semaphore_release (void)
731
 
{
732
 
  semaphore_release (&netcmd_semaphore);
733
 
}
734
 
 
735
 
/*
736
 
 * Get input from console.
737
 
 *
738
 
 * Return false on input error, or if service
739
 
 * exit event is signaled.
740
 
 */
741
 
 
742
 
bool
743
 
get_console_input_win32 (const char *prompt, const bool echo, char *input, const int capacity)
744
 
{
745
 
  HANDLE in = INVALID_HANDLE_VALUE;
746
 
  HANDLE err = INVALID_HANDLE_VALUE;
747
 
  DWORD len = 0;
748
 
 
749
 
  ASSERT (prompt);
750
 
  ASSERT (input);
751
 
  ASSERT (capacity > 0);
752
 
 
753
 
  input[0] = '\0';
754
 
 
755
 
  in = GetStdHandle (STD_INPUT_HANDLE);
756
 
  err = get_orig_stderr ();
757
 
 
758
 
  if (in != INVALID_HANDLE_VALUE
759
 
      && err != INVALID_HANDLE_VALUE
760
 
      && !win32_service_interrupt (&win32_signal)
761
 
      && WriteFile (err, prompt, strlen (prompt), &len, NULL))
762
 
    {
763
 
      bool is_console = (GetFileType (in) == FILE_TYPE_CHAR);
764
 
      DWORD flags_save = 0;
765
 
      int status = 0;
766
 
 
767
 
      if (is_console)
768
 
        {
769
 
          if (GetConsoleMode (in, &flags_save))
770
 
            {
771
 
              DWORD flags = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
772
 
              if (echo)
773
 
                flags |= ENABLE_ECHO_INPUT;
774
 
              SetConsoleMode (in, flags);
775
 
            }
776
 
          else
777
 
            is_console = 0;
778
 
        }
779
 
 
780
 
      status = ReadFile (in, input, capacity, &len, NULL);
781
 
 
782
 
      string_null_terminate (input, (int)len, capacity);
783
 
      chomp (input);
784
 
 
785
 
      if (!echo)
786
 
        WriteFile (err, "\r\n", 2, &len, NULL);
787
 
      if (is_console)
788
 
        SetConsoleMode (in, flags_save);
789
 
      if (status && !win32_service_interrupt (&win32_signal))
790
 
        return true;
791
 
    }
792
 
 
793
 
  return false;
794
 
}
795
 
 
796
 
/* get password from console */
797
 
 
798
 
char *
799
 
getpass (const char *prompt)
800
 
{
801
 
  static char line[256];
802
 
  if (get_console_input_win32 (prompt, false, line, sizeof (line)))
803
 
    return line;
804
 
  else
805
 
    return NULL;
806
 
}
807
 
 
808
 
/*
809
 
 * Return true if filename is safe to be used on Windows,
810
 
 * by avoiding the following reserved names:
811
 
 *
812
 
 * CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9,
813
 
 * LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, and CLOCK$
814
 
 *
815
 
 * See: http://msdn.microsoft.com/en-us/library/aa365247.aspx
816
 
 *  and http://msdn.microsoft.com/en-us/library/86k9f82k(VS.80).aspx
817
 
 */
818
 
 
819
 
static bool
820
 
cmp_prefix (const char *str, const bool n, const char *pre)
821
 
{
822
 
  size_t i = 0;
823
 
 
824
 
  if (!str)
825
 
    return false;
826
 
 
827
 
  while (true)
828
 
    {
829
 
      const int c1 = pre[i];
830
 
      int c2 = str[i];
831
 
      ++i;
832
 
      if (c1 == '\0')
833
 
        {
834
 
          if (n)
835
 
            {
836
 
              if (isdigit (c2))
837
 
                c2 = str[i];
838
 
              else
839
 
                return false;
840
 
            }
841
 
          return c2 == '\0' || c2 == '.';
842
 
        }
843
 
      else if (c2 == '\0')
844
 
        return false;
845
 
      if (c1 != tolower(c2))
846
 
        return false;
847
 
    }
848
 
}
849
 
 
850
 
bool
851
 
win_safe_filename (const char *fn)
852
 
{
853
 
  if (cmp_prefix (fn, false, "con"))
854
 
    return false;
855
 
  if (cmp_prefix (fn, false, "prn"))
856
 
    return false;
857
 
  if (cmp_prefix (fn, false, "aux"))
858
 
    return false;
859
 
  if (cmp_prefix (fn, false, "nul"))
860
 
    return false;
861
 
  if (cmp_prefix (fn, true, "com"))
862
 
    return false;
863
 
  if (cmp_prefix (fn, true, "lpt"))
864
 
    return false;
865
 
  if (cmp_prefix (fn, false, "clock$"))
866
 
    return false;
867
 
  return true;
868
 
}
869
 
 
870
 
/*
871
 
 * Service functions for openvpn_execve
872
 
 */
873
 
 
874
 
static char *
875
 
env_block (const struct env_set *es)
876
 
{
877
 
  if (es)
878
 
    {
879
 
      struct env_item *e;
880
 
      char *ret;
881
 
      char *p;
882
 
      size_t nchars = 1;
883
 
      
884
 
      for (e = es->list; e != NULL; e = e->next)
885
 
        nchars += strlen (e->string) + 1;
886
 
 
887
 
      ret = (char *) malloc (nchars);
888
 
      check_malloc_return (ret);
889
 
 
890
 
      p = ret;
891
 
      for (e = es->list; e != NULL; e = e->next)
892
 
        {
893
 
          if (env_allowed (e->string))
894
 
            {
895
 
              strcpy (p, e->string);
896
 
              p += strlen (e->string) + 1;
897
 
            }
898
 
        }
899
 
      *p = '\0';
900
 
      return ret;
901
 
    }
902
 
  else
903
 
    return NULL;
904
 
}
905
 
 
906
 
static char *
907
 
cmd_line (const struct argv *a)
908
 
{
909
 
  size_t nchars = 1;
910
 
  size_t maxlen = 0;
911
 
  size_t i;
912
 
  struct buffer buf;
913
 
  char *work = NULL;
914
 
 
915
 
  if (!a)
916
 
    return NULL;
917
 
 
918
 
  for (i = 0; i < a->argc; ++i)
919
 
    {
920
 
      const char *arg = a->argv[i];
921
 
      const size_t len = strlen (arg);
922
 
      nchars += len + 3;
923
 
      if (len > maxlen)
924
 
        maxlen = len;
925
 
    }
926
 
 
927
 
  work = (char *) malloc (maxlen + 1);
928
 
  check_malloc_return (work);
929
 
  buf = alloc_buf (nchars);
930
 
 
931
 
  for (i = 0; i < a->argc; ++i)
932
 
    {
933
 
      const char *arg = a->argv[i];
934
 
      strcpy (work, arg);
935
 
      string_mod (work, CC_PRINT, CC_DOUBLE_QUOTE|CC_CRLF, '_');
936
 
      if (i)
937
 
        buf_printf (&buf, " ");
938
 
      if (string_class (work, CC_ANY, CC_SPACE))
939
 
        buf_printf (&buf, "%s", work);
940
 
      else
941
 
        buf_printf (&buf, "\"%s\"", work);
942
 
    }
943
 
 
944
 
  free (work);
945
 
  return BSTR(&buf);
946
 
}
947
 
 
948
 
/*
949
 
 * Attempt to simulate fork/execve on Windows
950
 
 */
951
 
int
952
 
openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags)
953
 
{
954
 
  int ret = -1;
955
 
  static bool exec_warn = false;
956
 
 
957
 
  if (a && a->argv[0])
958
 
    {
959
 
      if (openvpn_execve_allowed (flags))
960
 
        {
961
 
          if (script_method == SM_EXECVE)
962
 
            {
963
 
              STARTUPINFO start_info;
964
 
              PROCESS_INFORMATION proc_info;
965
 
 
966
 
              char *env = env_block (es);
967
 
              char *cl = cmd_line (a);
968
 
              char *cmd = a->argv[0];
969
 
 
970
 
              CLEAR (start_info);
971
 
              CLEAR (proc_info);
972
 
 
973
 
              /* fill in STARTUPINFO struct */
974
 
              GetStartupInfo(&start_info);
975
 
              start_info.cb = sizeof(start_info);
976
 
              start_info.dwFlags = STARTF_USESHOWWINDOW;
977
 
              start_info.wShowWindow = SW_HIDE;
978
 
 
979
 
              if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
980
 
                {
981
 
                  DWORD exit_status = 0;
982
 
                  CloseHandle (proc_info.hThread);
983
 
                  WaitForSingleObject (proc_info.hProcess, INFINITE);
984
 
                  if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
985
 
                    ret = (int)exit_status;
986
 
                  else
987
 
                    msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %s failed", cmd);
988
 
                  CloseHandle (proc_info.hProcess);
989
 
                }
990
 
              else
991
 
                {
992
 
                  msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %s failed", cmd);
993
 
                }
994
 
              free (cl);
995
 
              free (env);
996
 
            }
997
 
          else if (script_method == SM_SYSTEM)
998
 
            {
999
 
              configure_win_path ();
1000
 
              ret = openvpn_system (argv_system_str (a), es, flags);
1001
 
            }
1002
 
          else
1003
 
            {
1004
 
              ASSERT (0);
1005
 
            }
1006
 
        }
1007
 
      else if (!exec_warn && (script_security < SSEC_SCRIPTS))
1008
 
        {
1009
 
          msg (M_WARN, SCRIPT_SECURITY_WARNING);
1010
 
          exec_warn = true;
1011
 
        }
1012
 
    }
1013
 
  else
1014
 
    {
1015
 
      msg (M_WARN, "openvpn_execve: called with empty argv");
1016
 
    }
1017
 
  return ret;
1018
 
}
1019
 
 
1020
 
/*
1021
 
 * call ourself in another process
1022
 
 */
1023
 
void
1024
 
fork_to_self (const char *cmdline)
1025
 
{
1026
 
  STARTUPINFO start_info;
1027
 
  PROCESS_INFORMATION proc_info;
1028
 
  char self_exe[256];
1029
 
  char *cl = string_alloc (cmdline, NULL);
1030
 
  DWORD status;
1031
 
 
1032
 
  CLEAR (start_info);
1033
 
  CLEAR (proc_info);
1034
 
  CLEAR (self_exe);
1035
 
 
1036
 
  status = GetModuleFileName (NULL, self_exe, sizeof(self_exe));
1037
 
  if (status == 0 || status == sizeof(self_exe))
1038
 
    {
1039
 
      msg (M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: cannot get module name via GetModuleFileName");
1040
 
      goto done;
1041
 
    }
1042
 
 
1043
 
  /* fill in STARTUPINFO struct */
1044
 
  GetStartupInfo(&start_info);
1045
 
  start_info.cb = sizeof(start_info);
1046
 
  start_info.dwFlags = STARTF_USESHOWWINDOW;
1047
 
  start_info.wShowWindow = SW_HIDE;
1048
 
 
1049
 
  if (CreateProcess (self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info))
1050
 
    {
1051
 
      CloseHandle (proc_info.hThread);
1052
 
      CloseHandle (proc_info.hProcess);
1053
 
    }
1054
 
  else
1055
 
    {
1056
 
      msg (M_WARN|M_ERRNO, "fork_to_self: CreateProcess failed: %s", cmdline);
1057
 
    }
1058
 
 
1059
 
 done:
1060
 
  free (cl);
1061
 
}
1062
 
 
1063
 
char *
1064
 
get_win_sys_path (void)
1065
 
{
1066
 
  ASSERT (win_sys_path);
1067
 
  return win_sys_path;
1068
 
}
1069
 
 
1070
 
void
1071
 
set_win_sys_path (const char *newpath, struct env_set *es)
1072
 
{
1073
 
  free (win_sys_path);
1074
 
  win_sys_path = string_alloc (newpath, NULL);
1075
 
  setenv_str (es, SYS_PATH_ENV_VAR_NAME, win_sys_path); /* route.exe needs this */
1076
 
}
1077
 
 
1078
 
void
1079
 
set_win_sys_path_via_env (struct env_set *es)
1080
 
{
1081
 
  char buf[256];
1082
 
  DWORD status = GetEnvironmentVariable (SYS_PATH_ENV_VAR_NAME, buf, sizeof(buf));
1083
 
  if (!status)
1084
 
    msg (M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1085
 
  if (status > sizeof (buf) - 1)
1086
 
    msg (M_FATAL, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME);
1087
 
  set_win_sys_path (buf, es);
1088
 
}
1089
 
 
1090
 
void
1091
 
env_set_add_win32 (struct env_set *es)
1092
 
{
1093
 
  set_win_sys_path (DEFAULT_WIN_SYS_PATH, es);
1094
 
}
1095
 
 
1096
 
 
1097
 
const char *
1098
 
win_get_tempdir()
1099
 
{
1100
 
  static char buf[MAX_PATH];
1101
 
  char *tmpdir = buf;
1102
 
 
1103
 
  CLEAR(buf);
1104
 
 
1105
 
  if (!GetTempPath(sizeof(buf),buf)) {
1106
 
    /* Warn if we can't find a valid temporary directory, which should
1107
 
     * be unlikely.
1108
 
     */
1109
 
    msg (M_WARN, "Could not find a suitable temporary directory."
1110
 
         " (GetTempPath() failed).  Consider to use --tmp-dir");
1111
 
    tmpdir = NULL;
1112
 
  }
1113
 
  return tmpdir;
1114
 
}
1115
 
#endif