OpenVPN
plugin.c
Go to the documentation of this file.
1 /*
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
6  * packet compression.
7  *
8  * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9  *
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.
13  *
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.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 #ifdef HAVE_CONFIG_VERSION_H
30 #include "config-version.h"
31 #endif
32 
33 #include "syshead.h"
34 
35 #ifdef ENABLE_PLUGIN
36 
37 #ifdef HAVE_DLFCN_H
38 #include <dlfcn.h>
39 #endif
40 
41 #include "buffer.h"
42 #include "error.h"
43 #include "misc.h"
44 #include "plugin.h"
45 #include "ssl_backend.h"
46 #include "base64.h"
47 #include "win32.h"
48 #include "memdbg.h"
49 
50 #define PLUGIN_SYMBOL_REQUIRED (1<<0)
51 
52 /* used only for program aborts */
53 static struct plugin_common *static_plugin_common = NULL; /* GLOBAL */
54 
55 static void
56 plugin_show_string_array(int msglevel, const char *name, const char *array[])
57 {
58  int i;
59  for (i = 0; array[i]; ++i)
60  {
61  if (env_safe_to_print(array[i]))
62  {
63  msg(msglevel, "%s[%d] = '%s'", name, i, array[i]);
64  }
65  }
66 }
67 
68 static void
69 plugin_show_args_env(int msglevel, const char *argv[], const char *envp[])
70 {
71  if (check_debug_level(msglevel))
72  {
73  plugin_show_string_array(msglevel, "ARGV", argv);
74  plugin_show_string_array(msglevel, "ENVP", envp);
75  }
76 }
77 
78 static const char *
79 plugin_type_name(const int type)
80 {
81  switch (type)
82  {
83  case OPENVPN_PLUGIN_UP:
84  return "PLUGIN_UP";
85 
87  return "PLUGIN_DOWN";
88 
90  return "PLUGIN_ROUTE_UP";
91 
93  return "PLUGIN_IPCHANGE";
94 
96  return "PLUGIN_TLS_VERIFY";
97 
99  return "PLUGIN_AUTH_USER_PASS_VERIFY";
100 
102  return "PLUGIN_CLIENT_CONNECT";
103 
105  return "PLUGIN_CLIENT_CONNECT";
106 
107  case OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER:
108  return "PLUGIN_CLIENT_CONNECT_DEFER";
109 
110  case OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2:
111  return "PLUGIN_CLIENT_CONNECT_DEFER_V2";
112 
114  return "PLUGIN_CLIENT_DISCONNECT";
115 
117  return "PLUGIN_LEARN_ADDRESS";
118 
120  return "PLUGIN_TLS_FINAL";
121 
123  return "PLUGIN_ENABLE_PF";
124 
126  return "PLUGIN_ROUTE_PREDOWN";
127 
128  default:
129  return "PLUGIN_???";
130  }
131 }
132 
133 static const char *
134 plugin_mask_string(const unsigned int type_mask, struct gc_arena *gc)
135 {
136  struct buffer out = alloc_buf_gc(256, gc);
137  bool first = true;
138  int i;
139 
140  for (i = 0; i < OPENVPN_PLUGIN_N; ++i)
141  {
142  if (OPENVPN_PLUGIN_MASK(i) & type_mask)
143  {
144  if (!first)
145  {
146  buf_printf(&out, "|");
147  }
148  buf_printf(&out, "%s", plugin_type_name(i));
149  first = false;
150  }
151  }
152  return BSTR(&out);
153 }
154 
155 static inline unsigned int
157 {
158  return ((1<<OPENVPN_PLUGIN_N)-1);
159 }
160 
161 struct plugin_option_list *
163 {
164  struct plugin_option_list *ret;
165  ALLOC_OBJ_CLEAR_GC(ret, struct plugin_option_list, gc);
166  return ret;
167 }
168 
169 bool
171  struct gc_arena *gc)
172 {
173  if (list->n < MAX_PLUGINS)
174  {
175  struct plugin_option *o = &list->plugins[list->n++];
176  o->argv = make_extended_arg_array(p, false, gc);
177  if (o->argv[0])
178  {
179  o->so_pathname = o->argv[0];
180  }
181  return true;
182  }
183  else
184  {
185  return false;
186  }
187 }
188 
189 #ifndef ENABLE_SMALL
190 void
191 plugin_option_list_print(const struct plugin_option_list *list, int msglevel)
192 {
193  int i;
194  struct gc_arena gc = gc_new();
195 
196  for (i = 0; i < list->n; ++i)
197  {
198  const struct plugin_option *o = &list->plugins[i];
199  msg(msglevel, " plugin[%d] %s '%s'", i, o->so_pathname, print_argv(o->argv, &gc, PA_BRACKET));
200  }
201 
202  gc_free(&gc);
203 }
204 #endif
205 
206 #ifndef _WIN32
207 
208 static void
209 libdl_resolve_symbol(void *handle, void **dest, const char *symbol, const char *plugin_name, const unsigned int flags)
210 {
211  *dest = dlsym(handle, symbol);
212  if ((flags & PLUGIN_SYMBOL_REQUIRED) && !*dest)
213  {
214  msg(M_FATAL, "PLUGIN: could not find required symbol '%s' in plugin shared object %s: %s", symbol, plugin_name, dlerror());
215  }
216 }
217 
218 #else /* ifndef _WIN32 */
219 
220 static void
221 dll_resolve_symbol(HMODULE module, void **dest, const char *symbol, const char *plugin_name, const unsigned int flags)
222 {
223  *dest = GetProcAddress(module, symbol);
224  if ((flags & PLUGIN_SYMBOL_REQUIRED) && !*dest)
225  {
226  msg(M_FATAL, "PLUGIN: could not find required symbol '%s' in plugin DLL %s", symbol, plugin_name);
227  }
228 }
229 
230 #endif /* ifndef _WIN32 */
231 
232 static void
233 plugin_init_item(struct plugin *p, const struct plugin_option *o)
234 {
235  struct gc_arena gc = gc_new();
236  bool rel = false;
237 
238  p->so_pathname = o->so_pathname;
240 
241 #ifndef _WIN32
242 
243  p->handle = NULL;
244 
245  /* If the plug-in filename is not an absolute path,
246  * or beginning with '.', it should use the PLUGIN_LIBDIR
247  * as the base directory for loading the plug-in.
248  *
249  * This means the following scenarios are loaded from these places:
250  * --plugin fancyplug.so -> $PLUGIN_LIBDIR/fancyplug.so
251  * --plugin my/fancyplug.so -> $PLUGIN_LIBDIR/my/fancyplug.so
252  * --plugin ./fancyplug.so -> $CWD/fancyplug.so
253  * --plugin /usr/lib/my/fancyplug.so -> /usr/lib/my/fancyplug.so
254  *
255  * Please note that $CWD means the directory OpenVPN is either started from
256  * or the directory OpenVPN have changed into using --cd before --plugin
257  * was parsed.
258  *
259  */
261  && p->so_pathname[0] != '.')
262  {
263  char full[PATH_MAX];
264 
265  openvpn_snprintf(full, sizeof(full), "%s/%s", PLUGIN_LIBDIR, p->so_pathname);
266  p->handle = dlopen(full, RTLD_NOW);
267  }
268  else
269  {
271  p->handle = dlopen(p->so_pathname, RTLD_NOW);
272  }
273  if (!p->handle)
274  {
275  msg(M_ERR, "PLUGIN_INIT: could not load plugin shared object %s: %s", p->so_pathname, dlerror());
276  }
277 
278 #define PLUGIN_SYM(var, name, flags) libdl_resolve_symbol(p->handle, (void *)&p->var, name, p->so_pathname, flags)
279 
280 #else /* ifndef _WIN32 */
281 
283  p->module = LoadLibraryW(wide_string(p->so_pathname, &gc));
284  if (!p->module)
285  {
286  msg(M_ERR, "PLUGIN_INIT: could not load plugin DLL: %s", p->so_pathname);
287  }
288 
289 #define PLUGIN_SYM(var, name, flags) dll_resolve_symbol(p->module, (void *)&p->var, name, p->so_pathname, flags)
290 
291 #endif /* ifndef _WIN32 */
292 
293  PLUGIN_SYM(open1, "openvpn_plugin_open_v1", 0);
294  PLUGIN_SYM(open2, "openvpn_plugin_open_v2", 0);
295  PLUGIN_SYM(open3, "openvpn_plugin_open_v3", 0);
296  PLUGIN_SYM(func1, "openvpn_plugin_func_v1", 0);
297  PLUGIN_SYM(func2, "openvpn_plugin_func_v2", 0);
298  PLUGIN_SYM(func3, "openvpn_plugin_func_v3", 0);
299  PLUGIN_SYM(close, "openvpn_plugin_close_v1", PLUGIN_SYMBOL_REQUIRED);
300  PLUGIN_SYM(abort, "openvpn_plugin_abort_v1", 0);
301  PLUGIN_SYM(client_constructor, "openvpn_plugin_client_constructor_v1", 0);
302  PLUGIN_SYM(client_destructor, "openvpn_plugin_client_destructor_v1", 0);
303  PLUGIN_SYM(min_version_required, "openvpn_plugin_min_version_required_v1", 0);
304  PLUGIN_SYM(initialization_point, "openvpn_plugin_select_initialization_point_v1", 0);
305 
306  if (!p->open1 && !p->open2 && !p->open3)
307  {
308  msg(M_FATAL, "PLUGIN: symbol openvpn_plugin_open_vX is undefined in plugin: %s", p->so_pathname);
309  }
310 
311  if (!p->func1 && !p->func2 && !p->func3)
312  {
313  msg(M_FATAL, "PLUGIN: symbol openvpn_plugin_func_vX is undefined in plugin: %s", p->so_pathname);
314  }
315 
316  /*
317  * Verify that we are sufficiently up-to-date to handle the plugin
318  */
319  if (p->min_version_required)
320  {
321  const int plugin_needs_version = (*p->min_version_required)();
322  if (plugin_needs_version > OPENVPN_PLUGIN_VERSION)
323  {
324  msg(M_FATAL, "PLUGIN_INIT: plugin needs interface version %d, but this version of OpenVPN only supports version %d: %s",
325  plugin_needs_version,
327  p->so_pathname);
328  }
329  }
330 
331  if (p->initialization_point)
332  {
334  }
335  else
336  {
338  }
339 
340  if (rel)
341  {
342  msg(M_WARN, "WARNING: plugin '%s' specified by a relative pathname -- using an absolute pathname would be more secure", p->so_pathname);
343  }
344 
345  p->initialized = true;
346 
347  gc_free(&gc);
348 }
349 
350 static void
351 plugin_vlog(openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist)
352 {
353  unsigned int msg_flags = 0;
354 
355  if (!format)
356  {
357  return;
358  }
359 
360  if (!name || name[0] == '\0')
361  {
362  msg(D_PLUGIN_DEBUG, "PLUGIN: suppressed log message from plugin with unknown name");
363  return;
364  }
365 
366  if (flags & PLOG_ERR)
367  {
368  msg_flags = M_INFO | M_NONFATAL;
369  }
370  else if (flags & PLOG_WARN)
371  {
372  msg_flags = M_INFO | M_WARN;
373  }
374  else if (flags & PLOG_NOTE)
375  {
376  msg_flags = M_INFO;
377  }
378  else if (flags & PLOG_DEBUG)
379  {
380  msg_flags = D_PLUGIN_DEBUG;
381  }
382 
383  if (flags & PLOG_ERRNO)
384  {
385  msg_flags |= M_ERRNO;
386  }
387  if (flags & PLOG_NOMUTE)
388  {
389  msg_flags |= M_NOMUTE;
390  }
391 
392  if (msg_test(msg_flags))
393  {
394  struct gc_arena gc;
395  char *msg_fmt;
396 
397  /* Never add instance prefix; not thread safe */
398  msg_flags |= M_NOIPREFIX;
399 
400  gc_init(&gc);
401  msg_fmt = gc_malloc(ERR_BUF_SIZE, false, &gc);
402  openvpn_snprintf(msg_fmt, ERR_BUF_SIZE, "PLUGIN %s: %s", name, format);
403  x_msg_va(msg_flags, msg_fmt, arglist);
404 
405  gc_free(&gc);
406  }
407 }
408 
409 static void
410 plugin_log(openvpn_plugin_log_flags_t flags, const char *name, const char *format, ...)
411 {
412  va_list arglist;
413  va_start(arglist, format);
414  plugin_vlog(flags, name, format, arglist);
415  va_end(arglist);
416 }
417 
419  plugin_log,
420  plugin_vlog,
421  secure_memzero, /* plugin_secure_memzero */
422  openvpn_base64_encode, /* plugin_base64_encode */
423  openvpn_base64_decode, /* plugin_base64_decode */
424 };
425 
426 
427 /* Provide a wrapper macro for a version patch level string to plug-ins.
428  * This is located here purely to not make the code too messy with #ifndef
429  * inside a struct declaration
430  */
431 #ifndef CONFIGURE_GIT_REVISION
432 #define _OPENVPN_PATCH_LEVEL OPENVPN_VERSION_PATCH
433 #else
434 #define _OPENVPN_PATCH_LEVEL "git:" CONFIGURE_GIT_REVISION CONFIGURE_GIT_FLAGS
435 #endif
436 
437 static void
439  const struct plugin_option *o,
440  struct openvpn_plugin_string_list **retlist,
441  const char **envp,
442  const int init_point)
443 {
444  ASSERT(p->initialized);
445 
446  /* clear return list */
447  if (retlist)
448  {
449  *retlist = NULL;
450  }
451 
452  if (!p->plugin_handle && init_point == p->requested_initialization_point)
453  {
454  struct gc_arena gc = gc_new();
455 
456  dmsg(D_PLUGIN_DEBUG, "PLUGIN_INIT: PRE");
458 
459  /*
460  * Call the plugin initialization
461  */
462  if (p->open3)
463  {
465  (const char **const) o->argv,
466  (const char **const) envp,
467  &callbacks,
468  SSLAPI,
473  struct openvpn_plugin_args_open_return retargs;
474 
475  CLEAR(retargs);
476  retargs.return_list = retlist;
477  if ((*p->open3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs) == OPENVPN_PLUGIN_FUNC_SUCCESS)
478  {
479  p->plugin_type_mask = retargs.type_mask;
480  p->plugin_handle = retargs.handle;
481  }
482  else
483  {
484  p->plugin_handle = NULL;
485  }
486  }
487  else if (p->open2)
488  {
489  p->plugin_handle = (*p->open2)(&p->plugin_type_mask, o->argv, envp, retlist);
490  }
491  else if (p->open1)
492  {
493  p->plugin_handle = (*p->open1)(&p->plugin_type_mask, o->argv, envp);
494  }
495  else
496  {
497  ASSERT(0);
498  }
499 
500  msg(D_PLUGIN, "PLUGIN_INIT: POST %s '%s' intercepted=%s %s",
501  p->so_pathname,
502  print_argv(o->argv, &gc, PA_BRACKET),
504  (retlist && *retlist) ? "[RETLIST]" : "");
505 
507  {
508  msg(M_FATAL, "PLUGIN_INIT: plugin %s expressed interest in unsupported plugin types: [want=0x%08x, have=0x%08x]",
509  p->so_pathname,
510  p->plugin_type_mask,
512  }
513 
514  if (p->plugin_handle == NULL)
515  {
516  msg(M_FATAL, "PLUGIN_INIT: plugin initialization function failed: %s",
517  p->so_pathname);
518  }
519 
520  gc_free(&gc);
521  }
522 }
523 
524 static int
525 plugin_call_item(const struct plugin *p,
526  void *per_client_context,
527  const int type,
528  const struct argv *av,
529  struct openvpn_plugin_string_list **retlist,
530  const char **envp,
531  int certdepth,
532  openvpn_x509_cert_t *current_cert
533  )
534 {
536 
537  /* clear return list */
538  if (retlist)
539  {
540  *retlist = NULL;
541  }
542 
543  if (p->plugin_handle && (p->plugin_type_mask & OPENVPN_PLUGIN_MASK(type)))
544  {
545  struct gc_arena gc = gc_new();
546  struct argv a = argv_insert_head(av, p->so_pathname);
547 
548  dmsg(D_PLUGIN_DEBUG, "PLUGIN_CALL: PRE type=%s", plugin_type_name(type));
549  plugin_show_args_env(D_PLUGIN_DEBUG, (const char **)a.argv, envp);
550 
551  /*
552  * Call the plugin work function
553  */
554  if (p->func3)
555  {
556  struct openvpn_plugin_args_func_in args = { type,
557  (const char **const) a.argv,
558  (const char **const) envp,
559  p->plugin_handle,
561  (current_cert ? certdepth : -1),
562  current_cert };
563 
564  struct openvpn_plugin_args_func_return retargs;
565 
566  CLEAR(retargs);
567  retargs.return_list = retlist;
568  status = (*p->func3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs);
569  }
570  else if (p->func2)
571  {
572  status = (*p->func2)(p->plugin_handle, type, (const char **)a.argv, envp, per_client_context, retlist);
573  }
574  else if (p->func1)
575  {
576  status = (*p->func1)(p->plugin_handle, type, (const char **)a.argv, envp);
577  }
578  else
579  {
580  ASSERT(0);
581  }
582 
583  msg(D_PLUGIN, "PLUGIN_CALL: POST %s/%s status=%d",
584  p->so_pathname,
585  plugin_type_name(type),
586  status);
587 
588  if (status == OPENVPN_PLUGIN_FUNC_ERROR)
589  {
590  msg(M_WARN, "PLUGIN_CALL: plugin function %s failed with status %d: %s",
591  plugin_type_name(type),
592  status,
593  p->so_pathname);
594  }
595 
596  argv_free(&a);
597  gc_free(&gc);
598  }
599  return status;
600 }
601 
602 static void
604 {
605  if (p->initialized)
606  {
607  msg(D_PLUGIN, "PLUGIN_CLOSE: %s", p->so_pathname);
608 
609  /*
610  * Call the plugin close function
611  */
612  if (p->plugin_handle)
613  {
614  (*p->close)(p->plugin_handle);
615  }
616 
617 #ifndef _WIN32
618  if (dlclose(p->handle))
619  {
620  msg(M_WARN, "PLUGIN_CLOSE: dlclose() failed on plugin: %s", p->so_pathname);
621  }
622 #elif defined(_WIN32)
623  if (!FreeLibrary(p->module))
624  {
625  msg(M_WARN, "PLUGIN_CLOSE: FreeLibrary() failed on plugin: %s", p->so_pathname);
626  }
627 #endif
628 
629  p->initialized = false;
630  }
631 }
632 
633 static void
634 plugin_abort_item(const struct plugin *p)
635 {
636  /*
637  * Call the plugin abort function
638  */
639  if (p->abort)
640  {
641  (*p->abort)(p->plugin_handle);
642  }
643 }
644 
645 static void
647  struct plugin_per_client *cli,
648  const int init_point)
649 {
650  const int n = pc->n;
651  int i;
652 
653  for (i = 0; i < n; ++i)
654  {
655  const struct plugin *p = &pc->plugins[i];
656  if (p->plugin_handle
657  && (init_point < 0 || init_point == p->requested_initialization_point)
658  && p->client_constructor)
659  {
661  }
662  }
663 }
664 
665 static void
667 {
668  const int n = pc->n;
669  int i;
670 
671  for (i = 0; i < n; ++i)
672  {
673  const struct plugin *p = &pc->plugins[i];
674  void *cc = cli->per_client_context[i];
675 
676  if (p->client_destructor && cc)
677  {
678  (*p->client_destructor)(p->plugin_handle, cc);
679  }
680  }
681  CLEAR(*cli);
682 }
683 
684 struct plugin_list *
686 {
687  struct plugin_list *pl;
688  ALLOC_OBJ_CLEAR(pl, struct plugin_list);
689  pl->common = src->common;
690  ASSERT(pl->common);
692  return pl;
693 }
694 
695 static struct plugin_common *
697 {
698  int i;
699  struct plugin_common *pc;
700 
701  ALLOC_OBJ_CLEAR(pc, struct plugin_common);
702 
703  for (i = 0; i < list->n; ++i)
704  {
705  plugin_init_item(&pc->plugins[i],
706  &list->plugins[i]);
707  pc->n = i + 1;
708  }
709 
710  static_plugin_common = pc;
711  return pc;
712 }
713 
714 static void
716  const struct plugin_option_list *list,
717  struct plugin_return *pr,
718  const struct env_set *es,
719  const int init_point)
720 {
721  struct gc_arena gc = gc_new();
722  int i;
723  const char **envp;
724 
725  envp = make_env_array(es, false, &gc);
726 
727  if (pr)
728  {
729  plugin_return_init(pr);
730  }
731 
732  for (i = 0; i < pc->n; ++i)
733  {
734  plugin_open_item(&pc->plugins[i],
735  &list->plugins[i],
736  pr ? &pr->list[i] : NULL,
737  envp,
738  init_point);
739  }
740 
741  if (pr)
742  {
743  pr->n = i;
744  }
745 
746  gc_free(&gc);
747 }
748 
749 static void
751 {
752  static_plugin_common = NULL;
753  if (pc)
754  {
755  int i;
756 
757  for (i = 0; i < pc->n; ++i)
758  {
759  plugin_close_item(&pc->plugins[i]);
760  }
761  free(pc);
762  }
763 }
764 
765 struct plugin_list *
767 {
768  struct plugin_list *pl;
769  ALLOC_OBJ_CLEAR(pl, struct plugin_list);
770  pl->common = plugin_common_init(list);
771  pl->common_owned = true;
772  return pl;
773 }
774 
775 void
777  const struct plugin_option_list *list,
778  struct plugin_return *pr,
779  const struct env_set *es,
780  const int init_point)
781 {
782  plugin_common_open(pl->common, list, pr, es, init_point);
783  plugin_per_client_init(pl->common, &pl->per_client, init_point);
784 }
785 
786 int
787 plugin_call_ssl(const struct plugin_list *pl,
788  const int type,
789  const struct argv *av,
790  struct plugin_return *pr,
791  struct env_set *es,
792  int certdepth,
793  openvpn_x509_cert_t *current_cert
794  )
795 {
796  if (pr)
797  {
798  plugin_return_init(pr);
799  }
800 
801  if (plugin_defined(pl, type))
802  {
803  struct gc_arena gc = gc_new();
804  int i;
805  const char **envp;
806  const int n = plugin_n(pl);
807  bool success = false;
808  bool error = false;
809  bool deferred = false;
810 
811  setenv_del(es, "script_type");
812  envp = make_env_array(es, false, &gc);
813 
814  for (i = 0; i < n; ++i)
815  {
816  const int status = plugin_call_item(&pl->common->plugins[i],
818  type,
819  av,
820  pr ? &pr->list[i] : NULL,
821  envp,
822  certdepth,
823  current_cert
824  );
825  switch (status)
826  {
828  success = true;
829  break;
830 
832  deferred = true;
833  break;
834 
835  default:
836  error = true;
837  break;
838  }
839  }
840 
841  if (pr)
842  {
843  pr->n = i;
844  }
845 
846  gc_free(&gc);
847 
848  if (type == OPENVPN_PLUGIN_ENABLE_PF && success)
849  {
851  }
852  else if (error)
853  {
855  }
856  else if (deferred)
857  {
859  }
860  }
861 
863 }
864 
865 void
867 {
868  if (pl)
869  {
870  if (pl->common)
871  {
873 
874  if (pl->common_owned)
875  {
877  }
878  }
879 
880  free(pl);
881  }
882 }
883 
884 void
886 {
887  struct plugin_common *pc = static_plugin_common;
888  static_plugin_common = NULL;
889  if (pc)
890  {
891  int i;
892 
893  for (i = 0; i < pc->n; ++i)
894  {
895  plugin_abort_item(&pc->plugins[i]);
896  }
897  }
898 }
899 
900 bool
901 plugin_defined(const struct plugin_list *pl, const int type)
902 {
903  bool ret = false;
904 
905  if (pl)
906  {
907  const struct plugin_common *pc = pl->common;
908 
909  if (pc)
910  {
911  int i;
912  const unsigned int mask = OPENVPN_PLUGIN_MASK(type);
913  for (i = 0; i < pc->n; ++i)
914  {
915  if (pc->plugins[i].plugin_type_mask & mask)
916  {
917  ret = true;
918  break;
919  }
920  }
921  }
922  }
923  return ret;
924 }
925 
926 /*
927  * Plugin return functions
928  */
929 
930 static void
932 {
933  if (l)
934  {
935  free(l->name);
936  string_clear(l->value);
937  free(l->value);
938  free(l);
939  }
940 }
941 
942 static void
944 {
946  while (l)
947  {
948  next = l->next;
950  l = next;
951  }
952 }
953 
954 static struct openvpn_plugin_string_list *
956 {
957  while (l)
958  {
959  if (!strcmp(l->name, name))
960  {
961  return l;
962  }
963  l = l->next;
964  }
965  return NULL;
966 }
967 
968 void
970  struct plugin_return *dest,
971  const char *colname)
972 {
973  int i;
974 
975  dest->n = 0;
976  for (i = 0; i < src->n; ++i)
977  {
978  dest->list[i] = openvpn_plugin_string_list_find(src->list[i], colname);
979  }
980  dest->n = i;
981 }
982 
983 void
985 {
986  int i;
987  for (i = 0; i < pr->n; ++i)
988  {
990  }
991  pr->n = 0;
992 }
993 
994 #ifdef ENABLE_DEBUG
995 void
996 plugin_return_print(const int msglevel, const char *prefix, const struct plugin_return *pr)
997 {
998  int i;
999  msg(msglevel, "PLUGIN_RETURN_PRINT %s", prefix);
1000  for (i = 0; i < pr->n; ++i)
1001  {
1002  struct openvpn_plugin_string_list *l = pr->list[i];
1003  int count = 0;
1004 
1005  msg(msglevel, "PLUGIN #%d (%s)", i, prefix);
1006  while (l)
1007  {
1008  msg(msglevel, "[%d] '%s' -> '%s'\n",
1009  ++count,
1010  l->name,
1011  l->value);
1012  l = l->next;
1013  }
1014  }
1015 }
1016 #endif /* ifdef ENABLE_DEBUG */
1017 #endif /* ENABLE_PLUGIN */
#define M_NONFATAL
Definition: error.h:95
Arguments used to transport variables to the plug-in.
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
Definition: win32.c:1157
void plugin_option_list_print(const struct plugin_option_list *list, int msglevel)
Definition: plugin.c:191
static void plugin_common_close(struct plugin_common *pc)
Definition: plugin.c:750
static struct plugin_common * plugin_common_init(const struct plugin_option_list *list)
Definition: plugin.c:696
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)
Definition: plugin.c:715
struct plugin_option plugins[MAX_PLUGINS]
Definition: plugin.h:52
struct openvpn_plugin_string_list ** return_list
static void plugin_init_item(struct plugin *p, const struct plugin_option *o)
Definition: plugin.c:233
void plugin_return_get_column(const struct plugin_return *src, struct plugin_return *dest, const char *colname)
Definition: plugin.c:969
unsigned int plugin_type_mask
Definition: plugin.h:58
void string_clear(char *str)
Definition: buffer.c:727
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition: buffer.h:401
static void plugin_return_init(struct plugin_return *pr)
Definition: plugin.h:171
#define M_INFO
Definition: errlevel.h:55
static void plugin_per_client_destroy(const struct plugin_common *pc, struct plugin_per_client *cli)
Definition: plugin.c:666
static bool env_safe_to_print(const char *str)
Definition: env_set.h:105
openvpn_plugin_handle_t * handle
struct plugin plugins[MAX_PLUGINS]
Definition: plugin.h:91
struct openvpn_plugin_string_list * list[MAX_PLUGINS]
Definition: plugin.h:104
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
openvpn_plugin_open_v1 open1
Definition: plugin.h:67
static struct openvpn_plugin_callbacks callbacks
Definition: plugin.c:418
#define OPENVPN_PLUGIN_DOWN
#define OPENVPN_PLUGIN_ROUTE_UP
X509 openvpn_x509_cert_t
#define M_NOMUTE
Definition: error.h:101
#define _OPENVPN_PATCH_LEVEL
Definition: plugin.c:432
#define OPENVPN_VERSION_MAJOR
Definition: config.h:712
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)
Definition: plugin.c:787
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
struct openvpn_plugin_string_list * next
openvpn_plugin_open_v2 open2
Definition: plugin.h:68
openvpn_plugin_select_initialization_point_v1 initialization_point
Definition: plugin.h:78
#define dmsg(flags,...)
Definition: error.h:153
openvpn_plugin_abort_v1 abort
Definition: plugin.h:74
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Definition: buffer.c:753
static void plugin_log(openvpn_plugin_log_flags_t flags, const char *name, const char *format,...)
Definition: plugin.c:410
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)
Definition: plugin.c:525
#define ASSERT(x)
Definition: error.h:200
#define OPENVPN_PLUGIN_ENABLE_PF
void x_msg_va(const unsigned int flags, const char *format, va_list arglist)
Definition: error.c:224
#define SSLAPI
Definition: ssl_backend.h:38
static bool check_debug_level(unsigned int level)
Definition: error.h:224
#define OPENVPN_PLUGIN_FUNC_SUCCESS
list flags
#define OPENVPN_PLUGIN_LEARN_ADDRESS
openvpn_plugin_log_flags_t
Definitions needed for the plug-in callback functions.
void setenv_del(struct env_set *es, const char *name)
Definition: env_set.c:330
const char * so_pathname
Definition: plugin.h:46
openvpn_plugin_close_v1 close
Definition: plugin.h:73
#define OPENVPN_PLUGIN_IPCHANGE
#define CLEAR(x)
Definition: basic.h:33
const char ** make_env_array(const struct env_set *es, const bool check_allowed, struct gc_arena *gc)
Definition: env_set.c:423
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
Definition: buffer.c:296
#define OPENVPN_PLUGIN_FUNC_DEFERRED
const char ** argv
Definition: plugin.h:47
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)
Definition: plugin.c:438
#define PLUGIN_SYMBOL_REQUIRED
Definition: plugin.c:50
#define OPENVPN_PLUGIN_TLS_VERIFY
#define OPENVPN_PLUGIN_FUNC_ERROR
static struct plugin_common * static_plugin_common
Definition: plugin.c:53
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
struct plugin_per_client per_client
Definition: plugin.h:96
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)
Definition: plugin.c:776
static void plugin_show_string_array(int msglevel, const char *name, const char *array[])
Definition: plugin.c:56
openvpn_plugin_func_v2 func2
Definition: plugin.h:71
char ** argv
Definition: argv.h:39
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1050
static void plugin_vlog(openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist)
Definition: plugin.c:351
static void openvpn_plugin_string_list_free(struct openvpn_plugin_string_list *l)
Definition: plugin.c:943
static void gc_init(struct gc_arena *a)
Definition: buffer.h:1002
#define OPENVPN_PLUGIN_INIT_PRE_DAEMON
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:405
static const char * plugin_mask_string(const unsigned int type_mask, struct gc_arena *gc)
Definition: plugin.c:134
#define OPENVPN_PLUGIN_VERSION
int openvpn_base64_decode(const char *str, void *data, int size)
Definition: base64.c:160
Arguments used to transport variables to and from the plug-in.
static void plugin_abort_item(const struct plugin *p)
Definition: plugin.c:634
static void plugin_per_client_init(const struct plugin_common *pc, struct plugin_per_client *cli, const int init_point)
Definition: plugin.c:646
struct plugin_list * plugin_list_inherit(const struct plugin_list *src)
Definition: plugin.c:685
#define OPENVPN_PLUGIN_TLS_FINAL
openvpn_plugin_client_destructor_v1 client_destructor
Definition: plugin.h:76
const char ** make_extended_arg_array(char **p, bool is_inline, struct gc_arena *gc)
Definition: misc.c:599
void * per_client_context[MAX_PLUGINS]
Definition: plugin.h:85
#define M_ERRNO
Definition: error.h:99
#define M_NOIPREFIX
Definition: error.h:107
#define OPENVPN_PLUGIN_CLIENT_DISCONNECT
int openvpn_base64_encode(const void *data, int size, char **str)
Definition: base64.c:54
static const char * plugin_type_name(const int type)
Definition: plugin.c:79
bool plugin_option_list_add(struct plugin_option_list *list, char **p, struct gc_arena *gc)
Definition: plugin.c:170
HMODULE module
Definition: plugin.h:64
const char * so_pathname
Definition: plugin.h:57
static bool msg_test(unsigned int flags)
Return true if flags represent an enabled, not muted log level.
Definition: error.h:231
#define msg(flags,...)
Definition: error.h:149
static void openvpn_plugin_string_list_item_free(struct openvpn_plugin_string_list *l)
Definition: plugin.c:931
static void plugin_show_args_env(int msglevel, const char *argv[], const char *envp[])
Definition: plugin.c:69
static unsigned int plugin_supported_types(void)
Definition: plugin.c:156
Arguments used to transport variables to and from the plug-in.
static void plugin_close_item(struct plugin *p)
Definition: plugin.c:603
bool initialized
Definition: plugin.h:56
openvpn_plugin_func_v1 func1
Definition: plugin.h:70
void plugin_return_free(struct plugin_return *pr)
Definition: plugin.c:984
void plugin_abort(void)
Definition: plugin.c:885
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition: buffer.h:1087
#define OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
#define M_ERR
Definition: error.h:110
bool plugin_defined(const struct plugin_list *pl, const int type)
Definition: plugin.c:901
struct plugin_option_list * plugin_option_list_new(struct gc_arena *gc)
Definition: plugin.c:162
openvpn_plugin_client_constructor_v1 client_constructor
Definition: plugin.h:75
#define PA_BRACKET
Definition: buffer.h:144
struct plugin_list * plugin_list_init(const struct plugin_option_list *list)
Definition: plugin.c:766
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
#define M_FATAL
Definition: error.h:94
int requested_initialization_point
Definition: plugin.h:59
static void dll_resolve_symbol(HMODULE module, void **dest, const char *symbol, const char *plugin_name, const unsigned int flags)
Definition: plugin.c:221
struct openvpn_plugin_string_list ** return_list
void plugin_list_close(struct plugin_list *pl)
Definition: plugin.c:866
#define OPENVPN_PLUGIN_ROUTE_PREDOWN
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
openvpn_plugin_open_v3 open3
Definition: plugin.h:69
#define M_WARN
Definition: error.h:96
#define ERR_BUF_SIZE
Definition: error.h:39
#define PACKAGE_VERSION
Definition: config.h:742
#define OPENVPN_PLUGIN_CLIENT_CONNECT
#define free
Definition: cmocka.c:1850
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
#define BSTR(buf)
Definition: buffer.h:129
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
Definition: argv.c:104
#define OPENVPN_PLUGINv3_STRUCTVER
Defines version of the v3 plugin argument structs.
#define MAX_PLUGINS
Definition: plugin.h:43
#define OPENVPN_PLUGIN_N
#define D_PLUGIN
Definition: errlevel.h:87
Definition: argv.h:35
Arguments used to transport variables from the plug-in back to the OpenVPN process.
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2
static SERVICE_STATUS status
Definition: interactive.c:56
struct plugin_common * common
Definition: plugin.h:97
Used by the openvpn_plugin_open_v3() function to pass callback function pointers to the plug-in...
bool platform_absolute_pathname(const char *pathname)
Return true if pathname is absolute.
Definition: platform.c:507
struct argv argv_insert_head(const struct argv *a, const char *head)
Inserts an argument string in front of all other argument slots.
Definition: argv.c:210
#define OPENVPN_PLUGIN_UP
#define OPENVPN_VERSION_MINOR
Definition: config.h:715
#define OPENVPN_PLUGIN_MASK(x)
static int plugin_n(const struct plugin_list *pl)
Definition: plugin.h:152
bool common_owned
Definition: plugin.h:98
static struct openvpn_plugin_string_list * openvpn_plugin_string_list_find(struct openvpn_plugin_string_list *l, const char *name)
Definition: plugin.c:955
#define PLUGIN_SYM(var, name, flags)
openvpn_plugin_func_v3 func3
Definition: plugin.h:72
openvpn_plugin_min_version_required_v1 min_version_required
Definition: plugin.h:77
#define D_PLUGIN_DEBUG
Definition: errlevel.h:137
openvpn_plugin_handle_t plugin_handle
Definition: plugin.h:80