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-2009 OpenVPN Technologies, Inc. <sales@openvpn.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 version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #define PLUGIN_SYMBOL_REQUIRED (1<<0)
38 /* used only for program aborts */
39 static struct plugin_common
*static_plugin_common
= NULL
; /* GLOBAL */
42 plugin_show_string_array (int msglevel
, const char *name
, const char *array
[])
45 for (i
= 0; array
[i
]; ++i
)
47 if (env_safe_to_print (array
[i
]))
48 msg (msglevel
, "%s[%d] = '%s'", name
, i
, array
[i
]);
53 plugin_show_args_env (int msglevel
, const char *argv
[], const char *envp
[])
55 if (check_debug_level (msglevel
))
57 plugin_show_string_array (msglevel
, "ARGV", argv
);
58 plugin_show_string_array (msglevel
, "ENVP", envp
);
63 plugin_type_name (const int type
)
67 case OPENVPN_PLUGIN_UP
:
69 case OPENVPN_PLUGIN_DOWN
:
71 case OPENVPN_PLUGIN_ROUTE_UP
:
72 return "PLUGIN_ROUTE_UP";
73 case OPENVPN_PLUGIN_IPCHANGE
:
74 return "PLUGIN_IPCHANGE";
75 case OPENVPN_PLUGIN_TLS_VERIFY
:
76 return "PLUGIN_TLS_VERIFY";
77 case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
:
78 return "PLUGIN_AUTH_USER_PASS_VERIFY";
79 case OPENVPN_PLUGIN_CLIENT_CONNECT
:
80 return "PLUGIN_CLIENT_CONNECT";
81 case OPENVPN_PLUGIN_CLIENT_CONNECT_V2
:
82 return "PLUGIN_CLIENT_CONNECT";
83 case OPENVPN_PLUGIN_CLIENT_DISCONNECT
:
84 return "PLUGIN_CLIENT_DISCONNECT";
85 case OPENVPN_PLUGIN_LEARN_ADDRESS
:
86 return "PLUGIN_LEARN_ADDRESS";
87 case OPENVPN_PLUGIN_TLS_FINAL
:
88 return "PLUGIN_TLS_FINAL";
89 case OPENVPN_PLUGIN_ENABLE_PF
:
90 return "OPENVPN_PLUGIN_ENABLE_PF";
97 plugin_mask_string (const unsigned int type_mask
, struct gc_arena
*gc
)
99 struct buffer out
= alloc_buf_gc (256, gc
);
103 for (i
= 0; i
< OPENVPN_PLUGIN_N
; ++i
)
105 if (OPENVPN_PLUGIN_MASK (i
) & type_mask
)
108 buf_printf (&out
, "|");
109 buf_printf (&out
, "%s", plugin_type_name (i
));
116 static inline unsigned int
117 plugin_supported_types (void)
119 return ((1<<OPENVPN_PLUGIN_N
)-1);
122 struct plugin_option_list
*
123 plugin_option_list_new (struct gc_arena
*gc
)
125 struct plugin_option_list
*ret
;
126 ALLOC_OBJ_CLEAR_GC (ret
, struct plugin_option_list
, gc
);
131 plugin_option_list_add (struct plugin_option_list
*list
, char **p
, struct gc_arena
*gc
)
133 if (list
->n
< MAX_PLUGINS
)
135 struct plugin_option
*o
= &list
->plugins
[list
->n
++];
136 o
->argv
= make_extended_arg_array (p
, gc
);
138 o
->so_pathname
= o
->argv
[0];
147 plugin_option_list_print (const struct plugin_option_list
*list
, int msglevel
)
150 struct gc_arena gc
= gc_new ();
152 for (i
= 0; i
< list
->n
; ++i
)
154 const struct plugin_option
*o
= &list
->plugins
[i
];
155 msg (msglevel
, " plugin[%d] %s '%s'", i
, o
->so_pathname
, print_argv (o
->argv
, &gc
, PA_BRACKET
));
162 #if defined(USE_LIBDL)
165 libdl_resolve_symbol (void *handle
, void **dest
, const char *symbol
, const char *plugin_name
, const unsigned int flags
)
167 *dest
= dlsym (handle
, symbol
);
168 if ((flags
& PLUGIN_SYMBOL_REQUIRED
) && !*dest
)
169 msg (M_FATAL
, "PLUGIN: could not find required symbol '%s' in plugin shared object %s: %s", symbol
, plugin_name
, dlerror());
172 #elif defined(USE_LOAD_LIBRARY)
175 dll_resolve_symbol (HMODULE module
, void **dest
, const char *symbol
, const char *plugin_name
, const unsigned int flags
)
177 *dest
= GetProcAddress (module
, symbol
);
178 if ((flags
& PLUGIN_SYMBOL_REQUIRED
) && !*dest
)
179 msg (M_FATAL
, "PLUGIN: could not find required symbol '%s' in plugin DLL %s", symbol
, plugin_name
);
185 plugin_init_item (struct plugin
*p
, const struct plugin_option
*o
)
187 struct gc_arena gc
= gc_new ();
190 p
->so_pathname
= o
->so_pathname
;
191 p
->plugin_type_mask
= plugin_supported_types ();
193 #if defined(USE_LIBDL)
196 #if defined(PLUGIN_LIBDIR)
197 if (!absolute_pathname (p
->so_pathname
))
201 openvpn_snprintf (full
, sizeof(full
), "%s/%s", PLUGIN_LIBDIR
, p
->so_pathname
);
202 p
->handle
= dlopen (full
, RTLD_NOW
);
203 #if defined(ENABLE_PLUGIN_SEARCH)
207 p
->handle
= dlopen (p
->so_pathname
, RTLD_NOW
);
214 rel
= !absolute_pathname (p
->so_pathname
);
215 p
->handle
= dlopen (p
->so_pathname
, RTLD_NOW
);
218 msg (M_ERR
, "PLUGIN_INIT: could not load plugin shared object %s: %s", p
->so_pathname
, dlerror());
220 # define PLUGIN_SYM(var, name, flags) libdl_resolve_symbol (p->handle, (void*)&p->var, name, p->so_pathname, flags)
222 #elif defined(USE_LOAD_LIBRARY)
224 rel
= !absolute_pathname (p
->so_pathname
);
225 p
->module
= LoadLibrary (p
->so_pathname
);
227 msg (M_ERR
, "PLUGIN_INIT: could not load plugin DLL: %s", p
->so_pathname
);
229 # define PLUGIN_SYM(var, name, flags) dll_resolve_symbol (p->module, (void*)&p->var, name, p->so_pathname, flags)
233 PLUGIN_SYM (open1
, "openvpn_plugin_open_v1", 0);
234 PLUGIN_SYM (open2
, "openvpn_plugin_open_v2", 0);
235 PLUGIN_SYM (func1
, "openvpn_plugin_func_v1", 0);
236 PLUGIN_SYM (func2
, "openvpn_plugin_func_v2", 0);
237 PLUGIN_SYM (close
, "openvpn_plugin_close_v1", PLUGIN_SYMBOL_REQUIRED
);
238 PLUGIN_SYM (abort
, "openvpn_plugin_abort_v1", 0);
239 PLUGIN_SYM (client_constructor
, "openvpn_plugin_client_constructor_v1", 0);
240 PLUGIN_SYM (client_destructor
, "openvpn_plugin_client_destructor_v1", 0);
241 PLUGIN_SYM (min_version_required
, "openvpn_plugin_min_version_required_v1", 0);
242 PLUGIN_SYM (initialization_point
, "openvpn_plugin_select_initialization_point_v1", 0);
244 if (!p
->open1
&& !p
->open2
)
245 msg (M_FATAL
, "PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s", p
->so_pathname
);
247 if (!p
->func1
&& !p
->func2
)
248 msg (M_FATAL
, "PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s", p
->so_pathname
);
251 * Verify that we are sufficiently up-to-date to handle the plugin
253 if (p
->min_version_required
)
255 const int plugin_needs_version
= (*p
->min_version_required
)();
256 if (plugin_needs_version
> OPENVPN_PLUGIN_VERSION
)
257 msg (M_FATAL
, "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s",
258 plugin_needs_version
,
259 OPENVPN_PLUGIN_VERSION
,
263 if (p
->initialization_point
)
264 p
->requested_initialization_point
= (*p
->initialization_point
)();
266 p
->requested_initialization_point
= OPENVPN_PLUGIN_INIT_PRE_DAEMON
;
269 msg (M_WARN
, "WARNING: plugin '%s' specified by a relative pathname -- using an absolute pathname would be more secure", p
->so_pathname
);
271 p
->initialized
= true;
277 plugin_open_item (struct plugin
*p
,
278 const struct plugin_option
*o
,
279 struct openvpn_plugin_string_list
**retlist
,
281 const int init_point
)
283 ASSERT (p
->initialized
);
285 /* clear return list */
289 if (!p
->plugin_handle
&& init_point
== p
->requested_initialization_point
)
291 struct gc_arena gc
= gc_new ();
293 dmsg (D_PLUGIN_DEBUG
, "PLUGIN_INIT: PRE");
294 plugin_show_args_env (D_PLUGIN_DEBUG
, o
->argv
, envp
);
297 * Call the plugin initialization
300 p
->plugin_handle
= (*p
->open2
)(&p
->plugin_type_mask
, o
->argv
, envp
, retlist
);
302 p
->plugin_handle
= (*p
->open1
)(&p
->plugin_type_mask
, o
->argv
, envp
);
306 msg (D_PLUGIN
, "PLUGIN_INIT: POST %s '%s' intercepted=%s %s",
308 print_argv (o
->argv
, &gc
, PA_BRACKET
),
309 plugin_mask_string (p
->plugin_type_mask
, &gc
),
310 (retlist
&& *retlist
) ? "[RETLIST]" : "");
312 if ((p
->plugin_type_mask
| plugin_supported_types()) != plugin_supported_types())
313 msg (M_FATAL
, "PLUGIN_INIT: plugin %s expressed interest in unsupported plugin types: [want=0x%08x, have=0x%08x]",
316 plugin_supported_types());
318 if (p
->plugin_handle
== NULL
)
319 msg (M_FATAL
, "PLUGIN_INIT: plugin initialization function failed: %s",
327 plugin_call_item (const struct plugin
*p
,
328 void *per_client_context
,
330 const struct argv
*av
,
331 struct openvpn_plugin_string_list
**retlist
,
334 int status
= OPENVPN_PLUGIN_FUNC_SUCCESS
;
336 /* clear return list */
340 if (p
->plugin_handle
&& (p
->plugin_type_mask
& OPENVPN_PLUGIN_MASK (type
)))
342 struct gc_arena gc
= gc_new ();
343 struct argv a
= argv_insert_head (av
, p
->so_pathname
);
345 dmsg (D_PLUGIN_DEBUG
, "PLUGIN_CALL: PRE type=%s", plugin_type_name (type
));
346 plugin_show_args_env (D_PLUGIN_DEBUG
, (const char **)a
.argv
, envp
);
349 * Call the plugin work function
352 status
= (*p
->func2
)(p
->plugin_handle
, type
, (const char **)a
.argv
, envp
, per_client_context
, retlist
);
354 status
= (*p
->func1
)(p
->plugin_handle
, type
, (const char **)a
.argv
, envp
);
358 msg (D_PLUGIN
, "PLUGIN_CALL: POST %s/%s status=%d",
360 plugin_type_name (type
),
363 if (status
== OPENVPN_PLUGIN_FUNC_ERROR
)
364 msg (M_WARN
, "PLUGIN_CALL: plugin function %s failed with status %d: %s",
365 plugin_type_name (type
),
376 plugin_close_item (struct plugin
*p
)
380 msg (D_PLUGIN
, "PLUGIN_CLOSE: %s", p
->so_pathname
);
383 * Call the plugin close function
385 if (p
->plugin_handle
)
386 (*p
->close
)(p
->plugin_handle
);
388 #if defined(USE_LIBDL)
389 if (dlclose (p
->handle
))
390 msg (M_WARN
, "PLUGIN_CLOSE: dlclose() failed on plugin: %s", p
->so_pathname
);
391 #elif defined(USE_LOAD_LIBRARY)
392 if (!FreeLibrary (p
->module
))
393 msg (M_WARN
, "PLUGIN_CLOSE: FreeLibrary() failed on plugin: %s", p
->so_pathname
);
396 p
->initialized
= false;
401 plugin_abort_item (const struct plugin
*p
)
404 * Call the plugin abort function
407 (*p
->abort
)(p
->plugin_handle
);
411 plugin_per_client_init (const struct plugin_common
*pc
,
412 struct plugin_per_client
*cli
,
413 const int init_point
)
418 for (i
= 0; i
< n
; ++i
)
420 const struct plugin
*p
= &pc
->plugins
[i
];
422 && (init_point
< 0 || init_point
== p
->requested_initialization_point
)
423 && p
->client_constructor
)
424 cli
->per_client_context
[i
] = (*p
->client_constructor
)(p
->plugin_handle
);
429 plugin_per_client_destroy (const struct plugin_common
*pc
, struct plugin_per_client
*cli
)
434 for (i
= 0; i
< n
; ++i
)
436 const struct plugin
*p
= &pc
->plugins
[i
];
437 void *cc
= cli
->per_client_context
[i
];
439 if (p
->client_destructor
&& cc
)
440 (*p
->client_destructor
)(p
->plugin_handle
, cc
);
446 plugin_list_inherit (const struct plugin_list
*src
)
448 struct plugin_list
*pl
;
449 ALLOC_OBJ_CLEAR (pl
, struct plugin_list
);
450 pl
->common
= src
->common
;
452 plugin_per_client_init (pl
->common
, &pl
->per_client
, -1);
456 static struct plugin_common
*
457 plugin_common_init (const struct plugin_option_list
*list
)
460 struct plugin_common
*pc
;
462 ALLOC_OBJ_CLEAR (pc
, struct plugin_common
);
464 for (i
= 0; i
< list
->n
; ++i
)
466 plugin_init_item (&pc
->plugins
[i
],
471 static_plugin_common
= pc
;
476 plugin_common_open (struct plugin_common
*pc
,
477 const struct plugin_option_list
*list
,
478 struct plugin_return
*pr
,
479 const struct env_set
*es
,
480 const int init_point
)
482 struct gc_arena gc
= gc_new ();
486 envp
= make_env_array (es
, false, &gc
);
489 plugin_return_init (pr
);
491 for (i
= 0; i
< pc
->n
; ++i
)
493 plugin_open_item (&pc
->plugins
[i
],
495 pr
? &pr
->list
[i
] : NULL
,
507 plugin_common_close (struct plugin_common
*pc
)
509 static_plugin_common
= NULL
;
514 for (i
= 0; i
< pc
->n
; ++i
)
515 plugin_close_item (&pc
->plugins
[i
]);
521 plugin_list_init (const struct plugin_option_list
*list
)
523 struct plugin_list
*pl
;
524 ALLOC_OBJ_CLEAR (pl
, struct plugin_list
);
525 pl
->common
= plugin_common_init (list
);
526 pl
->common_owned
= true;
531 plugin_list_open (struct plugin_list
*pl
,
532 const struct plugin_option_list
*list
,
533 struct plugin_return
*pr
,
534 const struct env_set
*es
,
535 const int init_point
)
537 plugin_common_open (pl
->common
, list
, pr
, es
, init_point
);
538 plugin_per_client_init (pl
->common
, &pl
->per_client
, init_point
);
542 plugin_call (const struct plugin_list
*pl
,
544 const struct argv
*av
,
545 struct plugin_return
*pr
,
549 plugin_return_init (pr
);
551 if (plugin_defined (pl
, type
))
553 struct gc_arena gc
= gc_new ();
556 const int n
= plugin_n (pl
);
557 bool success
= false;
559 bool deferred
= false;
561 mutex_lock_static (L_PLUGIN
);
563 setenv_del (es
, "script_type");
564 envp
= make_env_array (es
, false, &gc
);
566 for (i
= 0; i
< n
; ++i
)
568 const int status
= plugin_call_item (&pl
->common
->plugins
[i
],
569 pl
->per_client
.per_client_context
[i
],
572 pr
? &pr
->list
[i
] : NULL
,
576 case OPENVPN_PLUGIN_FUNC_SUCCESS
:
579 case OPENVPN_PLUGIN_FUNC_DEFERRED
:
591 mutex_unlock_static (L_PLUGIN
);
595 if (type
== OPENVPN_PLUGIN_ENABLE_PF
&& success
)
596 return OPENVPN_PLUGIN_FUNC_SUCCESS
;
598 return OPENVPN_PLUGIN_FUNC_ERROR
;
600 return OPENVPN_PLUGIN_FUNC_DEFERRED
;
603 return OPENVPN_PLUGIN_FUNC_SUCCESS
;
607 plugin_list_close (struct plugin_list
*pl
)
613 plugin_per_client_destroy (pl
->common
, &pl
->per_client
);
615 if (pl
->common_owned
)
616 plugin_common_close (pl
->common
);
626 struct plugin_common
*pc
= static_plugin_common
;
627 static_plugin_common
= NULL
;
632 for (i
= 0; i
< pc
->n
; ++i
)
633 plugin_abort_item (&pc
->plugins
[i
]);
638 plugin_defined (const struct plugin_list
*pl
, const int type
)
644 const struct plugin_common
*pc
= pl
->common
;
649 const unsigned int mask
= OPENVPN_PLUGIN_MASK (type
);
650 for (i
= 0; i
< pc
->n
; ++i
)
652 if (pc
->plugins
[i
].plugin_type_mask
& mask
)
664 * Plugin return functions
668 openvpn_plugin_string_list_item_free (struct openvpn_plugin_string_list
*l
)
673 string_clear (l
->value
);
680 openvpn_plugin_string_list_free (struct openvpn_plugin_string_list
*l
)
682 struct openvpn_plugin_string_list
*next
;
686 openvpn_plugin_string_list_item_free (l
);
691 static struct openvpn_plugin_string_list
*
692 openvpn_plugin_string_list_find (struct openvpn_plugin_string_list
*l
, const char *name
)
696 if (!strcmp (l
->name
, name
))
704 plugin_return_get_column (const struct plugin_return
*src
,
705 struct plugin_return
*dest
,
711 for (i
= 0; i
< src
->n
; ++i
)
712 dest
->list
[i
] = openvpn_plugin_string_list_find (src
->list
[i
], colname
);
717 plugin_return_free (struct plugin_return
*pr
)
720 for (i
= 0; i
< pr
->n
; ++i
)
721 openvpn_plugin_string_list_free (pr
->list
[i
]);
727 plugin_return_print (const int msglevel
, const char *prefix
, const struct plugin_return
*pr
)
730 msg (msglevel
, "PLUGIN_RETURN_PRINT %s", prefix
);
731 for (i
= 0; i
< pr
->n
; ++i
)
733 struct openvpn_plugin_string_list
*l
= pr
->list
[i
];
736 msg (msglevel
, "PLUGIN #%d (%s)", i
, prefix
);
739 msg (msglevel
, "[%d] '%s' -> '%s'\n",
750 static void dummy(void) {}
751 #endif /* ENABLE_PLUGIN */