diff options
Diffstat (limited to 'plugin/eurephia.c')
-rw-r--r-- | plugin/eurephia.c | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/plugin/eurephia.c b/plugin/eurephia.c index 71181f5..eda014f 100644 --- a/plugin/eurephia.c +++ b/plugin/eurephia.c @@ -204,6 +204,12 @@ eurephiaCTX *eurephiaInit(const char const **argv, const char const **envp) ctx->eurephia_fw_intf = NULL; } + // Prepare an empty disconnected list. + // This one is used to track all clients IP addresses and their corresponding eurephia session ID + // when they disconnect. This is especially needed in TUN mode, the eurephia_learn_address() + // delete call with otherwise have too little information to identify the session. + ctx->disconnected = eCreate_value_space(ctx, 12); + eurephia_log(ctx, LOG_INFO, 1, "eurephia-auth is initialised"); return ctx; } @@ -223,6 +229,11 @@ int eurephiaShutdown(eurephiaCTX *ctx) return 0; } + if( ctx->disconnected != NULL ) { + eFree_values(ctx, ctx->disconnected); + ctx->disconnected = NULL; + } + if( ctx->eurephia_fw_intf != NULL ) { if( ctx->fwcfg != NULL ) { eFW_StopFirewall(ctx); @@ -599,6 +610,12 @@ int eurephia_disconnect(eurephiaCTX *ctx, const char **env) { return 0; } + if( ctx->tuntype == tuntype_TUN ) { + // Put the clients IP address into the disconnected list, to be used and freed + // by eurephia_learn_address() afterwards + eAdd_value(ctx, ctx->disconnected, vpnipaddr, session->sessionkey); + } + ret = eDBregister_logout(ctx, session, bytes_sent, bytes_rec, duration); eDBfree_session(ctx, session); eurephia_log(ctx, LOG_INFO, 1, "User '%s' logged out", uname); @@ -646,7 +663,7 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *clien char *fwprofile = NULL, *fwdest = NULL; int ret = 0, fw_enabled = 0; - DEBUG(ctx, 10, "** Function call: eurephia_learn_address(ctx, '%.10s', '%.18s', ...)", + DEBUG(ctx, 10, "** Function call: eurephia_learn_address(ctx, '%.10s', '%.64s', ...)", mode, clientaddr); // Get firewall information @@ -656,7 +673,15 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *clien eurephia_log(ctx, LOG_CRITICAL, 0, "No firewall destination defined in the config."); } - if( strncmp(mode, "add", 3) == 0 ) { + // In TUN mode, if a client reconnects quickly after a disconnect, + // OpenVPN re-uses the session for this and just sends an update + // call to LEARN_ADDRESS. As eurephia in TUN mode treats disconnects + // with an explicit 'delete' (see eurephia-auth.c for more info) and + // don't wait for a separate LEARN_ADDRESS delete call (which never + // seems to come), we treat 'update' as an ordinary 'add' in TUN mode. + if( (strncmp(mode, "add", 3) == 0) + || ((ctx->tuntype == tuntype_TUN) && (strncmp(mode, "update", 6) == 0)) ) { + // Fetch needed info digest = GETENV_TLSDIGEST(ctx, env, 0); cname = GETENV_CNAME(ctx, env); @@ -674,8 +699,12 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *clien goto exit; } - // Update openvpn_lastlog with the active MAC address, and save it as a session variable - ret = eDBregister_vpnmacaddr(ctx, session, clientaddr); + if( ctx->tuntype == tuntype_TAP ) { + // Update openvpn_lastlog with the active MAC address, and save it as a session variable + ret = eDBregister_vpnmacaddr(ctx, session, clientaddr); + } else { + ret = 1; + } if( (fw_enabled) && (fwdest != NULL) ) { fwprofile = eDBget_firewall_profile(ctx, session); @@ -696,11 +725,26 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *clien } else if( strncmp(mode, "delete", 6) == 0 ) { - // Load the session, based on MAC address - session = eDBopen_session_macaddr(ctx, clientaddr); + // Load the session + if( ctx->tuntype == tuntype_TAP ) { + // in TAP mode - use the MAC address + session = eDBopen_session_macaddr(ctx, clientaddr); + } else { + // in TUN mode - use the disconnected list to find the session key + eurephiaVALUES *sessval = eGet_valuestruct(ctx->disconnected, clientaddr); + if( sessval ) { + session = eDBsession_load(ctx, sessval->val, stSESSION); + if( ctx->disconnected->next != NULL ) { + ctx->disconnected = eRemove_value(ctx, ctx->disconnected, + sessval->evgid, sessval->evid); + } else { + eClear_key_value(ctx->disconnected); + } + } + } if( session == NULL ) { eurephia_log(ctx, LOG_WARNING, 0, - "Could not find any session connected to this MAC address: %.18s", + "Could not find any session connected to the client address %s", clientaddr); ret = 0; goto exit; |