[server] command IP,SRC,PKT_SRC,DST,PORT,PROTO substitutions work for open/close cycles now
This commit is contained in:
parent
32b4c5e53f
commit
2b97e8b2e6
@ -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;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "replay_cache.h"
|
||||
#include "config_init.h"
|
||||
#include "fw_util.h"
|
||||
#include "cmd_cycle.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user