diff options
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/eurephia-auth.c | 8 | ||||
-rw-r--r-- | plugin/eurephia.c | 58 | ||||
-rw-r--r-- | plugin/eurephiadb_session.c | 57 | ||||
-rw-r--r-- | plugin/eurephiadb_session.h | 1 | ||||
-rw-r--r-- | plugin/firewall/eurephiafw.c | 2 |
5 files changed, 103 insertions, 23 deletions
diff --git a/plugin/eurephia-auth.c b/plugin/eurephia-auth.c index 71969e5..9245a40 100644 --- a/plugin/eurephia-auth.c +++ b/plugin/eurephia-auth.c @@ -270,6 +270,14 @@ OPENVPN_EXPORT int openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, case OPENVPN_PLUGIN_CLIENT_DISCONNECT: // Register logout result = eurephia_disconnect(ctx, envp); + if( (result == 1) && (ctx->tuntype == tuntype_TUN) ) { + // If running in TUN mode, OPENVPN_PLUGIN_LEARN_ADDRESS will not be called, + // so we fake this call here instead. + char *vpnipaddr = GETENV_POOLIPADDR(ctx, envp); + + result = (vpnipaddr ? eurephia_learn_address(ctx, "delete", vpnipaddr, envp) : 0); + free_nullsafe(ctx, vpnipaddr); + } break; case OPENVPN_PLUGIN_LEARN_ADDRESS: // Log IP address, MAC address and update firewall 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; diff --git a/plugin/eurephiadb_session.c b/plugin/eurephiadb_session.c index f8fb97a..f6c7faa 100644 --- a/plugin/eurephiadb_session.c +++ b/plugin/eurephiadb_session.c @@ -242,37 +242,34 @@ eurephiaSESSION *eDBopen_session_seed(eurephiaCTX *ctx, const char *digest, /** - * Open an existing eurephia session based on a MAC address. This function is only used - * when there is not enough information to generate a session seed and when the MAC address - * is available. Usually this only happens when the client has disconnected and the session - * is about to be marked as closed. + * Load a session based on a known session key * - * @param ctx eurephiaCTX - * @param macaddr MAC address of the client + * @param ctx eurephiaCTX + * @param sesskey A string containing the session key + * @param sesstype What kind of type the session data should be opend as (sessionType) * - * @return returns a eurephiaSESSION pointer on success, otherwise NULL. + * @return Returns a pointer to the corresponding eurephiaSESSION struct on success, otherwise NULL. */ -eurephiaSESSION *eDBopen_session_macaddr(eurephiaCTX *ctx, const char *macaddr) { + +eurephiaSESSION *eDBsession_load(eurephiaCTX *ctx, const char *sesskey, sessionType sesstype) { eurephiaSESSION *new_session = NULL; - DEBUG(ctx, 12, "Function call: eDBopen_session_mac(ctx, '%s')", macaddr); + DEBUG(ctx, 12, "Function call: eDBsession_load(ctx, '%s')", sesskey); new_session = (eurephiaSESSION *) malloc_nullsafe(ctx, sizeof(eurephiaSESSION) + 2); if( new_session == NULL ) { return NULL; } - - new_session->type = stSESSION; // When we have macaddr - this is a stSESSION type of session + new_session->type = sesstype; // Get the sessionkey from the database - new_session->sessionkey = eDBget_sessionkey_macaddr(ctx, macaddr); + new_session->sessionkey = strdup_nullsafe(sesskey); if( new_session->sessionkey == NULL ) { - eurephia_log(ctx, LOG_CRITICAL, 0, "Could not find an active session for MAC address '%s'", - macaddr); + eurephia_log(ctx, LOG_CRITICAL, 0, "Failed to set the session key to '%s'", + sesskey); free_nullsafe(ctx, new_session); return NULL; } - DEBUG(ctx, 13, "Session seed found, using sessionkey '%s'", new_session->sessionkey); // Load session values from the database new_session->sessvals = eDBload_sessiondata(ctx, new_session->sessionkey); @@ -280,3 +277,33 @@ eurephiaSESSION *eDBopen_session_macaddr(eurephiaCTX *ctx, const char *macaddr) // Return struct which contains the current session return new_session; } + + +/** + * Open an existing eurephia session based on a MAC address. This function is only used + * when there is not enough information to generate a session seed and when the MAC address + * is available. Usually this only happens when the client has disconnected and the session + * is about to be marked as closed. + * + * @param ctx eurephiaCTX + * @param macaddr MAC address of the client + * + * @return returns a eurephiaSESSION pointer on success, otherwise NULL. + */ +eurephiaSESSION *eDBopen_session_macaddr(eurephiaCTX *ctx, const char *macaddr) { + char *sesskey = NULL; + + DEBUG(ctx, 12, "Function call: eDBopen_session_mac(ctx, '%s')", macaddr); + + // Get the sessionkey from the database + sesskey = eDBget_sessionkey_macaddr(ctx, macaddr); + if( sesskey == NULL ) { + eurephia_log(ctx, LOG_CRITICAL, 0, "Could not find an active session for MAC address '%s'", + macaddr); + return NULL; + } + DEBUG(ctx, 13, "Session seed found, using sessionkey '%s'", sesskey); + + // Open and load the session from the database + return eDBsession_load(ctx, sesskey, stSESSION); +} diff --git a/plugin/eurephiadb_session.h b/plugin/eurephiadb_session.h index 5af2ce2..a3e159a 100644 --- a/plugin/eurephiadb_session.h +++ b/plugin/eurephiadb_session.h @@ -38,6 +38,7 @@ eurephiaSESSION *eDBopen_session_seed(eurephiaCTX *ctx, const char *digest, const char *vpnipaddr, const char *vpnipmask, const char *remipaddr, const char *remport); +eurephiaSESSION *eDBsession_load(eurephiaCTX *ctx, const char *sesskey, sessionType sesstype); eurephiaSESSION *eDBopen_session_macaddr(eurephiaCTX *ctx, const char *macaddr); #endif /* !EUREPHIADB_SESSION_H_ */ diff --git a/plugin/firewall/eurephiafw.c b/plugin/firewall/eurephiafw.c index d443e76..4ec2980 100644 --- a/plugin/firewall/eurephiafw.c +++ b/plugin/firewall/eurephiafw.c @@ -472,7 +472,7 @@ int eFW_UpdateFirewall(eurephiaCTX *ctx, eFWupdateRequest *request ) { eurephia_log(ctx, LOG_INFO, 3, "Function call: eFW_UpdateFirewall(ctx, %s, '%.18s', '%s', '%s')", (request->mode == fwADD ? "ADD" : "DELETE"), - request->macaddress, + (ctx->tuntype == tuntype_TAP ? request->macaddress : request->ipaddress), request->rule_destination, request->goto_destination); errno = 0; |