diff options
author | David Sommerseth <dazo@users.sourceforge.net> | 2013-06-07 19:08:30 +0200 |
---|---|---|
committer | David Sommerseth <dazo@users.sourceforge.net> | 2013-06-07 19:08:30 +0200 |
commit | e2bcae3f289d444a775b80d00d073fd37fcb2140 (patch) | |
tree | 0e4ef132fc9bb4fa4a474dbe2c069c6059fb8580 | |
parent | ef0c3ffb0c85def725b7ef56fd99339b670ee60a (diff) | |
download | eurephia-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.c | 90 |
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); +} |