[server] first pass at eliminating popen() write calls with run_extcmd_write() (used for PF firewalls)

This commit is contained in:
Michael Rash
2014-10-28 21:28:21 -04:00
parent b5fe62bfc7
commit 34e38fe39e
4 changed files with 113 additions and 29 deletions
+97 -3
View File
@@ -96,7 +96,7 @@ _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
pid_t pid=0;
FILE *output;
int retval = 0;
int retval = EXTCMD_SUCCESS_ALL_OUTPUT;
int line_ctr = 0, found_str = 0;
*pid_status = 0;
@@ -252,7 +252,7 @@ _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
/* Retval is forced to 0 as we don't care about the exit status of
* the child (for now)
*/
retval = 0;
retval = EXTCMD_SUCCESS_ALL_OUTPUT;
}
else
{
@@ -262,13 +262,14 @@ _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
if(output == NULL)
{
log_msg(LOG_ERR, "Got popen error %i: %s", errno, strerror(errno));
retval = -1;
retval = EXTCMD_OPEN_ERROR;
}
else
{
memset(so_buf, 0x0, so_buf_sz);
while((fgets(so_read_buf, IO_READ_BUF_LEN, output)) != NULL)
{
line_ctr++;
if(so_buf != NULL)
{
strlcat(so_buf, so_read_buf, so_buf_sz);
@@ -539,6 +540,91 @@ _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
}
#endif
int _run_extcmd_write(const char *cmd, const char *cmd_write, int *pid_status,
const fko_srv_options_t * const opts)
{
int retval = EXTCMD_SUCCESS_ALL_OUTPUT;
#if HAVE_EXECVPE
char *argv_new[MAX_CMDLINE_ARGS]; /* for execvpe() */
int argc_new=0;
int pipe_fd[2];
pid_t pid=0;
#else
FILE *fd = NULL;
#endif
*pid_status = 0;
#if HAVE_EXECVPE
if(opts->verbose > 1)
log_msg(LOG_INFO, "run_extcmd_write() (with execvpe()): running CMD: %s", cmd);
memset(argv_new, 0x0, sizeof(argv_new));
if(strtoargv(cmd, argv_new, &argc_new, opts) != 1)
{
log_msg(LOG_ERR,
"run_extcmd_write(): Error converting cmd str to argv via strtoargv()");
return EXTCMD_ARGV_ERROR;
}
if(pipe(pipe_fd) < 0)
{
log_msg(LOG_ERR, "run_extcmd_write(): pipe() failed: %s", strerror(errno));
free_argv(argv_new, &argc_new);
return EXTCMD_PIPE_ERROR;
}
pid = fork();
if (pid == 0)
{
if(chdir("/") != 0)
exit(EXTCMD_CHDIR_ERROR);
close(pipe_fd[1]);
dup2(pipe_fd[0], STDIN_FILENO);
/* don't use env
*/
execvpe(argv_new[0], argv_new, (char * const *)NULL);
}
else if(pid == -1)
{
log_msg(LOG_ERR, "run_extcmd_write(): fork() failed: %s", strerror(errno));
free_argv(argv_new, &argc_new);
return EXTCMD_FORK_ERROR;
}
close(pipe_fd[0]);
if(write(pipe_fd[1], cmd_write, strlen(cmd_write)) < 0)
retval = EXTCMD_WRITE_ERROR;
free_argv(argv_new, &argc_new);
waitpid(pid, pid_status, 0);
#else
if ((fd = popen(cmd, "w")) == NULL)
{
log_msg(LOG_ERR, "Got popen error %i: %s", errno, strerror(errno));
retval = EXTCMD_OPEN_ERROR;
}
else
{
if (fwrite(cmd_write, strlen(cmd_write), 1, fd) != 1)
{
log_msg(LOG_ERR, "Could not write to cmd stdin");
retval = -1;
}
pclose(fd);
}
#endif
return retval;
}
/* _run_extcmd() wrapper, run an external command.
*/
int
@@ -571,3 +657,11 @@ search_extcmd(const char *cmd, const int want_stderr, const int timeout,
return _run_extcmd(0, 0, cmd, NULL, 0, want_stderr, timeout,
substr_search, pid_status, opts);
}
/* _run_extcmd_write() wrapper, run a command which is expecting input via stdin
*/
int run_extcmd_write(const char *cmd, const char *cmd_write, int *pid_status,
const fko_srv_options_t * const opts)
{
return _run_extcmd_write(cmd, cmd_write, pid_status, opts);
}
+3 -1
View File
@@ -41,6 +41,7 @@
* may end up in.
*/
enum {
EXTCMD_WRITE_ERROR = -9,
EXTCMD_CHDIR_ERROR = -8,
EXTCMD_OPEN_ERROR = -7,
EXTCMD_ARGV_ERROR = -6,
@@ -87,7 +88,8 @@ int run_extcmd_as(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
int search_extcmd(const char *cmd, const int want_stderr,
const int timeout, const char *substr_search,
int *pid_status, const fko_srv_options_t * const opts);
int run_extcmd_write(const char *cmd, const char *cmd_write, int *pid_status,
const fko_srv_options_t * const opts);
#endif /* EXTCMD_H */
/***EOF***/
+11 -23
View File
@@ -94,7 +94,7 @@ fw_dump_rules(const fko_srv_options_t * const opts)
static int
anchor_active(const fko_srv_options_t *opts)
{
int res = 0, pid_status = 0;
int pid_status = 0;
char anchor_search_str[MAX_PF_ANCHOR_SEARCH_LEN] = {0};
/* Build our anchor search string
@@ -113,6 +113,7 @@ anchor_active(const fko_srv_options_t *opts)
if(search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT,
anchor_search_str, &pid_status, opts) > 0)
return 1;
return 0;
}
@@ -194,8 +195,6 @@ process_spa_request(const fko_srv_options_t * const opts,
char new_rule[MAX_PF_NEW_RULE_LEN] = {0};
char write_cmd[CMD_BUFSIZE] = {0};
FILE *pfctl_fd = NULL;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
@@ -261,15 +260,9 @@ process_spa_request(const fko_srv_options_t * const opts,
opts->fw_config->anchor
);
if ((pfctl_fd = popen(write_cmd, "w")) == NULL)
{
log_msg(LOG_WARNING, "Could not execute command: %s",
write_cmd);
free_acc_port_list(port_list);
return(-1);
}
res = run_extcmd_write(write_cmd, cmd_out, &pid_status, opts);
if (fwrite(cmd_out, strlen(cmd_out), 1, pfctl_fd) == 1)
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Rule for %s, %s expires at %u",
spadat->use_src_ip,
@@ -286,9 +279,11 @@ process_spa_request(const fko_srv_options_t * const opts,
fwc.next_expire = exp_ts;
}
else
{
log_msg(LOG_WARNING, "Could not write rule to pf anchor");
pclose(pfctl_fd);
free_acc_port_list(port_list);
return(-1);
}
}
else
{
@@ -345,8 +340,6 @@ check_firewall_rules(const fko_srv_options_t * const opts)
time_t now, rule_exp, min_exp=0;
int i=0, res=0, anchor_ndx=0, is_delete=0, pid_status=0;
FILE *pfctl_fd = NULL;
/* If we have not yet reached our expected next expire
time, continue.
*/
@@ -504,18 +497,13 @@ check_firewall_rules(const fko_srv_options_t * const opts)
opts->fw_config->anchor
);
if ((pfctl_fd = popen(write_cmd, "w")) == NULL)
res = run_extcmd_write(write_cmd, anchor_rules_copy, &pid_status, opts);
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_WARNING, "Could not execute command: %s",
write_cmd);
write_cmd);
return;
}
if (fwrite(anchor_rules_copy, strlen(anchor_rules_copy), 1, pfctl_fd) != 1)
{
log_msg(LOG_WARNING, "Could not write rules to pf anchor");
}
pclose(pfctl_fd);
}
else
{
+2 -2
View File
@@ -45,9 +45,9 @@
#define PF_ADD_RULE_ARGS "pass in quick proto %u from %s to any port %u keep state label " EXPIRE_COMMENT_PREFIX "%u"
#define PF_WRITE_ANCHOR_RULES_ARGS "-a %s -f -"
#if HAVE_EXECVPE
#define PF_LIST_ANCHOR_RULES_ARGS "-a %s -s rules 2> /dev/null"
#else
#define PF_LIST_ANCHOR_RULES_ARGS "-a %s -s rules"
#else
#define PF_LIST_ANCHOR_RULES_ARGS "-a %s -s rules 2> /dev/null"
#endif
#define PF_ANCHOR_CHECK_ARGS "-s Anchor" SH_REDIR /* to check for fwknop anchor */
#define PF_DEL_ALL_ANCHOR_RULES "-a %s -F all" SH_REDIR