[server] start on sudo usage for command exec (issue #159)

This commit is contained in:
Michael Rash
2015-07-02 23:44:16 -04:00
parent ff9adc5f51
commit 4c7679fabd
7 changed files with 94 additions and 12 deletions
+23 -4
View File
@@ -526,11 +526,30 @@ directive starts a new stanza.
the *fwknopd* server as the user specified by the ``CMD_EXEC_USER'' or
as the user that started *fwknopd* if that is not set.
*CMD_EXEC_ALL_SUDO* '<Y/N>'::
*sudo* provides a powerful means of restricting the sets of commands that
users can execute via the ``sudoers'' file. By enabling this feature (and
in ``ENABLE_CMD_EXEC'' mode), all incoming commands from valid SPA packets
will be prefixed by ``/path/to/sudo -u <user>'' where the path to sudo is
set by the ``SUDO_EXE'' variable, and ``<user>'' is set by the
``CMD_EXEC_USER'' variable (default is ``root'' if not set).
*CMD_EXEC_USER* '<username>'::
This specifies the user that will execute commands contained within a SPA
packet. If not specified, fwknopd will execute it as the user it is
running as (most likely root). Setting this to a non-root user is highly
recommended.
This specifies the user (via setuid) that will execute commands contained
within a SPA packet. If not specified, fwknopd will execute it as the user
it is running as (most likely root). Setting this to a non-root user such
as ``nobody'' is highly recommended if elevated permissions are not
needed.
*CMD_EXEC_GROUP* '<groupname>'::
This specifies the group (via setgid) that will execute commands contained
within a SPA packet. If not specified, fwknopd will execute it as the user
it is running as (most likely root). Setting this to a non-root user such
as ``nobody'' is highly recommended if elevated permissions are not
needed.
*SUDO_EXE* '<path>'::
Define the path to the sudo binary. Default is ``/usr/bin/sudo''.
*REQUIRE_USERNAME* '<username>'::
Require a specific username from the client system as encoded in the SPA
+8
View File
@@ -1480,6 +1480,10 @@ parse_access_file(fko_srv_options_t *opts)
{
add_acc_bool(&(curr_acc->enable_cmd_exec), val);
}
else if(CONF_VAR_IS(var, "ENABLE_CMD_SUDO_EXEC"))
{
add_acc_bool(&(curr_acc->enable_cmd_sudo_exec), val);
}
else if(CONF_VAR_IS(var, "CMD_EXEC_USER"))
{
if(add_acc_string(&(curr_acc->cmd_exec_user), val) != SUCCESS)
@@ -1956,7 +1960,9 @@ dump_access_list(const fko_srv_options_t *opts)
" HMAC_DIGEST_TYPE: %d\n"
" FW_ACCESS_TIMEOUT: %i\n"
" ENABLE_CMD_EXEC: %s\n"
" ENABLE_CMD_SUDO_EXEC: %s\n"
" CMD_EXEC_USER: %s\n"
" CMD_EXEC_GROUP: %s\n"
" REQUIRE_USERNAME: %s\n"
" REQUIRE_SOURCE_ADDRESS: %s\n"
" FORCE_NAT (ip): %s\n"
@@ -1989,7 +1995,9 @@ dump_access_list(const fko_srv_options_t *opts)
acc->hmac_type,
acc->fw_access_timeout,
acc->enable_cmd_exec ? "Yes" : "No",
acc->enable_cmd_sudo_exec ? "Yes" : "No",
(acc->cmd_exec_user == NULL) ? "<not set>" : acc->cmd_exec_user,
(acc->cmd_exec_group == NULL) ? "<not set>" : acc->cmd_exec_group,
(acc->require_username == NULL) ? "<not set>" : acc->require_username,
acc->require_source_address ? "Yes" : "No",
acc->force_nat ? acc->force_nat_ip : "<not set>",
+3
View File
@@ -126,6 +126,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
#endif
"GPG_HOME_DIR",
"GPG_EXE",
"SUDO_EXE",
"FIREWALL_EXE",
"VERBOSE",
#if AFL_FUZZING
@@ -148,6 +149,7 @@ enum {
AFL_PKT_FILE,
GPG_HOME_DIR,
GPG_EXE_PATH,
SUDO_EXE_PATH,
FIREWD_DISABLE_CHECK_SUPPORT,
IPT_DISABLE_CHECK_SUPPORT,
PCAP_FILE,
@@ -205,6 +207,7 @@ static struct option cmd_opts[] =
{"run-dir", 1, NULL, 'r'},
{"restart", 0, NULL, 'R'},
{"status", 0, NULL, 'S'},
{"sudo-exe", 1, NULL, SUDO_EXE_PATH },
{"test", 0, NULL, 't'},
{"udp-server", 0, NULL, 'U'},
{"verbose", 0, NULL, 'v'},
+19 -1
View File
@@ -864,6 +864,11 @@ validate_options(fko_srv_options_t *opts)
if(opts->config[CONF_GPG_EXE] == NULL)
set_config_entry(opts, CONF_GPG_EXE, DEF_GPG_EXE);
/* sudo executable
*/
if(opts->config[CONF_SUDO_EXE] == NULL)
set_config_entry(opts, CONF_SUDO_EXE, DEF_SUDO_EXE);
/* Enable SPA over HTTP.
*/
if(opts->config[CONF_ENABLE_SPA_OVER_HTTP] == NULL)
@@ -1233,6 +1238,19 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
case FW_FLUSH:
opts->fw_flush = 1;
break;
case GPG_EXE_PATH:
if (is_valid_exe(optarg))
{
set_config_entry(opts, CONF_GPG_EXE, optarg);
}
else
{
log_msg(LOG_ERR,
"[*] gpg path '%s' could not stat()/does not exist?",
optarg);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
break;
case GPG_HOME_DIR:
if (is_valid_dir(optarg))
{
@@ -1241,7 +1259,7 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
else
{
log_msg(LOG_ERR,
"[*] Directory '%s' could not stat()/does not exist?",
"[*] gpg home directory '%s' could not stat()/does not exist?",
optarg);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
+7
View File
@@ -98,6 +98,11 @@
#else
#define DEF_GPG_EXE "/usr/bin/gpg"
#endif
#ifdef SUDO_EXE
#define DEF_SUDO_EXE SUDO_EXE
#else
#define DEF_SUDO_EXE "/usr/bin/sudo"
#endif
#define DEF_ENABLE_SPA_OVER_HTTP "N"
#define DEF_ENABLE_TCP_SERVER "N"
#define DEF_TCPSERV_PORT "62201"
@@ -305,6 +310,7 @@ enum {
#endif
CONF_GPG_HOME_DIR,
CONF_GPG_EXE,
CONF_SUDO_EXE,
CONF_FIREWALL_EXE,
CONF_VERBOSE,
#if AFL_FUZZING
@@ -366,6 +372,7 @@ typedef struct acc_stanza
unsigned char use_rijndael;
int fw_access_timeout;
unsigned char enable_cmd_exec;
unsigned char enable_cmd_sudo_exec;
char *cmd_exec_user;
char *cmd_exec_group;
uid_t cmd_exec_uid;
+30 -7
View File
@@ -76,31 +76,54 @@ hex_dump(const unsigned char *data, const int size)
return;
}
/* Basic directory checks (stat() and whether the path is actually
* a directory).
/* Basic directory/binary checks (stat() and whether the path is actually
* a directory or an executable).
*/
int
is_valid_dir(const char *path)
static int
is_valid_path(const char *path, const int file_type)
{
#if HAVE_STAT
struct stat st;
/* If we are unable to stat the given dir, then return with error.
/* If we are unable to stat the given path, then return with error.
*/
if(stat(path, &st) != 0)
{
log_msg(LOG_ERR, "[-] unable to stat() directory: %s: %s",
log_msg(LOG_ERR, "[-] unable to stat() path: %s: %s",
path, strerror(errno));
return(0);
}
if(!S_ISDIR(st.st_mode))
if(file_type == IS_DIR)
{
if(!S_ISDIR(st.st_mode))
return(0);
}
else if(file_type == IS_EXE)
{
if(!S_ISREG(st.st_mode) || ! (st.st_mode & S_IXUSR))
return(0);
}
else
return(0);
#endif /* HAVE_STAT */
return(1);
}
int
is_valid_dir(const char *path)
{
return is_valid_path(path, IS_DIR);
}
int
is_valid_exe(const char *path)
{
return is_valid_path(path, IS_EXE);
}
int
verify_file_perms_ownership(const char *file)
{
+4
View File
@@ -54,11 +54,15 @@
x == '#' || x == '\n' || x == '\r' || x == ';' || x == '\0' \
)
#define IS_DIR 1
#define IS_EXE 2
/* Prototypes
*/
void hex_dump(const unsigned char *data, const int size);
char* dump_ctx(fko_ctx_t ctx);
int is_valid_dir(const char *path);
int is_valid_exe(const char *path);
int verify_file_perms_ownership(const char *file);
int strtoargv(const char * const args_str, char **argv_new, int *argc_new,
const fko_srv_options_t * const opts);