Changed the way running external commands are hanlded to address issues with it not working on some systems/configurations. Just using system and popen and fw commands are run with stdout and stderr tied to gether.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@230 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart
2010-07-03 02:07:28 +00:00
parent 3c3d75abb5
commit b6c57aa6a0
9 changed files with 173 additions and 107 deletions
+31 -32
View File
@@ -133,6 +133,37 @@ AS_IF([test "x$with_gpgme" != xno],
fi
], [have_gpgme=no])], [have_gpgme=no])
dnl Add various common way to sbin dir to the path (just in case)
APP_PATH=$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/local/sbin
dnl Check for gpg (not gpg2)
dnl
AC_ARG_WITH([gpg],
[AS_HELP_STRING([--with-gpg=/path/to/gpg],
[Specify path to the gpg executable that gpgme will use @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ],
[AC_MSG_ERROR([--with-gpg requires an argument specifying a path to gpg])],
[
AC_CHECK_FILE([$withval], [], [
AC_MSG_WARN([Specified path to gpg does not exist on this system])
gpg_exe_warn="*not found*"
])
GPG_EXE=$withval
]
)
],
[
AC_PATH_PROG(GPG_EXE, [gpg], [], [$APP_PATH])
]
)
AS_IF([test "x$GPG_EXE" != x],
[
AC_DEFINE_UNQUOTED([GPG_EXE], ["$GPG_EXE"], [Path to gpg executable])
gpg_exe=$GPG_EXE
], [ gpg_exe="(not found)"]
)
dnl Check for libpcap, gdbm (or ndbm) if we are building the server component
dnl
AS_IF([test "$want_server" = yes], [
@@ -150,38 +181,6 @@ AS_IF([test "$want_server" = yes], [
)]
)
dnl Add various common way to sbin dir to the path (just in case)
APP_PATH=$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/local/sbin
dnl Check for gpg (not gpg2)
dnl
AC_ARG_WITH([gpg],
[AS_HELP_STRING([--with-gpg=/path/to/gpg],
[Specify path to the gpg executable that gpgme will use @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ],
[AC_MSG_ERROR([--with-gpg requires an argument specifying a path to gpg])],
[
AC_CHECK_FILE([$withval], [], [
AC_MSG_WARN([Specified path to gpg does not exist on this system])
gpg_exe_warn="*not found*"
])
GPG_EXE=$withval
]
)
],
[
AC_PATH_PROG(GPG_EXE, [gpg], [], [$APP_PATH])
]
)
AS_IF([test "x$GPG_EXE" != x],
[
AC_DEFINE_UNQUOTED([GPG_EXE], ["$GPG_EXE"], [Path to gpg executable])
gpg_exe=$GPG_EXE
], [ gpg_exe="(not found)"]
)
dnl Check for iptables
dnl
AC_ARG_WITH([iptables],
+93 -28
View File
@@ -5,21 +5,25 @@
*
*/
/*
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/select.h>
*/
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include "fwknopd_common.h"
#include "extcmd.h"
#include "log_msg.h"
static sig_atomic_t got_sigalrm;
/* Takes a file descriptor and makes it non-blocking.
*/
static int
set_nonblock(int fd)
{
@@ -41,37 +45,97 @@ set_nonblock(int fd)
return(0);
}
*/
/* Run en external command returning exit status, and filling provided
* buffers with STDOUT an STDERR up to the size provided.
static void
alarm_handler(int sig)
{
got_sigalrm = 1;
}
/* Run en external command returning exit status, and optionally filling
* provided buffer with STDOUT output up to the size provided.
*
* Note: XXX: We are not using the timeout parameter at present. We still need
* to implement a reliable timeout mechanism.
*/
int
_run_extcmd(uid_t user_uid, char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status)
_run_extcmd(uid_t user_uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeout)
{
pid_t pid;
FILE *ipt;
int retval = 0;
char so_read_buf[IO_READ_BUF_LEN];
pid_t pid;
struct timeval tv;
fd_set rfds;
fd_set efds;
int selval;
if(so_buf == 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);
}
}
int so[2], se[2]; /* For our pipes */
exit(WEXITSTATUS(system(cmd)));
}
int bytes_read;
/* Retval is forced to 0 as we don't care about the exit status of
* the child (for now)>
*/
retval = 0;
}
else
{
/* Looking for output use popen and fill the buffer to its limit.
*/
ipt = popen(cmd, "r");
char so_read_buf[IO_READ_BUF_LEN];
char se_read_buf[IO_READ_BUF_LEN];
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);
/* Set our remaining_buf counters to one less than the given size so we
* can leave room for a terminating '\0'.
*/
int so_buf_remaining = (so_buf_sz > 0) ? so_buf_sz-1 : 0;
int se_buf_remaining = (se_buf_sz > 0) ? se_buf_sz-1 : 0;
while((fgets(so_read_buf, IO_READ_BUF_LEN, ipt)) != NULL)
{
if(so_buf == NULL)
continue;
/* Be optimistic :)
*/
int retval = EXTCMD_SUCCESS_ALL_OUTPUT;
strlcat(so_buf, so_read_buf, so_buf_sz);
if(strlen(so_buf) >= so_buf_sz-1)
break;
}
pclose(ipt);
}
}
return(retval);
}
/*** END TEST Section ***/
#if 0
/* Create the pipes we will use for getting stdout and stderr
* from the child process.
*/
@@ -278,18 +342,19 @@ _run_extcmd(uid_t user_uid, char *cmd, char *so_buf, char *se_buf, size_t so_buf
*/
return(retval);
}
#endif
/* Run an external command. This is wrapper around _run_extcmd()
*/
run_extcmd(char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status)
run_extcmd(char *cmd, char *so_buf, size_t so_buf_sz, int timeout)
{
return _run_extcmd(0, cmd, so_buf, se_buf, so_buf_sz, se_buf_sz, status);
return _run_extcmd(0, cmd, so_buf, so_buf_sz, timeout);
}
/* Run an external command as the specified user. This is wrapper around _run_extcmd()
*/
run_extcmd_as(uid_t user_uid, char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status)
run_extcmd_as(uid_t user_uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeout)
{
return _run_extcmd(user_uid, cmd, so_buf, se_buf, so_buf_sz, se_buf_sz, status);
return _run_extcmd(user_uid, cmd, so_buf, so_buf_sz, timeout);
}
+2 -2
View File
@@ -66,8 +66,8 @@ enum {
/* Function prototypes
*/
int run_extcmd(char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status);
int run_extcmd_as(uid_t uid, char *cmd, char *so_buf, char *se_buf, size_t so_buf_sz, size_t se_buf_sz, int *status);
int run_extcmd(char *cmd, char *so_buf, size_t so_buf_sz, int timeout);
int run_extcmd_as(uid_t uid, char *cmd, char *so_buf, size_t so_buf_sz, int timeout);
#endif /* EXTCMD_H */
+25 -24
View File
@@ -155,10 +155,10 @@ delete_all_chains(void)
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
memset(cmd_buf, 0x0, CMD_BUFSIZE);
@@ -176,10 +176,10 @@ delete_all_chains(void)
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
@@ -207,11 +207,12 @@ create_fw_chains(void)
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
@@ -228,11 +229,12 @@ create_fw_chains(void)
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
}
@@ -485,7 +487,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
//--DSS tmp
//fprintf(stderr, "ADD CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Rule to %s for %s, %s expires at %u",
@@ -502,7 +504,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
in_chain->next_expire = exp_ts;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
/* If we have to make an corresponding OUTPUT rule if out_chain target
* is not NULL.
@@ -524,7 +526,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added OUTPUT Rule to %s for %s, %s expires at %u",
@@ -541,7 +543,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
out_chain->next_expire = exp_ts;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
@@ -591,7 +593,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added FORWARD Rule to %s for %s, %s expires at %u",
@@ -608,7 +610,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
fwd_chain->next_expire = exp_ts;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
if(dnat_chain->to_chain != NULL && strlen(dnat_chain->to_chain))
@@ -630,7 +632,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
//--DSS tmp
//fprintf(stderr, "ADD DNAT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added DNAT Rule to %s for %s, %s expires at %u",
@@ -647,7 +649,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
dnat_chain->next_expire = exp_ts;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
/* If SNAT (or MASQUERADE) is wanted, then we add those rules here as well.
@@ -691,7 +693,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
snat_target
);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Source NAT Rule to %s for %s, %s expires at %u",
@@ -708,7 +710,7 @@ process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
snat_chain->next_expire = exp_ts;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
@@ -765,16 +767,15 @@ check_firewall_rules(fko_srv_options_t *opts)
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
res = run_extcmd(cmd_buf, cmd_out, err,
STANDARD_CMD_OUT_BUFSIZE, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if(!EXTCMD_IS_SUCCESS(res))
{
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
continue;
}
if(opts->verbose > 1)
if(opts->verbose > 2)
log_msg(LOG_INFO, "RES=%i, CMD_BUF: %s\nRULES LIST: %s", res, cmd_buf, cmd_out);
ndx = strstr(cmd_out, "_exp_");
@@ -855,7 +856,7 @@ check_firewall_rules(fko_srv_options_t *opts)
//fprintf(stderr, "DELETE RULE CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, NULL, err, 0, CMD_BUFSIZE, &status);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Removed rule %s from %s with expire time of %u.",
@@ -866,7 +867,7 @@ check_firewall_rules(fko_srv_options_t *opts)
ch[i].active_rules--;
}
else
parse_extcmd_error(res, status, err);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
else
+11 -11
View File
@@ -35,17 +35,17 @@
/* iptables command args
*/
#define IPT_ADD_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s"
#define IPT_ADD_OUT_RULE_ARGS "-t %s -A %s -p %i -d %s --sport %i -m comment --comment _exp_%u -j %s"
#define IPT_ADD_FWD_RULE_ARGS "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment _exp_%u -j %s"
#define IPT_ADD_DNAT_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s --to-destination %s:%i"
#define IPT_ADD_SNAT_RULE_ARGS "-t %s -A %s -p %i -d %s --dport %i -m comment --comment _exp_%u -j %s %s"
#define IPT_DEL_RULE_ARGS "-t %s -D %s %i"
#define IPT_NEW_CHAIN_ARGS "-t %s -N %s"
#define IPT_FLUSH_CHAIN_ARGS "-t %s -F %s"
#define IPT_DEL_CHAIN_ARGS "-t %s -X %s"
#define IPT_ADD_JUMP_RULE_ARGS "-t %s -I %s %i -j %s"
#define IPT_LIST_RULES_ARGS "-t %s -L %s --line-numbers -n"
#define IPT_ADD_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_OUT_RULE_ARGS "-t %s -A %s -p %i -d %s --sport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_FWD_RULE_ARGS "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_DNAT_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s --to-destination %s:%i 2>&1"
#define IPT_ADD_SNAT_RULE_ARGS "-t %s -A %s -p %i -d %s --dport %i -m comment --comment _exp_%u -j %s %s 2>&1"
#define IPT_DEL_RULE_ARGS "-t %s -D %s %i 2>&1"
#define IPT_NEW_CHAIN_ARGS "-t %s -N %s 2>&1"
#define IPT_FLUSH_CHAIN_ARGS "-t %s -F %s 2>&1"
#define IPT_DEL_CHAIN_ARGS "-t %s -X %s 2>&1"
#define IPT_ADD_JUMP_RULE_ARGS "-t %s -I %s %i -j %s 2>&1"
#define IPT_LIST_RULES_ARGS "-t %s -L %s --line-numbers -n 2>&1"
#define DEF_FW_ACCESS_TIMEOUT 60
+5 -7
View File
@@ -461,12 +461,10 @@ incoming_spa(fko_srv_options_t *opts)
res = run_extcmd_as(acc->cmd_exec_uid,
spadat.spa_message_remain,
NULL, NULL, 0, 0, &status);
spadat.spa_message_remain, NULL, 0, 0);
}
else /* Just run it as we are (root that is). */
res = run_extcmd(spadat.spa_message_remain,
NULL, NULL, 0, 0, &status);
res = run_extcmd(spadat.spa_message_remain, NULL, 0, 5);
/* --DSS XXX: I have found that the status (and res for that
* matter) have been unreliable indicators of the
@@ -475,11 +473,11 @@ incoming_spa(fko_srv_options_t *opts)
*/
status = WEXITSTATUS(status);
if(opts->verbose > 1)
if(opts->verbose > 2)
log_msg(LOG_WARNING,
"CMD_EXEC: result: %i, command returned %i", res, status);
"CMD_EXEC: command returned %i", res);
if(res != 0 || status != 0)
if(res != 0)
res = SPA_MSG_COMMAND_ERROR;
}
+4 -2
View File
@@ -161,8 +161,10 @@ pcap_capture(fko_srv_options_t *opts)
if(WIFSIGNALED(status))
log_msg(LOG_WARNING, "TCP server got signal: %i", WTERMSIG(status));
log_msg(LOG_WARNING, "TCP server exited with status of %i. Attempting restart.",
WEXITSTATUS(status));
log_msg(LOG_WARNING,
"TCP server exited with status of %i. Attempting restart.",
WEXITSTATUS(status)
);
opts->tcp_server_pid = 0;
+1
View File
@@ -61,6 +61,7 @@ sig_handler(int sig)
return;
case SIGCHLD:
got_sigchld = 1;
waitpid(-1, NULL, WNOHANG);
return;
}
}
+1 -1
View File
@@ -188,7 +188,7 @@ run_tcp_server(fko_srv_options_t *opts)
{
memset(sipbuf, 0x0, MAX_IP_STR_LEN);
inet_ntop(AF_INET, &(caddr.sin_addr.s_addr), sipbuf, MAX_IP_STR_LEN);
log_msg(LOG_INFO|LOG_STDERR, "tcp_server: Got TCP connection from %s.", sipbuf);
log_msg(LOG_INFO, "tcp_server: Got TCP connection from %s.", sipbuf);
}
/* Though hacky and clunky, we just sleep for a second then