123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- * OpenVPN -- An application to securely tunnel IP networks
- * over a single TCP/UDP port, with support for SSL/TLS-based
- * session authentication and key exchange,
- * packet encryption, packet authentication, and
- * packet compression.
- *
- * Copyright (C) 2017 David Sommerseth <davids@openvpn.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING included with this
- * distribution); if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "openvpn-plugin.h"
- #define PLUGIN_NAME "base64.c"
- /* Exported plug-in v3 API functions */
- plugin_log_t ovpn_log = NULL; /**< Pointer to the OpenVPN log function. See plugin_log() */
- plugin_vlog_t ovpn_vlog = NULL; /**< Pointer to the OpenVPN vlog function. See plugin_vlog() */
- plugin_base64_encode_t ovpn_base64_encode = NULL; /**< Pointer to the openvpn_base64_encode () function */
- plugin_base64_decode_t ovpn_base64_decode = NULL; /**< Pointer to the openvpn_base64_decode () function */
- /**
- * Search the environment pointer for a specific env var name
- *
- * PLEASE NOTE! The result is not valid outside the local
- * scope of the calling function. Once the calling function
- * returns, any returned pointers are invalid.
- *
- * @param name String containing the env.var name to search for
- * @param envp String array pointer to the environment variable
- *
- * @return Returns a pointer to the value in the environment variable
- * table on successful match. Otherwise NULL is returned
- *
- */
- static const char *
- get_env(const char *name, const char *envp[])
- {
- if (envp)
- {
- int i;
- const int namelen = strlen(name);
- for (i = 0; envp[i]; ++i)
- {
- if (!strncmp(envp[i], name, namelen))
- {
- const char *cp = envp[i] + namelen;
- if (*cp == '=')
- {
- return cp + 1;
- }
- }
- }
- }
- return NULL;
- }
- /**
- * This function is called when OpenVPN loads the plug-in.
- * The purpose is to initialize the plug-in and tell OpenVPN
- * which plug-in hooks this plug-in wants to be involved in
- *
- * For the arguments, see the include/openvpn-plugin.h file
- * for details on the function parameters
- *
- * @param v3structver An integer containing the API version of
- * the plug-in structs OpenVPN uses
- * @param args A pointer to the argument struct for
- * information and features provided by
- * OpenVPN to the plug-in
- * @param ret A pointer to the struct OpenVPN uses to
- * receive information back from the plug-in
- *
- * @return Must return OPENVPN_PLUGIN_FUNC_SUCCESS when everything
- * completed successfully. Otherwise it must be returned
- * OPENVPN_PLUGIN_FUNC_ERROR, which will stop OpenVPN
- * from running
- *
- */
- 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)
- {
- /* Check that we are API compatible */
- if (v3structver != OPENVPN_PLUGINv3_STRUCTVER)
- {
- printf("base64.c: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
- /* Which callbacks to intercept. */
- ret->type_mask =
- OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
- |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2);
- /* we don't need a plug-in context in this example, but OpenVPN expects "something" */
- ret->handle = calloc(1, 1);
- /* Hook into the exported functions from OpenVPN */
- ovpn_log = args->callbacks->plugin_log;
- ovpn_vlog = args->callbacks->plugin_vlog;
- ovpn_base64_encode = args->callbacks->plugin_base64_encode;
- ovpn_base64_decode = args->callbacks->plugin_base64_decode;
- /* Print some version information about the OpenVPN process using this plug-in */
- ovpn_log(PLOG_NOTE, PLUGIN_NAME, "OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
- args->ovpn_version, args->ovpn_version_major,
- args->ovpn_version_minor, args->ovpn_version_patch);
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- /**
- * This function is called by OpenVPN each time the OpenVPN reaches
- * a point where plug-in calls should happen. It only happens for those
- * plug-in hooks enabled in openvpn_plugin_open_v3().
- *
- * For the arguments, see the include/openvpn-plugin.h file
- * for details on the function parameters
- *
- * @param args Pointer to a struct with details about the plug-in
- * call from the main OpenVPN process.
- * @param returndata Pointer to a struct where the plug-in can provide
- * information back to OpenVPN to be processed
- *
- * @return Must return OPENVPN_PLUGIN_FUNC_SUCCESS or
- * OPENVPN_PLUGIN_FUNC_DEFERRED on success. Otherwise it
- * should return OPENVPN_FUNC_ERROR, which will stop and reject
- * the client session from progressing.
- *
- */
- OPENVPN_EXPORT int
- openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
- {
- if (type != OPENVPN_PLUGIN_TLS_VERIFY
- && type != OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
- {
- ovpn_log(PLOG_ERR, PLUGIN_NAME, "Unsupported plug-in hook call attempted");
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
- /* get username/password from envp string array */
- const char *clcert_cn = get_env("X509_0_CN", envp);
- if (!clcert_cn)
- {
- /* Ignore certificate checks not being a client certificate */
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- /* test the BASE64 encode function */
- char *buf = NULL;
- int r = ovpn_base64_encode(clcert_cn, strlen(clcert_cn), &buf);
- ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 encoded '%s' (return value %i): '%s'",
- clcert_cn, r, buf);
- /* test the BASE64 decode function */
- char buf2[256] = {0};
- r = ovpn_base64_decode(buf, &buf2, 255);
- ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 decoded '%s' (return value %i): '%s'",
- buf, r, buf2);
- /* Verify the result, and free the buffer allocated by ovpn_base64_encode() */
- r = strcmp(clcert_cn, buf2);
- free(buf);
- return (r == 0) ? OPENVPN_PLUGIN_FUNC_SUCCESS : OPENVPN_PLUGIN_FUNC_ERROR;
- }
- /**
- * This cleans up the last part of the plug-in, allows it to
- * shut down cleanly and release the plug-in global context buffer
- *
- * @param handle Pointer to the plug-in global context buffer, which
- * need to be released by this function
- */
- OPENVPN_EXPORT void
- openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
- {
- struct plugin_context *context = (struct plugin_context *) handle;
- free(context);
- }
|