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 */
43struct 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 */
53static const char *
54get_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
75OPENVPN_EXPORT int
76openvpn_plugin_open_v3(const int v3structver,
77 struct openvpn_plugin_args_open_in const *args,
78 struct openvpn_plugin_args_open_return *ret)
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");
86 return OPENVPN_PLUGIN_FUNC_ERROR;
87 }
88
89 if (args->ssl_api != SSLAPI_OPENSSL)
90 {
91 printf("This plug-in can only be used against OpenVPN with OpenSSL\n");
92 return OPENVPN_PLUGIN_FUNC_ERROR;
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,
98 args->ovpn_version_minor, args->ovpn_version_patch);
99
100 /* Which callbacks to intercept. */
101 ret->type_mask =
102 OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP)
103 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN)
104 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ROUTE_UP)
105 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_IPCHANGE)
106 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
107 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
108 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
109 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT)
110 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
111 |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
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");
119 return OPENVPN_PLUGIN_FUNC_ERROR;
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
129 return OPENVPN_PLUGIN_FUNC_SUCCESS;
130}
131
132void
133show(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
146 case OPENVPN_PLUGIN_ROUTE_UP:
147 printf("OPENVPN_PLUGIN_ROUTE_UP\n");
148 break;
149
150 case OPENVPN_PLUGIN_IPCHANGE:
151 printf("OPENVPN_PLUGIN_IPCHANGE\n");
152 break;
153
154 case OPENVPN_PLUGIN_TLS_VERIFY:
155 printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
156 break;
157
158 case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
159 printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
160 break;
161
162 case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
163 printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
164 break;
165
166 case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
167 printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
168 break;
169
170 case OPENVPN_PLUGIN_LEARN_ADDRESS:
171 printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
172 break;
173
174 case OPENVPN_PLUGIN_TLS_FINAL:
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
196static void
197x509_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
249OPENVPN_EXPORT int
250openvpn_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);
264 x509_print_info(args->current_cert);
265 printf("----------------------------------\n");
266 }
267
268 /* check entered username/password against what we require */
269 if (args->type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
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 {
278 return OPENVPN_PLUGIN_FUNC_SUCCESS;
279 }
280 else
281 {
282 return OPENVPN_PLUGIN_FUNC_ERROR;
283 }
284 }
285 else
286 {
287 return OPENVPN_PLUGIN_FUNC_SUCCESS;
288 }
289}
290
291OPENVPN_EXPORT void
292openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
293{
294 struct plugin_context *context = (struct plugin_context *) handle;
295 free(context);
296}
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition log_v3.c:292
static void x509_print_info(X509 *x509crt)
Definition log_v3.c:197
void show(const int type, const char *argv[], const char *envp[])
Definition log_v3.c:133
static const char * get_env(const char *name, const char *envp[])
Definition log_v3.c:54
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_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
Definition argv.h:35
Contains all state information for one tunnel.
Definition openvpn.h:474
const char * password
Definition log.c:42
const char * username
Definition log.c:41