OpenVPN
log_v3.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-2024 OpenVPN Inc <sales@openvpn.net>
9  * Copyright (C) 2010-2024 David Sommerseth <dazo@eurephia.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2
13  * as published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 /*
26  * This plugin is similar to simple.c, except it also logs extra information
27  * to stdout for every plugin method called by OpenVPN. The only difference
28  * between this (log_v3.c) and log.c is that this module uses the v3 plug-in
29  * API.
30  *
31  * See the README file for build instructions.
32  */
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 
38 #include "openvpn-plugin.h"
39 
40 /*
41  * Our context, where we keep our state.
42  */
43 struct plugin_context {
44  const char *username;
45  const char *password;
46 };
47 
48 /*
49  * Given an environmental variable name, search
50  * the envp array for its value, returning it
51  * if found or NULL otherwise.
52  */
53 static const char *
54 get_env(const char *name, const char *envp[])
55 {
56  if (envp)
57  {
58  int i;
59  const int namelen = strlen(name);
60  for (i = 0; envp[i]; ++i)
61  {
62  if (!strncmp(envp[i], name, namelen))
63  {
64  const char *cp = envp[i] + namelen;
65  if (*cp == '=')
66  {
67  return cp + 1;
68  }
69  }
70  }
71  }
72  return NULL;
73 }
74 
76 openvpn_plugin_open_v3(const int v3structver,
77  struct openvpn_plugin_args_open_in const *args,
79 {
80  struct plugin_context *context = NULL;
81 
82  /* Check that we are API compatible */
83  if (v3structver != OPENVPN_PLUGINv3_STRUCTVER)
84  {
85  printf("log_v3: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
87  }
88 
89  if (args->ssl_api != SSLAPI_OPENSSL)
90  {
91  printf("This plug-in can only be used against OpenVPN with OpenSSL\n");
93  }
94 
95  /* Print some version information about the OpenVPN process using this plug-in */
96  printf("log_v3: OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
97  args->ovpn_version, args->ovpn_version_major,
99 
100  /* Which callbacks to intercept. */
101  ret->type_mask =
112 
113 
114  /* Allocate our context */
115  context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
116  if (context == NULL)
117  {
118  printf("PLUGIN: allocating memory for context failed\n");
120  }
121 
122  /* Set the username/password we will require. */
123  context->username = "foo";
124  context->password = "bar";
125 
126  /* Point the global context handle to our newly created context */
127  ret->handle = (void *) context;
128 
130 }
131 
132 void
133 show(const int type, const char *argv[], const char *envp[])
134 {
135  size_t i;
136  switch (type)
137  {
138  case OPENVPN_PLUGIN_UP:
139  printf("OPENVPN_PLUGIN_UP\n");
140  break;
141 
142  case OPENVPN_PLUGIN_DOWN:
143  printf("OPENVPN_PLUGIN_DOWN\n");
144  break;
145 
147  printf("OPENVPN_PLUGIN_ROUTE_UP\n");
148  break;
149 
151  printf("OPENVPN_PLUGIN_IPCHANGE\n");
152  break;
153 
155  printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
156  break;
157 
159  printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
160  break;
161 
163  printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
164  break;
165 
167  printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
168  break;
169 
171  printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
172  break;
173 
175  printf("OPENVPN_PLUGIN_TLS_FINAL\n");
176  break;
177 
178  default:
179  printf("OPENVPN_PLUGIN_?\n");
180  break;
181  }
182 
183  printf("ARGV\n");
184  for (i = 0; argv[i] != NULL; ++i)
185  {
186  printf("%d '%s'\n", (int)i, argv[i]);
187  }
188 
189  printf("ENVP\n");
190  for (i = 0; envp[i] != NULL; ++i)
191  {
192  printf("%d '%s'\n", (int)i, envp[i]);
193  }
194 }
195 
196 static void
197 x509_print_info(X509 *x509crt)
198 {
199  int i, n;
200  int fn_nid;
201  ASN1_OBJECT *fn;
202  ASN1_STRING *val;
203  X509_NAME *x509_name;
204  X509_NAME_ENTRY *ent;
205  const char *objbuf;
206  unsigned char *buf = NULL;
207 
208  x509_name = X509_get_subject_name(x509crt);
209  n = X509_NAME_entry_count(x509_name);
210  for (i = 0; i < n; ++i)
211  {
212  ent = X509_NAME_get_entry(x509_name, i);
213  if (!ent)
214  {
215  continue;
216  }
217  fn = X509_NAME_ENTRY_get_object(ent);
218  if (!fn)
219  {
220  continue;
221  }
222  val = X509_NAME_ENTRY_get_data(ent);
223  if (!val)
224  {
225  continue;
226  }
227  fn_nid = OBJ_obj2nid(fn);
228  if (fn_nid == NID_undef)
229  {
230  continue;
231  }
232  objbuf = OBJ_nid2sn(fn_nid);
233  if (!objbuf)
234  {
235  continue;
236  }
237  if (ASN1_STRING_to_UTF8(&buf, val) < 0)
238  {
239  continue;
240  }
241 
242  printf("X509 %s: %s\n", objbuf, (char *)buf);
243  OPENSSL_free(buf);
244  }
245 }
246 
247 
248 
249 OPENVPN_EXPORT int
250 openvpn_plugin_func_v3(const int version,
251  struct openvpn_plugin_args_func_in const *args,
252  struct openvpn_plugin_args_func_return *retptr)
253 {
254  struct plugin_context *context = (struct plugin_context *) args->handle;
255 
256  printf("\nopenvpn_plugin_func_v3() :::::>> ");
257  show(args->type, args->argv, args->envp);
258 
259  /* Dump some X509 information if we're in the TLS_VERIFY phase */
260  if ((args->type == OPENVPN_PLUGIN_TLS_VERIFY) && args->current_cert)
261  {
262  printf("---- X509 Subject information ----\n");
263  printf("Certificate depth: %i\n", args->current_cert_depth);
265  printf("----------------------------------\n");
266  }
267 
268  /* check entered username/password against what we require */
270  {
271  /* get username/password from envp string array */
272  const char *username = get_env("username", args->envp);
273  const char *password = get_env("password", args->envp);
274 
275  if (username && !strcmp(username, context->username)
276  && password && !strcmp(password, context->password))
277  {
279  }
280  else
281  {
283  }
284  }
285  else
286  {
288  }
289 }
290 
291 OPENVPN_EXPORT void
293 {
294  struct plugin_context *context = (struct plugin_context *) handle;
295  free(context);
296 }
OPENVPN_PLUGIN_CLIENT_CONNECT_V2
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2
Definition: openvpn-plugin.h:126
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
OPENVPN_PLUGIN_DOWN
#define OPENVPN_PLUGIN_DOWN
Definition: openvpn-plugin.h:118
openvpn_plugin_args_func_in::handle
openvpn_plugin_handle_t handle
Definition: openvpn-plugin.h:434
argv
Definition: argv.h:35
openvpn_plugin_args_open_in
Arguments used to transport variables to the plug-in.
Definition: openvpn-plugin.h:359
context
Contains all state information for one tunnel.
Definition: openvpn.h:476
plugin_context
Definition: sample-client-connect.c:62
OPENVPN_PLUGINv3_STRUCTVER
#define OPENVPN_PLUGINv3_STRUCTVER
Defines version of the v3 plugin argument structs.
Definition: openvpn-plugin.h:226
OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
#define OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
Definition: openvpn-plugin.h:122
openvpn_plugin_args_open_return::type_mask
int type_mask
Definition: openvpn-plugin.h:396
openvpn_plugin_args_func_in::current_cert_depth
int current_cert_depth
Definition: openvpn-plugin.h:436
show
void show(const int type, const char *argv[], const char *envp[])
Definition: log_v3.c:133
OPENVPN_PLUGIN_MASK
#define OPENVPN_PLUGIN_MASK(x)
Definition: openvpn-plugin.h:137
openvpn_plugin_args_open_in::ssl_api
const ovpnSSLAPI ssl_api
Definition: openvpn-plugin.h:365
openvpn_plugin_args_open_in::ovpn_version_patch
const char *const ovpn_version_patch
Definition: openvpn-plugin.h:369
openvpn_plugin_args_open_in::ovpn_version_major
const unsigned int ovpn_version_major
Definition: openvpn-plugin.h:367
openvpn_plugin_open_v3
OPENVPN_EXPORT int openvpn_plugin_open_v3(const int v3structver, struct openvpn_plugin_args_open_in const *args, struct openvpn_plugin_args_open_return *ret)
Definition: log_v3.c:76
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
openvpn_plugin_args_func_in::current_cert
openvpn_x509_cert_t * current_cert
Definition: openvpn-plugin.h:437
OPENVPN_PLUGIN_IPCHANGE
#define OPENVPN_PLUGIN_IPCHANGE
Definition: openvpn-plugin.h:120
OPENVPN_EXPORT
#define OPENVPN_EXPORT
Definition: openvpn-plugin.h:156
OPENVPN_PLUGIN_ROUTE_UP
#define OPENVPN_PLUGIN_ROUTE_UP
Definition: openvpn-plugin.h:119
get_env
static const char * get_env(const char *name, const char *envp[])
Definition: log_v3.c:54
openvpn_plugin_args_func_in::envp
const char **const envp
Definition: openvpn-plugin.h:433
OPENVPN_PLUGIN_TLS_VERIFY
#define OPENVPN_PLUGIN_TLS_VERIFY
Definition: openvpn-plugin.h:121
openvpn_plugin_args_open_in::ovpn_version
const char * ovpn_version
Definition: openvpn-plugin.h:366
x509_print_info
static void x509_print_info(X509 *x509crt)
Definition: log_v3.c:197
openvpn_plugin_args_func_return
Arguments used to transport variables to and from the plug-in.
Definition: openvpn-plugin.h:452
openvpn_plugin_func_v3
OPENVPN_EXPORT int openvpn_plugin_func_v3(const int version, struct openvpn_plugin_args_func_in const *args, struct openvpn_plugin_args_func_return *retptr)
Definition: log_v3.c:250
plugin_context::password
const char * password
Definition: log.c:42
openvpn_plugin_close_v1
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition: log_v3.c:292
OPENVPN_PLUGIN_CLIENT_DISCONNECT
#define OPENVPN_PLUGIN_CLIENT_DISCONNECT
Definition: openvpn-plugin.h:124
openvpn_plugin_args_open_return
Arguments used to transport variables from the plug-in back to the OpenVPN process.
Definition: openvpn-plugin.h:394
openvpn_plugin_args_func_in
Arguments used to transport variables to and from the plug-in.
Definition: openvpn-plugin.h:429
openvpn_plugin_args_open_return::handle
openvpn_plugin_handle_t handle
Definition: openvpn-plugin.h:397
OPENVPN_PLUGIN_FUNC_SUCCESS
#define OPENVPN_PLUGIN_FUNC_SUCCESS
Definition: openvpn-plugin.h:148
OPENVPN_PLUGIN_TLS_FINAL
#define OPENVPN_PLUGIN_TLS_FINAL
Definition: openvpn-plugin.h:127
SSLAPI_OPENSSL
@ SSLAPI_OPENSSL
Definition: openvpn-plugin.h:334
openvpn_plugin_args_func_in::argv
const char **const argv
Definition: openvpn-plugin.h:432
plugin_context::username
const char * username
Definition: log.c:41
openvpn-plugin.h
openvpn_plugin_handle_t
void * openvpn_plugin_handle_t
Definition: openvpn-plugin.h:143
openvpn_plugin_args_open_in::ovpn_version_minor
const unsigned int ovpn_version_minor
Definition: openvpn-plugin.h:368