diff --git a/server/extcmd.c b/server/extcmd.c index 0f6330a1..6f81660a 100644 --- a/server/extcmd.c +++ b/server/extcmd.c @@ -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); +} diff --git a/server/extcmd.h b/server/extcmd.h index 54e59143..203de638 100644 --- a/server/extcmd.h +++ b/server/extcmd.h @@ -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***/ diff --git a/server/fw_util_pf.c b/server/fw_util_pf.c index 11410022..402ba9f2 100644 --- a/server/fw_util_pf.c +++ b/server/fw_util_pf.c @@ -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 { diff --git a/server/fw_util_pf.h b/server/fw_util_pf.h index e2a4f7e0..e1c6f093 100644 --- a/server/fw_util_pf.h +++ b/server/fw_util_pf.h @@ -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