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";
137 for (i = 0; i < OPENVPN_PLUGIN_N; ++i)
139 if (OPENVPN_PLUGIN_MASK(i) & type_mask)
152static inline unsigned int
155 return ((1 << OPENVPN_PLUGIN_N) - 1);
192 for (i = 0; i <
list->n; ++i)
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 DWORD len = GetFullPathNameW(wpath, _countof(normalized_plugin_path), normalized_plugin_path, NULL);
288 if (len == 0 || len >= _countof(normalized_plugin_path))
293 SetLastError(ERROR_FILENAME_EXCED_RANGE);
295 msg(
M_ERR,
"PLUGIN_INIT: could not load plugin DLL: %ls. Failed to normalize plugin path.",
302 "PLUGIN_INIT: could not load plugin DLL: %ls. The DLL is not in a trusted directory.",
303 normalized_plugin_path);
306 p->
module = LoadLibraryW(normalized_plugin_path);
309 msg(
M_ERR,
"PLUGIN_INIT: could not load plugin DLL: %ls", normalized_plugin_path);
312#define PLUGIN_SYM(var, name, flags) \
313 dll_resolve_symbol(p->module, (void *)&p->var, name, p->so_pathname, flags)
317 PLUGIN_SYM(open1,
"openvpn_plugin_open_v1", 0);
318 PLUGIN_SYM(open2,
"openvpn_plugin_open_v2", 0);
319 PLUGIN_SYM(open3,
"openvpn_plugin_open_v3", 0);
320 PLUGIN_SYM(func1,
"openvpn_plugin_func_v1", 0);
321 PLUGIN_SYM(func2,
"openvpn_plugin_func_v2", 0);
322 PLUGIN_SYM(func3,
"openvpn_plugin_func_v3", 0);
324 PLUGIN_SYM(abort,
"openvpn_plugin_abort_v1", 0);
325 PLUGIN_SYM(client_constructor,
"openvpn_plugin_client_constructor_v1", 0);
326 PLUGIN_SYM(client_destructor,
"openvpn_plugin_client_destructor_v1", 0);
327 PLUGIN_SYM(min_version_required,
"openvpn_plugin_min_version_required_v1", 0);
328 PLUGIN_SYM(initialization_point,
"openvpn_plugin_select_initialization_point_v1", 0);
332 msg(
M_FATAL,
"PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s",
338 msg(
M_FATAL,
"PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s",
348 if (plugin_needs_version > OPENVPN_PLUGIN_VERSION)
351 "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s",
352 plugin_needs_version, OPENVPN_PLUGIN_VERSION, p->
so_pathname);
368 "WARNING: plugin '%s' specified by a relative pathname -- using an absolute pathname would be more secure",
378plugin_vlog(openvpn_plugin_log_flags_t flags,
const char *name,
const char *format, va_list arglist)
380 unsigned int msg_flags = 0;
387 if (!name || name[0] ==
'\0')
389 msg(
D_PLUGIN_DEBUG,
"PLUGIN: suppressed log message from plugin with unknown name");
393 if (flags & PLOG_ERR)
397 else if (flags & PLOG_WARN)
401 else if (flags & PLOG_NOTE)
405 else if (flags & PLOG_DEBUG)
410 if (flags & PLOG_ERRNO)
414 if (flags & PLOG_NOMUTE)
429 snprintf(msg_fmt,
ERR_BUF_SIZE,
"PLUGIN %s: %s", name, format);
430 x_msg_va(msg_flags, msg_fmt, arglist);
437plugin_log(openvpn_plugin_log_flags_t flags,
const char *name,
const char *format, ...)
440 va_start(arglist, format);
458#ifndef CONFIGURE_GIT_REVISION
459#define _OPENVPN_PATCH_LEVEL OPENVPN_VERSION_PATCH
461#define _OPENVPN_PATCH_LEVEL "git:" CONFIGURE_GIT_REVISION CONFIGURE_GIT_FLAGS
466 struct openvpn_plugin_string_list **retlist,
const char **envp,
467 const int init_point)
490 (
const char **
const)o->
argv,
491 (
const char **
const)envp,
495 OPENVPN_VERSION_MAJOR,
496 OPENVPN_VERSION_MINOR,
498 struct openvpn_plugin_args_open_return retargs;
501 retargs.return_list = retlist;
502 if ((*p->
open3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs)
503 == OPENVPN_PLUGIN_FUNC_SUCCESS)
528 (retlist && *retlist) ?
"[RETLIST]" :
"");
533 "PLUGIN_INIT: plugin %s expressed interest in unsupported plugin types: [want=0x%08x, have=0x%08x]",
548 const struct argv *av,
struct openvpn_plugin_string_list **retlist,
551 int status = OPENVPN_PLUGIN_FUNC_SUCCESS;
572 struct openvpn_plugin_args_func_in args = { type,
573 (
const char **
const)a.
argv,
574 (
const char **
const)envp,
577 (current_cert ? certdepth : -1),
580 struct openvpn_plugin_args_func_return retargs;
583 retargs.return_list = retlist;
584 status = (*p->
func3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs);
589 per_client_context, retlist);
603 if (
status == OPENVPN_PLUGIN_FUNC_ERROR)
605 msg(
M_WARN,
"PLUGIN_CALL: plugin function %s failed with status %d: %s",
631 if (dlclose(p->handle))
636 if (!FreeLibrary(p->
module))
660 const int init_point)
665 for (i = 0; i < n; ++i)
682 for (i = 0; i < n; ++i)
714 for (i = 0; i < list->
n; ++i)
739 for (i = 0; i < pc->
n; ++i)
761 for (i = 0; i < pc->
n; ++i)
804 bool deferred_auth_done =
false;
809 for (i = 0; i < n; ++i)
813 type, av, pr ? &pr->
list[i] : NULL, envp, certdepth, current_cert);
816 case OPENVPN_PLUGIN_FUNC_SUCCESS:
819 case OPENVPN_PLUGIN_FUNC_DEFERRED:
820 if ((type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) && deferred_auth_done)
837 msg(
M_FATAL,
"Exiting due to multiple authentication plug-ins "
838 "performing deferred authentication. Only one "
839 "authentication plug-in doing deferred auth is "
840 "allowed. Ignoring the result and stopping now, "
841 "the current authentication result is not to be "
845 deferred_auth_done =
true;
863 return OPENVPN_PLUGIN_FUNC_ERROR;
865 else if (deferred_auth_done)
867 return OPENVPN_PLUGIN_FUNC_DEFERRED;
871 return OPENVPN_PLUGIN_FUNC_SUCCESS;
902 for (i = 0; i < pc->
n; ++i)
921 const unsigned int mask = OPENVPN_PLUGIN_MASK(type);
922 for (i = 0; i < pc->
n; ++i)
954 struct openvpn_plugin_string_list *next;
963static struct openvpn_plugin_string_list *
968 if (!strcmp(l->name, name))
984 for (i = 0; i < src->
n; ++i)
995 for (i = 0; i < pr->
n; ++i)
1007 msg(msglevel,
"PLUGIN_RETURN_PRINT %s", prefix);
1008 for (i = 0; i < pr->
n; ++i)
1010 struct openvpn_plugin_string_list *l = pr->
list[i];
1013 msg(msglevel,
"PLUGIN #%d (%s)", i, prefix);
1016 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,...)
printf-style append to a buffer with overflow check.
void string_clear(char *str)
Securely clear a null-terminated string.
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Format a NULL-terminated argument vector as a single string.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
#define PA_BRACKET
Flag for print_argv(): wrap each argument in square brackets.
static void gc_init(struct gc_arena *a)
Initialise a garbage collection arena to an empty state.
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
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 msglvl_t flags, const char *format, va_list arglist)
static bool check_debug_level(msglvl_t level)
static bool msg_test(msglvl_t flags)
Return true if flags represent an enabled, not muted log level.
void plugin_list_close(struct plugin_list *pl)
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(msglvl_t 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_option_list_print(const struct plugin_option_list *list, msglvl_t msglevel)
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)
static void plugin_show_string_array(msglvl_t msglevel, const char *name, const char *array[])
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)
void plugin_return_print(const msglvl_t msglevel, const char *prefix, const struct plugin_return *pr)
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)
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.
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_open_v1 open1
openvpn_plugin_abort_v1 abort
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.