26#ifdef HAVE_CONFIG_VERSION_H
27#include "config-version.h"
47#define PLUGIN_SYMBOL_REQUIRED (1 << 0)
56 for (
i = 0; array[
i]; ++
i)
60 msg(msglevel,
"%s[%d] = '%s'", name,
i, array[
i]);
80 case OPENVPN_PLUGIN_UP:
83 case OPENVPN_PLUGIN_DOWN:
86 case OPENVPN_PLUGIN_ROUTE_UP:
87 return "PLUGIN_ROUTE_UP";
89 case OPENVPN_PLUGIN_IPCHANGE:
90 return "PLUGIN_IPCHANGE";
92 case OPENVPN_PLUGIN_TLS_VERIFY:
93 return "PLUGIN_TLS_VERIFY";
95 case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
96 return "PLUGIN_AUTH_USER_PASS_VERIFY";
98 case OPENVPN_PLUGIN_CLIENT_CONNECT:
99 return "PLUGIN_CLIENT_CONNECT";
101 case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
102 return "PLUGIN_CLIENT_CONNECT_V2";
104 case OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER:
105 return "PLUGIN_CLIENT_CONNECT_DEFER";
107 case OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2:
108 return "PLUGIN_CLIENT_CONNECT_DEFER_V2";
110 case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
111 return "PLUGIN_CLIENT_DISCONNECT";
113 case OPENVPN_PLUGIN_LEARN_ADDRESS:
114 return "PLUGIN_LEARN_ADDRESS";
116 case OPENVPN_PLUGIN_TLS_FINAL:
117 return "PLUGIN_TLS_FINAL";
119 case OPENVPN_PLUGIN_ROUTE_PREDOWN:
120 return "PLUGIN_ROUTE_PREDOWN";
122 case OPENVPN_PLUGIN_CLIENT_CRRESPONSE:
123 return "PLUGIN_CRRESPONSE";
152static inline unsigned int
206libdl_resolve_symbol(
void *handle,
void **dest,
const char *symbol,
const char *plugin_name,
207 const unsigned int flags)
209 *dest = dlsym(handle, symbol);
212 msg(
M_FATAL,
"PLUGIN: could not find required symbol '%s' in plugin shared object %s: %s",
213 symbol, plugin_name, dlerror());
221 const unsigned int flags)
223 *dest = GetProcAddress(module, symbol);
226 msg(
M_FATAL,
"PLUGIN: could not find required symbol '%s' in plugin DLL %s", symbol,
265 snprintf(full,
sizeof(full),
"%s/%s", PLUGIN_LIBDIR, p->
so_pathname);
266 p->handle = dlopen(full, RTLD_NOW);
279#define PLUGIN_SYM(var, name, flags) \
280 libdl_resolve_symbol(p->handle, (void *)&p->var, name, p->so_pathname, flags)
285 WCHAR normalized_plugin_path[MAX_PATH] = { 0 };
287 if (!GetFullPathNameW(wpath, MAX_PATH, normalized_plugin_path, NULL))
289 msg(
M_ERR,
"PLUGIN_INIT: could not load plugin DLL: %ls. Failed to normalize plugin path.",
296 "PLUGIN_INIT: could not load plugin DLL: %ls. The DLL is not in a trusted directory.",
297 normalized_plugin_path);
300 p->module = LoadLibraryW(normalized_plugin_path);
303 msg(
M_ERR,
"PLUGIN_INIT: could not load plugin DLL: %ls", normalized_plugin_path);
306#define PLUGIN_SYM(var, name, flags) \
307 dll_resolve_symbol(p->module, (void *)&p->var, name, p->so_pathname, flags)
311 PLUGIN_SYM(open1,
"openvpn_plugin_open_v1", 0);
312 PLUGIN_SYM(open2,
"openvpn_plugin_open_v2", 0);
313 PLUGIN_SYM(open3,
"openvpn_plugin_open_v3", 0);
314 PLUGIN_SYM(func1,
"openvpn_plugin_func_v1", 0);
315 PLUGIN_SYM(func2,
"openvpn_plugin_func_v2", 0);
316 PLUGIN_SYM(func3,
"openvpn_plugin_func_v3", 0);
318 PLUGIN_SYM(abort,
"openvpn_plugin_abort_v1", 0);
319 PLUGIN_SYM(client_constructor,
"openvpn_plugin_client_constructor_v1", 0);
320 PLUGIN_SYM(client_destructor,
"openvpn_plugin_client_destructor_v1", 0);
321 PLUGIN_SYM(min_version_required,
"openvpn_plugin_min_version_required_v1", 0);
322 PLUGIN_SYM(initialization_point,
"openvpn_plugin_select_initialization_point_v1", 0);
326 msg(
M_FATAL,
"PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s",
332 msg(
M_FATAL,
"PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s",
342 if (plugin_needs_version > OPENVPN_PLUGIN_VERSION)
345 "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s",
346 plugin_needs_version, OPENVPN_PLUGIN_VERSION, p->
so_pathname);
362 "WARNING: plugin '%s' specified by a relative pathname -- using an absolute pathname would be more secure",
372plugin_vlog(openvpn_plugin_log_flags_t flags,
const char *name,
const char *format, va_list arglist)
374 unsigned int msg_flags = 0;
381 if (!name || name[0] ==
'\0')
383 msg(
D_PLUGIN_DEBUG,
"PLUGIN: suppressed log message from plugin with unknown name");
387 if (flags & PLOG_ERR)
391 else if (flags & PLOG_WARN)
395 else if (flags & PLOG_NOTE)
399 else if (flags & PLOG_DEBUG)
404 if (flags & PLOG_ERRNO)
408 if (flags & PLOG_NOMUTE)
423 snprintf(msg_fmt,
ERR_BUF_SIZE,
"PLUGIN %s: %s", name, format);
424 x_msg_va(msg_flags, msg_fmt, arglist);
431plugin_log(openvpn_plugin_log_flags_t flags,
const char *name,
const char *format, ...)
434 va_start(arglist, format);
452#ifndef CONFIGURE_GIT_REVISION
453#define _OPENVPN_PATCH_LEVEL OPENVPN_VERSION_PATCH
455#define _OPENVPN_PATCH_LEVEL "git:" CONFIGURE_GIT_REVISION CONFIGURE_GIT_FLAGS
460 struct openvpn_plugin_string_list **retlist,
const char **envp,
461 const int init_point)
484 (
const char **
const)o->
argv,
485 (
const char **
const)envp,
489 OPENVPN_VERSION_MAJOR,
490 OPENVPN_VERSION_MINOR,
492 struct openvpn_plugin_args_open_return retargs;
495 retargs.return_list = retlist;
496 if ((*p->
open3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs)
497 == OPENVPN_PLUGIN_FUNC_SUCCESS)
522 (retlist && *retlist) ?
"[RETLIST]" :
"");
527 "PLUGIN_INIT: plugin %s expressed interest in unsupported plugin types: [want=0x%08x, have=0x%08x]",
542 const struct argv *av,
struct openvpn_plugin_string_list **retlist,
545 int status = OPENVPN_PLUGIN_FUNC_SUCCESS;
566 struct openvpn_plugin_args_func_in args = { type,
567 (
const char **
const)a.
argv,
568 (
const char **
const)envp,
571 (current_cert ? certdepth : -1),
574 struct openvpn_plugin_args_func_return retargs;
577 retargs.return_list = retlist;
578 status = (*p->
func3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs);
583 per_client_context, retlist);
597 if (
status == OPENVPN_PLUGIN_FUNC_ERROR)
599 msg(
M_WARN,
"PLUGIN_CALL: plugin function %s failed with status %d: %s",
625 if (dlclose(p->handle))
630 if (!FreeLibrary(p->module))
654 const int init_point)
659 for (
i = 0;
i < n; ++
i)
676 for (
i = 0;
i < n; ++
i)
708 for (
i = 0;
i < list->
n; ++
i)
733 for (
i = 0;
i < pc->
n; ++
i)
755 for (
i = 0;
i < pc->
n; ++
i)
798 bool deferred_auth_done =
false;
803 for (
i = 0;
i < n; ++
i)
807 type, av, pr ? &pr->
list[
i] : NULL, envp, certdepth, current_cert);
810 case OPENVPN_PLUGIN_FUNC_SUCCESS:
813 case OPENVPN_PLUGIN_FUNC_DEFERRED:
814 if ((type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) && deferred_auth_done)
831 msg(
M_FATAL,
"Exiting due to multiple authentication plug-ins "
832 "performing deferred authentication. Only one "
833 "authentication plug-in doing deferred auth is "
834 "allowed. Ignoring the result and stopping now, "
835 "the current authentication result is not to be "
839 deferred_auth_done =
true;
857 return OPENVPN_PLUGIN_FUNC_ERROR;
859 else if (deferred_auth_done)
861 return OPENVPN_PLUGIN_FUNC_DEFERRED;
865 return OPENVPN_PLUGIN_FUNC_SUCCESS;
896 for (
i = 0;
i < pc->
n; ++
i)
915 const unsigned int mask = OPENVPN_PLUGIN_MASK(type);
916 for (
i = 0;
i < pc->
n; ++
i)
948 struct openvpn_plugin_string_list *next;
957static struct openvpn_plugin_string_list *
962 if (!strcmp(l->name, name))
978 for (
i = 0;
i < src->
n; ++
i)
989 for (
i = 0;
i < pr->
n; ++
i)
998plugin_return_print(
const int msglevel,
const char *prefix,
const struct plugin_return *pr)
1001 msg(msglevel,
"PLUGIN_RETURN_PRINT %s", prefix);
1002 for (
i = 0;
i < pr->
n; ++
i)
1004 struct openvpn_plugin_string_list *l = pr->
list[
i];
1007 msg(msglevel,
"PLUGIN #%d (%s)",
i, prefix);
1010 msg(msglevel,
"[%d] '%s' -> '%s'", ++count, l->name, l->value);
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
struct argv argv_insert_head(const struct argv *a, const char *head)
Inserts an argument string in front of all other argument slots.
bool buf_printf(struct buffer *buf, const char *format,...)
void string_clear(char *str)
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
static void gc_init(struct gc_arena *a)
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
static void gc_free(struct gc_arena *a)
#define ALLOC_OBJ_CLEAR(dptr, type)
static struct gc_arena gc_new(void)
const char ** make_env_array(const struct env_set *es, const bool check_allowed, struct gc_arena *gc)
void setenv_del(struct env_set *es, const char *name)
static bool env_safe_to_print(const char *str)
static SERVICE_STATUS status
const char ** make_extended_arg_array(char **p, bool is_inline, struct gc_arena *gc)
void x_msg_va(const unsigned int flags, const char *format, va_list arglist)
static bool msg_test(unsigned int flags)
Return true if flags represent an enabled, not muted log level.
static bool check_debug_level(unsigned int level)
void plugin_list_close(struct plugin_list *pl)
static void plugin_show_string_array(int msglevel, const char *name, const char *array[])
static struct openvpn_plugin_string_list * openvpn_plugin_string_list_find(struct openvpn_plugin_string_list *l, const char *name)
static struct plugin_common * static_plugin_common
struct plugin_option_list * plugin_option_list_new(struct gc_arena *gc)
static void plugin_abort_item(const struct plugin *p)
bool plugin_option_list_add(struct plugin_option_list *list, char **p, struct gc_arena *gc)
static void plugin_per_client_destroy(const struct plugin_common *pc, struct plugin_per_client *cli)
static void plugin_show_args_env(int msglevel, const char *argv[], const char *envp[])
#define PLUGIN_SYMBOL_REQUIRED
static void plugin_open_item(struct plugin *p, const struct plugin_option *o, struct openvpn_plugin_string_list **retlist, const char **envp, const int init_point)
void plugin_return_free(struct plugin_return *pr)
static void plugin_per_client_init(const struct plugin_common *pc, struct plugin_per_client *cli, const int init_point)
struct plugin_list * plugin_list_inherit(const struct plugin_list *src)
static unsigned int plugin_supported_types(void)
static void plugin_common_close(struct plugin_common *pc)
static const char * plugin_type_name(const int type)
static void openvpn_plugin_string_list_item_free(struct openvpn_plugin_string_list *l)
static void openvpn_plugin_string_list_free(struct openvpn_plugin_string_list *l)
static const char * plugin_mask_string(const unsigned int type_mask, struct gc_arena *gc)
static int plugin_call_item(const struct plugin *p, void *per_client_context, const int type, const struct argv *av, struct openvpn_plugin_string_list **retlist, const char **envp, int certdepth, openvpn_x509_cert_t *current_cert)
#define _OPENVPN_PATCH_LEVEL
static void plugin_init_item(struct plugin *p, const struct plugin_option *o)
int plugin_call_ssl(const struct plugin_list *pl, const int type, const struct argv *av, struct plugin_return *pr, struct env_set *es, int certdepth, openvpn_x509_cert_t *current_cert)
struct plugin_list * plugin_list_init(const struct plugin_option_list *list)
static void plugin_vlog(openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist)
#define PLUGIN_SYM(var, name, flags)
static void dll_resolve_symbol(HMODULE module, void **dest, const char *symbol, const char *plugin_name, const unsigned int flags)
static struct plugin_common * plugin_common_init(const struct plugin_option_list *list)
static void plugin_close_item(struct plugin *p)
void plugin_return_get_column(const struct plugin_return *src, struct plugin_return *dest, const char *colname)
void plugin_option_list_print(const struct plugin_option_list *list, int msglevel)
static void plugin_common_open(struct plugin_common *pc, const struct plugin_option_list *list, struct plugin_return *pr, const struct env_set *es, const int init_point)
bool plugin_defined(const struct plugin_list *pl, const int type)
void plugin_list_open(struct plugin_list *pl, const struct plugin_option_list *list, struct plugin_return *pr, const struct env_set *es, const int init_point)
static struct openvpn_plugin_callbacks callbacks
static int plugin_n(const struct plugin_list *pl)
static void plugin_return_init(struct plugin_return *pr)
static plugin_log_t plugin_log
int openvpn_base64_decode(const char *str, void *data, int size)
int openvpn_base64_encode(const void *data, int size, char **str)
Control Channel SSL library backend module.
mbedtls_x509_crt openvpn_x509_cert_t
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
struct gc_entry * list
First element of the linked list of gc_entry structures.
struct plugin plugins[MAX_PLUGINS]
struct plugin_common * common
struct plugin_per_client per_client
struct plugin_option plugins[MAX_PLUGINS]
void * per_client_context[MAX_PLUGINS]
struct openvpn_plugin_string_list * list[MAX_PLUGINS]
openvpn_plugin_abort_v1 abort
HMODULE openvpn_plugin_open_v1 open1
openvpn_plugin_select_initialization_point_v1 initialization_point
openvpn_plugin_close_v1 close
openvpn_plugin_handle_t plugin_handle
int requested_initialization_point
openvpn_plugin_open_v3 open3
openvpn_plugin_open_v2 open2
openvpn_plugin_client_destructor_v1 client_destructor
unsigned int plugin_type_mask
openvpn_plugin_min_version_required_v1 min_version_required
openvpn_plugin_client_constructor_v1 client_constructor
openvpn_plugin_func_v1 func1
openvpn_plugin_func_v2 func2
openvpn_plugin_func_v3 func3
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
bool plugin_in_trusted_dir(const WCHAR *plugin_path)
Checks if a plugin is located in a trusted directory.