367 lines
9.0 KiB
C
367 lines
9.0 KiB
C
/* $Id$
|
|
*****************************************************************************
|
|
*
|
|
* File: fw_util_ipfw.c
|
|
*
|
|
* Author: Damien S. Stuart
|
|
*
|
|
* Purpose: Fwknop routines for managing ipfw 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"
|
|
|
|
#if FIREWALL_IPFW
|
|
|
|
#include "fw_util.h"
|
|
#include "utils.h"
|
|
#include "log_msg.h"
|
|
#include "config_init.h" /* for the IS_EMPTY_LINE macro */
|
|
#include "extcmd.h"
|
|
#include "access.h"
|
|
|
|
static struct fw_config fwc;
|
|
static char cmd_buf[CMD_BUFSIZE];
|
|
static char err_buf[CMD_BUFSIZE];
|
|
static char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
|
|
|
|
unsigned short
|
|
get_next_rule_num(void)
|
|
{
|
|
unsigned short i, next_rule;
|
|
|
|
for(i=0; i < fwc.max_rules; i++)
|
|
{
|
|
if(fwc.rule_map[i] == 0)
|
|
return(fwc.start_rule_num + i);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
void
|
|
zero_cmd_buffers(void)
|
|
{
|
|
memset(cmd_buf, 0x0, CMD_BUFSIZE);
|
|
memset(err_buf, 0x0, CMD_BUFSIZE);
|
|
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
|
|
}
|
|
|
|
/* Print all firewall rules currently instantiated by the running fwknopd
|
|
* daemon to stdout.
|
|
*/
|
|
int
|
|
fw_dump_rules(fko_srv_options_t *opts)
|
|
{
|
|
int res, got_err = 0;
|
|
|
|
zero_cmd_buffers();
|
|
|
|
/* Create the list command for active rules
|
|
*/
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_RULES_ARGS,
|
|
opts->fw_config->fw_command,
|
|
opts->fw_config->active_set_num
|
|
);
|
|
|
|
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
|
|
printf("\nActive Rules:\n");
|
|
res = system(cmd_buf);
|
|
|
|
/* Expect full success on this */
|
|
if(! EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
got_err++;
|
|
}
|
|
|
|
/* Create the list command for expired rules
|
|
*/
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_RULES_ARGS,
|
|
opts->fw_config->fw_command,
|
|
opts->fw_config->expire_set_num
|
|
);
|
|
|
|
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
|
|
printf("\nExpired Rules:\n");
|
|
res = system(cmd_buf);
|
|
|
|
/* Expect full success on this */
|
|
if(! EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
got_err++;
|
|
}
|
|
|
|
return(got_err);
|
|
}
|
|
|
|
void
|
|
fw_config_init(fko_srv_options_t *opts)
|
|
{
|
|
|
|
memset(&fwc, 0x0, sizeof(struct fw_config));
|
|
|
|
/* Set our firewall exe command path (iptables in most cases).
|
|
*/
|
|
strlcpy(fwc.fw_command, opts->config[CONF_FIREWALL_EXE], MAX_PATH_LEN);
|
|
|
|
fwc.start_rule_num = atoi(opts->config[CONF_IPFW_START_RULE_NUM]);
|
|
fwc.max_rules = atoi(opts->config[CONF_IPFW_MAX_RULES]);
|
|
fwc.active_set_num = atoi(opts->config[CONF_IPFW_ACTIVE_SET_NUM]);
|
|
fwc.expire_set_num = atoi(opts->config[CONF_IPFW_EXPIRE_SET_NUM]);
|
|
|
|
/* Let us find it via our opts struct as well.
|
|
*/
|
|
opts->fw_config = &fwc;
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
fw_initialize(fko_srv_options_t *opts)
|
|
{
|
|
int res = 0;
|
|
|
|
/* For now, we just call fw_cleanup to start with clean slate.
|
|
*/
|
|
res = fw_cleanup();
|
|
|
|
if(res != 0)
|
|
{
|
|
fprintf(stderr, "Fatal: Errors detected during ipfw rules initialization.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Allocate our rule_map array for tracking active (and expired) rules.
|
|
*/
|
|
fwc.rule_map = calloc(fwc.max_rules, sizeof(char));
|
|
|
|
if(fwc.rule_map == NULL)
|
|
{
|
|
fprintf(stderr, "Fatal: Memory allocation error in fw_initialize.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Create a check-state rule if necessary.
|
|
*/
|
|
if(strncasecmp(opts->config[CONF_IPFW_ADD_CHECK_STATE], "Y", 1) == 0)
|
|
{
|
|
zero_cmd_buffers();
|
|
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_ADD_CHECK_STATE_ARGS,
|
|
fwc.fw_command,
|
|
fwc.start_rule_num,
|
|
fwc.active_set_num
|
|
);
|
|
|
|
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
|
|
|
if(EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_INFO, "Added check-state rule %u to set %u",
|
|
fwc.start_rule_num,
|
|
fwc.active_set_num
|
|
);
|
|
|
|
(fwc.rule_map)[0] = 1;
|
|
}
|
|
else
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
}
|
|
}
|
|
|
|
int
|
|
fw_cleanup(void)
|
|
{
|
|
int res, got_err = 0;
|
|
|
|
zero_cmd_buffers();
|
|
|
|
if(fwc.active_set_num > 0)
|
|
{
|
|
/* Create the set delete command for active rules
|
|
*/
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DEL_RULE_SET_ARGS,
|
|
fwc.fw_command,
|
|
fwc.active_set_num
|
|
);
|
|
|
|
//printf("CMD: '%s'\n", cmd_buf);
|
|
res = system(cmd_buf);
|
|
|
|
/* Expect full success on this */
|
|
if(! EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
got_err++;
|
|
}
|
|
}
|
|
|
|
if(fwc.expire_set_num > 0)
|
|
{
|
|
/* Create the set delete command for active rules
|
|
*/
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DEL_RULE_SET_ARGS,
|
|
fwc.fw_command,
|
|
fwc.expire_set_num
|
|
);
|
|
|
|
//printf("CMD: '%s'\n", cmd_buf);
|
|
res = system(cmd_buf);
|
|
|
|
/* Expect full success on this */
|
|
if(! EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
got_err++;
|
|
}
|
|
}
|
|
|
|
/* Free the rule map.
|
|
*/
|
|
free(fwc.rule_map);
|
|
|
|
return(got_err);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Rule Processing - Create an access request...
|
|
*/
|
|
int
|
|
process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
|
|
{
|
|
/* TODO: Implement me */
|
|
|
|
char nat_ip[16] = {0};
|
|
char *ndx;
|
|
|
|
unsigned short rule_num;
|
|
|
|
acc_port_list_t *port_list = NULL;
|
|
acc_port_list_t *ple;
|
|
|
|
unsigned int fst_proto;
|
|
unsigned int fst_port;
|
|
|
|
int res = 0;
|
|
time_t now;
|
|
unsigned int exp_ts;
|
|
|
|
/* Parse and expand our access message.
|
|
*/
|
|
expand_acc_port_list(&port_list, spadat->spa_message_remain);
|
|
|
|
/* Start at the top of the proto-port list...
|
|
*/
|
|
ple = port_list;
|
|
|
|
/* Remember the first proto/port combo in case we need them
|
|
* for NAT access requests.
|
|
*/
|
|
fst_proto = ple->proto;
|
|
fst_port = ple->port;
|
|
|
|
/* Set our expire time value.
|
|
*/
|
|
time(&now);
|
|
exp_ts = now + spadat->fw_access_timeout;
|
|
|
|
/* For straight access requests, we currently support multiple proto/port
|
|
* request.
|
|
*/
|
|
if(spadat->message_type == FKO_ACCESS_MSG
|
|
|| spadat->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG)
|
|
{
|
|
rule_num = get_next_rule_num();
|
|
|
|
/* Create an access command for each proto/port for the source ip.
|
|
*/
|
|
while(ple != NULL)
|
|
{
|
|
zero_cmd_buffers();
|
|
|
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_ADD_RULE_ARGS,
|
|
fwc.fw_command,
|
|
rule_num,
|
|
fwc.active_set_num,
|
|
ple->proto,
|
|
spadat->use_src_ip,
|
|
ple->port,
|
|
exp_ts
|
|
);
|
|
|
|
//--DSS tmp
|
|
//fprintf(stderr, "ADD CMD: %s\n", cmd_buf);
|
|
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
|
if(EXTCMD_IS_SUCCESS(res))
|
|
{
|
|
log_msg(LOG_INFO, "Added Rule %u for %s, %s expires at %u",
|
|
rule_num,
|
|
spadat->use_src_ip,
|
|
spadat->spa_message_remain, exp_ts
|
|
);
|
|
|
|
(fwc.rule_map)[fwc.start_rule_num + rule_num] = 1;
|
|
|
|
/* Reset the next expected expire time for this chain if it
|
|
* is warranted.
|
|
*/
|
|
if(fwc.next_expire < now || exp_ts < fwc.next_expire)
|
|
fwc.next_expire = exp_ts;
|
|
}
|
|
else
|
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
|
|
ple = ple->next;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* No other modes supported yet.
|
|
*/
|
|
return(-1);
|
|
}
|
|
|
|
return(res);
|
|
}
|
|
|
|
/* Iterate over the current rule set and purge expired
|
|
* firewall rules.
|
|
*/
|
|
void
|
|
check_firewall_rules(fko_srv_options_t *opts)
|
|
{
|
|
char exp_str[12];
|
|
char rule_num_str[6];
|
|
char *ndx, *rn_start, *rn_end, *tmp_mark;
|
|
|
|
int i, res, rn_offset;
|
|
time_t now, rule_exp, min_exp = 0;
|
|
|
|
time(&now);
|
|
|
|
zero_cmd_buffers();
|
|
|
|
}
|
|
|
|
#endif /* FIREWALL_IPFW */
|
|
|
|
/***EOF***/
|