In commit 4e1cc5f6dda22e9 the create_temp_filename() function was
reviewed and hardened, which in the end renamed this function to
create_temp_file() in commit 495e3cec5d156.

With these changes it became more evident that OpenVPN needs a directory
where it can create temporary files.  The create_temp_file() will create
such files f.ex. if --client-connect or --plugin which makes use of
the OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY hook, such as openvpn-auth-pam.so.

When this happens, OpenVPN will normally create these files in the directory
OpenVPN was started.  In many cases, this will fail due to restricted access.
By using --tmp-dir and pointing it to a directory writeable to the user
running OpenVPN, it works again.

This patch makes OpenVPN use a more suitable temproary directory by default,
instead of the current working directory.  On non-Windows platforms this
default value is set to '/tmp', but can be modified at compile-time by
running ./configure --with-tmp-dir-path=<TEMP DIR PATH>.  On Windows, it
will look up %TEMP% and %TMP% first, and if that doesn't give any clues, it
will fallback to C:\WINDOWS\Temp in the end.

In any cases, this default value can be overridden in the configuration
file by using the --tmp-dir option, as before.

To check what the default is at runime, you can see this easily by doing
this:

      $ ./openvpn --verb 4 --dev tun | grep tmp_dir

Signed-off-by: David Sommerseth <dav...@redhat.com>
Tested-by: Jan Just Keijser <janj...@nikhef.nl>
---
 configure.ac    |   11 +++++++++++
 options.c       |   15 +++++++++++----
 win/config.h.in |    3 +++
 win32.c         |   19 +++++++++++++++++++
 win32.h         |    3 +++
 5 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index e0847bc..a9f022e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -279,6 +279,11 @@ AC_ARG_WITH(netstat-path,
 )
 AC_DEFINE_UNQUOTED(NETSTAT_PATH, "$NETSTAT", [Path to netstat tool])

+AC_ARG_WITH(tmp-dir-path,
+   [  --with-tmp-dir-path=PATH  Default tmp-dir to use when not configured 
(unset defaults to /tmp)],
+   [TMPDIRPATH="$withval"]
+)
+
 AC_ARG_WITH(mem-check,
    [  --with-mem-check=TYPE  Build with debug memory checking, TYPE = dmalloc 
or valgrind],
    [MEMCHECK="$withval"]
@@ -566,6 +571,12 @@ LDFLAGS="$LDFLAGS -Wl,--fatal-warnings"
 AC_CHECK_FUNC(epoll_create, AC_DEFINE(HAVE_EPOLL_CREATE, 1, [epoll_create 
function is defined]))
 LDFLAGS="$OLDLDFLAGS"

+dnl set the default temporary directory
+if test -z "$TMPDIRPATH"; then
+   TMPDIRPATH="/tmp"
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_TMPDIR, "$TMPDIRPATH", [Default --tmp-dir])
+
 dnl
 dnl check for valgrind tool
 dnl
diff --git a/options.c b/options.c
index 36e8393..0b91657 100644
--- a/options.c
+++ b/options.c
@@ -766,11 +766,20 @@ init_options (struct options *o, const bool init_gc)
 #ifdef ENABLE_X509ALTUSERNAME
   o->x509_username_field = X509_USERNAME_FIELD_DEFAULT;
 #endif
-#endif
-#endif
+#endif /* USE_SSL */
+#endif /* USE_CRYPTO */
 #ifdef ENABLE_PKCS11
   o->pkcs11_pin_cache_period = -1;
 #endif                 /* ENABLE_PKCS11 */
+
+  /* Set default --tmp-dir */
+#ifdef WIN32
+  /* On Windows, find temp dir via enviroment variables */
+  o->tmp_dir = win_get_tempdir();
+#else
+  /* Non-windows platforms have this value defined via ./configure */
+  o->tmp_dir = DEFAULT_TMPDIR;
+#endif /* WIN32 */
 }

 void
@@ -1916,8 +1925,6 @@ options_postprocess_verify_ce (const struct options 
*options, const struct conne
        msg (M_USAGE, "--client-connect requires --mode server");
       if (options->client_disconnect_script)
        msg (M_USAGE, "--client-disconnect requires --mode server");
-      if (options->tmp_dir)
-       msg (M_USAGE, "--tmp-dir requires --mode server");
       if (options->client_config_dir || options->ccd_exclusive)
        msg (M_USAGE, "--client-config-dir/--ccd-exclusive requires --mode 
server");
       if (options->enable_c2c)
diff --git a/win/config.h.in b/win/config.h.in
index fb349d0..abf71d2 100644
--- a/win/config.h.in
+++ b/win/config.h.in
@@ -286,6 +286,9 @@ typedef unsigned long in_addr_t;
 /* Route command */
 #define ROUTE_PATH "route"

+/* Default temporary directory, if not found via getenv() */
+#define DEFAULT_TMPDIR "C:\\WINDOWS\\Temp"   /* FIXME: Should be configurable 
*/
+
 #ifdef _MSC_VER
 /* MSVC++ hacks */
 #pragma warning(disable:4244) // conversion from 'foo' to 'bar', possible loss 
of data
diff --git a/win32.c b/win32.c
index 7c9901e..c9eb184 100644
--- a/win32.c
+++ b/win32.c
@@ -1093,4 +1093,23 @@ env_set_add_win32 (struct env_set *es)
   set_win_sys_path (DEFAULT_WIN_SYS_PATH, es);
 }

+
+const char *
+win_get_tempdir()
+{
+  static char *tmpdir = NULL;
+
+  /* Try to use %TEMP% or %TMP% */
+  tmpdir = getenv("TEMP");
+  if( !tmpdir ) {
+    tmpdir = getenv("TMP");
+  }
+  if( !tmpdir ) {
+    /* Warn if we're using a hard coded path */
+    msg (M_WARN, "Could not find %TEMP% or %TMP% environment variables.  "
+         "Falling back to %s.  Consider to use --tmp-dir", DEFAULT_TMPDIR);
+    tmpdir = DEFAULT_TMPDIR;
+  }
+  return tmpdir;
+}
 #endif
diff --git a/win32.h b/win32.h
index fcc3062..b6a162e 100644
--- a/win32.h
+++ b/win32.h
@@ -270,5 +270,8 @@ char *get_win_sys_path (void);
 /* call self in a subprocess */
 void fork_to_self (const char *cmdline);

+/* Find temporary directory */
+const char *win_get_tempdir();
+
 #endif
 #endif
-- 
1.7.4


Reply via email to