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 (); #if defined(USE_LIBDL) 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()); # define PLUGIN_SYM(var, name, flags) libdl_resolve_symbol (p->handle, (void*)&p->var, name, p->so_pathname, flags) #elif defined(USE_LOAD_LIBRARY) rel = !absolute_pathname (p->so_pathname); p->module = LoadLibrary (p->so_pathname); if (!p->module) msg (M_ERR, "PLUGIN_INIT: could not load plugin DLL: %s", p->so_pathname); # define PLUGIN_SYM(var, name, flags) dll_resolve_symbol (p->module, (void*)&p->var, name, p->so_pathname, flags) #endif PLUGIN_SYM (open1, "openvpn_plugin_open_v1", 0); PLUGIN_SYM (open2, "openvpn_plugin_open_v2", 0); PLUGIN_SYM (open3, "openvpn_plugin_open_v3", 0); PLUGIN_SYM (func1, "openvpn_plugin_func_v1", 0); PLUGIN_SYM (func2, "openvpn_plugin_func_v2", 0); PLUGIN_SYM (func3, "openvpn_plugin_func_v3", 0); PLUGIN_SYM (close, "openvpn_plugin_close_v1", PLUGIN_SYMBOL_REQUIRED); PLUGIN_SYM (abort, "openvpn_plugin_abort_v1", 0); PLUGIN_SYM (client_constructor, "openvpn_plugin_client_constructor_v1", 0); PLUGIN_SYM (client_destructor, "openvpn_plugin_client_destructor_v1", 0); PLUGIN_SYM (min_version_required, "openvpn_plugin_min_version_required_v1", 0); PLUGIN_SYM (initialization_point, "openvpn_plugin_select_initialization_point_v1", 0); if (!p->open1 && !p->open2 && !p->open3) msg (M_FATAL, "PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s", p->so_pathname); if (!p->func1 && !p->func2 && !p->func3) msg (M_FATAL, "PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s", p->so_pathname); /* * Verify that we are sufficiently up-to-date to handle the plugin */ if (p->min_version_required) { const int plugin_needs_version = (*p->min_version_required)(); if (plugin_needs_version > OPENVPN_PLUGIN_VERSION) msg (M_FATAL, "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s", plugin_needs_version, OPENVPN_PLUGIN_VERSION, p->so_pathname); } if (p->initialization_point) p->requested_initialization_point = (*p->initialization_point)(); 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); }
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 the plug-in filename is not an absolute path, * or beginning with '.', it should use the PLUGIN_LIBDIR * as the base directory for loading the plug-in. * * This means the following scenarios are loaded from these places: * --plugin fancyplug.so -> $PLUGIN_LIBDIR/fancyplug.so * --plugin my/fancyplug.so -> $PLUGIN_LIBDIR/my/fancyplug.so * --plugin ./fancyplug.so -> $CWD/fancyplug.so * --plugin /usr/lib/my/fancyplug.so -> /usr/lib/my/fancyplug.so * * Please note that $CWD means the directory OpenVPN is either started from * or the directory OpenVPN have changed into using --cd before --plugin * was parsed. * */ if (!platform_absolute_pathname(p->so_pathname) && p->so_pathname[0] != '.') { char full[PATH_MAX]; openvpn_snprintf(full, sizeof(full), "%s/%s", PLUGIN_LIBDIR, p->so_pathname); p->handle = dlopen(full, RTLD_NOW); } else { rel = !platform_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()); } #define PLUGIN_SYM(var, name, flags) libdl_resolve_symbol(p->handle, (void *)&p->var, name, p->so_pathname, flags) #else /* ifndef _WIN32 */ rel = !platform_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); } #define PLUGIN_SYM(var, name, flags) dll_resolve_symbol(p->module, (void *)&p->var, name, p->so_pathname, flags) #endif /* ifndef _WIN32 */ PLUGIN_SYM(open1, "openvpn_plugin_open_v1", 0); PLUGIN_SYM(open2, "openvpn_plugin_open_v2", 0); PLUGIN_SYM(open3, "openvpn_plugin_open_v3", 0); PLUGIN_SYM(func1, "openvpn_plugin_func_v1", 0); PLUGIN_SYM(func2, "openvpn_plugin_func_v2", 0); PLUGIN_SYM(func3, "openvpn_plugin_func_v3", 0); PLUGIN_SYM(close, "openvpn_plugin_close_v1", PLUGIN_SYMBOL_REQUIRED); PLUGIN_SYM(abort, "openvpn_plugin_abort_v1", 0); PLUGIN_SYM(client_constructor, "openvpn_plugin_client_constructor_v1", 0); PLUGIN_SYM(client_destructor, "openvpn_plugin_client_destructor_v1", 0); PLUGIN_SYM(min_version_required, "openvpn_plugin_min_version_required_v1", 0); PLUGIN_SYM(initialization_point, "openvpn_plugin_select_initialization_point_v1", 0); if (!p->open1 && !p->open2 && !p->open3) { msg(M_FATAL, "PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s", p->so_pathname); } if (!p->func1 && !p->func2 && !p->func3) { msg(M_FATAL, "PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s", p->so_pathname); } /* * Verify that we are sufficiently up-to-date to handle the plugin */ if (p->min_version_required) { const int plugin_needs_version = (*p->min_version_required)(); if (plugin_needs_version > OPENVPN_PLUGIN_VERSION) { msg(M_FATAL, "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s", plugin_needs_version, OPENVPN_PLUGIN_VERSION, p->so_pathname); } } if (p->initialization_point) { p->requested_initialization_point = (*p->initialization_point)(); } 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); }