Hi, Now that the minor "fix" for plugin header seems settled, back to the base64 export patch from David.
On Fri, May 5, 2017 at 5:46 PM, David Sommerseth <dav...@openvpn.net> wrote: > This patch builds on the "Export secure_memzero() to plug-ins" patch and > adds export of openvpn_base64_encode() and openvpn_base64_decode() > > This also ships with a very simple plug-in which demonstrates how to use > the new exported functions. > > Signed-off-by: David Sommerseth <dav...@openvpn.net> > --- > include/openvpn-plugin.h.in | 31 ++++++ > sample/sample-plugins/simple/base64.c | 204 > ++++++++++++++++++++++++++++++++++ > src/openvpn/plugin.c | 5 +- > 3 files changed, 239 insertions(+), 1 deletion(-) > create mode 100644 sample/sample-plugins/simple/base64.c The exports are very useful an work as expected. The sample code would be appreciated by plugin authors though it could have been a separate patch. I have not tested the sample code but looks right and is well documented. Only a two of typos to nitpick over (see below) -- hopefully those could be fixed at merge time. So ACK from me. > > diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in > index ec83f3a6..68180d62 100644 > --- a/include/openvpn-plugin.h.in > +++ b/include/openvpn-plugin.h.in > @@ -221,6 +221,8 @@ struct openvpn_plugin_string_list > * OpenVPN to plug-ins. > * > * 4 Exported secure_memzero() as plugin_secure_memzero() > + * Exported openvpn_base64_encode() as plugin_base64_encode() > + * Exported openvpn_base64_decode() as plugin_base64_decode() > */ > #define OPENVPN_PLUGINv3_STRUCTVER 4 > > @@ -269,6 +271,33 @@ typedef void (*plugin_vlog_t)(openvpn_plugin_log_flags_t > flags, > */ > typedef void (*plugin_secure_memzero_t)(void *data, size_t len); > > +/** > + * Export of openvpn_base64_encode() to be used inside plug-ins > + * > + * @param data Pointer to data to BASE64 encode > + * @param size Length of data, in bytes > + * @param *str Pointer to the return buffer. This needed memory is > + * allocated by openvpn_base64_encode() and needs to be > free()d > + * after use. > + * > + * @return int Returns the length of the buffer created, or -1 on error. > + * > + */ > +typedef int (*plugin_base64_encode_t)(const void *data, int size, char > **str); > + > +/** > + * Export of openvpn_base64_decode() to be used inside plug-ins > + * > + * @param str Pointer to the BASE64 encoded data > + * @param data Pointer to the buffer where save the decoded data > + * @param size Size of the destination buffer > + * > + * @return int Returns the length of the decoded data, or -1 on error or > + * if the destination buffer is too small. > + * > + */ > +typedef int (*plugin_base64_decode_t)(const char *str, void *data, int size); > + > > /** > * Used by the openvpn_plugin_open_v3() function to pass callback > @@ -291,6 +320,8 @@ struct openvpn_plugin_callbacks > plugin_log_t plugin_log; > plugin_vlog_t plugin_vlog; > plugin_secure_memzero_t plugin_secure_memzero; > + plugin_base64_encode_t plugin_base64_encode; > + plugin_base64_decode_t plugin_base64_decode; > }; > > /** > diff --git a/sample/sample-plugins/simple/base64.c > b/sample/sample-plugins/simple/base64.c > new file mode 100644 > index 00000000..503b5ba0 > --- /dev/null > +++ b/sample/sample-plugins/simple/base64.c > @@ -0,0 +1,204 @@ > +/* > + * 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 <dav...@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 BAS64 encode function */ typo: BAS64 --> BASE64 > + 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 BAS64 encode function */ typo: BAS64 encode --> BASE64 decode > + 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); > +} > + > diff --git a/src/openvpn/plugin.c b/src/openvpn/plugin.c > index a652d528..ca278af1 100644 > --- a/src/openvpn/plugin.c > +++ b/src/openvpn/plugin.c > @@ -44,6 +44,7 @@ > #include "misc.h" > #include "plugin.h" > #include "ssl_backend.h" > +#include "base64.h" > #include "win32.h" > #include "memdbg.h" > > @@ -411,7 +412,9 @@ plugin_log(openvpn_plugin_log_flags_t flags, const char > *name, const char *forma > static struct openvpn_plugin_callbacks callbacks = { > plugin_log, > plugin_vlog, > - secure_memzero /* plugin_secure_memzero */ > + secure_memzero, /* plugin_secure_memzero */ > + openvpn_base64_encode, /* plugin_base64_encode */ > + openvpn_base64_decode, /* plugin_base64_decode */ > }; > > > -- > 2.11.0 > > > ------------------------------------------------------------------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > Openvpn-devel mailing list > Openvpn-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/openvpn-devel Acked by: selva.n...@gmail.com ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel