Skip to contentSkip to conversation

plugin: Export base64 encode and decode functions

PATCH In review David Sommerseth 4 participants 11 messages May 5, 2017 – Aug 5, 2018

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 plugin: Export base64 encode and decode functions

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.

---
 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
include/openvpn-plugin.h.in +31 -0
index ec83f3a6..68180d62 100644
@@ -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;
 };
 
 /**
sample/sample-plugins/simple/base64.c new file +204 -0

204 lines not on this page · raw message

src/openvpn/plugin.c +4 -1
index a652d528..ca278af1 100644
@@ -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 */
 };
 
 
Signature · 1 line
2.11.0
#1 lore raw

PATCH 2/2 sample-plugins/simple: Clean up the build method

This replaces a not so well functioning ./build script with a more proper Makefile. The README file is also updated accordingly.

---
 sample/sample-plugins/simple/Makefile | 17 +++++++++++++++++
 sample/sample-plugins/simple/README   | 33 +++++++++++++++++++++++++++------
 sample/sample-plugins/simple/build    | 15 ---------------
 3 files changed, 44 insertions(+), 21 deletions(-)
 create mode 100644 sample/sample-plugins/simple/Makefile
 delete mode 100755 sample/sample-plugins/simple/build
sample/sample-plugins/simple/Makefile new file +17 -0
new file mode 100644
index 00000000..24909759
@@ -0,0 +1,17 @@
+
+CFLAGS = -I../../../include -O2 -Wall -g -std=c99 -pthread -fPIC
+LDFLAGS = -fPIC
+
+all : base64.so simple.so
+
+base64.so : base64.o
+	$(CC) -shared $(LDFLAGS) -o $@ $^
+
+simple.so : simple.o
+	$(CC) -shared $(LDFLAGS) -o $@ $^
+
+.c.o :
+	$(CC) -c $(CFLAGS) $<
+
+clean :
+	rm -f *.o *.so
sample/sample-plugins/simple/README +27 -6
index 4400cd30..15fcc55c 100644
@@ -1,16 +1,37 @@
-OpenVPN plugin examples.
+Simple OpenVPN plugin examples
+==============================
 
 Examples provided:
 
 simple.c -- using the --auth-user-pass-verify callback, verify
             that the username/password is "foo"/"bar".
 
-To build:
+base64.c -- Very simple plug-in demonstrating how to use the
+            BASE64 encode/decode functions via the plug-in v3 API.
 
-  ./build simple (Linux/BSD/etc.)
-  ./winbuild simple (MinGW on Windows)
+
+Non-Windows users can just run `make` inside this directory to build all
+the plug-ins.
+
+    $ make
+
+To build a specific plug-in, run:
+
+    $ make simple.so
+    $ make base64.so
+
+Windows users may use the winbuild script which takes the file name of the
+plug-in to build without the extension.
+
+    > winbuild simple
+    > winbuild base64
 
 To use in OpenVPN, add to config file:
 
-  plugin simple.so (Linux/BSD/etc.)
-  plugin simple.dll (MinGW on Windows)
+For non-Windows users:
+  plugin simple.so
+  plugin base64.so
+
+Windows users:
+  plugin simple.dll
+  plugin base64.dll
sample/sample-plugins/simple/build deleted +0 -15
deleted file mode 100755
index bbb05f7c..00000000
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-#
-# Build an OpenVPN plugin module on *nix.  The argument should
-# be the base name of the C source file (without the .c).
-#
-
-# This directory is where we will look for openvpn-plugin.h
-CPPFLAGS="${CPPFLAGS:--I../../..}"
-
-CC="${CC:-gcc}"
-CFLAGS="${CFLAGS:--O2 -Wall -g}"
-
-$CC $CPPFLAGS $CFLAGS -fPIC -c $1.c && \
-$CC $CFLAGS -fPIC -shared $LDFLAGS -Wl,-soname,$1.so -o $1.so $1.o -lc
Signature · 1 line
2.11.0
#2 lore raw
In reply to David Sommerseth

Hi,

Thanks for the patch exporting base64_encode/decode

A quick question/comment though: quoting from your sample base64.c

Quoted 9 lines · David Sommerseth
sample/sample-plugins/simple/base64.c new file +6 -0
+    /*  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);

While this looks right[*], in openvpn-plugin.h (lines 344-370) the handle in the _return struct
is defined as openvpn_plugin_handle_t * where that type itself is void *, making handle void **.
Also the comment accompanying "struct openvpn_plugin_args_open_return" indicates
*handle should be set to the pointer to the context but that cant be right.

The compiler will not warn about void * and void ** mismatches, so ignoring the definition and
saving the context pointer in ret->handle works, but the declaration of handle in the return struct
should be simply openvpn_plugin_handle_t without the *. The same comment also refers to
*type_mask instead of type_mask.which is not right either.
.
Am I missing something?

Selva

[*] By the way, this being an example, it may be best to show the correct type by casting the
return value of calloc to (openvpn_plugin_handle_t)

#3 lore raw
Quoted 27 lines · Selva Nair

Hi,

Thanks for the patch exporting base64_encode/decode

A quick question/comment though: quoting from your sample base64.c

On Fri, May 5, 2017 at 5:46 PM, David Sommerseth <[email protected]... <mailto:[email protected]...>> wrote:

+ /* 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);

While this looks right[*], in openvpn-plugin.h (lines 344-370) the handle in the _return struct
is defined as openvpn_plugin_handle_t * where that type itself is void *, making handle void **.
Also the comment accompanying "struct openvpn_plugin_args_open_return" indicates
*handle should be set to the pointer to the context but that cant be right.

Quoted 5 lines

The compiler will not warn about void * and void ** mismatches, so ignoring the definition and
saving the context pointer in ret->handle works, but the declaration of handle in the return struct
should be simply openvpn_plugin_handle_t without the *.

I had to dig into the history here, to refresh how these things came to be. This really puzzled me a lot. Both the v1 and v2 APIs declares:

OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t \
OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_vX)

Which basically renders to:

openvpn_plugin_handle_t openvpn_plugin_open_vX(...)

Which then ends up as:

void * openvpn_plugin_open_vX(...)

So these functions return a pointer.

Similar to the _func_vX(...) and _close_v1(...) functions, they also use just openvpn_plugin_handle_t handle in the argument declaration, which means the argument is a pointer (void *).

The v3 API is the only one ending up using openvpn_plugin_handle_t * handle. And the same happens to the return_list member as well, which

This truly looks like an oversight in the patch review. So the core intention was to make it end up as 'void *'. Instead the API was "copy-pasted" from the v2 API without thoroughly reviewing this well enough. And then we end up with openvpn_plugin_handle_t *' which in effect is void **`.

On the other hand, I vaguely remember there were some issues in these areas when writing the v3 plug-in API back in late 2010. But my memory is failing me now. As we also didn't have the same traceability back then as we have today, finding the threads to recall why things.

The traces I found are:

- IRC reviews

<https://www.mail-archive.com/[email protected]/msg04664.html>

<https://www.mail-archive.com/[email protected]/msg04689.html>

- Patches sent to the mailing list:
v2:
<https://www.mail-archive.com/[email protected]/msg04564.html>
v1:
<https://www.mail-archive.com/[email protected]/msg04238.html>
My hunch now is that this is just an oversight.

v3 is what got applied to the ML.

(It is so good we've improved our track-ability since those earlier days.)

I think it is a bit too risky to actually fix the plug-in API to fix this. So we need to use (openvpn_plugin_handle_t *) in the v3 API.

I'll update the patch accordingly.

Quoted 2 lines

The same comment also refers to *type_mask instead of type_mask.which is not right either.

That is an error in the documentation That's an easy and safe fix.

Quoted 1 line

Am I missing something?

No, I don't think so. You seem just to have caught a somewhat sloppy review which was done many years ago.

Quoted 3 lines

[*] By the way, this being an example, it may be best to show the correct type by casting the
return value of calloc to (openvpn_plugin_handle_t)

Yes, but shouldn't it be (openvpn_plugin_handle_t *) ?

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#4 lore raw

Hi,

Thanks for the follow up with details. I also put some further thought into this overnight and totally agree with your observations. With one exception :)

Quoted 3 lines · David Sommerseth

I think it is a bit too risky to actually fix the plug-in API to fix this. So we need to use (openvpn_plugin_handle_t *) in the v3 API.

We can fix it by removing the * without breaking the API. And I think that is the right thing to do. In any case all working plugins that use v3 has to be using handle (an not *handle) to store the context pointer and then retrieving it as passed back in the func call.

A code that sets *handle = context_ptr is clearly wrong and would segfault Any that sets handle = &context_ptr would get the wrong pointer back in the func call so would not function properly.

So both those usages can be assumed not to exist.

So the only concern would be plugins which set handle = (openvpn_plugin_handle_t *) context_ptr. That is only a cast issue and will continue to compile and "work" even if the struct is changed to have "openvpn_plugin_handle_t handle).

Quoted 2 lines

I'll update the patch accordingly.

So I suggest to change the API to define handle in the return struct as openvpn_plugin_handle_t without the *. It also avoids giving the wrong impression that one should set handle = &context_ptr in the _open_v3() call.

Quoted 6 lines

[*] By the way, this being an example, it may be best to show the

Quoted 2 lines

correct type by casting the
return value of calloc to (openvpn_plugin_handle_t)

Yes, but shouldn't it be (openvpn_plugin_handle_t *) ?

I assumed the fix would be to change the struct.

Thanks,

Selva

#5 lore raw
In reply to David Sommerseth

Hi David,

Quoted 6 lines · David Sommerseth

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.

This has remained in a limbo mainly because of me pushing for a correction to the plugin_v3 API. Obviously that hasn't got any traction.

If you separate this into two patches: (i) export base64 (ii) usage sample we can get (i) merged right away and move on to patches that would benefit from it.

Thanks,

Selva

#6 lore raw
Quoted 11 lines · Selva

Hi David,

On Fri, May 5, 2017 at 5:46 PM, David Sommerseth <[email protected]... <mailto:[email protected]...>> 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.

Quoted 7 lines


This has remained in a limbo mainly because of me pushing for a correction to the plugin_v3 API. Obviously that hasn't got any traction.

If you separate this into two patches: (i) export base64 (ii) usage sample we can get (i) merged right away and move on to patches that would benefit from it.

Hi Selva,

This has gone in-and-out of my TODO list for quite some time, and I've even had some help from Antonio double checking the plugin_v3 API corrections. I've just been side-tracked on more urgent matters.

We actually ended up concluding that we can fix the API without making things worse. Which is the most important detail here.

I'll try to get some time fixing this and respond a bit quicker.

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN, Inc
#7 lore raw

Hi David,

Quoted 27 lines · David Sommerseth
Quoted 6 lines · Selva

Hi David,

On Fri, May 5, 2017 at 5:46 PM, David Sommerseth <[email protected]... <mailto:[email protected]...>> wrote:

This patch builds on the "Export secure_memzero() to plug-ins" patch

and

Quoted 3 lines

adds export of openvpn_base64_encode() and openvpn_base64_decode()

This also ships with a very simple plug-in which demonstrates how to

use

Quoted 4 lines

the new exported functions.

This has remained in a limbo mainly because of me pushing for a

correction

Quoted 3 lines

to the plugin_v3 API. Obviously that hasn't got any traction.

If you separate this into two patches: (i) export base64 (ii) usage

sample

Quoted 1 line

we can get (i) merged right away and move on to patches that would

benefit

Quoted 1 line

from it.

Hi Selva,

Quoted 8 lines

This has gone in-and-out of my TODO list for quite some time, and I've even had some help from Antonio double checking the plugin_v3 API corrections. I've just been side-tracked on more urgent matters.

We actually ended up concluding that we can fix the API without making things worse. Which is the most important detail here.

I'll try to get some time fixing this and respond a bit quicker.

Good to know its still on your radar. I'll resubmit the API patch so that it gets
on to patchwork.

Selva

#8 lore raw

Hi,

Quoted 36 lines · Selva

Hi David,

Quoted 32 lines · David Sommerseth
Quoted 18 lines · Selva

Hi David,

On Fri, May 5, 2017 at 5:46 PM, David Sommerseth <[email protected]... <mailto:[email protected]...>> 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.

This has remained in a limbo mainly because of me pushing for a correction
to the plugin_v3 API. Obviously that hasn't got any traction.

Quoted 5 lines

If you separate this into two patches: (i) export base64 (ii) usage sample
we can get (i) merged right away and move on to patches that would benefit
from it.

Hi Selva,

This has gone in-and-out of my TODO list for quite some time, and I've even had some help from Antonio double checking the plugin_v3 API corrections. I've just been side-tracked on more urgent matters.

Quoted 8 lines
Quoted 4 lines

We actually ended up concluding that we can fix the API without making things worse. Which is the most important detail here.

I'll try to get some time fixing this and respond a bit quicker.

Good to know its still on your radar. I'll resubmit the API patch so that it gets on to patchwork.

David: A not so gentle reminder..

Selva

#9 lore raw
In reply to David Sommerseth

Hi,

Now that the minor "fix" for plugin header seems settled, back to the base64 export patch from David.

Quoted 6 lines · David Sommerseth

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.

Quoted 7 lines
---
 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.

Quoted 224 lines
include/openvpn-plugin.h.in +31 -0
index ec83f3a6..68180d62 100644
@@ -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;
 };
 
 /**
sample/sample-plugins/simple/base64.c new file +161 -0
new file mode 100644
index 00000000..503b5ba0
@@ -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 <[email protected]...>
+ *
+ *  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;
+    }

sample/sample-plugins/simple/base64.c line 171

Quoted 10 lines
sample/sample-plugins/simple/base64.c new file +10 -0
+
+    /* 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

sample/sample-plugins/simple/base64.c line 177

Quoted 6 lines
sample/sample-plugins/simple/base64.c new file +6 -0
+    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

Quoted 54 lines
sample/sample-plugins/simple/base64.c new file +27 -0
+    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);
+}
+
src/openvpn/plugin.c +4 -2
index a652d528..ca278af1 100644
@@ -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

Quoted 7 lines

------------------------------------------------------------------------------
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 [email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Acked by: [email protected]...

#10 lore raw
In reply to David Sommerseth

Your patch has been applied to the master and release/2.4 branch, with the comment fixes (BAS64 -> BASE64, and encode->decode on the 2nd comment).

release/2.4, because the "secure_memzero" also is in 2.4 (went into 2.4.3), and everything else creates needless pain for plugin authors. The code change on the openvpn side is very small, and it's fully in the "long term compatibility" category.

commit 6690769f78bbfb889fef2a54088d979896c87d51 (master) commit 6c26116759ddf1e9327a9239e14f8c94c98ec638 (release/2.4)

Author: David Sommerseth
Date:   Fri May 5 23:46:23 2017 +0200
     plugin: Export base64 encode and decode functions

     Signed-off-by: David Sommerseth <[email protected]...>
     Acked-by: Selva Nair <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg14558.html
     Signed-off-by: Gert Doering <[email protected]...>

--
kind regards,

Gert Doering