diff options
Diffstat (limited to 'plugin/firewall/iptables')
-rw-r--r-- | plugin/firewall/iptables/efw-iptables.c | 192 |
1 files changed, 79 insertions, 113 deletions
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 |