~smoser/ubuntu/oneiric/openvpn/lp-794916

« back to all changes in this revision

Viewing changes to misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Gonzalez Iniesta
  • Date: 2008-08-16 13:34:24 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20080816133424-0i83yb6dw4hjglo1
Tags: 2.1~rc9-3
* debian/rules: run ./configure with path to 'route', for
  those build daemons without 'route'. (Closes: #495082)
* Created NEWS.Debian with info on new option script-security.
  (Closes: #494998)

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *             packet encryption, packet authentication, and
6
6
 *             packet compression.
7
7
 *
8
 
 *  Copyright (C) 2002-2008 OpenVPN Solutions LLC <info@openvpn.net>
 
8
 *  Copyright (C) 2002-2008 Telethra, Inc. <sales@openvpn.net>
9
9
 *
10
10
 *  This program is free software; you can redistribute it and/or modify
11
11
 *  it under the terms of the GNU General Public License version 2
35
35
#include "manage.h"
36
36
#include "crypto.h"
37
37
#include "route.h"
 
38
#include "win32.h"
38
39
 
39
40
#include "memdbg.h"
40
41
 
41
42
#ifdef CONFIG_FEATURE_IPROUTE
42
 
const char *iproute_path = IPROUTE_PATH;
 
43
const char *iproute_path = IPROUTE_PATH; /* GLOBAL */
43
44
#endif
44
45
 
 
46
/* contains an SSEC_x value defined in misc.h */
 
47
int script_security = SSEC_BUILT_IN; /* GLOBAL */
 
48
 
45
49
/* Redefine the top level directory of the filesystem
46
50
   to restrict access to files for security */
47
51
void
195
199
 
196
200
  if (plugin_defined (plugins, plugin_type))
197
201
    {
198
 
      struct buffer cmd = alloc_buf_gc (256, &gc);
199
 
 
 
202
      struct argv argv = argv_new ();
200
203
      ASSERT (arg);
201
 
 
202
 
      buf_printf (&cmd,
203
 
                  "\"%s\" %d %d %s %s %s",
204
 
                  arg,
205
 
                  tun_mtu, link_mtu,
206
 
                  ifconfig_local, ifconfig_remote,
207
 
                  context);
208
 
 
209
 
      if (plugin_call (plugins, plugin_type, BSTR (&cmd), NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
 
204
      argv_printf (&argv,
 
205
                   "%s %d %d %s %s %s",
 
206
                   arg,
 
207
                   tun_mtu, link_mtu,
 
208
                   ifconfig_local, ifconfig_remote,
 
209
                   context);
 
210
 
 
211
      if (plugin_call (plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
210
212
        msg (M_FATAL, "ERROR: up/down plugin call failed");
 
213
 
 
214
      argv_reset (&argv);
211
215
    }
212
216
 
213
217
  if (command)
214
218
    {
215
 
      struct buffer cmd = alloc_buf_gc (256, &gc);
216
 
 
 
219
      struct argv argv = argv_new ();
217
220
      ASSERT (arg);
218
 
 
219
221
      setenv_str (es, "script_type", script_type);
220
 
 
221
 
      buf_printf (&cmd,
222
 
                  "%s \"%s\" %d %d %s %s %s",
 
222
      argv_printf (&argv,
 
223
                  "%s %s %d %d %s %s %s",
223
224
                  command,
224
225
                  arg,
225
226
                  tun_mtu, link_mtu,
226
227
                  ifconfig_local, ifconfig_remote,
227
228
                  context);
228
 
      msg (M_INFO, "%s", BSTR (&cmd));
229
 
      system_check (BSTR (&cmd), es, S_SCRIPT|S_FATAL, "script failed");
 
229
      argv_msg (M_INFO, &argv);
 
230
      openvpn_execve_check (&argv, es, S_SCRIPT|S_FATAL, "script failed");
 
231
      argv_reset (&argv);
230
232
    }
231
233
 
232
234
  gc_free (&gc);
374
376
}
375
377
 
376
378
/*
377
 
 * Wrapper around the system() call.
378
 
 */
379
 
int
380
 
openvpn_system (const char *command, const struct env_set *es, unsigned int flags)
381
 
{
382
 
#ifdef HAVE_SYSTEM
383
 
  int ret;
384
 
 
385
 
  /*
386
 
   * We need to bracket this code by mutex because system() doesn't
387
 
   * accept an environment list, so we have to use the process-wide
388
 
   * list which is shared between all threads.
389
 
   */
390
 
  mutex_lock_static (L_SYSTEM);
391
 
  perf_push (PERF_SCRIPT);
392
 
 
393
 
  /*
394
 
   * add env_set to environment.
395
 
   */
396
 
  if (flags & S_SCRIPT)
397
 
    env_set_add_to_environment (es);
398
 
 
399
 
 
400
 
  /* debugging */
401
 
  dmsg (D_SCRIPT, "SYSTEM[%u] '%s'", flags, command);
402
 
  if (flags & S_SCRIPT)
403
 
    env_set_print (D_SCRIPT, es);
404
 
 
405
 
  /*
406
 
   * execute the command
407
 
   */
408
 
  ret = system (command);
409
 
 
410
 
  /* debugging */
411
 
  dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
412
 
 
413
 
  /*
414
 
   * remove env_set from environment
415
 
   */
416
 
  if (flags & S_SCRIPT)
417
 
    env_set_remove_from_environment (es);
418
 
 
419
 
  perf_pop ();
420
 
  mutex_unlock_static (L_SYSTEM);
421
 
  return ret;
422
 
 
423
 
#else
424
 
  msg (M_FATAL, "Sorry but I can't execute the shell command '%s' because this operating system doesn't appear to support the system() call", command);
425
 
  return -1; /* NOTREACHED */
426
 
#endif
427
 
}
428
 
 
429
 
/*
430
379
 * Warn if a given file is group/others accessible.
431
380
 */
432
381
void
488
437
  struct buffer out = alloc_buf_gc (256, gc);
489
438
#ifdef WIN32
490
439
  if (stat == -1)
491
 
    buf_printf (&out, "shell command did not execute -- ");
492
 
  buf_printf (&out, "system() returned error code %d", stat);
 
440
    buf_printf (&out, "external program did not execute -- ");
 
441
  buf_printf (&out, "returned error code %d", stat);
493
442
#else
494
443
  if (stat == -1)
495
 
    buf_printf (&out, "shell command fork failed");
 
444
    buf_printf (&out, "external program fork failed");
496
445
  else if (!WIFEXITED (stat))
497
 
    buf_printf (&out, "shell command did not exit normally");
 
446
    buf_printf (&out, "external program did not exit normally");
498
447
  else
499
448
    {
500
449
      const int cmd_ret = WEXITSTATUS (stat);
501
450
      if (!cmd_ret)
502
 
        buf_printf (&out, "shell command exited normally");
 
451
        buf_printf (&out, "external program exited normally");
503
452
      else if (cmd_ret == 127)
504
 
        buf_printf (&out, "could not execute shell command");
 
453
        buf_printf (&out, "could not execute external program");
505
454
      else
506
 
        buf_printf (&out, "shell command exited with error status: %d", cmd_ret);
 
455
        buf_printf (&out, "external program exited with error status: %d", cmd_ret);
507
456
    }
508
457
#endif
509
458
  return (const char *)out.data;
510
459
}
511
460
 
512
461
/*
513
 
 * Run system(), exiting on error.
 
462
 * Wrapper around openvpn_execve
514
463
 */
515
464
bool
516
 
system_check (const char *command, const struct env_set *es, unsigned int flags, const char *error_message)
 
465
openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
517
466
{
518
467
  struct gc_arena gc = gc_new ();
519
 
  const int stat = openvpn_system (command, es, flags);
 
468
  const int stat = openvpn_execve (a, es, flags);
520
469
  int ret = false;
521
470
 
522
471
  if (system_ok (stat))
532
481
  return ret;
533
482
}
534
483
 
 
484
bool
 
485
openvpn_execve_allowed (const unsigned int flags)
 
486
{
 
487
  if (flags & S_SCRIPT)
 
488
    return script_security >= SSEC_SCRIPTS;
 
489
  else
 
490
    return script_security >= SSEC_BUILT_IN;
 
491
}
 
492
 
 
493
#ifndef WIN32
 
494
/*
 
495
 * Run execve() inside a fork().  Designed to replicate the semantics of system() but
 
496
 * in a safer way that doesn't require the invocation of a shell or the risks
 
497
 * assocated with formatting and parsing a command line.
 
498
 */
 
499
int
 
500
openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags)
 
501
{
 
502
  struct gc_arena gc = gc_new ();
 
503
  int ret = -1;
 
504
 
 
505
  if (a && a->argv[0])
 
506
    {
 
507
#if defined(ENABLE_EXECVE)
 
508
      if (openvpn_execve_allowed (flags))
 
509
        {
 
510
          const char *cmd = a->argv[0];
 
511
          char *const *argv = a->argv;
 
512
          char *const *envp = (char *const *)make_env_array (es, true, &gc);
 
513
          pid_t pid;
 
514
 
 
515
          pid = fork ();
 
516
          if (pid == (pid_t)0) /* child side */
 
517
            {
 
518
              execve (cmd, argv, envp);
 
519
              exit (127);
 
520
            }
 
521
          else if (pid < (pid_t)0) /* fork failed */
 
522
            ;
 
523
          else /* parent side */
 
524
            {
 
525
              if (waitpid (pid, &ret, 0) != pid)
 
526
                ret = -1;
 
527
            }
 
528
        }
 
529
      else
 
530
        {
 
531
          msg (M_WARN, "openvpn_execve: external program may not be called due to setting of --script-security level");
 
532
        }
 
533
#else
 
534
      msg (M_WARN, "openvpn_execve: execve function not available");
 
535
#endif
 
536
    }
 
537
  else
 
538
    {
 
539
      msg (M_WARN, "openvpn_execve: called with empty argv");
 
540
    }
 
541
 
 
542
  gc_free (&gc);
 
543
  return ret;
 
544
}
 
545
#endif
 
546
 
535
547
/*
536
548
 * Initialize random number seed.  random() is only used
537
549
 * when "weak" random numbers are acceptable.
769
781
 
770
782
          while (e)
771
783
            {
772
 
              msg (msglevel, "ENV [%d] '%s'", i, e->string);
 
784
              if (env_safe_to_print (e->string))
 
785
                msg (msglevel, "ENV [%d] '%s'", i, e->string);
773
786
              ++i;
774
787
              e = e->next;
775
788
            }
900
913
void
901
914
setenv_str_safe (struct env_set *es, const char *name, const char *value)
902
915
{
903
 
  char buf[64];
904
 
  openvpn_snprintf (buf, sizeof(buf), "OPENVPN_%s", name);
905
 
  setenv_str (es, buf, value);
 
916
  uint8_t b[64];
 
917
  struct buffer buf;
 
918
  buf_set_write (&buf, b, sizeof (b));
 
919
  if (buf_printf (&buf, "OPENVPN_%s", name))
 
920
    setenv_str (es, BSTR(&buf), value);
 
921
  else
 
922
    msg (M_WARN, "setenv_str_safe: name overflow");
906
923
}
907
924
 
908
925
void
1084
1101
  return ret;
1085
1102
}
1086
1103
 
 
1104
#ifdef USE_CRYPTO
 
1105
 
1087
1106
/* create a temporary filename in directory */
1088
1107
const char *
1089
1108
create_temp_filename (const char *directory, const char *prefix, struct gc_arena *gc)
1095
1114
  ++counter;
1096
1115
  mutex_unlock_static (L_CREATE_TEMP);
1097
1116
 
1098
 
  buf_printf (&fname, PACKAGE "_%s_%u_%u_%u.tmp",
1099
 
              prefix,
1100
 
              openvpn_getpid (),
1101
 
              counter,
1102
 
              (unsigned int)now);
 
1117
  {
 
1118
    uint8_t rndbytes[16];
 
1119
    const char *rndstr;
 
1120
 
 
1121
    prng_bytes (rndbytes, sizeof (rndbytes));
 
1122
    rndstr = format_hex_ex (rndbytes, sizeof (rndbytes), 40, 0, NULL, gc);
 
1123
    buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr);
 
1124
  }
1103
1125
 
1104
1126
  return gen_path (directory, BSTR (&fname), gc);
1105
1127
}
1106
1128
 
 
1129
#endif
 
1130
 
1107
1131
/*
1108
1132
 * Put a directory and filename together.
1109
1133
 */
1114
1138
 
1115
1139
  if (safe_filename
1116
1140
      && strcmp (safe_filename, ".")
1117
 
      && strcmp (safe_filename, ".."))
 
1141
      && strcmp (safe_filename, "..")
 
1142
#ifdef WIN32
 
1143
      && win_safe_filename (safe_filename)
 
1144
#endif
 
1145
      )
1118
1146
    {
1119
 
      struct buffer out = alloc_buf_gc (256, gc);
 
1147
      const size_t outsize = strlen(safe_filename) + (directory ? strlen (directory) : 0) + 16;
 
1148
      struct buffer out = alloc_buf_gc (outsize, gc);
1120
1149
      char dirsep[2];
1121
1150
 
1122
1151
      dirsep[0] = OS_SPECIFIC_DIRSEP;
1145
1174
#endif
1146
1175
}
1147
1176
 
 
1177
bool
 
1178
absolute_pathname (const char *pathname)
 
1179
{
 
1180
  if (pathname)
 
1181
    {
 
1182
      const int c = pathname[0];
 
1183
#ifdef WIN32
 
1184
      return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\');
 
1185
#else
 
1186
      return c == '/';
 
1187
#endif
 
1188
    }
 
1189
  else
 
1190
    return false;
 
1191
}
 
1192
 
1148
1193
/*
1149
1194
 * Return the next largest power of 2
1150
1195
 * or u if u is a power of 2.
1435
1480
      CLEAR (*up);
1436
1481
      up->nocache = nocache;
1437
1482
    }
 
1483
  else
 
1484
    {
 
1485
      msg (M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
 
1486
    }
1438
1487
}
1439
1488
 
1440
1489
/*
1449
1498
  return string_mod_const (str, CC_PRINT, CC_CRLF, '.', gc);
1450
1499
}
1451
1500
 
 
1501
static bool
 
1502
is_password_env_var (const char *str)
 
1503
{
 
1504
  return (strncmp (str, "password", 8) == 0);
 
1505
}
 
1506
 
 
1507
bool
 
1508
env_allowed (const char *str)
 
1509
{
 
1510
  return (script_security >= SSEC_PW_ENV || !is_password_env_var (str));
 
1511
}
 
1512
 
 
1513
bool
 
1514
env_safe_to_print (const char *str)
 
1515
{
 
1516
#ifndef UNSAFE_DEBUG
 
1517
  if (is_password_env_var (str))
 
1518
    return false;
 
1519
#endif
 
1520
  return true;
 
1521
}
 
1522
 
1452
1523
/* Make arrays of strings */
1453
1524
 
1454
1525
const char **
1455
 
make_env_array (const struct env_set *es, struct gc_arena *gc)
 
1526
make_env_array (const struct env_set *es,
 
1527
                const bool check_allowed,
 
1528
                struct gc_arena *gc)
1456
1529
{
1457
1530
  char **ret = NULL;
1458
1531
  struct env_item *e = NULL;
1471
1544
  /* fill return array */
1472
1545
  if (es)
1473
1546
    {
1474
 
      e = es->list;
1475
 
      for (i = 0; i < n; ++i)
 
1547
      i = 0;
 
1548
      for (e = es->list; e != NULL; e = e->next)
1476
1549
        {
1477
 
          ASSERT (e);
1478
 
          ret[i] = e->string;
1479
 
          e = e->next;
 
1550
          if (!check_allowed || env_allowed (e->string))
 
1551
            {
 
1552
              ASSERT (i < n);
 
1553
              ret[i++] = e->string;
 
1554
            }
1480
1555
        }
1481
1556
    }
1482
1557
 
1591
1666
  sleep (n);
1592
1667
}
1593
1668
 
 
1669
#if 0
1594
1670
/*
1595
1671
 * Configure PATH.  On Windows, sometimes PATH is not set correctly
1596
1672
 * by default.
1632
1708
    }
1633
1709
#endif
1634
1710
}
 
1711
#endif
 
1712
 
 
1713
#ifdef ARGV_TEST
 
1714
void
 
1715
argv_test (void)
 
1716
{
 
1717
  struct gc_arena gc = gc_new ();
 
1718
  char line[512];
 
1719
  const char *s;
 
1720
 
 
1721
  struct argv a;
 
1722
  argv_init (&a);
 
1723
 
 
1724
#ifdef WIN32
 
1725
  argv_printf (&a, "%s foo bar %s", "c:\\src\\test\\jyargs.exe", "foo bar");
 
1726
  //argv_printf (&a, "%s %s %s", "c:\\src\\test files\\batargs.bat", "foo", "bar");  
 
1727
#else
 
1728
  argv_printf (&a, "./myechox foo bar");
 
1729
#endif
 
1730
 
 
1731
  argv_msg_prefix (M_INFO, &a, "ARGV");
 
1732
  openvpn_execve_check (&a, NULL, 0, "command failed");
 
1733
 
 
1734
  argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
 
1735
  s = argv_str (&a, &gc, PA_BRACKET);
 
1736
  printf ("%s\n", s);
 
1737
 
 
1738
  {
 
1739
    struct argv b = argv_insert_head (&a, "MARK");
 
1740
    s = argv_str (&b, &gc, PA_BRACKET);
 
1741
    argv_reset (&b);
 
1742
    printf ("%s\n", s);
 
1743
  }
 
1744
 
 
1745
  argv_printf (&a, "foo bar %d", 99);
 
1746
  s = argv_str (&a, &gc, PA_BRACKET);
 
1747
  argv_reset (&a);
 
1748
  printf ("%s\n", s);
 
1749
 
 
1750
  s = argv_str (&a, &gc, PA_BRACKET);
 
1751
  argv_reset (&a);
 
1752
  printf ("%s\n", s);
 
1753
 
 
1754
  argv_printf (&a, "foo bar %d", 99);
 
1755
  argv_printf_cat (&a, "bar %d foo", 42);
 
1756
  argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7);
 
1757
  s = argv_str (&a, &gc, PA_BRACKET);
 
1758
  printf ("%s\n", s);
 
1759
 
 
1760
#if 0
 
1761
  while (fgets (line, sizeof(line), stdin) != NULL)
 
1762
    {
 
1763
      char *term;
 
1764
      const char *f = line;
 
1765
      int i = 0;
 
1766
 
 
1767
      while ((term = argv_term (&f)) != NULL) 
 
1768
        {
 
1769
          printf ("[%d] '%s'\n", i, term);
 
1770
          ++i;
 
1771
          free (term);
 
1772
        }
 
1773
    }
 
1774
#endif
 
1775
 
 
1776
  argv_reset (&a);
 
1777
  gc_free (&gc);
 
1778
}
 
1779
#endif