[server] command IP,SRC,PKT_SRC,DST,PORT,PROTO substitutions work for open/close cycles now

This commit is contained in:
Michael Rash 2015-10-17 06:30:33 -07:00
parent 32b4c5e53f
commit 2b97e8b2e6
3 changed files with 199 additions and 46 deletions

View File

@ -31,6 +31,7 @@
#include "log_msg.h"
#include "extcmd.h"
#include "cmd_cycle.h"
#include "access.h"
static char cmd_buf[CMD_CYCLE_BUFSIZE];
static char err_buf[CMD_CYCLE_BUFSIZE];
@ -46,45 +47,165 @@ zero_cmd_buffers(void)
static int pid_status = 0;
static int
do_var_subs(const char * const str)
is_var(const char * const var, const char * const cmd_str)
{
int i;
/* Look for a '$' char
*/
if (str != NULL && str[0] != 0x0)
for(i=0; i < strlen(var); i++)
{
for (i=0; i<strlen(str); i++)
{
if(str[i] == '$')
if(cmd_str[i] != var[i])
return 0;
}
return 1;
i++;
}
}
static int
build_cmd(spa_data_t *spadat, const char * const cmd_cycle_str)
{
char port_str[MAX_PORT_STR_LEN+1] = {0};
char proto_str[MAX_PROTO_STR_LEN+1] = {0};
acc_port_list_t *port_list = NULL;
int i=0, buf_idx=0;
if(expand_acc_port_list(&port_list, spadat->spa_message_remain) != 1)
{
free_acc_port_list(port_list);
return 0;
}
int
cmd_cycle_open(fko_srv_options_t *opts, acc_stanza_t *acc,
spa_data_t *spadat, const int stanza_num, int *res)
{
cmd_cycle_list_t *last_clist=NULL, *new_clist=NULL, *tmp_clist=NULL;
time_t now;
char *open_cmd=NULL, *close_cmd=NULL;
/* We only look at the first port/proto combination for command
* open/close cycles even if the SPA message had multiple ports
* and protocols set.
*/
snprintf(port_str, MAX_PORT_STR_LEN+1, "%d", port_list->port);
snprintf(proto_str, MAX_PROTO_STR_LEN+1, "%d", port_list->proto);
if(opts->test)
zero_cmd_buffers();
/* Look for the following variables for substitution:
* IP, SRC, PKT_SRC, DST, PORT, and PROTO
*/
for(i=0; i < strnlen(cmd_cycle_str, CMD_CYCLE_BUFSIZE); i++)
{
log_msg(LOG_WARNING,
"[%s] (stanza #%d) --test mode enabled, skipping CMD_CYCLE_OPEN execution.",
if(cmd_cycle_str[i] == '$')
{
/* Found the start of a variable, now validate it and
* swap in the IP/port/proto.
*/
if(is_var("IP", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, spadat->use_src_ip,
CMD_CYCLE_BUFSIZE);
i += strlen("IP");
buf_idx += strlen(spadat->use_src_ip);
}
/* SRC is a synonym for IP
*/
else if(is_var("SRC", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, spadat->use_src_ip,
CMD_CYCLE_BUFSIZE);
i += strlen("SRC");
buf_idx += strlen(spadat->use_src_ip);
}
/* Special case for the SPA packet source IP in
* the IP header (i.e. not from the decrypted SPA
* payload) if the user really wants this.
*/
else if(is_var("PKT_SRC", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, spadat->pkt_source_ip,
CMD_CYCLE_BUFSIZE);
i += strlen("PKT_SRC");
buf_idx += strlen(spadat->pkt_source_ip);
}
else if(is_var("DST", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, spadat->pkt_destination_ip,
CMD_CYCLE_BUFSIZE);
i += strlen("DST");
buf_idx += strlen(spadat->pkt_destination_ip);
}
else if (is_var("PORT", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, port_str, CMD_CYCLE_BUFSIZE);
i += strlen("PORT");
buf_idx += strlen(port_str);
}
else if (is_var("PROTO", (cmd_cycle_str+i+1)))
{
strlcat(cmd_buf, proto_str, CMD_CYCLE_BUFSIZE);
i += strlen("PROTO");
buf_idx += strlen(proto_str);
}
continue;
}
cmd_buf[buf_idx++] = cmd_cycle_str[i];
if(buf_idx == CMD_CYCLE_BUFSIZE)
{
free_acc_port_list(port_list);
return 0;
}
}
free_acc_port_list(port_list);
return 1;
}
static int
cmd_open(fko_srv_options_t *opts, acc_stanza_t *acc,
spa_data_t *spadat, const int stanza_num)
{
/* CMD_CYCLE_OPEN: Build the open command by taking care of variable
* substitutions if necessary.
*/
if(build_cmd(spadat, acc->cmd_cycle_open))
{
log_msg(LOG_INFO, "[%s] (stanza #%d) Running CMD_CYCLE_OPEN command: %s",
spadat->pkt_source_ip, stanza_num, cmd_buf);
/* Run the open command
*/
run_extcmd(cmd_buf, err_buf, CMD_CYCLE_BUFSIZE,
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
}
else
{
log_msg(LOG_ERR,
"[%s] (stanza #%d) Could not build CMD_CYCLE_OPEN command.",
spadat->pkt_source_ip, stanza_num
);
return 0;
}
return 1;
}
log_msg(LOG_INFO, "[%s] (stanza #%d) CMD_CYCLE_OPEN: %s",
spadat->pkt_source_ip, stanza_num, acc->cmd_cycle_open);
log_msg(LOG_INFO, "[%s] (stanza #%d) expected CMD_CYCLE_CLOSE: %s",
spadat->pkt_source_ip, stanza_num, acc->cmd_cycle_close);
static int
add_cmd_close(fko_srv_options_t *opts, acc_stanza_t *acc,
spa_data_t *spadat, const int stanza_num)
{
cmd_cycle_list_t *last_clist=NULL, *new_clist=NULL, *tmp_clist=NULL;
time_t now;
int cmd_close_len = 0;
/* CMD_CYCLE_CLOSE: Build the close command, but don't execute it until
* the expiration timer has passed.
*/
if(build_cmd(spadat, acc->cmd_cycle_close))
{
/* Now the corresponding close command is now in cmd_buf
*/
cmd_close_len = strnlen(cmd_buf, CMD_CYCLE_BUFSIZE-1);
log_msg(LOG_INFO, "[%s] (stanza #%d) Running CMD_CYCLE_CLOSE command in %d seconds: %s",
spadat->pkt_source_ip, stanza_num, acc->cmd_cycle_timer, cmd_buf);
}
else
{
log_msg(LOG_ERR,
"[%s] (stanza #%d) Could not build CMD_CYCLE_CLOSE command.",
spadat->pkt_source_ip, stanza_num
);
return 0;
}
/* Add the corresponding close command - to be executed after the
* designated timer has expired.
@ -94,7 +215,7 @@ cmd_cycle_open(fko_srv_options_t *opts, acc_stanza_t *acc,
log_msg(LOG_ERR,
"[*] Fatal memory allocation error creating string list entry"
);
return 0; // FIXME: handle this
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
}
if(opts->cmd_cycle_list == NULL)
@ -112,36 +233,51 @@ cmd_cycle_open(fko_srv_options_t *opts, acc_stanza_t *acc,
last_clist->next = new_clist;
}
/* Set the source IP, expiration timer, and close command
/* Set the source IP
*/
strlcpy(new_clist->src_ip, spadat->pkt_source_ip,
strlcpy(new_clist->src_ip, spadat->use_src_ip,
sizeof(new_clist->src_ip));
/* Set the expiration timer
*/
time(&now);
new_clist->expire = now + acc->cmd_cycle_timer;
/* Now, execute the open command
/* Set the close command
*/
if(do_var_subs(acc->cmd_cycle_open))
if((new_clist->close_cmd = calloc(1, cmd_close_len)) == NULL)
{
log_msg(LOG_ERR,
"[*] Fatal memory allocation error creating command close string"
);
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
}
else
{
/* Run the open command as-is
strlcpy(new_clist->close_cmd, cmd_buf, cmd_close_len);
/* Set the access.conf stanza number
*/
open_cmd = acc->cmd_cycle_open;
new_clist->stanza_num = stanza_num;
return 1;
}
zero_cmd_buffers();
/* This is the main driver for open/close command cycles
*/
int
cmd_cycle_open(fko_srv_options_t *opts, acc_stanza_t *acc,
spa_data_t *spadat, const int stanza_num, int *res)
{
if(! cmd_open(opts, acc, spadat, stanza_num))
return 0;
snprintf(cmd_buf, CMD_CYCLE_BUFSIZE-1, "%s", open_cmd);
run_extcmd(cmd_buf, err_buf, CMD_CYCLE_BUFSIZE,
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
if(! add_cmd_close(opts, acc, spadat, stanza_num))
return 0;
return FKO_SUCCESS;
}
/* Run all close commands based on the expiration timer
*/
void
cmd_cycle_close(fko_srv_options_t *opts)
{
@ -160,11 +296,13 @@ cmd_cycle_close(fko_srv_options_t *opts)
{
tmp_clist = opts->cmd_cycle_list;
do {
log_msg(LOG_INFO, "close command for src IP: %s", tmp_clist->src_ip);
if(tmp_clist->expire <= now)
{
log_msg(LOG_INFO,
"[%s] (stanza #%d) Timer expired, running CMD_CYCLE_CLOSE command: %s",
tmp_clist->src_ip, tmp_clist->stanza_num,
tmp_clist->close_cmd);
// FIXME: must remove this element from the list
log_msg(LOG_INFO, "EXPIRED!", tmp_clist->src_ip);
}
} while((tmp_clist = tmp_clist->next));
}
@ -182,6 +320,7 @@ free_cmd_cycle_list(fko_srv_options_t *opts)
while(clist != NULL)
{
tmp_clist = clist->next;
free(clist->close_cmd);
free(clist);
clist = tmp_clist;
}

View File

@ -1177,9 +1177,22 @@ incoming_spa(fko_srv_options_t *opts)
continue;
}
else
{
if(acc->cmd_cycle_open != NULL)
{
if(cmd_cycle_open(opts, acc, &spadat, stanza_num, &res))
break; /* successfully processed a matching access stanza */
else
{
acc = acc->next;
continue;
}
}
else
{
process_spa_request(opts, acc, &spadat);
}
}
/* If we made it here, then the SPA packet was processed according
* to a matching access.conf stanza, so we're done with this packet.

View File

@ -31,6 +31,7 @@
#include "replay_cache.h"
#include "config_init.h"
#include "fw_util.h"
#include "cmd_cycle.h"
#include <stdarg.h>