summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2013-06-07 19:08:30 +0200
committerDavid Sommerseth <dazo@users.sourceforge.net>2013-06-07 19:08:30 +0200
commite2bcae3f289d444a775b80d00d073fd37fcb2140 (patch)
tree0e4ef132fc9bb4fa4a474dbe2c069c6059fb8580
parentef0c3ffb0c85def725b7ef56fd99339b670ee60a (diff)
downloadeurephia-e2bcae3f289d444a775b80d00d073fd37fcb2140.tar.gz
eurephia-e2bcae3f289d444a775b80d00d073fd37fcb2140.tar.xz
eurephia-e2bcae3f289d444a775b80d00d073fd37fcb2140.zip
plugin: Save the client certificate information in a OpenVPN per-client-context
As the X.509 certificate data isn't available when the certificate has been validated, save the parsed certificate information in the per-client-context OpenVPN provides in the v3 plug-in API. When the client disconnects, the certificate information and per-client-context buffer is released as well. Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
-rw-r--r--plugin/eurephia-auth.c90
1 files changed, 73 insertions, 17 deletions
diff --git a/plugin/eurephia-auth.c b/plugin/eurephia-auth.c
index a491a44..dfe8ff2 100644
--- a/plugin/eurephia-auth.c
+++ b/plugin/eurephia-auth.c
@@ -48,6 +48,15 @@
#ifdef ENABLE_DEBUG /* To avoid compiler warnings when ENABLE_DEBUG is not defined */
/**
+ * A structure which is prepared in openvpn_plugin_client_constructor_v1().
+ * This function is called by OpenVPN to initialise a per client memory buffer.
+ *
+ */
+typedef struct _eurephiaClientCTX {
+ certinfo *cert;
+} eurephiaClientCTX;
+
+/**
* Simple "converter" from OPENVPN_PLUGIN_* type IDs to string
*
* @param type int value, corresponding to an OPENVPN_PLUGIN_* type
@@ -373,6 +382,7 @@ OPENVPN_EXPORT int openvpn_plugin_func_v3(const int apiver,
struct openvpn_plugin_args_func_return *ovpn_return)
{
eurephiaCTX *ctx = (eurephiaCTX *) args->handle;
+ eurephiaClientCTX *cctx = NULL;
int result = 0;
certinfo *ci = NULL;
@@ -390,18 +400,7 @@ OPENVPN_EXPORT int openvpn_plugin_func_v3(const int apiver,
#endif
if( args->type != OPENVPN_PLUGIN_UP ) {
- // Exctract certificate information from either environment variables
- // or the X.509 certificate if we have that available
- if( args->current_cert != NULL ) {
- ci = parse_x509_cert(args->current_cert);
- } else {
- ci = parse_tlsid(GETENV_TLSID(ctx, args->envp, args->argv[1]),
- GETENV_TLSDIGEST(ctx, args->envp, args->argv[1]));
- }
- if( ci == NULL ) {
- eurephia_log(ctx, LOG_FATAL, 0, "Failed to extract certificate info");
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
+ cctx = (eurephiaClientCTX *) args->per_client_context;
}
switch( args->type ) {
@@ -416,32 +415,56 @@ OPENVPN_EXPORT int openvpn_plugin_func_v3(const int apiver,
break;
case OPENVPN_PLUGIN_TLS_VERIFY: // Validate certificates
+ // Exctract certificate information from either environment variables
+ // or the X.509 certificate if we have that available
+ if( args->current_cert != NULL ) {
+ ci = parse_x509_cert(args->current_cert);
+ }
+ if( ci == NULL ) {
+ eurephia_log(ctx, LOG_FATAL, 0, "Failed to extract certificate info");
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
result = eurephia_tlsverify(ctx, args->envp, args->argv[1], ci);
+
+ if( args->argv[1][0] == '0' ) {
+ // It's a user certificate,
+ // save a pointer to this certificate info
+ cctx->cert = ci;
+ } else {
+ // CA/sub-CA certificates can be released
+ free_certinfo(ci);
+ }
break;
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY: // Validate user name and password
- result = eurephia_userauth(ctx, args->envp, ci);
+ result = eurephia_userauth(ctx, args->envp, cctx->cert);
break;
case OPENVPN_PLUGIN_CLIENT_CONNECT: // Register login
- result = eurephia_connect(ctx, args->envp, ci);
+ result = eurephia_connect(ctx, args->envp, cctx->cert);
break;
case OPENVPN_PLUGIN_CLIENT_DISCONNECT: // Register logout
- result = eurephia_disconnect(ctx, args->envp, ci);
+ result = eurephia_disconnect(ctx, args->envp, cctx->cert);
break;
case OPENVPN_PLUGIN_LEARN_ADDRESS: // Log IP address, MAC address and update firewall
result = eurephia_learn_address(ctx, args->argv[1],
args->argv[2],
- args->envp, ci);
+ args->envp, cctx->cert);
+
+ if( strncmp(args->argv[1], "delete", 6) == 0 ) {
+ // if we receive a 'delete' command,
+ // release the certificate information too
+ free_certinfo(cctx->cert);
+ cctx->cert = NULL;
+ }
break;
default: // This should normally not be reached at all
eurephia_log(ctx, LOG_FATAL, 0, "Unknown OPENVPN_PLUGIN type: %i", args->type);
break;
}
- free_certinfo(ci);
return (result == 1 ? OPENVPN_PLUGIN_FUNC_SUCCESS : OPENVPN_PLUGIN_FUNC_ERROR);
}
@@ -460,3 +483,36 @@ OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
eurephiaShutdown(ctx);
}
+
+/**
+ * Called when openvpn is wants to allocate a memory buffer for a new client
+ *
+ * @param handle Contains a pointer to the eurephiaCTX
+ *
+ * @return Returns a pointer to the initialised client context
+ */
+OPENVPN_EXPORT void * openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
+{
+ eurephiaCTX *ctx = (eurephiaCTX *) handle;
+ struct eurephiaClientCTX *cctx = malloc_nullsafe(ctx, sizeof(eurephiaClientCTX)+2);
+ return cctx;
+}
+
+
+
+/**
+ * Called when a client disconnects and openvpn wants to destroy the client context
+ *
+ * @param handle Contains a pointer to the eurephiaCTX
+ * @paran per_client_ctx Pointer to the client context to be released
+ */
+OPENVPN_EXPORT void openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle,
+ void *per_client_ctx)
+{
+ eurephiaClientCTX *cctx = (eurephiaClientCTX *) per_client_ctx;
+
+ if( cctx->cert ) {
+ free_certinfo(cctx->cert);
+ }
+ free(per_client_ctx);
+}