diff --git a/server/extcmd.c b/server/extcmd.c index ef040daf..377fda87 100644 --- a/server/extcmd.c +++ b/server/extcmd.c @@ -82,33 +82,31 @@ alarm_handler(int sig) */ static int _run_extcmd(uid_t user_uid, const char *cmd, char *so_buf, const size_t so_buf_sz, - const int timeout, const fko_srv_options_t * const opts) + const int timeout, const char *substr_search, const fko_srv_options_t * const opts) { - FILE *ipt; - int retval = 0; char so_read_buf[IO_READ_BUF_LEN] = {0}; - int res; - char *argv_new[MAX_CMDLINE_ARGS]; /* for execvpe() */ int argc_new=0; int pipe_fd[2]; pid_t pid=0; FILE *output; - int status; + int retval = 0, status; + int line_ctr = 0, found_str = 0; memset(argv_new, 0x0, sizeof(argv_new)); if(strtoargv(cmd, argv_new, &argc_new, opts) != 1) { - log_msg(LOG_ERR, "Error converting cmd str to argv"); + log_msg(LOG_ERR, + "run_extcmd: Error converting cmd str to argv via strtoargv()"); return(-1); } - if(so_buf != NULL) + if(so_buf != NULL || substr_search != NULL) { if(pipe(pipe_fd) < 0) { - log_msg(LOG_ERR, "[*] pipe() error"); + log_msg(LOG_ERR, "run_extcmd: pipe() failed: %s", strerror(errno)); free_argv(argv_new, &argc_new); return -1; } @@ -117,119 +115,98 @@ _run_extcmd(uid_t user_uid, const char *cmd, char *so_buf, const size_t so_buf_s pid = fork(); if (pid == 0) { - if(so_buf != NULL) + if(so_buf != NULL || substr_search != NULL) { close(pipe_fd[0]); dup2(pipe_fd[1], STDOUT_FILENO); dup2(pipe_fd[1], STDERR_FILENO); } + /* If user is not null, then we setuid to that user before running the + * command. + */ +#if 0 + if(user_uid > 0) + { + if(setuid(user_uid) < 0) + { + exit(EXTCMD_SETUID_ERROR); + } + } +#endif + /* don't use env */ execvpe(argv_new[0], argv_new, (char * const *)NULL); } else if(pid == -1) { - log_msg(LOG_ERR, "[*] Could not fork() for cmd."); + log_msg(LOG_ERR, "run_extcmd: fork() failed: %s", strerror(errno)); free_argv(argv_new, &argc_new); return -1; } /* Only the parent process makes it here */ - if(so_buf != NULL) + if(so_buf != NULL || substr_search != NULL) { close(pipe_fd[1]); if ((output = fdopen(pipe_fd[0], "r")) != NULL) { - memset(so_buf, 0x0, so_buf_sz); + if(so_buf != NULL) + memset(so_buf, 0x0, so_buf_sz); while((fgets(so_read_buf, IO_READ_BUF_LEN, output)) != NULL) { - strlcat(so_buf, so_read_buf, so_buf_sz); + line_ctr++; - if(strlen(so_buf) >= so_buf_sz-1) - break; + if(so_buf != NULL) + { + strlcat(so_buf, so_read_buf, so_buf_sz); + + if(strlen(so_buf) >= so_buf_sz-1) + break; + } + else /* we are looking for a substring */ + { + /* Get past comments and empty lines (note: we only look at the + * first character). + */ + if(IS_EMPTY_LINE(so_read_buf[0])) + continue; + + if(strstr(so_read_buf, substr_search) != NULL) + { + found_str = 1; + break; + } + } } fclose(output); } else { log_msg(LOG_ERR, - "[*] Could not fdopen() pipe output file descriptor."); + "run_extcmd: could not fdopen() pipe output file descriptor."); free_argv(argv_new, &argc_new); return -1; } } - waitpid(pid, &status, 0); - free_argv(argv_new, &argc_new); - return(retval); + waitpid(pid, &status, 0); - - - if(so_buf == NULL) + if(substr_search != NULL) { - - /* Since we do not have to capture output, we will fork here (which we - * would have to do anyway if we are running as another user as well). - */ - pid = fork(); - if(pid == -1) - { - log_msg(LOG_ERR, "run_extcmd: fork failed: %s", strerror(errno)); - return(EXTCMD_FORK_ERROR); - } - else if (pid == 0) - { - /* We are the child */ - /* If user is not null, then we setuid to that user before running the - * command. - */ - if(user_uid > 0) - { - if(setuid(user_uid) < 0) - { - exit(EXTCMD_SETUID_ERROR); - } - } - res = system(cmd); - exit(WEXITSTATUS(res)); - } - - /* Retval is forced to 0 as we don't care about the exit status of - * the child (for now)> - */ - retval = 0; + if(found_str) + retval = line_ctr; + else + retval = 0; } else - { - /* Looking for output use popen and fill the buffer to its limit. - */ - ipt = popen(cmd, "r"); - - if(ipt == NULL) - { - log_msg(LOG_ERR, "Got popen error %i: %s", errno, strerror(errno)); - retval = -1; - } - else - { - memset(so_buf, 0x0, so_buf_sz); - - while((fgets(so_read_buf, IO_READ_BUF_LEN, ipt)) != NULL) - { - strlcat(so_buf, so_read_buf, so_buf_sz); - - if(strlen(so_buf) >= so_buf_sz-1) - break; - } - - pclose(ipt); - } - } + //retval = status; + retval = 0; return(retval); } @@ -445,20 +422,29 @@ _run_extcmd(uid_t user_uid, const char *cmd, char *so_buf, const size_t so_buf_s } #endif -/* Run an external command. This is wrapper around _run_extcmd() +/* _run_extcmd() wrapper, run an external command. */ int run_extcmd(const char *cmd, char *so_buf, const size_t so_buf_sz, const int timeout, const fko_srv_options_t * const opts) { - return _run_extcmd(0, cmd, so_buf, so_buf_sz, timeout, opts); + return _run_extcmd(0, cmd, so_buf, so_buf_sz, timeout, NULL, opts); } -/* Run an external command as the specified user. This is wrapper around _run_extcmd() +/* _run_extcmd() wrapper, run an external command as the specified user. */ int run_extcmd_as(uid_t user_uid, const char *cmd,char *so_buf, const size_t so_buf_sz, const int timeout, const fko_srv_options_t * const opts) { - return _run_extcmd(user_uid, cmd, so_buf, so_buf_sz, timeout, opts); + return _run_extcmd(user_uid, cmd, so_buf, so_buf_sz, timeout, NULL, opts); +} + +/* _run_extcmd() wrapper, search command output for a substring. +*/ +int +search_extcmd(const char *cmd, const int timeout, const char *substr_search, + const fko_srv_options_t * const opts) +{ + return _run_extcmd(0, cmd, NULL, 0, timeout, substr_search, opts); } diff --git a/server/extcmd.h b/server/extcmd.h index 56291610..13058d1f 100644 --- a/server/extcmd.h +++ b/server/extcmd.h @@ -75,6 +75,8 @@ int run_extcmd(const char *cmd, char *so_buf, const size_t so_buf_sz, const int timeout, const fko_srv_options_t * const opts); int run_extcmd_as(uid_t uid, const char *cmd, char *so_buf, const size_t so_buf_sz, const int timeout, const fko_srv_options_t * const opts); +int search_extcmd(const char *cmd, const int timeout, const char *substr_search, + const fko_srv_options_t * const opts); #endif /* EXTCMD_H */ diff --git a/server/fw_util_iptables.c b/server/fw_util_iptables.c index 1d8780e8..70c4cdd7 100644 --- a/server/fw_util_iptables.c +++ b/server/fw_util_iptables.c @@ -420,46 +420,19 @@ jump_rule_exists_no_chk_support(const fko_srv_options_t * const opts, const int int exists = 0; char cmd_buf[CMD_BUFSIZE] = {0}; char chain_search[CMD_BUFSIZE] = {0}; - char line_buf[CMD_BUFSIZE] = {0}; - FILE *ipt; - snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS " 2>&1", + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS, fwc.fw_command, fwc.chain[chain_num].table, fwc.chain[chain_num].from_chain ); - ipt = popen(cmd_buf, "r"); - - if(ipt == NULL) - { - log_msg(LOG_ERR, - "Got error %i trying to get rules list.\n", errno); - return(exists); - } - /* include spaces on either side as produced by 'iptables -L' output */ snprintf(chain_search, CMD_BUFSIZE-1, " %s ", fwc.chain[chain_num].to_chain); - while((fgets(line_buf, CMD_BUFSIZE-1, ipt)) != NULL) - { - /* Get past comments and empty lines (note: we only look at the - * first character). - */ - if(IS_EMPTY_LINE(line_buf[0])) - continue; - - if(strstr(line_buf, chain_search) != NULL) - { - exists = 1; - break; - } - } - - pclose(ipt); - + exists = search_extcmd(cmd_buf, 0, chain_search, opts); if(exists) log_msg(LOG_DEBUG, "jump_rule_exists_no_chk_support() jump rule found"); @@ -612,10 +585,26 @@ delete_all_chains(const fko_srv_options_t * const opts) /* Now flush and remove the chain. */ snprintf(cmd_buf, CMD_BUFSIZE-1, - "(%s " IPT_FLUSH_CHAIN_ARGS "; %s " IPT_DEL_CHAIN_ARGS ")", // > /dev/null 2>&1", + "%s " IPT_FLUSH_CHAIN_ARGS, fwc.fw_command, fwc.chain[i].table, - fwc.chain[i].to_chain, + fwc.chain[i].to_chain + ); + + res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0, opts); + chop_newline(err_buf); + + log_msg(LOG_DEBUG, "delete_all_chains() CMD: '%s' (res: %d, err: %s)", + cmd_buf, res, err_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); + + zero_cmd_buffers(); + + snprintf(cmd_buf, CMD_BUFSIZE-1, + "%s " IPT_DEL_CHAIN_ARGS, fwc.fw_command, fwc.chain[i].table, fwc.chain[i].to_chain @@ -631,6 +620,7 @@ delete_all_chains(const fko_srv_options_t * const opts) if(! EXTCMD_IS_SUCCESS(res)) log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf); } + return; } static int