[server] add search_extcmd() to replace all popen() calls with the execvpe() no env strategy
This commit is contained in:
+69
-83
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
+21
-31
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user