Currently openvpn requires/endorses specifying full path in plugin
parameter. As build system already aware of plugin location, it is
possible to load plugin relative to this directory, so full path is not
required nor more secured.

Windows is a little more complex as user may change installation
directory at install time, so we read plugindir location from the
registry, installer will set this value.

This replaces the old unused logic of the PLUGIN_LIBDIR macro.

The old unused logic of  ENABLE_PLUGIN_SEARCH is also removed as plugins
are relative to the plugindir.

Signed-off-by: Alon Bar-Lev <alon.bar...@gmail.com>
---
 src/openvpn/Makefile.am |    1 +
 src/openvpn/options.c   |    3 +
 src/openvpn/plugin.c    |  102 +++++++++++++++++++++++++++++++----------------
 3 files changed, 72 insertions(+), 34 deletions(-)

diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am
index d090d67..a2af0d4 100644
--- a/src/openvpn/Makefile.am
+++ b/src/openvpn/Makefile.am
@@ -23,6 +23,7 @@ INCLUDES = \
        -I$(top_srcdir)/src/compat

 AM_CFLAGS = \
+       -DOPENVPN_PLUGINDIR="\"$(plugindir)\"" \
        $(TAP_CFLAGS) \
        $(OPTIONAL_CRYPTO_CFLAGS) \
        $(OPTIONAL_LZO_CFLAGS) \
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 367c1bc..d2e8e51 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -3458,6 +3458,9 @@ usage_version (void)
   msg (M_INFO|M_NOPREFIX, "git revision: %s", CONFIGURE_GIT_REVISION);
 #endif
 #endif
+#ifdef OPENVPN_PLUGINDIR
+  msg (M_INFO|M_NOPREFIX, "build plugindir: %s", OPENVPN_PLUGINDIR);
+#endif
   openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */
 }

diff --git a/src/openvpn/plugin.c b/src/openvpn/plugin.c
index 7ce2f5e..9cdf982 100644
--- a/src/openvpn/plugin.c
+++ b/src/openvpn/plugin.c
@@ -196,46 +196,83 @@ static void
 plugin_init_item (struct plugin *p, const struct plugin_option *o)
 {
   struct gc_arena gc = gc_new ();
-  bool rel = false;

   p->so_pathname = o->so_pathname;
   p->plugin_type_mask = plugin_supported_types ();

 #ifndef WIN32
-
-  p->handle = NULL;
-#if defined(PLUGIN_LIBDIR)
-  if (!absolute_pathname (p->so_pathname))
-    {
-      char full[PATH_MAX];
-
-      openvpn_snprintf (full, sizeof(full), "%s/%s", PLUGIN_LIBDIR, 
p->so_pathname);
-      p->handle = dlopen (full, RTLD_NOW);
-#if defined(ENABLE_PLUGIN_SEARCH)
-      if (!p->handle)
-       {
-         rel = true;
-         p->handle = dlopen (p->so_pathname, RTLD_NOW);
-       }
-#endif
-    }
-  else
-#endif
-    {
-      rel = !absolute_pathname (p->so_pathname);
-      p->handle = dlopen (p->so_pathname, RTLD_NOW);
-    }
-  if (!p->handle)
-    msg (M_ERR, "PLUGIN_INIT: could not load plugin shared object %s: %s", 
p->so_pathname, dlerror());
+  {
+    char _abs_so_pathname[PATH_MAX];
+    const char *abs_so_pathname;
+
+    if (absolute_pathname (p->so_pathname))
+      abs_so_pathname = p->so_pathname;
+    else
+      {
+       openvpn_snprintf(_abs_so_pathname, SIZE(_abs_so_pathname), "%s%c%s", 
OPENVPN_PLUGINDIR, OS_SPECIFIC_DIRSEP, p->so_pathname);
+        abs_so_pathname = _abs_so_pathname;
+      }
+
+    p->handle = dlopen (abs_so_pathname, RTLD_NOW);
+    if (!p->handle)
+      msg (M_ERR, "PLUGIN_INIT: could not load plugin shared object '%s': %s", 
abs_so_pathname, dlerror());

 # define PLUGIN_SYM(var, name, flags) libdl_resolve_symbol (p->handle, 
(void*)&p->var, name, p->so_pathname, flags)

+  }
 #else
-
-  rel = !absolute_pathname (p->so_pathname);
-  p->module = LoadLibraryW (wide_string (p->so_pathname, &gc));
-  if (!p->module)
-    msg (M_ERR, "PLUGIN_INIT: could not load plugin DLL: %s", p->so_pathname);
+  {
+    WCHAR _abs_so_pathname[PATH_MAX];
+    WCHAR *abs_so_pathname;
+
+    if (absolute_pathname (p->so_pathname))
+      abs_so_pathname = wide_string(p->so_pathname, &gc);
+    else
+      {
+         WCHAR _plugindir[PATH_MAX];
+         WCHAR _plugindir_expanded[PATH_MAX];
+         WCHAR *plugindir = NULL;
+         HKEY key;
+
+         if (RegOpenKeyExW(
+             HKEY_LOCAL_MACHINE,
+             L"SOFTWARE\\OpenVPN",
+             0,
+             KEY_READ,
+             &key
+           ) == ERROR_SUCCESS)
+           {
+             DWORD len = sizeof (_plugindir);
+             DWORD data_type;
+
+             if (RegQueryValueExW(
+                 key,
+                 L"plugindir",
+                 NULL,
+                 &data_type,
+                 (PBYTE)_plugindir,
+                 &len) == ERROR_SUCCESS &&
+                 data_type == REG_SZ)
+               {
+                 plugindir = _plugindir;
+               }
+           }
+
+         if (plugindir == NULL)
+           plugindir = wide_string (OPENVPN_PLUGINDIR, &gc);
+
+         if (ExpandEnvironmentStringsW(plugindir, _plugindir_expanded, 
SIZE(_plugindir_expanded)) != 0)
+          plugindir = _plugindir_expanded;
+
+        _snwprintf(_abs_so_pathname, SIZE(_abs_so_pathname), L"%s%C%s", 
plugindir, OS_SPECIFIC_DIRSEP, wide_string(p->so_pathname, &gc));
+        abs_so_pathname = _abs_so_pathname;
+      }
+
+    p->module = LoadLibraryW (abs_so_pathname);
+
+    if (!p->module)
+      msg (M_ERR, "PLUGIN_INIT: could not load plugin DLL: '%S'", 
abs_so_pathname);
+  }

 # define PLUGIN_SYM(var, name, flags) dll_resolve_symbol (p->module, 
(void*)&p->var, name, p->so_pathname, flags)

@@ -278,9 +315,6 @@ plugin_init_item (struct plugin *p, const struct 
plugin_option *o)
   else
     p->requested_initialization_point = OPENVPN_PLUGIN_INIT_PRE_DAEMON;

-  if (rel)
-    msg (M_WARN, "WARNING: plugin '%s' specified by a relative pathname -- 
using an absolute pathname would be more secure", p->so_pathname);
-
   p->initialized = true;

   gc_free (&gc);
-- 
1.7.3.4


Reply via email to