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