2
* OpenVPN -- An application to securely tunnel IP networks
3
* over a single TCP/UDP port, with support for SSL/TLS-based
4
* session authentication and key exchange,
5
* packet encryption, packet authentication, and
8
* Copyright (C) 2002-2004 James Yonan <jim@yonan.net>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program (see the file COPYING included with this
22
* distribution); if not, write to the Free Software Foundation, Inc.,
23
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include "config-win32.h"
44
plugin_show_string_array (int msglevel, const char *name, const char *array[])
47
for (i = 0; array[i]; ++i)
48
msg (msglevel, "%s[%d] = '%s'", name, i, array[i]);
52
plugin_show_args_env (int msglevel, const char *argv[], const char *envp[])
54
if (check_debug_level (msglevel))
56
plugin_show_string_array (msglevel, "ARGV", argv);
57
plugin_show_string_array (msglevel, "ENVP", envp);
62
plugin_type_name (const int type)
66
case OPENVPN_PLUGIN_UP:
68
case OPENVPN_PLUGIN_DOWN:
70
case OPENVPN_PLUGIN_ROUTE_UP:
71
return "PLUGIN_ROUTE_UP";
72
case OPENVPN_PLUGIN_IPCHANGE:
73
return "PLUGIN_IPCHANGE";
74
case OPENVPN_PLUGIN_TLS_VERIFY:
75
return "PLUGIN_TLS_VERIFY";
76
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
77
return "PLUGIN_AUTH_USER_PASS_VERIFY";
78
case OPENVPN_PLUGIN_CLIENT_CONNECT:
79
return "PLUGIN_CLIENT_CONNECT";
80
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
81
return "PLUGIN_CLIENT_DISCONNECT";
82
case OPENVPN_PLUGIN_LEARN_ADDRESS:
83
return "PLUGIN_LEARN_ADDRESS";
90
plugin_mask_string (const unsigned int type_mask, struct gc_arena *gc)
92
struct buffer out = alloc_buf_gc (256, gc);
96
for (i = 0; i < OPENVPN_PLUGIN_N; ++i)
98
if (OPENVPN_PLUGIN_MASK (i) & type_mask)
101
buf_printf (&out, "|");
102
buf_printf (&out, "%s", plugin_type_name (i));
109
static inline unsigned int
110
plugin_supported_types (void)
112
return ((1<<OPENVPN_PLUGIN_N)-1);
115
struct plugin_option_list *
116
plugin_option_list_new (struct gc_arena *gc)
118
struct plugin_option_list *ret;
119
ALLOC_OBJ_CLEAR_GC (ret, struct plugin_option_list, gc);
124
plugin_option_list_add (struct plugin_option_list *list, const char *so_pathname, const char *args)
126
if (list->n < MAX_PLUGINS)
128
struct plugin_option *o = &list->plugins[list->n++];
129
o->so_pathname = so_pathname;
139
plugin_option_list_print (const struct plugin_option_list *list, int msglevel)
142
for (i = 0; i < list->n; ++i)
144
const struct plugin_option *o = &list->plugins[i];
145
msg (msglevel, " plugin[%d] %s '%s'", i, o->so_pathname, o->args);
150
#if defined(USE_LIBDL)
153
libdl_resolve_symbol (void *handle, void **dest, const char *symbol, const char *plugin_name)
155
*dest = dlsym (handle, symbol);
157
msg (M_FATAL, "PLUGIN: could not find symbol '%s' in plugin shared object %s: %s", symbol, plugin_name, dlerror());
160
#elif defined(USE_LOAD_LIBRARY)
163
dll_resolve_symbol (HMODULE module, void **dest, const char *symbol, const char *plugin_name)
165
*dest = GetProcAddress (module, symbol);
167
msg (M_FATAL, "PLUGIN: could not find symbol '%s' in plugin DLL %s", symbol, plugin_name);
173
plugin_init_item (struct plugin *p, const struct plugin_option *o, const char **envp)
175
struct gc_arena gc = gc_new ();
176
const char **argv = make_arg_array (o->so_pathname, o->args, &gc);
177
p->so_pathname = o->so_pathname;
178
p->plugin_type_mask = plugin_supported_types ();
180
#if defined(USE_LIBDL)
181
p->handle = dlopen (p->so_pathname, RTLD_NOW);
183
msg (M_ERR, "PLUGIN_INIT: could not load plugin shared object %s: %s", p->so_pathname, dlerror());
184
libdl_resolve_symbol (p->handle, (void*)&p->open, "openvpn_plugin_open_v1", p->so_pathname);
185
libdl_resolve_symbol (p->handle, (void*)&p->func, "openvpn_plugin_func_v1", p->so_pathname);
186
libdl_resolve_symbol (p->handle, (void*)&p->close, "openvpn_plugin_close_v1", p->so_pathname);
187
#elif defined(USE_LOAD_LIBRARY)
188
p->module = LoadLibrary (p->so_pathname);
190
msg (M_ERR, "PLUGIN_INIT: could not load plugin DLL: %s", p->so_pathname);
191
dll_resolve_symbol (p->module, (void*)&p->open, "openvpn_plugin_open_v1", p->so_pathname);
192
dll_resolve_symbol (p->module, (void*)&p->func, "openvpn_plugin_func_v1", p->so_pathname);
193
dll_resolve_symbol (p->module, (void*)&p->close, "openvpn_plugin_close_v1", p->so_pathname);
196
dmsg (D_PLUGIN_DEBUG, "PLUGIN_INIT: PRE");
197
plugin_show_args_env (D_PLUGIN_DEBUG, argv, envp);
200
* Call the plugin initialization
202
p->plugin_handle = (*p->open)(&p->plugin_type_mask, argv, envp);
204
msg (D_PLUGIN, "PLUGIN_INIT: POST %s '%s' intercepted=%s",
206
o->args ? o->args : "[NULL]",
207
plugin_mask_string (p->plugin_type_mask, &gc));
209
if ((p->plugin_type_mask | plugin_supported_types()) != plugin_supported_types())
210
msg (M_FATAL, "PLUGIN_INIT: plugin %s expressed interest in unsupported plugin types: [want=0x%08x, have=0x%08x]",
213
plugin_supported_types());
215
if (p->plugin_handle == NULL)
216
msg (M_FATAL, "PLUGIN_INIT: plugin initialization function failed: %s",
223
plugin_call_item (const struct plugin *p, const int type, const char *args, const char **envp)
225
int status = OPENVPN_PLUGIN_FUNC_SUCCESS;
227
if (p->plugin_type_mask & OPENVPN_PLUGIN_MASK (type))
229
struct gc_arena gc = gc_new ();
230
const char **argv = make_arg_array (p->so_pathname, args, &gc);
232
dmsg (D_PLUGIN_DEBUG, "PLUGIN_CALL: PRE type=%s", plugin_type_name (type));
233
plugin_show_args_env (D_PLUGIN_DEBUG, argv, envp);
236
* Call the plugin work function
238
status = (*p->func)(p->plugin_handle, type, argv, envp);
240
msg (D_PLUGIN, "PLUGIN_CALL: POST %s/%s status=%d",
242
plugin_type_name (type),
245
if (status != OPENVPN_PLUGIN_FUNC_SUCCESS)
246
msg (M_WARN, "PLUGIN_CALL: plugin function %s failed with status %d: %s",
247
plugin_type_name (type),
257
plugin_close_item (const struct plugin *p)
259
msg (D_PLUGIN, "PLUGIN_CLOSE: %s", p->so_pathname);
262
* Call the plugin close function
264
(*p->close)(p->plugin_handle);
266
#if defined(USE_LIBDL)
267
if (dlclose (p->handle))
268
msg (M_WARN, "PLUGIN_CLOSE: dlclose() failed on plugin: %s", p->so_pathname);
269
#elif defined(USE_LOAD_LIBRARY)
270
if (!FreeLibrary (p->module))
271
msg (M_WARN, "PLUGIN_CLOSE: FreeLibrary() failed on plugin: %s", p->so_pathname);
276
plugin_list_open (const struct plugin_option_list *list, const struct env_set *es)
278
struct gc_arena gc = gc_new ();
280
struct plugin_list *pl;
283
ALLOC_OBJ_CLEAR (pl, struct plugin_list);
285
envp = make_env_array (es, &gc);
287
for (i = 0; i < list->n; ++i)
288
plugin_init_item (&pl->plugins[i], &list->plugins[i], envp);
297
plugin_call (const struct plugin_list *pl, const int type, const char *args, struct env_set *es)
301
if (plugin_defined (pl, type))
303
struct gc_arena gc = gc_new ();
307
mutex_lock_static (L_PLUGIN);
309
setenv_del (es, "script_type");
310
envp = make_env_array (es, &gc);
312
for (i = 0; i < pl->n; ++i)
314
if (plugin_call_item (&pl->plugins[i], type, args, envp)) /* if any one plugin in the chain fails, return failure */
321
mutex_unlock_static (L_PLUGIN);
330
plugin_list_close (struct plugin_list *pl)
336
for (i = 0; i < pl->n; ++i)
337
plugin_close_item (&pl->plugins[i]);
343
plugin_defined (const struct plugin_list *pl, const int type)
349
const unsigned int mask = OPENVPN_PLUGIN_MASK (type);
350
for (i = 0; i < pl->n; ++i)
352
if (pl->plugins[i].plugin_type_mask & mask)
363
static void dummy(void) {}
364
#endif /* ENABLE_PLUGIN */