OpenVPN
base64.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) 2017-2025 David Sommerseth <davids@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
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include "openvpn-plugin.h"
29
30#define PLUGIN_NAME "base64.c"
31
32/* Exported plug-in v3 API functions */
34plugin_log_t ovpn_log = NULL;
36plugin_vlog_t ovpn_vlog = NULL;
38plugin_base64_encode_t ovpn_base64_encode = NULL;
40plugin_base64_decode_t ovpn_base64_decode = NULL;
41
56static const char *
57get_env(const char *name, const char *envp[])
58{
59 if (envp)
60 {
61 const size_t namelen = strlen(name);
62 for (int i = 0; envp[i]; ++i)
63 {
64 if (!strncmp(envp[i], name, namelen))
65 {
66 const char *cp = envp[i] + namelen;
67 if (*cp == '=')
68 {
69 return cp + 1;
70 }
71 }
72 }
73 }
74 return NULL;
75}
76
77
100OPENVPN_EXPORT int
101openvpn_plugin_open_v3(const int v3structver, struct openvpn_plugin_args_open_in const *args,
102 struct openvpn_plugin_args_open_return *ret)
103{
104 /* Check that we are API compatible */
105 if (v3structver != OPENVPN_PLUGINv3_STRUCTVER)
106 {
107 printf("base64.c: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
108 return OPENVPN_PLUGIN_FUNC_ERROR;
109 }
110
111 /* Which callbacks to intercept. */
112 ret->type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
113 | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2);
114
115 /* we don't need a plug-in context in this example, but OpenVPN expects "something" */
116 ret->handle = calloc(1, 1);
117
118 /* Hook into the exported functions from OpenVPN */
119 ovpn_log = args->callbacks->plugin_log;
120 ovpn_vlog = args->callbacks->plugin_vlog;
121 ovpn_base64_encode = args->callbacks->plugin_base64_encode;
122 ovpn_base64_decode = args->callbacks->plugin_base64_decode;
123
124 /* Print some version information about the OpenVPN process using this plug-in */
125 ovpn_log(PLOG_NOTE, PLUGIN_NAME, "OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
126 args->ovpn_version, args->ovpn_version_major, args->ovpn_version_minor,
127 args->ovpn_version_patch);
128
129 return OPENVPN_PLUGIN_FUNC_SUCCESS;
130}
131
132
154OPENVPN_EXPORT int
155openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[],
156 const char *envp[])
157{
158 if (type != OPENVPN_PLUGIN_TLS_VERIFY && type != OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
159 {
160 ovpn_log(PLOG_ERR, PLUGIN_NAME, "Unsupported plug-in hook call attempted");
161 return OPENVPN_PLUGIN_FUNC_ERROR;
162 }
163
164 /* get username/password from envp string array */
165 const char *clcert_cn = get_env("X509_0_CN", envp);
166 if (!clcert_cn)
167 {
168 /* Ignore certificate checks not being a client certificate */
169 return OPENVPN_PLUGIN_FUNC_SUCCESS;
170 }
171
172 /* test the BASE64 encode function */
173 char *buf = NULL;
174 int r = ovpn_base64_encode(clcert_cn, (int)strlen(clcert_cn), &buf);
175 ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 encoded '%s' (return value %i): '%s'", clcert_cn, r,
176 buf);
177
178 /* test the BASE64 decode function */
179 char buf2[256] = { 0 };
180 r = ovpn_base64_decode(buf, &buf2, 255);
181 ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 decoded '%s' (return value %i): '%s'", buf, r, buf2);
182
183 /* Verify the result, and free the buffer allocated by ovpn_base64_encode() */
184 r = strcmp(clcert_cn, buf2);
185 free(buf);
186
187 return (r == 0) ? OPENVPN_PLUGIN_FUNC_SUCCESS : OPENVPN_PLUGIN_FUNC_ERROR;
188}
189
190
198OPENVPN_EXPORT void
199openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
200{
201 struct plugin_context *context = (struct plugin_context *)handle;
202 free(context);
203}
OPENVPN_EXPORT int openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
This function is called by OpenVPN each time the OpenVPN reaches a point where plug-in calls should h...
Definition base64.c:155
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
This cleans up the last part of the plug-in, allows it to shut down cleanly and release the plug-in g...
Definition base64.c:199
#define PLUGIN_NAME
Definition base64.c:30
plugin_log_t ovpn_log
Pointer to the OpenVPN log function.
Definition base64.c:34
plugin_base64_decode_t ovpn_base64_decode
Pointer to the openvpn_base64_decode () function.
Definition base64.c:40
plugin_base64_encode_t ovpn_base64_encode
Pointer to the openvpn_base64_encode () function.
Definition base64.c:38
plugin_vlog_t ovpn_vlog
Pointer to the OpenVPN vlog function.
Definition base64.c:36
static const char * get_env(const char *name, const char *envp[])
Search the environment pointer for a specific env var name.
Definition base64.c:57
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)
This function is called when OpenVPN loads the plug-in.
Definition base64.c:101
Definition argv.h:35
Contains all state information for one tunnel.
Definition openvpn.h:474