Started firewall rule processing. Added rule initialization. Added some of the initial routines for external command execution with ability to capture stdout, stderr, and exit status.
git-svn-id: file:///home/mbr/svn/fwknop/trunk@211 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
parent
9282a0fd29
commit
83a10b96f6
@ -5,7 +5,7 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
|
||||
pcap_capture.c pcap_capture.h process_packet.c \
|
||||
process_packet.h log_msg.c log_msg.h utils.c utils.h \
|
||||
sig_handler.c sig_handler.h replay_dbm.c replay_dbm.h \
|
||||
access.c access.h
|
||||
access.c access.h fw_util.c fw_util.h extcmd.c extcmd.h
|
||||
|
||||
fwknopd_LDADD = $(top_builddir)/lib/libfko.la
|
||||
|
||||
|
||||
@ -296,6 +296,45 @@ validate_options(fko_srv_options_t *opts)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
set_preconfig_entries(fko_srv_options_t *opts)
|
||||
{
|
||||
/* First, set any default or otherwise static settings here. Some may
|
||||
* end up being overwritten via config file or command-line.
|
||||
*/
|
||||
/* Default Hostname (or unknown if gethostname cannot tell us).
|
||||
*/
|
||||
if(gethostname(opts->hostname, MAX_HOSTNAME_LEN-1) < 0)
|
||||
strcpy(opts->hostname, "UNKNOWN");
|
||||
|
||||
/* Set the conf hostname entry here in case it is not set in the conf
|
||||
* file.
|
||||
*/
|
||||
set_config_entry(opts, CONF_HOSTNAME, opts->hostname);
|
||||
|
||||
/* Setup the local executables based on build-time info.
|
||||
*/
|
||||
#ifdef GPG_EXE
|
||||
set_config_entry(opts, CONF_EXE_GPG, GPG_EXE);
|
||||
#endif
|
||||
#ifdef MAIL_EXE
|
||||
set_config_entry(opts, CONF_EXE_MAIL, MAIL_EXE);
|
||||
#endif
|
||||
#ifdef SENDMAIL_EXE
|
||||
set_config_entry(opts, CONF_EXE_SENDMAIL, SENDMAIL_EXE);
|
||||
#endif
|
||||
#ifdef SH_EXE
|
||||
set_config_entry(opts, CONF_EXE_SH, SH_EXE);
|
||||
#endif
|
||||
#ifdef IPTABLES_EXE
|
||||
set_config_entry(opts, CONF_EXE_IPTABLES, IPTABLES_EXE);
|
||||
#endif
|
||||
#ifdef IPFW_EXE
|
||||
set_config_entry(opts, CONF_EXE_IPFW, IPFW_EXE);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Initialize program configuration via config file and/or command-line
|
||||
* switches.
|
||||
*/
|
||||
@ -312,18 +351,9 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
|
||||
*/
|
||||
memset(opts, 0x00, sizeof(fko_srv_options_t));
|
||||
|
||||
/* First, set any default or otherwise static settings here. Some may
|
||||
* end up being overwritten via config file or command-line.
|
||||
/* Set some preconfiguration options (i.e. build-time defaults)
|
||||
*/
|
||||
/* Default Hostname (or unknown if gethostname cannot tell us).
|
||||
*/
|
||||
if(gethostname(opts->hostname, MAX_HOSTNAME_LEN-1) < 0)
|
||||
strcpy(opts->hostname, "UNKNOWN");
|
||||
|
||||
/* Set the conf hostname entry here in case it is not set in the conf
|
||||
* file.
|
||||
*/
|
||||
set_config_entry(opts, CONF_HOSTNAME, opts->hostname);
|
||||
set_preconfig_entries(opts);
|
||||
|
||||
/* In case this is a re-config.
|
||||
*/
|
||||
|
||||
261
server/extcmd.c
Normal file
261
server/extcmd.c
Normal file
@ -0,0 +1,261 @@
|
||||
/* extcmd.c
|
||||
*
|
||||
* A test program to run an external command and capture its
|
||||
* stdout and stderr and exit code into varaibles to print later.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include "extcmd.h"
|
||||
|
||||
|
||||
/* Takes a file descriptor and makes it non-blocking.
|
||||
*/
|
||||
static int
|
||||
set_nonblock(int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) < 0)
|
||||
{
|
||||
perror("fcntl F_GETFL error:");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
val |= O_NONBLOCK;
|
||||
|
||||
if(fcntl(fd, F_SETFL, val) < 0)
|
||||
{
|
||||
perror("fcntl F_SETFL error setting O_NONBLOCK");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Run en external command returning exit status, and filling provided
|
||||
* buffers with STDOUT an STDERR up to the size provided.
|
||||
*/
|
||||
int
|
||||
run_extcmd(char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
struct timeval tv;
|
||||
fd_set rfds;
|
||||
fd_set efds;
|
||||
int selval;
|
||||
|
||||
int so[2], se[2]; /* For our pipes */
|
||||
|
||||
int bytes_read;
|
||||
|
||||
char so_read_buf[IO_READ_BUF_LEN];
|
||||
char se_read_buf[IO_READ_BUF_LEN];
|
||||
|
||||
/* Set our remaining_buf counters to one less than the given size so we
|
||||
* can leave room for a terminating '\0'.
|
||||
*/
|
||||
int so_buf_remaining = (so_buf_sz > 0) ? so_buf_sz-1 : 0;
|
||||
int se_buf_remaining = (se_buf_sz > 0) ? se_buf_sz-1 : 0;
|
||||
|
||||
/* Be optimistic :)
|
||||
*/
|
||||
int retval = EXTCMD_SUCCESS_ALL_OUTPUT;
|
||||
|
||||
/* Create the pipes we will use for getting stdout and stderr
|
||||
* from the child process.
|
||||
*/
|
||||
pipe(so);
|
||||
pipe(se);
|
||||
|
||||
/* Fork off a child process to run the command and provide its outputs.
|
||||
*/
|
||||
pid = fork();
|
||||
if(pid == -1)
|
||||
{
|
||||
return(EXTCMD_FORK_ERROR);
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/* We are the child, so we dup stdout and stderr to our respective
|
||||
* write-end of the pipes, close stdin and the read-end of the pipes
|
||||
* (since we don't need them here). Then use system() to run the
|
||||
* command and exit with the exit status of that command so we can
|
||||
* grab it from the waitpid call in the parent.
|
||||
*/
|
||||
close(fileno(stdin));
|
||||
dup2(so[1], fileno(stdout));
|
||||
dup2(se[1], fileno(stderr));
|
||||
close(so[0]);
|
||||
close(se[0]);
|
||||
|
||||
/* --DSS XXX: It would be more efficient to use one of the exec()
|
||||
* calls. (i.e. 'return(execvp(ext_cmd, &argv[1]));' ).
|
||||
* but for now, we use system() and exit with the external
|
||||
* command exit status.
|
||||
*/
|
||||
exit(WEXITSTATUS(system(cmd)));
|
||||
}
|
||||
|
||||
/* Parent from here */
|
||||
|
||||
/* Give the exit status an initial value of -1.
|
||||
*/
|
||||
*status = -1;
|
||||
|
||||
/* Close the write-end of the pipes (we are only reading).
|
||||
*/
|
||||
close(so[1]);
|
||||
close(se[1]);
|
||||
|
||||
/* Set our pipes to non-blocking
|
||||
*/
|
||||
set_nonblock(so[0]);
|
||||
set_nonblock(se[0]);
|
||||
|
||||
tv.tv_sec = EXTCMD_DEF_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
/* Initialize and setup our file descriptor sets for select.
|
||||
*/
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&efds);
|
||||
FD_SET(so[0], &rfds);
|
||||
FD_SET(se[0], &rfds);
|
||||
FD_SET(so[0], &efds);
|
||||
FD_SET(se[0], &efds);
|
||||
|
||||
/* Start with fully clear buffers.
|
||||
*/
|
||||
memset(so_buf, 0x0, so_buf_sz);
|
||||
memset(se_buf, 0x0, se_buf_sz);
|
||||
|
||||
/* Read both stdout and stderr piped from the child until we get eof,
|
||||
* fill the buffers, or error out.
|
||||
*/
|
||||
while(so_buf_remaining > 0 || se_buf_remaining > 0)
|
||||
{
|
||||
selval = select(8, &rfds, NULL, &efds, &tv);
|
||||
|
||||
if(selval == -1)
|
||||
{
|
||||
/* Select error - so kill the child and bail.
|
||||
*/
|
||||
kill(pid, SIGTERM);
|
||||
return(EXTCMD_SELECT_ERROR);
|
||||
}
|
||||
|
||||
if(selval == 0)
|
||||
{
|
||||
/* Timeout - so kill the child and bail
|
||||
*/
|
||||
kill(pid, SIGTERM);
|
||||
return(retval | EXTCMD_EXECUTION_TIMEOUT);
|
||||
}
|
||||
|
||||
/* The stdout pipe...
|
||||
*/
|
||||
if(so_buf_remaining > 0)
|
||||
{
|
||||
bytes_read = read(so[0], so_read_buf, IO_READ_BUF_LEN);
|
||||
if(bytes_read > 0)
|
||||
{
|
||||
/* We have data, so process it...
|
||||
*/
|
||||
if(bytes_read > so_buf_remaining)
|
||||
{
|
||||
bytes_read = so_buf_remaining;
|
||||
retval |= EXTCMD_SUCCESS_PARTIAL_STDOUT;
|
||||
}
|
||||
|
||||
memcpy(so_buf, so_read_buf, bytes_read);
|
||||
so_buf += bytes_read;
|
||||
so_buf_remaining -= bytes_read;
|
||||
}
|
||||
else if(bytes_read < 0)
|
||||
{
|
||||
/* Anything other than EAGAIN or EWOULDBLOCK is conisdered
|
||||
* error enough to bail. We are done here so we force the
|
||||
* buf_remaining value to 0.
|
||||
*/
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
retval |= EXTCMD_STDOUT_READ_ERROR;
|
||||
so_buf_remaining = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bytes read was 0 which indicate end of file. So we are
|
||||
* done.
|
||||
*/
|
||||
so_buf_remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* The stderr pipe...
|
||||
*/
|
||||
if(se_buf_remaining > 0)
|
||||
{
|
||||
bytes_read = read(se[0], se_read_buf, IO_READ_BUF_LEN);
|
||||
if(bytes_read > 0)
|
||||
{
|
||||
/* We have data, so process it...
|
||||
*/
|
||||
if(bytes_read > se_buf_remaining)
|
||||
{
|
||||
bytes_read = se_buf_remaining;
|
||||
retval |= EXTCMD_SUCCESS_PARTIAL_STDERR;
|
||||
}
|
||||
|
||||
memcpy(se_buf, se_read_buf, bytes_read);
|
||||
se_buf += bytes_read;
|
||||
se_buf_remaining -= bytes_read;
|
||||
}
|
||||
else if(bytes_read < 0)
|
||||
{
|
||||
/* Anything other than EAGAIN or EWOULDBLOCK is conisdered
|
||||
* error enough to bail. We are done here so we force the
|
||||
* buf_remaining value to 0.
|
||||
*/
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
retval |= EXTCMD_STDERR_READ_ERROR;
|
||||
se_buf_remaining = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bytes read was 0 which indicate end of file. So we are
|
||||
* done.
|
||||
*/
|
||||
se_buf_remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(so[0]);
|
||||
close(se[0]);
|
||||
|
||||
/* Wait for the external command to finish and capture its exit status.
|
||||
*/
|
||||
waitpid(pid, status, 0);
|
||||
|
||||
if(*status != 0)
|
||||
retval != EXTCMD_EXECUTION_ERROR;
|
||||
|
||||
/* Return the our status of this operation command.
|
||||
*/
|
||||
return(retval);
|
||||
}
|
||||
71
server/extcmd.h
Normal file
71
server/extcmd.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* $Id$
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: extcmd.h
|
||||
*
|
||||
* Author: Damien Stuart (dstuart@dstuart.org)
|
||||
*
|
||||
* Purpose: Header file for extcmd.c.
|
||||
*
|
||||
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
|
||||
*
|
||||
* License (GNU Public License):
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef EXTCMD_H
|
||||
#define EXTCMD_H
|
||||
|
||||
#define IO_READ_BUF_LEN 256
|
||||
#define EXTCMD_DEF_TIMEOUT 15
|
||||
|
||||
/* The various return status states in which an external command result
|
||||
* may end up in.
|
||||
*/
|
||||
enum {
|
||||
EXTCMD_SELECT_ERROR = -2,
|
||||
EXTCMD_FORK_ERROR = -1,
|
||||
EXTCMD_SUCCESS_ALL_OUTPUT = 0x00,
|
||||
EXTCMD_SUCCESS_PARTIAL_STDOUT = 0x01,
|
||||
EXTCMD_SUCCESS_PARTIAL_STDERR = 0x02,
|
||||
EXTCMD_STDOUT_READ_ERROR = 0x04,
|
||||
EXTCMD_STDERR_READ_ERROR = 0x08,
|
||||
EXTCMD_EXECUTION_ERROR = 0x10,
|
||||
EXTCMD_EXECUTION_TIMEOUT = 0x20
|
||||
};
|
||||
|
||||
/* Some convenience macros for testing the extcmd return status.
|
||||
*/
|
||||
#define EXTCMD_IS_SUCCESS(x) (x == EXTCMD_SUCCESS_ALL_OUTPUT)
|
||||
#define EXTCMD_IS_SUCCESS_PARTIAL_STDOUT(x) (x && EXTCMD_SUCCESS_PARTIAL_STDOUT)
|
||||
#define EXTCMD_IS_SUCCESS_PARTIAL_STDERR(x) (x && EXTCMD_SUCCESS_PARTIAL_STDERR)
|
||||
#define EXTCMD_IS_SUCCESS_PARTIAL_OUTPUT(x) \
|
||||
((x && EXTCMD_SUCCESS_PARTIAL_STDOUT) \
|
||||
|| x && EXTCMD_SUCCESS_PARTIAL_STDERR)
|
||||
#define EXTCMD_STDOUT_READ_ERROR(x) (x && EXTCMD_STDOUT_READ_ERROR)
|
||||
#define EXTCMD_STDERR_READ_ERROR(x) (x && EXTCMD_STDERR_READ_ERROR)
|
||||
#define EXTCMD_READ_ERROR(x) \
|
||||
((x && EXTCMD_STDOUT_READ_ERROR) \
|
||||
|| x && EXTCMD_STDERR_READ_ERROR)
|
||||
#define EXTCMD_EXECUTION_ERROR(x) (x && EXTCMD_EXECUTION_ERROR)
|
||||
|
||||
#define EXTCMD_NOERROR(x,y) ((y == 0) \
|
||||
&& (EXTCMD_IS_SUCCESS(x) || EXTCMD_IS_SUCCESS_PARTIAL_OUTPUT(x))
|
||||
|
||||
/* Function prototypes
|
||||
*/
|
||||
int run_extcmd(char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status);
|
||||
|
||||
#endif /* EXTCMD_H */
|
||||
|
||||
/***EOF***/
|
||||
384
server/fw_util.c
Normal file
384
server/fw_util.c
Normal file
@ -0,0 +1,384 @@
|
||||
/* $Id$
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: fw_util.c
|
||||
*
|
||||
* Author: Damien S. Stuart
|
||||
*
|
||||
* Purpose: Fwknop routines for managing the firewall rules.
|
||||
*
|
||||
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
|
||||
*
|
||||
* License (GNU Public License):
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fwknopd_common.h"
|
||||
#include "fw_util.h"
|
||||
#include "log_msg.h"
|
||||
#include "config_init.h" /* for the IS_EMPTY_LINE macro */
|
||||
#include "extcmd.h"
|
||||
|
||||
static struct fw_config fwc;
|
||||
|
||||
static void
|
||||
parse_extcmd_error(int retval, int status, char *se_buf)
|
||||
{
|
||||
char errmsg[256];
|
||||
char *emptr = errmsg;
|
||||
|
||||
if(retval < 0)
|
||||
{
|
||||
log_msg(LOG_ERR|LOG_STDERR, "Extcmd fork error: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(emptr, "Extcmd return: %i, command exit status: %i", retval, status);
|
||||
emptr += strlen(emptr);
|
||||
|
||||
if(EXTCMD_EXECUTION_ERROR(retval))
|
||||
{
|
||||
sprintf(errmsg, "Extcmd stderr=%s", se_buf);
|
||||
emptr += strlen(emptr);
|
||||
}
|
||||
|
||||
if(EXTCMD_IS_SUCCESS_PARTIAL_STDOUT(retval))
|
||||
{
|
||||
sprintf(errmsg, "\n - Got partial stdout");
|
||||
emptr += strlen(emptr);
|
||||
}
|
||||
|
||||
if(EXTCMD_IS_SUCCESS_PARTIAL_STDERR(retval))
|
||||
{
|
||||
sprintf(errmsg, "\n - Got partial stderr");
|
||||
emptr += strlen(emptr);
|
||||
}
|
||||
|
||||
if(EXTCMD_STDOUT_READ_ERROR(retval))
|
||||
{
|
||||
sprintf(errmsg, "\n - Got read error on stdout");
|
||||
emptr += strlen(emptr);
|
||||
}
|
||||
|
||||
if(EXTCMD_STDERR_READ_ERROR(retval))
|
||||
{
|
||||
sprintf(errmsg, "\n - Got read error on stderr");
|
||||
emptr += strlen(emptr);
|
||||
}
|
||||
|
||||
log_msg(LOG_WARNING|LOG_STDERR, errmsg);
|
||||
}
|
||||
|
||||
static int
|
||||
jump_rule_exists(int chain_num)
|
||||
{
|
||||
int num, x, pos = 0;
|
||||
char cmd_buf[256];
|
||||
char target[256];
|
||||
char line_buf[256] = {0};
|
||||
FILE *ipt;
|
||||
|
||||
sprintf(cmd_buf, "%s " IPT_LIST_RULES_ARGS,
|
||||
fwc.fw_command,
|
||||
fwc.chain[chain_num].table,
|
||||
fwc.chain[chain_num].from_chain
|
||||
);
|
||||
|
||||
ipt = popen(cmd_buf, "r");
|
||||
|
||||
if(ipt == NULL)
|
||||
{
|
||||
log_msg(LOG_ERR|LOG_STDERR,
|
||||
"Got error %i trying to get rules list.\n", errno);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
while((fgets(line_buf, 255, ipt)) != NULL)
|
||||
{
|
||||
/* Get past comments and empty lines (note: we only look at the
|
||||
* first character.
|
||||
*/
|
||||
if(IS_EMPTY_LINE(line_buf[0]))
|
||||
continue;
|
||||
|
||||
if(sscanf(line_buf, "%i %s ", &num, target) == 2)
|
||||
{
|
||||
//printf("GOT MATCH: '%s' - (pos=%i, target=%s)\n",
|
||||
// line_buf, num, target);
|
||||
|
||||
if(strcmp(target, fwc.chain[chain_num].to_chain) == 0)
|
||||
{
|
||||
pos = num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pclose(ipt);
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
/* Quietly flush and delete all fwknop custom chains.
|
||||
*/
|
||||
static void
|
||||
delete_all_chains(void)
|
||||
{
|
||||
int i, pos, res, status;
|
||||
int jump_rule_num;
|
||||
char cmd_buf[256];
|
||||
char err[256];
|
||||
|
||||
for(i=0; i<(NUM_FWKNOP_CHAIN_TYPES-1); i++)
|
||||
{
|
||||
if(fwc.chain[i].target[0] == '\0')
|
||||
continue;
|
||||
|
||||
/* First look for a jump rule to this chain and remove it if it
|
||||
* is there.
|
||||
*/
|
||||
if((jump_rule_num = jump_rule_exists(i)) > 0)
|
||||
{
|
||||
sprintf(cmd_buf, "%s " IPT_DEL_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
fwc.chain[i].table,
|
||||
fwc.chain[i].from_chain,
|
||||
jump_rule_num
|
||||
);
|
||||
|
||||
//printf("CMD: '%s'\n", cmd_buf);
|
||||
//system(cmd_buf);
|
||||
res = run_extcmd(cmd_buf, NULL, err, 0, 256, &status);
|
||||
/* Expect full success on this */
|
||||
if(! EXTCMD_IS_SUCCESS(res))
|
||||
parse_extcmd_error(res, status, err);
|
||||
}
|
||||
|
||||
/* Now flush and remove the chain.
|
||||
*/
|
||||
sprintf(cmd_buf,
|
||||
"(%s " IPT_FLUSH_CHAIN_ARGS "; %s " IPT_DEL_CHAIN_ARGS ")", // > /dev/null 2>&1",
|
||||
fwc.fw_command,
|
||||
fwc.chain[i].table,
|
||||
fwc.chain[i].to_chain,
|
||||
fwc.fw_command,
|
||||
fwc.chain[i].table,
|
||||
fwc.chain[i].to_chain
|
||||
);
|
||||
|
||||
//printf("CMD: '%s'\n", cmd_buf);
|
||||
//system(cmd_buf);
|
||||
res = run_extcmd(cmd_buf, NULL, err, 0, 256, &status);
|
||||
/* Expect full success on this */
|
||||
if(! EXTCMD_IS_SUCCESS(res))
|
||||
parse_extcmd_error(res, status, err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the fwknop custom chains (at least those that are configured).
|
||||
*/
|
||||
static int
|
||||
create_fw_chains(void)
|
||||
{
|
||||
int i;
|
||||
int res, status, got_err = 0;
|
||||
char cmd_buf[256];
|
||||
char err[256];
|
||||
|
||||
for(i=0; i<(NUM_FWKNOP_CHAIN_TYPES-1); i++)
|
||||
{
|
||||
if(fwc.chain[i].target[0] == '\0')
|
||||
continue;
|
||||
|
||||
/* Create the custom chain.
|
||||
*/
|
||||
sprintf(cmd_buf, "%s " IPT_NEW_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
fwc.chain[i].table,
|
||||
fwc.chain[i].to_chain
|
||||
);
|
||||
|
||||
//printf("CMD: '%s'\n", cmd_buf);
|
||||
//res = system(cmd_buf);
|
||||
res = run_extcmd(cmd_buf, NULL, err, 0, 256, &status);
|
||||
/* Expect full success on this */
|
||||
if(! EXTCMD_IS_SUCCESS(res))
|
||||
{
|
||||
parse_extcmd_error(res, status, err);
|
||||
got_err++;
|
||||
}
|
||||
|
||||
/* Then create the jump rule to that chain.
|
||||
*/
|
||||
sprintf(cmd_buf, "%s " IPT_ADD_JUMP_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
fwc.chain[i].table,
|
||||
fwc.chain[i].from_chain,
|
||||
fwc.chain[i].jump_rule_pos,
|
||||
fwc.chain[i].to_chain
|
||||
);
|
||||
|
||||
//printf("CMD: '%s'\n", cmd_buf);
|
||||
//res = system(cmd_buf);
|
||||
res = run_extcmd(cmd_buf, NULL, err, 0, 256, &status);
|
||||
/* Expect full success on this */
|
||||
if(! EXTCMD_IS_SUCCESS(res))
|
||||
{
|
||||
parse_extcmd_error(res, status, err);
|
||||
got_err++;
|
||||
}
|
||||
}
|
||||
|
||||
return(got_err);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_fw_chain_conf(int type, char *conf_str)
|
||||
{
|
||||
int i, j;
|
||||
char *mark;
|
||||
char tbuf[1024] = {0};
|
||||
char *ndx = conf_str;
|
||||
|
||||
char *chain_fields[FW_NUM_CHAIN_FIELDS];
|
||||
|
||||
struct fw_chain *chain = &(fwc.chain[type]);
|
||||
|
||||
chain->type = type;
|
||||
|
||||
if(ndx != NULL)
|
||||
chain_fields[0] = tbuf;
|
||||
|
||||
i = 0;
|
||||
j = 1;
|
||||
while(*ndx != '\0')
|
||||
{
|
||||
if(*ndx != ' ')
|
||||
{
|
||||
if(*ndx == ',')
|
||||
{
|
||||
tbuf[i] = '\0';
|
||||
chain_fields[j++] = &(tbuf[++i]);
|
||||
}
|
||||
else
|
||||
tbuf[i++] = *ndx;
|
||||
}
|
||||
ndx++;
|
||||
}
|
||||
|
||||
/* Sanity check - j should be the number of chain fields
|
||||
* (excluding the type).
|
||||
*/
|
||||
if(j != FW_NUM_CHAIN_FIELDS)
|
||||
{
|
||||
fprintf(stderr, "[*] Custom Chain config parse error.\n"
|
||||
"Wrong number of fields for chain type %i\n"
|
||||
"Line: %s\n", type, conf_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Pull and set Target */
|
||||
strlcpy(chain->target, chain_fields[0], MAX_TARGET_NAME_LEN);
|
||||
|
||||
/* Pull and set Direction */
|
||||
if(strcmp(chain_fields[1], FW_CHAIN_DIR_SRC_STR) == 0)
|
||||
chain->direction = FW_CHAIN_DIR_SRC;
|
||||
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_DST_STR) == 0)
|
||||
chain->direction = FW_CHAIN_DIR_DST;
|
||||
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_BOTH_STR) == 0)
|
||||
chain->direction = FW_CHAIN_DIR_BOTH;
|
||||
else
|
||||
chain->direction = FW_CHAIN_DIR_UNKNOWN;
|
||||
|
||||
/* Pull and set Table */
|
||||
strlcpy(chain->table, chain_fields[2], MAX_TABLE_NAME_LEN);
|
||||
|
||||
/* Pull and set From_chain */
|
||||
strlcpy(chain->from_chain, chain_fields[3], MAX_CHAIN_NAME_LEN);
|
||||
|
||||
/* Pull and set Jump_rule_position */
|
||||
chain->jump_rule_pos = atoi(chain_fields[4]);
|
||||
|
||||
/* Pull and set To_chain */
|
||||
strlcpy(chain->to_chain, chain_fields[5], MAX_CHAIN_NAME_LEN);
|
||||
|
||||
/* Pull and set Jump_rule_position */
|
||||
chain->rule_pos = atoi(chain_fields[6]);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
fw_initialize(fko_srv_options_t *opts)
|
||||
{
|
||||
int res;
|
||||
|
||||
memset(&fwc, 0x0, sizeof(struct fw_config));
|
||||
|
||||
/* Set our firewall exe command path (iptables in most cases).
|
||||
*/
|
||||
strlcpy(fwc.fw_command, opts->config[CONF_EXE_IPTABLES], MAX_PATH_LEN);
|
||||
|
||||
/* Pull the fwknop chain config info and setup our internal
|
||||
* config struct. The IPT_INPUT is the only one that is
|
||||
* required. The rest are optional.
|
||||
*/
|
||||
if(opts->config[CONF_IPT_INPUT_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_INPUT_ACCESS, opts->config[CONF_IPT_INPUT_ACCESS]);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "The IPT_INPUT_ACCESS chain must be defined in the config file.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(opts->config[CONF_IPT_OUTPUT_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_OUTPUT_ACCESS, opts->config[CONF_IPT_OUTPUT_ACCESS]);
|
||||
|
||||
if(opts->config[CONF_IPT_FORWARD_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_FORWARD_ACCESS, opts->config[CONF_IPT_FORWARD_ACCESS]);
|
||||
|
||||
if(opts->config[CONF_IPT_DNAT_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_DNAT_ACCESS, opts->config[CONF_IPT_DNAT_ACCESS]);
|
||||
|
||||
if(opts->config[CONF_IPT_SNAT_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_SNAT_ACCESS, opts->config[CONF_IPT_SNAT_ACCESS]);
|
||||
|
||||
if(opts->config[CONF_IPT_MASQUERADE_ACCESS] != NULL)
|
||||
set_fw_chain_conf(IPT_MASQUERADE_ACCESS, opts->config[CONF_IPT_MASQUERADE_ACCESS]);
|
||||
|
||||
/* Let us find it via our opts struct as well.
|
||||
*/
|
||||
opts->fw_config = &fwc;
|
||||
|
||||
/* Flush the chains (just in case) so we can start fresh.
|
||||
*/
|
||||
delete_all_chains();
|
||||
|
||||
/* Now create any configured chains.
|
||||
*/
|
||||
res = create_fw_chains();
|
||||
|
||||
if(res != 0)
|
||||
{
|
||||
fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fw_cleanup(void)
|
||||
{
|
||||
delete_all_chains();
|
||||
}
|
||||
|
||||
/***EOF***/
|
||||
36
server/fw_util.h
Normal file
36
server/fw_util.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* $Id$
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: fw_util.h
|
||||
*
|
||||
* Author: Damien Stuart (dstuart@dstuart.org)
|
||||
*
|
||||
* Purpose: Header file for fw_util.c.
|
||||
*
|
||||
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
|
||||
*
|
||||
* License (GNU Public License):
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef FW_UTIL_H
|
||||
#define FW_UTIL_H
|
||||
|
||||
/* Function prototypes
|
||||
*/
|
||||
void fw_initialize(fko_srv_options_t *opts);
|
||||
void fw_cleanup(void);
|
||||
|
||||
#endif /* FW_UTIL_H */
|
||||
|
||||
/***EOF***/
|
||||
@ -238,6 +238,10 @@ main(int argc, char **argv)
|
||||
);
|
||||
}
|
||||
|
||||
/* Initialize the firewall rules handler.
|
||||
*/
|
||||
fw_initialize(&opts);
|
||||
|
||||
/* Intiate pcap capture mode...
|
||||
*/
|
||||
pcap_capture(&opts);
|
||||
@ -287,6 +291,7 @@ main(int argc, char **argv)
|
||||
|
||||
/* Other cleanup.
|
||||
*/
|
||||
fw_cleanup();
|
||||
free_logging();
|
||||
free_configs(&opts);
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ PCAP_INTF eth0;
|
||||
# By default fwknopd puts the pcap interface into promiscuous mode. Set
|
||||
# this to 'N' to disable that behavior (non-promiscuous).
|
||||
#
|
||||
#ENABLE_PCAP_PROMISC N;
|
||||
ENABLE_PCAP_PROMISC Y;
|
||||
|
||||
# Define the filter used for PCAP modes; we default to udp port 62201.
|
||||
# However, if an fwknop client uses the --rand-port option to send the
|
||||
@ -276,22 +276,25 @@ IPT_EXEC_TRIES 1;
|
||||
# "Rule_position": Defines the position where rule are added within the
|
||||
# To_chain.
|
||||
#
|
||||
#IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1;
|
||||
IPT_INPUT_ACCESS ACCEPT, src, filter, INPUT, 1, FWKNOP_INPUT, 1;
|
||||
|
||||
# The IPT_OUTPUT_ACCESS variable is only used if ENABLE_IPT_OUTPUT is enabled
|
||||
#
|
||||
#IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1;
|
||||
IPT_OUTPUT_ACCESS ACCEPT, dst, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1;
|
||||
|
||||
# The IPT_FORWARD_ACCESS variable is only used if ENABLE_IPT_FORWARDING is
|
||||
# enabled.
|
||||
#
|
||||
#IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1;
|
||||
#IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1;
|
||||
IPT_FORWARD_ACCESS ACCEPT, src, filter, FORWARD, 1, FWKNOP_FORWARD, 1;
|
||||
IPT_DNAT_ACCESS DNAT, src, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1;
|
||||
|
||||
# The IPT_SNAT_ACCESS variable is not used unless both ENABLE_IPT_SNAT and
|
||||
# ENABLE_IPT_FORWARDING are enabled. Also, the external static IP must be
|
||||
# set with the SNAT_TRANSLATE_IP variable. The default is to use the
|
||||
# IPT_MASQUERADE_ACCESS variable.
|
||||
#
|
||||
#IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
|
||||
#IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
|
||||
IPT_SNAT_ACCESS SNAT, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
|
||||
IPT_MASQUERADE_ACCESS MASQUERADE, src, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
|
||||
|
||||
# Directories
|
||||
#
|
||||
|
||||
@ -149,12 +149,12 @@ enum {
|
||||
//CONF_EXTERNAL_CMD_ALARM,
|
||||
//CONF_ENABLE_EXT_CMD_PREFIX,
|
||||
//CONF_EXT_CMD_PREFIX,
|
||||
//CONF_IPT_INPUT_ACCESS,
|
||||
//CONF_IPT_OUTPUT_ACCESS,
|
||||
//CONF_IPT_FORWARD_ACCESS,
|
||||
//CONF_IPT_DNAT_ACCESS,
|
||||
//CONF_IPT_SNAT_ACCESS,
|
||||
//CONF_IPT_MASQUERADE_ACCESS,
|
||||
CONF_IPT_INPUT_ACCESS,
|
||||
CONF_IPT_OUTPUT_ACCESS,
|
||||
CONF_IPT_FORWARD_ACCESS,
|
||||
CONF_IPT_DNAT_ACCESS,
|
||||
CONF_IPT_SNAT_ACCESS,
|
||||
CONF_IPT_MASQUERADE_ACCESS,
|
||||
//CONF_FWKNOP_DIR,
|
||||
CONF_FWKNOP_RUN_DIR,
|
||||
//CONF_FWKNOP_MOD_DIR,
|
||||
@ -232,12 +232,12 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
|
||||
//"EXTERNAL_CMD_ALARM",
|
||||
//"ENABLE_EXT_CMD_PREFIX",
|
||||
//"EXT_CMD_PREFIX",
|
||||
//"IPT_INPUT_ACCESS",
|
||||
//"IPT_OUTPUT_ACCESS",
|
||||
//"IPT_FORWARD_ACCESS",
|
||||
//"IPT_DNAT_ACCESS",
|
||||
//"IPT_SNAT_ACCESS",
|
||||
//"IPT_MASQUERADE_ACCESS",
|
||||
"IPT_INPUT_ACCESS",
|
||||
"IPT_OUTPUT_ACCESS",
|
||||
"IPT_FORWARD_ACCESS",
|
||||
"IPT_DNAT_ACCESS",
|
||||
"IPT_SNAT_ACCESS",
|
||||
"IPT_MASQUERADE_ACCESS",
|
||||
//"FWKNOP_DIR",
|
||||
"FWKNOP_RUN_DIR",
|
||||
//"FWKNOP_MOD_DIR",
|
||||
@ -314,6 +314,74 @@ typedef struct acc_stanza
|
||||
struct acc_stanza *next;
|
||||
} acc_stanza_t;
|
||||
|
||||
|
||||
/* Firewall-related data and types. */
|
||||
/* --DSS XXX: These are arbitrary. We should determine appropriate values.
|
||||
*/
|
||||
#define MAX_TABLE_NAME_LEN 16
|
||||
#define MAX_CHAIN_NAME_LEN 32
|
||||
#define MAX_TARGET_NAME_LEN 32
|
||||
|
||||
#define MAX_FW_COMMAND_ARGS_LEN 256
|
||||
|
||||
/* iptables command args
|
||||
*/
|
||||
#define IPT_ADD_RULE_ARGS "-t %s -I %s %i -p %s -s %s -d %s --dport %s -j %s"
|
||||
#define IPT_DEL_RULE_ARGS "-t %s -D %s %i"
|
||||
#define IPT_NEW_CHAIN_ARGS "-t %s -N %s"
|
||||
#define IPT_FLUSH_CHAIN_ARGS "-t %s -F %s"
|
||||
#define IPT_DEL_CHAIN_ARGS "-t %s -X %s"
|
||||
#define IPT_ADD_JUMP_RULE_ARGS "-t %s -I %s %i -j %s"
|
||||
#define IPT_LIST_RULES_ARGS " -t %s -L %s --line-numbers -n"
|
||||
|
||||
/* Fwknop custom chain types
|
||||
*/
|
||||
enum {
|
||||
IPT_INPUT_ACCESS,
|
||||
IPT_OUTPUT_ACCESS,
|
||||
IPT_FORWARD_ACCESS,
|
||||
IPT_DNAT_ACCESS,
|
||||
IPT_SNAT_ACCESS,
|
||||
IPT_MASQUERADE_ACCESS,
|
||||
NUM_FWKNOP_CHAIN_TYPES /* Leave this entry last */
|
||||
};
|
||||
|
||||
#define FW_CHAIN_DIR_SRC_STR "src"
|
||||
#define FW_CHAIN_DIR_DST_STR "dst"
|
||||
#define FW_CHAIN_DIR_BOTH_STR "both"
|
||||
|
||||
/* Fwknop chain directions
|
||||
*/
|
||||
enum {
|
||||
FW_CHAIN_DIR_UNKNOWN,
|
||||
FW_CHAIN_DIR_SRC,
|
||||
FW_CHAIN_DIR_DST,
|
||||
FW_CHAIN_DIR_BOTH
|
||||
};
|
||||
|
||||
/* Structure to define an fwknop firewall chain configuration.
|
||||
*/
|
||||
struct fw_chain {
|
||||
int type;
|
||||
char target[MAX_TARGET_NAME_LEN];
|
||||
int direction;
|
||||
char table[MAX_TABLE_NAME_LEN];
|
||||
char from_chain[MAX_CHAIN_NAME_LEN];
|
||||
int jump_rule_pos;
|
||||
char to_chain[MAX_CHAIN_NAME_LEN];
|
||||
int rule_pos;
|
||||
};
|
||||
|
||||
/* Based on the fw_chain fields (not counting type)
|
||||
*/
|
||||
#define FW_NUM_CHAIN_FIELDS 7
|
||||
|
||||
struct fw_config {
|
||||
struct fw_chain chain[NUM_FWKNOP_CHAIN_TYPES];
|
||||
char fw_command[MAX_PATH_LEN];
|
||||
};
|
||||
|
||||
|
||||
/* SPA Packet info struct.
|
||||
*/
|
||||
typedef struct spa_pkt_info
|
||||
@ -354,7 +422,11 @@ typedef struct fko_srv_options
|
||||
*/
|
||||
char *config[NUMBER_OF_CONFIG_ENTRIES];
|
||||
|
||||
acc_stanza_t *acc_stanzas; /* List of access stanzas */
|
||||
acc_stanza_t *acc_stanzas; /* List of access stanzas */
|
||||
|
||||
/* Firewall config info.
|
||||
*/
|
||||
struct fw_config *fw_config;
|
||||
|
||||
/* Misc
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user