[server] add sudo support, closes #159

This commit is contained in:
Michael Rash 2015-07-19 20:23:04 -07:00
parent 89b2e8f477
commit d681485e29
9 changed files with 448 additions and 60 deletions

View File

@ -1,7 +1,14 @@
fwknop-2.6.7 (05//2015):
fwknop-2.6.7 (07//2015):
- [server] Added sudo support for command execution mode. This was
suggested by Github user 'freegigi' (issue #159) as a means to provide
command filtering using the powerful sudoers syntax. This feature is
implemented by prefixing any incoming command from a valid SPA packet
with the sudo command along with optional user and group requirements
as defined by the following new access.conf variables:
ENABLE_CMD_SUDO_EXEC, CMD_SUDO_EXEC_USER, and CMD_SUDO_EXEC_GROUP.
- [server] Kevin Layer reported a bug to the fwknop mailing list that
simultaneous NAT access for two different access.conf stanza was not
functioning properly. After some diagnosis, this is a result of
functioning properly. After some diagnosis, this was a result of
rule_exists() not properly detecting and differentiating existing DNAT
rules from new ones with different port numbers when 'iptables -C'
support is not available. This was against iptables-1.4.7, and has been

View File

@ -543,7 +543,7 @@ 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>'::
*ENABLE_CMD_SUDO_EXEC* '<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

View File

@ -76,6 +76,58 @@ add_acc_string(char **var, const char *val)
return SUCCESS;
}
/* Add an access user entry
*/
static int
add_acc_user(char **user_var, uid_t *uid_var, struct passwd *upw,
const char *val, const char *var_name)
{
struct passwd *pw = NULL;
if(add_acc_string(user_var, val) != SUCCESS)
return FATAL_ERR;
errno = 0;
upw = pw = getpwnam(val);
if(pw == NULL)
{
log_msg(LOG_ERR, "[*] Unable to determine UID for %s: %s.",
var_name, errno ? strerror(errno) : "Not a user on this system");
return FATAL_ERR;
}
*uid_var = pw->pw_uid;
return SUCCESS;
}
/* Add an access group entry
*/
static int
add_acc_group(char **group_var, gid_t *gid_var,
const char *val, const char *var_name)
{
struct passwd *pw = NULL;
if(add_acc_string(group_var, val) != SUCCESS)
return FATAL_ERR;
errno = 0;
pw = getpwnam(val);
if(pw == NULL)
{
log_msg(LOG_ERR, "[*] Unable to determine UID for %s: %s.",
var_name, errno ? strerror(errno) : "Not a group on this system");
return FATAL_ERR;
}
*gid_var = pw->pw_gid;
return SUCCESS;
}
/* Decode base64 encoded string into access entry
*/
static int
@ -803,6 +855,12 @@ free_acc_stanza_data(acc_stanza_t *acc)
free(acc->hmac_key_base64);
}
if(acc->cmd_sudo_exec_user != NULL)
free(acc->cmd_sudo_exec_user);
if(acc->cmd_sudo_exec_group != NULL)
free(acc->cmd_sudo_exec_group);
if(acc->cmd_exec_user != NULL)
free(acc->cmd_exec_user);
@ -1077,7 +1135,9 @@ set_acc_defaults(fko_srv_options_t *opts)
/* Perform some sanity checks on an acc stanza data.
*/
static int
acc_data_is_valid(fko_srv_options_t *opts, struct passwd *user_pw, acc_stanza_t * const acc)
acc_data_is_valid(fko_srv_options_t *opts,
struct passwd *user_pw, struct passwd *sudo_user_pw,
acc_stanza_t * const acc)
{
if(acc == NULL)
{
@ -1176,6 +1236,17 @@ acc_data_is_valid(fko_srv_options_t *opts, struct passwd *user_pw, acc_stanza_t
acc->cmd_exec_gid = user_pw->pw_gid;
}
if(sudo_user_pw != NULL
&& acc->cmd_sudo_exec_uid != 0 && acc->cmd_sudo_exec_gid == 0)
{
log_msg(LOG_INFO,
"Setting gid to group associated with CMD_SUDO_EXEC_USER '%s' in stanza source: '%s'",
acc->cmd_exec_user,
acc->source
);
acc->cmd_sudo_exec_gid = sudo_user_pw->pw_gid;
}
return(1);
}
@ -1193,8 +1264,8 @@ parse_access_file(fko_srv_options_t *opts)
char var[MAX_LINE_LEN] = {0};
char val[MAX_LINE_LEN] = {0};
struct passwd *pw = NULL;
struct passwd *user_pw = NULL;
struct passwd *sudo_user_pw = NULL;
struct stat st;
acc_stanza_t *curr_acc = NULL;
@ -1293,7 +1364,7 @@ parse_access_file(fko_srv_options_t *opts)
* stanza for the minimum required data.
*/
if(curr_acc != NULL) {
if(!acc_data_is_valid(opts, user_pw, curr_acc))
if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
{
log_msg(LOG_ERR, "[*] Data error in access file: '%s'",
opts->config[CONF_ACCESS_FILE]);
@ -1484,47 +1555,45 @@ parse_access_file(fko_srv_options_t *opts)
{
add_acc_bool(&(curr_acc->enable_cmd_sudo_exec), val);
}
else if(CONF_VAR_IS(var, "CMD_SUDO_EXEC_USER"))
{
if(add_acc_user(&(curr_acc->cmd_sudo_exec_user),
&(curr_acc->cmd_sudo_exec_uid), sudo_user_pw,
val, "CMD_SUDO_EXEC_USER") != SUCCESS)
{
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
}
else if(CONF_VAR_IS(var, "CMD_SUDO_EXEC_GROUP"))
{
if(add_acc_group(&(curr_acc->cmd_sudo_exec_group),
&(curr_acc->cmd_sudo_exec_gid), val,
"CMD_SUDO_EXEC_GROUP") != SUCCESS)
{
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
}
else if(CONF_VAR_IS(var, "CMD_EXEC_USER"))
{
if(add_acc_string(&(curr_acc->cmd_exec_user), val) != SUCCESS)
if(add_acc_user(&(curr_acc->cmd_exec_user),
&(curr_acc->cmd_exec_uid), user_pw,
val, "CMD_EXEC_USER") != SUCCESS)
{
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
errno = 0;
user_pw = pw = getpwnam(val);
if(pw == NULL)
{
log_msg(LOG_ERR, "[*] Unable to determine UID for CMD_EXEC_USER: %s.",
errno ? strerror(errno) : "Not a user on this system");
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
curr_acc->cmd_exec_uid = pw->pw_uid;
}
else if(CONF_VAR_IS(var, "CMD_EXEC_GROUP"))
{
if(add_acc_string(&(curr_acc->cmd_exec_group), val) != SUCCESS)
if(add_acc_group(&(curr_acc->cmd_exec_group),
&(curr_acc->cmd_exec_gid), val,
"CMD_SUDO_EXEC_GROUP") != SUCCESS)
{
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
errno = 0;
pw = getpwnam(val);
if(pw == NULL)
{
log_msg(LOG_ERR, "[*] Unable to determine GID for CMD_EXEC_GROUP: %s.",
errno ? strerror(errno) : "Not a group on this system");
fclose(file_ptr);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
curr_acc->cmd_exec_gid = pw->pw_gid;
}
else if(CONF_VAR_IS(var, "REQUIRE_USERNAME"))
{
@ -1759,7 +1828,7 @@ parse_access_file(fko_srv_options_t *opts)
/* Sanity check the last stanza
*/
if(!acc_data_is_valid(opts, user_pw, curr_acc))
if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
{
log_msg(LOG_ERR,
"[*] Data error in access file: '%s'",
@ -1961,6 +2030,8 @@ dump_access_list(const fko_srv_options_t *opts)
" FW_ACCESS_TIMEOUT: %i\n"
" ENABLE_CMD_EXEC: %s\n"
" ENABLE_CMD_SUDO_EXEC: %s\n"
" CMD_SUDO_EXEC_USER: %s\n"
" CMD_SUDO_EXEC_GROUP: %s\n"
" CMD_EXEC_USER: %s\n"
" CMD_EXEC_GROUP: %s\n"
" REQUIRE_USERNAME: %s\n"
@ -1996,6 +2067,8 @@ dump_access_list(const fko_srv_options_t *opts)
acc->fw_access_timeout,
acc->enable_cmd_exec ? "Yes" : "No",
acc->enable_cmd_sudo_exec ? "Yes" : "No",
(acc->cmd_sudo_exec_user == NULL) ? "<not set>" : acc->cmd_sudo_exec_user,
(acc->cmd_sudo_exec_group == NULL) ? "<not set>" : acc->cmd_sudo_exec_group,
(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,

View File

@ -1322,6 +1322,19 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
case 'S':
opts->status = 1;
break;
case SUDO_EXE_PATH:
if (is_valid_exe(optarg))
{
set_config_entry(opts, CONF_SUDO_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 't':
opts->test = 1;
break;

View File

@ -111,7 +111,7 @@ copy_or_search(char *so_read_buf, char *so_buf, const size_t so_buf_sz,
}
/* Run an external command returning exit status, and optionally filling
* provided buffer with STDOUT output up to the size provided.
* 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.
@ -136,6 +136,8 @@ _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf,
#endif
#if AFL_FUZZING
/* Don't allow command execution in AFL fuzzing mode
*/
return 0;
#endif

View File

@ -378,6 +378,10 @@ typedef struct acc_stanza
int fw_access_timeout;
unsigned char enable_cmd_exec;
unsigned char enable_cmd_sudo_exec;
char *cmd_sudo_exec_user;
char *cmd_sudo_exec_group;
uid_t cmd_sudo_exec_uid;
gid_t cmd_sudo_exec_gid;
char *cmd_exec_user;
char *cmd_exec_group;
uid_t cmd_exec_uid;

View File

@ -304,6 +304,7 @@ incoming_spa(fko_srv_options_t *opts)
int is_err, cmd_exec_success = 0, attempted_decrypt = 0;
int conf_pkt_age = 0;
char dump_buf[CTX_DUMP_BUFSIZE];
char cmd_buf[MAX_SPA_CMD_LEN] = {0};
spa_pkt_info_t *spa_pkt = &(opts->spa_pkt);
@ -881,24 +882,54 @@ incoming_spa(fko_srv_options_t *opts)
spadat.pkt_source_ip, stanza_num, spadat.spa_message_remain
);
/* Do we need to become another user? If so, we call
* run_extcmd_as and pass the cmd_exec_uid.
*/
if(acc->cmd_exec_user != NULL && strncasecmp(acc->cmd_exec_user, "root", 4) != 0)
memset(cmd_buf, 0x0, sizeof(cmd_buf));
if(acc->enable_cmd_sudo_exec)
{
/* Run the command via sudo - this allows sudo filtering
* to apply to the incoming command
*/
strlcpy(cmd_buf, opts->config[CONF_SUDO_EXE],
sizeof(cmd_buf));
if(acc->cmd_sudo_exec_user != NULL
&& strncasecmp(acc->cmd_sudo_exec_user, "root", 4) != 0)
{
strlcat(cmd_buf, " -u ", sizeof(cmd_buf));
strlcat(cmd_buf, acc->cmd_sudo_exec_user, sizeof(cmd_buf));
}
if(acc->cmd_exec_group != NULL
&& strncasecmp(acc->cmd_sudo_exec_group, "root", 4) != 0)
{
strlcat(cmd_buf, " -g ", sizeof(cmd_buf));
strlcat(cmd_buf,
acc->cmd_sudo_exec_group, sizeof(cmd_buf));
}
strlcat(cmd_buf, " ", sizeof(cmd_buf));
strlcat(cmd_buf, spadat.spa_message_remain, sizeof(cmd_buf));
}
else
strlcpy(cmd_buf, spadat.spa_message_remain, sizeof(cmd_buf));
if(acc->cmd_exec_user != NULL
&& strncasecmp(acc->cmd_exec_user, "root", 4) != 0)
{
log_msg(LOG_INFO,
"[%s] (stanza #%d) setuid/setgid user/group to %s/%s (UID=%i,GID=%i) before running command.",
spadat.pkt_source_ip, stanza_num, acc->cmd_exec_user,
"[%s] (stanza #%d) Running command '%s' setuid/setgid user/group to %s/%s (UID=%i,GID=%i)",
spadat.pkt_source_ip, stanza_num, cmd_buf, acc->cmd_exec_user,
acc->cmd_exec_group == NULL ? acc->cmd_exec_user : acc->cmd_exec_group,
acc->cmd_exec_uid, acc->cmd_exec_gid);
res = run_extcmd_as(acc->cmd_exec_uid, acc->cmd_exec_gid,
spadat.spa_message_remain, NULL, 0,
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
cmd_buf, NULL, 0, WANT_STDERR, NO_TIMEOUT,
&pid_status, opts);
}
else /* Just run it as we are (root that is). */
res = run_extcmd(spadat.spa_message_remain, NULL, 0,
WANT_STDERR, 5, &pid_status, opts);
{
log_msg(LOG_INFO,
"[%s] (stanza #%d) Running command '%s'",
spadat.pkt_source_ip, stanza_num, cmd_buf);
res = run_extcmd(cmd_buf, NULL, 0, WANT_STDERR,
5, &pid_status, opts);
}
/* should only call WEXITSTATUS() if WIFEXITED() is true
*/

View File

@ -201,6 +201,9 @@ my $fuzzing_test_tag = '';
my $fuzzing_class = 'bogus data';
my %fuzzing_spa_packets = ();
my $total_fuzzing_pkts = 0;
our $sudo_access_conf = "$run_dir/sudo_access.conf";
my $sudo_conf = '/etc/sudoers';
my $sudo_conf_testing = '';
my $server_test_file = '';
my $client_only_mode = 0;
my $server_only_mode = 0;
@ -267,6 +270,7 @@ our $valgrind_path = '';
our $fiu_run_path = '';
our $sudo_path = '';
our $gcov_path = '';
my $touch_path = '';
my $lcov_path = '';
my $coverage_diff_path = 'coverage_diff.py';
my $genhtml_path = '';
@ -875,6 +879,11 @@ my %test_keys = (
'server_exec_err' => $OPTIONAL,
'fw_rule_created' => $OPTIONAL,
'fw_rule_removed' => $OPTIONAL,
'sudo_test' => $OPTIONAL,
'sudo_conf' => $OPTIONAL,
'sudo_exec_user' => $OPTIONAL,
'sudo_exec_group' => $OPTIONAL,
'exec_user' => $OPTIONAL,
'server_conf' => $OPTIONAL,
'client_only' => $OPTIONAL_NUMERIC,
'server_only' => $OPTIONAL_NUMERIC,
@ -902,6 +911,7 @@ my %test_keys = (
'server_conf_file' => $OPTIONAL,
'digest_cache_file' => $OPTIONAL,
'cmd_exec_file_owner' => $OPTIONAL,
'cmd_exec_file_not_created' => $OPTIONAL,
'rm_rule_mid_cycle' => $OPTIONAL,
'server_receive_re' => $OPTIONAL,
'no_exit_intf_down' => $OPTIONAL,
@ -4672,28 +4682,103 @@ sub get_mod_paths() {
return \@paths;
}
sub write_sudo_access_conf() {
my $test_hr = shift;
unlink $sudo_access_conf if -e $sudo_access_conf;
# mbr localhost = NOPASSWD: /usr/bin/cat, /usr/bin/touch
# mbr localhost = NOPASSWD: /usr/bin/cat, (root) /usr/bin/touch
# mbr localhost = NOPASSWD: /usr/bin/cat, (mbr : mbr) /usr/bin/touch
if ($test_hr->{'sudo_conf'}) {
open ST, "> $sudo_conf_testing" or die $!;
$test_hr->{'sudo_conf'} =~ s/USER/$username/g;
if ($test_hr->{'sudo_conf'} =~ /TOUCH/) {
if ($touch_path) {
$test_hr->{'sudo_conf'} =~ s/TOUCH/$touch_path/;
} else {
$test_hr->{'sudo_conf'} =~ s|TOUCH|/bin/touch|;
}
}
print ST $test_hr->{'sudo_conf'}, "\n";
close ST;
&write_test_file(
"[+] Setting $sudo_conf_testing file to:\n$test_hr->{'sudo_conf'}\n",
$curr_test_file);
}
copy $cf{'hmac_cmd_access'}, $sudo_access_conf or die $!;
open CA, ">> $sudo_access_conf" or die $!;
print CA "ENABLE_CMD_SUDO_EXEC Y\n";
if ($test_hr->{'exec_user'} eq $YES) {
print CA "CMD_EXEC_USER $username\n";
}
if ($test_hr->{'sudo_exec_user'} eq $YES) {
print CA "CMD_SUDO_EXEC_USER $username\n";
}
if ($test_hr->{'sudo_exec_group'} eq $YES) {
print CA "CMD_SUDO_EXEC_GROUP $username\n";
}
close CA;
return;
}
sub spa_cmd_exec_cycle() {
my $test_hr = shift;
unlink $cmd_exec_test_file if -e $cmd_exec_test_file;
if ($test_hr->{'sudo_test'} eq $YES) {
### we need to write the access.conf file based on sudo
### requirements
&write_sudo_access_conf($test_hr);
}
if (-e $cmd_exec_test_file) {
&write_test_file("[-] $cmd_exec_test_file file exists before SPA cycle.\n",
$curr_test_file);
} else {
&write_test_file("[+] $cmd_exec_test_file does not exist before SPA cycle.\n",
$curr_test_file);
}
my $rv = &spa_cycle($test_hr);
if (-e $cmd_exec_test_file) {
&run_cmd("ls -l $cmd_exec_test_file", $cmd_out_tmp, $curr_test_file);
if ($test_hr->{'cmd_exec_file_owner'}) {
$test_hr->{'cmd_exec_file_owner'} =~ s/USER/$username/;
my $user = (getpwuid((stat($cmd_exec_test_file))[4]))[0];
if ($user and $user eq 'nobody') {
&write_test_file("[+] $cmd_exec_test_file is owned by user 'nobody'\n",
if ($user and $user eq $test_hr->{'cmd_exec_file_owner'}) {
&write_test_file("[+] $cmd_exec_test_file is owned by user: $user\n",
$curr_test_file);
$rv = 1;
} else {
&write_test_file("[+] $cmd_exec_test_file is not " .
"owned by user: $test_hr->{'cmd_exec_file_owner'}\n",
$curr_test_file);
&run_cmd("ls -l $cmd_exec_test_file", $cmd_out_tmp, $curr_test_file);
$rv = 1;
}
}
if ($test_hr->{'cmd_exec_file_not_created'}) {
&write_test_file("[-] $cmd_exec_test_file file exists, setting rv=0.\n",
$curr_test_file);
$rv = 0;
}
unlink $cmd_exec_test_file;
} else {
&write_test_file("[-] $cmd_exec_test_file file does not exist, setting rv=0.\n",
$curr_test_file);
$rv = 0;
if ($test_hr->{'cmd_exec_file_not_created'}) {
&write_test_file("[+] $cmd_exec_test_file file does not exist.\n",
$curr_test_file);
$rv = 1;
} else {
&write_test_file("[-] $cmd_exec_test_file file does not exist, setting rv=0.\n",
$curr_test_file);
$rv = 0;
}
}
return $rv;
@ -6936,17 +7021,32 @@ sub init() {
push @tests_to_exclude, qr/perl FKO module.*FUZZING/;
}
$sudo_path = &find_command('sudo') unless $sudo_path;
$killall_path = &find_command('killall') unless $killall_path;
$pgrep_path = &find_command('pgrep') unless $pgrep_path;
$lib_view_cmd = &find_command('ldd') unless $lib_view_cmd;
$git_path = &find_command('git') unless $git_path;
$perl_path = &find_command('perl') unless $perl_path;
$sudo_path = &find_command('sudo') unless $sudo_path;
$killall_path = &find_command('killall') unless $killall_path;
$pgrep_path = &find_command('pgrep') unless $pgrep_path;
$lib_view_cmd = &find_command('ldd') unless $lib_view_cmd;
$git_path = &find_command('git') unless $git_path;
$perl_path = &find_command('perl') unless $perl_path;
$touch_path = &find_command('touch') unless $touch_path;
if ($sudo_path) {
$username = (getpwuid((stat($test_suite_path))[4]))[0];
die "[*] Could not determine $test_suite_path owner"
unless $username;
### see if sudo is configured to accept custom configs
if (-e $sudo_conf) {
open SR, "< $sudo_conf" or die $!;
while (<SR>) {
if (/^#includedir\s+(\/\S+)/) {
$sudo_conf_testing = "$1/fwknop_testing";
last;
}
}
close SR;
}
} else {
push @tests_to_exclude, qr/sudo/;
}
### see if the 'nobody' user is on the system

View File

@ -28,6 +28,20 @@
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'server_positive_output_matches' => [qr/Command messages are not allowed/]
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => 'command execution invalid path',
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "badpath $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} ".
"$verbose_str",
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_cmd_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'cmd_exec_file_not_created' => $YES,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
@ -87,12 +101,156 @@
'detail' => "command execution uid/gid 'nobody'",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} ".
"$verbose_str",
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_cmd_giduid_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (1)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, TOUCH',
'cmd_exec_file_owner' => 'root',
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (2)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, (root) TOUCH',
'sudo_exec_user' => $YES,
'cmd_exec_file_owner' => 'root',
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (3)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, TOUCH',
'sudo_exec_user' => $YES,
'cmd_exec_file_not_created' => $YES,
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'server_positive_output_matches' => [qr/is not allowed to execute/]
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (4)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, (USER) TOUCH',
'sudo_exec_user' => $YES,
'cmd_exec_file_owner' => 'USER',
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (5)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, (baduser) TOUCH',
'sudo_exec_user' => $YES,
'cmd_exec_file_not_created' => $YES,
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'server_positive_output_matches' => [qr/is not allowed to execute/]
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (6)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, notouchcmd',
'sudo_exec_user' => $YES,
'cmd_exec_file_not_created' => $YES,
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'server_positive_output_matches' => [qr/is not allowed to execute/]
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (7)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, (USER : USER) TOUCH',
'sudo_exec_user' => $YES,
'cmd_exec_file_owner' => 'USER',
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client+server',
'detail' => "command exec sudo current user (8)",
'function' => \&spa_cmd_exec_cycle,
'cmdline' => qq|$fwknopCmd --server-cmd "touch $cmd_exec_test_file" | .
"-a $fake_ip -D $loopback_ip --rc-file $cf{'rc_hmac_b64_key'} " .
$verbose_str,
'cmd_exec_file_owner' => 'nobody',
'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $sudo_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'sudo_test' => $YES,
'exec_user' => $YES,
'sudo_conf' => 'USER localhost = NOPASSWD: /usr/bin/cat, (USER : USER) TOUCH',
'sudo_exec_user' => $YES,
'sudo_exec_group' => $YES,
'cmd_exec_file_owner' => 'USER',
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
},
);