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