From 787ce00e997d63a9ce1f1c16cf79b3ff1afd2588 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Wed, 25 Aug 2010 19:22:10 +0200 Subject: Completed the needed changes for the new firewall plug-in API Moved over the missing pieces to use the eFWupdateRequest struct. This is a continuation of the work started in commit bdd956adcccd91ff553278fd73cea7 Signed-off-by: David Sommerseth --- plugin/eurephia.c | 24 ++-- plugin/firewall/eurephiafw.c | 29 ++--- plugin/firewall/eurephiafw_helpers.h | 4 +- plugin/firewall/iptables/efw-iptables.c | 192 +++++++++++++------------------- 4 files changed, 114 insertions(+), 135 deletions(-) diff --git a/plugin/eurephia.c b/plugin/eurephia.c index 370885e..5e1e19c 100644 --- a/plugin/eurephia.c +++ b/plugin/eurephia.c @@ -257,7 +257,7 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **env, const char *depth_str int result = 0; char *ipaddr; char *tls_digest, *tls_id; - unsigned int depth = atoi_nullsafe(depth_str); + unsigned int depth = atoi_nullsafe(depth_str); certinfo *ci = NULL; DEBUG(ctx, 10, "** Function call: eurephia_tlsverify(...)"); @@ -269,7 +269,9 @@ int eurephia_tlsverify(eurephiaCTX *ctx, const char **env, const char *depth_str // If fw blacklisting is configured, also blacklist there too if( (ctx->fwcfg != NULL) && (ctx->fwcfg->fwblacklist != NULL ) ) { - eFW_UpdateFirewall(ctx, FWRULE_BLACKLIST, ipaddr, ctx->fwcfg->fwblacklist, NULL); + eFWupdateRequest req = { .mode = fwBLACKLIST, }; + strncpy(req.ipaddress, ipaddr, sizeof(req.ipaddress)); + eFW_UpdateFirewall(ctx, &req); } free_nullsafe(ctx, ipaddr); return 0; @@ -341,7 +343,9 @@ int eurephia_userauth(eurephiaCTX *ctx, const char **env) // If fw blacklisting is configured, also blacklist there too if( (ctx->fwcfg != NULL) && (ctx->fwcfg->fwblacklist != NULL ) ) { - eFW_UpdateFirewall(ctx, FWRULE_BLACKLIST, ipaddr, ctx->fwcfg->fwblacklist, NULL); + eFWupdateRequest req = { .mode = fwBLACKLIST, }; + strncpy(req.ipaddress, ipaddr, sizeof(req.ipaddress)); + eFW_UpdateFirewall(ctx, &req); } free_nullsafe(ctx, ipaddr); @@ -669,8 +673,11 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macad if( (fw_enabled) && (fwdest != NULL) ) { fwprofile = eDBget_firewall_profile(ctx, session); if( fwprofile != NULL ) { - eFW_UpdateFirewall(ctx, FWRULE_ADD, macaddr, fwdest, fwprofile); - free_nullsafe(ctx, fwprofile); + eFWupdateRequest req = { .mode = fwADD, }; + strncpy(req.macaddress, macaddr, sizeof(req.macaddress)); + strncpy(req.rule_destination, fwdest, sizeof(req.rule_destination)); + strncpy(req.goto_destination, fwprofile, sizeof(req.goto_destination)); + eFW_UpdateFirewall(ctx, &req); } } eDBfree_session(ctx, session); @@ -690,8 +697,11 @@ int eurephia_learn_address(eurephiaCTX *ctx, const char *mode, const char *macad if( (fw_enabled) && (fwdest != NULL) ) { fwprofile = eDBget_firewall_profile(ctx, session); if( fwprofile != NULL ) { - eFW_UpdateFirewall(ctx, FWRULE_DELETE, macaddr, fwdest, fwprofile); - free_nullsafe(ctx, fwprofile); + eFWupdateRequest req = { .mode = fwDELETE, }; + strncpy(req.macaddress, macaddr, sizeof(req.macaddress)); + strncpy(req.rule_destination, fwdest, sizeof(req.rule_destination)); + strncpy(req.goto_destination, fwprofile, sizeof(req.goto_destination)); + eFW_UpdateFirewall(ctx, &req); } } ret = eDBdestroy_session(ctx, session); diff --git a/plugin/firewall/eurephiafw.c b/plugin/firewall/eurephiafw.c index 8b24486..774fe21 100644 --- a/plugin/firewall/eurephiafw.c +++ b/plugin/firewall/eurephiafw.c @@ -265,11 +265,11 @@ void eFW_StartFirewall(eurephiaCTX *ctx) { updreq.mode = fwINITIALISE; strncpy(updreq.rule_destination, fwdest, 64); mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)&updreq, sizeof(eFWupdateRequest), 1); - if( mqres < 1 ) { + (const char *)&updreq, EFW_MSG_SIZE, 1); + if( mqres < 0 ) { eurephia_log(ctx, LOG_ERROR, 0, - "Could not request firewall initialisation of the %s chain: %s", - fwdest, strerror(errno)); + "Could not request firewall initialisation of the %s chain: (%i) %s", + fwdest, mqres, strerror(errno)); }; if( ctx->fwcfg->fwblacklist != NULL ) { @@ -282,16 +282,19 @@ void eFW_StartFirewall(eurephiaCTX *ctx) { strncpy(updreq.rule_destination, ctx->fwcfg->fwblacklist, 64); errno = 0; mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)&updreq, sizeof(eFWupdateRequest), 1); - if( mqres < 1 ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not request flushing of the %s chain: %s", - ctx->fwcfg->fwblacklist, strerror(errno)); + (const char *)&updreq, EFW_MSG_SIZE, 1); + if( mqres < 0 ) { + eurephia_log(ctx, LOG_ERROR, 0, "Could not request flushing of the %s chain: (%i) %s", + ctx->fwcfg->fwblacklist, mqres, strerror(errno)); }; // Registering already blacklisted IP addresses into the proper firewall chain memset(&updreq, 0, sizeof(eFWupdateRequest)); updreq.mode = fwBLACKLIST; blacklisted = eDBget_blacklisted_ip(ctx); + strncpy(updreq.rule_destination, ctx->fwcfg->fwblacklist, 64); + strncpy(updreq.goto_destination, + ctx->fwcfg->fwblacklist_sendto ? ctx->fwcfg->fwblacklist_sendto : "\0", 64); p = blacklisted; while( p != NULL ) { if( p->val != NULL ) { @@ -333,8 +336,8 @@ void eFW_StopFirewall(eurephiaCTX *ctx) { errno = 0; mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)&updreq, sizeof(eFWupdateRequest), 1); - if( mqres < 1 ) { + (const char *)&updreq, EFW_MSG_SIZE, 1); + if( mqres < 0 ) { eurephia_log(ctx, LOG_CRITICAL, 0, "Could not request firewall flushing of the %s chain: %s", fwdest, strerror(errno)); @@ -350,7 +353,7 @@ void eFW_StopFirewall(eurephiaCTX *ctx) { updreq.mode = fwSHUTDOWN; errno = 0; mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)&updreq, sizeof(eFWupdateRequest), 1); + (const char *)&updreq, EFW_MSG_SIZE, 1); if( mqres < 1 ) { eurephia_log(ctx, LOG_PANIC, 0, "Could not initiate shutdown on eFW module: %s", strerror(errno)); @@ -437,7 +440,7 @@ int eFW_UpdateFirewall(eurephiaCTX *ctx, eFWupdateRequest *request ) { request->goto_destination); errno = 0; mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)request, sizeof(eFWupdateRequest), prio); + (const char *)request, EFW_MSG_SIZE, prio); if( mqres < 0 ) { eurephia_log(ctx, LOG_CRITICAL, 0, "eFW_updateFirewall: Failed to send update request - %s", @@ -468,7 +471,7 @@ int eFW_UpdateFirewall(eurephiaCTX *ctx, eFWupdateRequest *request ) { errno = 0; mqres = mq_send((*ctx->fwcfg).thrdata.msgq, - (const char *)request, sizeof(eFWupdateRequest), prio); + (const char *)request, EFW_MSG_SIZE, prio); if( mqres < 0 ) { eurephia_log(ctx, LOG_CRITICAL, 0, "eFW_updateFirewall: Failed to send update request - %s", diff --git a/plugin/firewall/eurephiafw_helpers.h b/plugin/firewall/eurephiafw_helpers.h index 09d9930..285bfa1 100644 --- a/plugin/firewall/eurephiafw_helpers.h +++ b/plugin/firewall/eurephiafw_helpers.h @@ -33,8 +33,8 @@ #ifndef EUREPHIAFW_HELPERS_H_ #define EUREPHIAFW_HELPERS_H_ -#define EFW_MSG_SIZE 1024 /**< Maximum size of a message in the POSIX MQ queue */ -#define MQUEUE_NAME "/eurephiaFW" /**< Name of the MQ queue */ +#define EFW_MSG_SIZE sizeof(eFWupdateRequest) /**< Maximum size of a message in the POSIX MQ queue */ +#define MQUEUE_NAME "/eurephiaFW" /**< Name of the MQ queue */ #define SEMPH_MASTER "eurephiafw_master" /**< Name of the semaphore the main openvpn process uses */ #define SEMPH_WORKER "eurephiafw_worker" /**< Name of the semaphore the firewall process uses */ diff --git a/plugin/firewall/iptables/efw-iptables.c b/plugin/firewall/iptables/efw-iptables.c index 8e90ac4..ed0ec9d 100644 --- a/plugin/firewall/iptables/efw-iptables.c +++ b/plugin/firewall/iptables/efw-iptables.c @@ -47,6 +47,16 @@ #define INTERFACEVER "1.0" /**< The version of this firewall interface (driver) */ #define INTERFACEAPIVER 1 /**< Define the API level this firewall interface uses. */ +static const char *eFWmode_str[7] = { + "ADD", + "DELETE", + "BLACKLIST", + "FLUSH", + "INITIALISE", + "SHUTDOWN", + NULL +}; + /** * Mandatory function, contains driver information. * @@ -67,8 +77,8 @@ int eFWinterfaceAPIversion() { } -int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *msg); -int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args); +int process_input(eurephiaCTX *ctx, const char *fwcmd, const eFWupdateRequest *req); +int call_iptables(eurephiaCTX *ctx, const char *fwcmd, const char **ipt_args); /** @@ -81,7 +91,7 @@ void eFW_RunFirewall(void *fwargs) { eurephiaCTX *ctx = (eurephiaCTX *) cfg->ctx; int quit = 0; unsigned int prio; - char buf[EFW_MSG_SIZE+2]; + eFWupdateRequest req; struct timespec tsp; DEBUG(ctx, 28, "eFW_RunFirewall: Waiting for eFW master to get ready"); @@ -100,25 +110,26 @@ void eFW_RunFirewall(void *fwargs) { // Main loop ... grab messages of the messague queue until shutdown command is sent, or a failure happens while( quit == 0 ) { - memset(buf, 0, EFW_MSG_SIZE+2); - if( mq_receive(cfg->msgq, &buf[0], EFW_MSG_SIZE, &prio) == -1 ) { + memset(&req, 0, sizeof(req)); + if( mq_receive(cfg->msgq, (char *)&req, EFW_MSG_SIZE, &prio) == -1 ) { eurephia_log(ctx, LOG_FATAL, 0, "eFW_RunFirewall: Error while reading messages from queue: %s", strerror(errno)); exit(2); } - quit = (strncmp(buf, "FWSHUTDOWN", 10) == 0 ); - if( !quit ) { + if( req.mode != fwSHUTDOWN ) { int res = 0; - DEBUG(ctx, 20, "eFW_RunFirewall: Received '%s'", buf); + DEBUG(ctx, 20, "eFW_RunFirewall: Received %s", eFWmode_str[req.mode]); - res = process_input(ctx, cfg->fw_command, buf); + res = process_input(ctx, cfg->fw_command, &req); if( ! res ) { quit = 1; eurephia_log(ctx, LOG_FATAL, 0, "eFW_RunFirewall: Failed updating iptables"); } + } else { + quit = 1; } } @@ -160,151 +171,106 @@ void eFW_RunFirewall(void *fwargs) { * @return Returns 1 on success, otherwise 0. If 0 is sent, it means the firewall process should shut down, * and it should only be used in very critical situations. */ -int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *input) { - char mode[3], *addr = NULL, *destchain = NULL, *jump = NULL; - char *msg = NULL, *orig_msg = NULL; - char *iptables_args[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - int ret = 0; +int process_input(eurephiaCTX *ctx, const char *fwcmd, const eFWupdateRequest *req) { + const char *iptables_args[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + int ret = 0; - orig_msg = strdup_nullsafe(input); - msg = orig_msg; - DEBUG(ctx, 36, "eFW_RunFirewall::process_input(ctx, '%s')", msg); + DEBUG(ctx, 36, "eFW_RunFirewall::process_input(ctx, %s, %s, %s, %s, %s)", + eFWmode_str[req->mode], req->ipaddress, req->macaddress, + req->rule_destination, req->goto_destination); // // Simple parsing of the input string // - mode[0] = '-'; - mode[1] = *msg; - mode[2] = 0; - msg += 2; - iptables_args[0] = (char *)fwcmd; - switch( mode[1] ) { - case 'A': - case 'D': - iptables_args[1] = mode; - addr = msg; // start of string for macaddr - - // Search for end of macaddr and NULL terminate it - destchain = addr+1; - while( (*destchain != 0x20) || (*destchain == 0) ) { - destchain++; + switch( req->mode ) { + case fwADD: + iptables_args[1] = "-A"; + case fwDELETE: + if( iptables_args[1] == NULL ) { + iptables_args[1] = "-D"; } - if( *destchain == 0 ) { - return 0; + // Prepare iptables arguments + iptables_args[2] = req->rule_destination; + if( req->ipaddress ) { + iptables_args[3] = "-s\0"; + iptables_args[4] = req->ipaddress; } - *destchain = 0; // end of string for macaddr - destchain++; // start of string for destchain - // Search for end of destchain and NULL terminate it - jump = destchain+1; - while( (*jump != 0x20) || (*jump == 0) ) { - jump++; + if( req->macaddress ) { + iptables_args[3] = "-m\0"; + iptables_args[4] = "mac\0"; + iptables_args[5] = "--mac-source\0"; + iptables_args[6] = req->macaddress; } - *jump = 0; // end of string for destchain - jump++; // start of string for jump - - // Prepare iptables arguments - iptables_args[2] = destchain; - iptables_args[3] = "-m\0"; - iptables_args[4] = "mac\0"; - iptables_args[5] = "--mac-source\0"; - iptables_args[6] = addr; iptables_args[7] = "-m\0"; iptables_args[8] = "state\0"; iptables_args[9] = "--state\0"; iptables_args[10] = "NEW\0"; iptables_args[11] = "-j\0"; - iptables_args[12] = jump; + iptables_args[12] = req->goto_destination; iptables_args[13] = NULL; eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules " - "==> mode: %s macaddr: '%s' destchain: '%s' jump: '%s'", - (mode[1] == 'A' ? "ADD":"DELETE"), addr, destchain, jump); + "==> mode: %s ipaddr: %s macaddr: '%s' destchain: '%s' jump: '%s'", + eFWmode_str[req->mode], req->ipaddress, req->macaddress, + req->rule_destination, req->goto_destination); ret = call_iptables(ctx, fwcmd, iptables_args); break; - case 'B': - addr = msg; // start of string for IP address to block - - // Search for end of IP address and NULL terminate it - destchain = addr+1; - while( (*destchain != 0x20) || (*destchain == 0) ) { - destchain++; - } - if( *destchain == 0 ) { - return 0; - } - *destchain = 0; // end of string for IP address - destchain++; // start of string for destchain - - // Search for end of destchain and NULL terminate it - jump = destchain+1; - while( (*jump != 0x20) || (*jump == 0) ) { - jump++; - } - *jump = 0; // end of string for destchain - jump++; // start of string for jump - if( *jump == 0 ) { - return 0; - } - + case fwBLACKLIST: iptables_args[1] = "-A\0"; - iptables_args[2] = destchain; + iptables_args[2] = req->rule_destination; iptables_args[3] = "-s\0"; - iptables_args[4] = addr; + iptables_args[4] = req->ipaddress; iptables_args[5] = "-j\0"; - iptables_args[6] = jump; + iptables_args[6] = strlen_nullsafe(req->goto_destination) > 0 + ? req->goto_destination : "DROP\0"; iptables_args[7] = NULL; eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules " "==> mode: BLACKLIST destchain: '%s' IP address: %s Send to: '%s'", - destchain, addr, jump); - ret = call_iptables(ctx, fwcmd, iptables_args); + req->rule_destination, req->ipaddress, req->goto_destination); + ret = call_iptables(ctx, fwcmd, iptables_args); break; - case 'F': - iptables_args[1] = mode; - destchain = msg; - iptables_args[2] = destchain; - iptables_args[3] = NULL; + case fwFLUSH: + iptables_args[1] = "-F\0"; + iptables_args[2] = req->rule_destination; + iptables_args[3] = NULL; eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules " - "==> mode: FLUSH destchain: '%s'", destchain); - ret = call_iptables(ctx, fwcmd, iptables_args); + "==> mode: FLUSH destchain: '%s'", req->rule_destination); + ret = call_iptables(ctx, fwcmd, iptables_args); break; - case 'I': - // Init chain - flush it and then add needed rule for stateful inspection - destchain = msg; - + case fwINITIALISE: + // Init chain - flush it and then add needed rule for stateful inspection eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - Initialising iptables chain '%s'", - destchain); - - // Flush phase - iptables_args[1] = "-F"; - destchain = msg; - iptables_args[2] = destchain; - iptables_args[3] = NULL; - ret = call_iptables(ctx, fwcmd, iptables_args); - - // Add stateful inspection - iptables_args[1] = "-I\0"; - iptables_args[2] = destchain; - iptables_args[3] = "-m\0"; + req->rule_destination); + + // Flush phase + iptables_args[1] = "-F"; + iptables_args[2] = req->rule_destination; + iptables_args[3] = NULL; + ret = call_iptables(ctx, fwcmd, iptables_args); + + // Add stateful inspection + iptables_args[1] = "-I\0"; + iptables_args[2] = req->rule_destination; + iptables_args[3] = "-m\0"; iptables_args[4] = "state\0"; iptables_args[5] = "--state\0"; iptables_args[6] = "ESTABLISHED,RELATED\0"; iptables_args[7] = "-j\0"; iptables_args[8] = "ACCEPT\0"; - ret &= call_iptables(ctx, fwcmd, iptables_args); - break; + ret &= call_iptables(ctx, fwcmd, iptables_args); + break; default: eurephia_log(ctx, LOG_CRITICAL, 0, "eFW_RunFirewall::process_input: Malformed update request"); - ret = 1; + ret = 1; } - free_nullsafe(ctx, orig_msg); - return ret; + return ret; } @@ -319,7 +285,7 @@ int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *input) { * @return Returns 1 on success, otherwise 0. When 0 is returned, the complete firewall process will be * shut down. */ -int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args) { +int call_iptables(eurephiaCTX *ctx, const char *fwcmd, const char **ipt_args) { pid_t pid; int cmdret = -1; @@ -333,7 +299,7 @@ int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args) { switch( pid ) { case 0: // child process - execute the program and exit - execve(fwcmd, ipt_args, NULL); + execve(fwcmd, (char * const*) ipt_args, NULL); exit(1); // execve should replace the process, but if it fails to do so, make sure we exit default: // parent process -- cgit