summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2010-12-14 18:47:58 +0100
committerDavid Sommerseth <dazo@users.sourceforge.net>2010-12-14 18:47:58 +0100
commit6440a3a4592a8c0f0f8fd50cd551b41c1e066efe (patch)
treeca70948f4f3ee7e4993e2359948102c5631c770b
parent64318873ac1aa92e6377a1a4a53932bcce78d187 (diff)
downloadeurephia-6440a3a4592a8c0f0f8fd50cd551b41c1e066efe.tar.gz
eurephia-6440a3a4592a8c0f0f8fd50cd551b41c1e066efe.tar.xz
eurephia-6440a3a4592a8c0f0f8fd50cd551b41c1e066efe.zip
Implemented proper TUN support in eurephia
Now eurephia will support both TUN and TAP configurations in OpenVPN. Thanks to Tavis Paquette and Matthew Gyurgyik for their willingness to test out this patch. Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
-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;