summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS.txt3
-rw-r--r--common/eurephia_context.h1
-rw-r--r--plugin/eurephia-auth.c8
-rw-r--r--plugin/eurephia.c58
-rw-r--r--plugin/eurephiadb_session.c57
-rw-r--r--plugin/eurephiadb_session.h1
-rw-r--r--plugin/firewall/eurephiafw.c2
7 files changed, 107 insertions, 23 deletions
diff --git a/CREDITS.txt b/CREDITS.txt
index 3f12c2f..878a5fb 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -44,3 +44,6 @@ or indirectly, will be credited here.
* Tavis Paquette <unspin@dream.cx>
- Helped out solving FreeBSD building issues
- Also helped testing out the new TUN support for eurephia
+
+* Matthew Gyurgyik <pyther@pyther.net>
+ - Helped out testing the TUN support in eurephia on Linux with iptables support
diff --git a/common/eurephia_context.h b/common/eurephia_context.h
index d7c1bae..56b1ed7 100644
--- a/common/eurephia_context.h
+++ b/common/eurephia_context.h
@@ -70,6 +70,7 @@ typedef struct {
eurephiaLOG *log; /**< Log context, used by eurephia_log() */
int fatal_error; /**< If this flag is set, the execution should stop immediately */
int context_type; /**< Defines the context type */
+ eurephiaVALUES *disconnected; /**< List over disconnected clients which has not yet been removed */
} eurephiaCTX;
#endif
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;