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-2018 OpenVPN Inc <sales@openvpn.net>
9  * Copyright (C) 2010 David Sommerseth <dazo@users.sourceforge.net>
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 
117  /* Set the username/password we will require. */
118  context->username = "foo";
119  context->password = "bar";
120 
121  /* Point the global context handle to our newly created context */
122  ret->handle = (void *) context;
123 
125 }
126 
127 void
128 show(const int type, const char *argv[], const char *envp[])
129 {
130  size_t i;
131  switch (type)
132  {
133  case OPENVPN_PLUGIN_UP:
134  printf("OPENVPN_PLUGIN_UP\n");
135  break;
136 
137  case OPENVPN_PLUGIN_DOWN:
138  printf("OPENVPN_PLUGIN_DOWN\n");
139  break;
140 
142  printf("OPENVPN_PLUGIN_ROUTE_UP\n");
143  break;
144 
146  printf("OPENVPN_PLUGIN_IPCHANGE\n");
147  break;
148 
150  printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
151  break;
152 
154  printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
155  break;
156 
158  printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
159  break;
160 
162  printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
163  break;
164 
166  printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
167  break;
168 
170  printf("OPENVPN_PLUGIN_TLS_FINAL\n");
171  break;
172 
173  default:
174  printf("OPENVPN_PLUGIN_?\n");
175  break;
176  }
177 
178  printf("ARGV\n");
179  for (i = 0; argv[i] != NULL; ++i)
180  {
181  printf("%d '%s'\n", (int)i, argv[i]);
182  }
183 
184  printf("ENVP\n");
185  for (i = 0; envp[i] != NULL; ++i)
186  {
187  printf("%d '%s'\n", (int)i, envp[i]);
188  }
189 }
190 
191 static void
192 x509_print_info(X509 *x509crt)
193 {
194  int i, n;
195  int fn_nid;
196  ASN1_OBJECT *fn;
197  ASN1_STRING *val;
198  X509_NAME *x509_name;
199  X509_NAME_ENTRY *ent;
200  const char *objbuf;
201  unsigned char *buf = NULL;
202 
203  x509_name = X509_get_subject_name(x509crt);
204  n = X509_NAME_entry_count(x509_name);
205  for (i = 0; i < n; ++i)
206  {
207  ent = X509_NAME_get_entry(x509_name, i);
208  if (!ent)
209  {
210  continue;
211  }
212  fn = X509_NAME_ENTRY_get_object(ent);
213  if (!fn)
214  {
215  continue;
216  }
217  val = X509_NAME_ENTRY_get_data(ent);
218  if (!val)
219  {
220  continue;
221  }
222  fn_nid = OBJ_obj2nid(fn);
223  if (fn_nid == NID_undef)
224  {
225  continue;
226  }
227  objbuf = OBJ_nid2sn(fn_nid);
228  if (!objbuf)
229  {
230  continue;
231  }
232  if (ASN1_STRING_to_UTF8(&buf, val) < 0)
233  {
234  continue;
235  }
236 
237  printf("X509 %s: %s\n", objbuf, (char *)buf);
238  OPENSSL_free(buf);
239  }
240 }
241 
242 
243 
244 OPENVPN_EXPORT int
245 openvpn_plugin_func_v3(const int version,
246  struct openvpn_plugin_args_func_in const *args,
247  struct openvpn_plugin_args_func_return *retptr)
248 {
249  struct plugin_context *context = (struct plugin_context *) args->handle;
250 
251  printf("\nopenvpn_plugin_func_v3() :::::>> ");
252  show(args->type, args->argv, args->envp);
253 
254  /* Dump some X509 information if we're in the TLS_VERIFY phase */
255  if ((args->type == OPENVPN_PLUGIN_TLS_VERIFY) && args->current_cert)
256  {
257  printf("---- X509 Subject information ----\n");
258  printf("Certificate depth: %i\n", args->current_cert_depth);
260  printf("----------------------------------\n");
261  }
262 
263  /* check entered username/password against what we require */
265  {
266  /* get username/password from envp string array */
267  const char *username = get_env("username", args->envp);
268  const char *password = get_env("password", args->envp);
269 
270  if (username && !strcmp(username, context->username)
271  && password && !strcmp(password, context->password))
272  {
274  }
275  else
276  {
278  }
279  }
280  else
281  {
283  }
284 }
285 
286 OPENVPN_EXPORT void
288 {
289  struct plugin_context *context = (struct plugin_context *) handle;
290  free(context);
291 }
Arguments used to transport variables to the plug-in.
openvpn_x509_cert_t * current_cert
const char * password
Definition: log.c:42
Contains all state information for one tunnel.
Definition: openvpn.h:500
openvpn_plugin_handle_t * handle
void show(const int type, const char *argv[], const char *envp[])
Definition: log_v3.c:128
#define OPENVPN_PLUGIN_DOWN
#define OPENVPN_PLUGIN_ROUTE_UP
const unsigned int ovpn_version_minor
#define OPENVPN_EXPORT
#define OPENVPN_PLUGIN_FUNC_SUCCESS
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
#define OPENVPN_PLUGIN_LEARN_ADDRESS
const char * username
Definition: log.c:41
#define OPENVPN_PLUGIN_IPCHANGE
#define OPENVPN_PLUGIN_TLS_VERIFY
#define OPENVPN_PLUGIN_FUNC_ERROR
static const char * get_env(const char *name, const char *envp[])
Definition: log_v3.c:54
Arguments used to transport variables to and from the plug-in.
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:245
#define OPENVPN_PLUGIN_TLS_FINAL
openvpn_plugin_handle_t handle
const unsigned int ovpn_version_major
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition: log_v3.c:287
#define OPENVPN_PLUGIN_CLIENT_DISCONNECT
void * openvpn_plugin_handle_t
static void x509_print_info(X509 *x509crt)
Definition: log_v3.c:192
Arguments used to transport variables to and from the plug-in.
#define OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
#define free
Definition: cmocka.c:1850
#define OPENVPN_PLUGINv3_STRUCTVER
Defines version of the v3 plugin argument structs.
Definition: argv.h:35
Arguments used to transport variables from the plug-in back to the OpenVPN process.
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2
#define OPENVPN_PLUGIN_UP
#define OPENVPN_PLUGIN_MASK(x)
const char *const ovpn_version_patch