From e2bcae3f289d444a775b80d00d073fd37fcb2140 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Fri, 7 Jun 2013 19:08:30 +0200 Subject: 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 --- plugin/eurephia-auth.c | 90 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 17 deletions(-) (limited to 'plugin') 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 @@ -47,6 +47,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 * @@ -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); +} -- cgit