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