2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

testsudoers: add -D and -R options to set cwd and chroot like sudo

This commit is contained in:
Todd C. Miller 2023-06-30 10:43:37 -06:00
parent 01ad570e24
commit bdc8a7f35e
7 changed files with 274 additions and 4 deletions

View File

@ -1091,6 +1091,10 @@ plugins/sudoers/regress/testsudoers/test23.out.ok
plugins/sudoers/regress/testsudoers/test23.sh plugins/sudoers/regress/testsudoers/test23.sh
plugins/sudoers/regress/testsudoers/test24.out.ok plugins/sudoers/regress/testsudoers/test24.out.ok
plugins/sudoers/regress/testsudoers/test24.sh plugins/sudoers/regress/testsudoers/test24.sh
plugins/sudoers/regress/testsudoers/test25.out.ok
plugins/sudoers/regress/testsudoers/test25.sh
plugins/sudoers/regress/testsudoers/test26.out.ok
plugins/sudoers/regress/testsudoers/test26.sh
plugins/sudoers/regress/testsudoers/test3.out.ok plugins/sudoers/regress/testsudoers/test3.out.ok
plugins/sudoers/regress/testsudoers/test3.sh plugins/sudoers/regress/testsudoers/test3.sh
plugins/sudoers/regress/testsudoers/test4.out.ok plugins/sudoers/regress/testsudoers/test4.out.ok

View File

@ -213,9 +213,10 @@ REPLAY_OBJS = getdate.o sudoreplay.o
REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i) REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i)
TEST_OBJS = fmtsudoers.lo fmtsudoers_cvt.lo group_plugin.lo interfaces.lo \ TEST_OBJS = check_util.lo fmtsudoers.lo fmtsudoers_cvt.lo group_plugin.lo \
ldap_util.lo locale.lo lookup.lo net_ifs.o parse_ldif.o \ interfaces.lo ldap_util.lo locale.lo lookup.lo net_ifs.o \
sudo_printf.o testsudoers.o testsudoers_pwutil.o tsgetgrpw.o parse_ldif.o sudo_printf.o testsudoers.o testsudoers_pwutil.o \
tsgetgrpw.o
IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \ IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \
$(CVTSUDOERS_IOBJS) $(REPLAY_IOBJS) $(CVTSUDOERS_IOBJS) $(REPLAY_IOBJS)

View File

@ -0,0 +1,63 @@
A simple sudoers rule should not allow the user to set the cwd:
Parses OK
Entries for user root:
ALL = /bin/ls
host allowed
runas allowed
cmnd allowed
User root is not allowed to change directory to /
Command denied
User can run commands with cwd set to sudoers value:
Parses OK
Entries for user root:
ALL = CWD=/some/where/else /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed
User cannot override the sudoers cwd:
Parses OK
Entries for user root:
ALL = CWD=/some/where/else /bin/ls
host allowed
runas allowed
cmnd allowed
User root is not allowed to change directory to /
Command denied
User can set cwd if sudoers rule sets cwd to '*':
Parses OK
Entries for user root:
ALL = CWD=* /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed
User can set cwd runcwd Defaults is '*':
Parses OK
Entries for user root:
ALL = /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed

View File

@ -0,0 +1,56 @@
#!/bin/sh
#
# Test user-specified cwd handling
#
: ${TESTSUDOERS=testsudoers}
exec 2>&1
cd /
retval=0
# Sudo used to allow the user to set the cwd to the current value.
# Now, a cwd must be explicitly set in sudoers to use the -D option.
printf "A simple sudoers rule should not allow the user to set the cwd:\n"
$TESTSUDOERS -D / root /bin/ls <<'EOF'
root ALL = /bin/ls
EOF
if [ $? -eq 0 ]; then
retval=1
fi
printf "\nUser can run commands with cwd set to sudoers value:\n"
$TESTSUDOERS -D /some/where/else root /bin/ls <<'EOF'
root ALL = CWD=/some/where/else /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
printf "\nUser cannot override the sudoers cwd:\n"
$TESTSUDOERS -D / root /bin/ls <<'EOF'
root ALL = CWD=/some/where/else /bin/ls
EOF
if [ $? -eq 0 ]; then
retval=1
fi
printf "\nUser can set cwd if sudoers rule sets cwd to '*':\n"
$TESTSUDOERS -D /usr root /bin/ls <<'EOF'
root ALL = CWD=* /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
printf "\nUser can set cwd runcwd Defaults is '*':\n"
$TESTSUDOERS -D /usr root /bin/ls <<'EOF'
Defaults runcwd = "*"
root ALL = /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
exit $retval

View File

@ -0,0 +1,61 @@
A simple sudoers rule should not allow the user to chroot:
Parses OK
Entries for user root:
ALL = /bin/ls
host allowed
runas allowed
cmnd allowed
User root is not allowed to change root directory to /
Command denied
User can run commands with chroot set to sudoers value:
Parses OK
Entries for user root:
ALL = CHROOT=/some/where/else /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed
User cannot override the sudoers chroot:
Parses OK
Entries for user root:
ALL = CHROOT=/some/where/else /bin/ls
host allowed
runas allowed
cmnd unmatched
Command unmatched
User can chroot if sudoers rule sets chroot to '*':
Parses OK
Entries for user root:
ALL = CHROOT=* /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed
User can chroot if runchroot Defaults is '*':
Parses OK
Entries for user root:
ALL = /bin/ls
host allowed
runas allowed
cmnd allowed
Command allowed

View File

@ -0,0 +1,58 @@
#!/bin/sh
#
# Test user-specified chroot handling
#
: ${TESTSUDOERS=testsudoers}
exec 2>&1
cd /
retval=0
printf "A simple sudoers rule should not allow the user to chroot:\n"
$TESTSUDOERS -R / root /bin/ls <<'EOF'
root ALL = /bin/ls
EOF
if [ $? -eq 0 ]; then
retval=1
fi
printf "\nUser can run commands with chroot set to sudoers value:\n"
$TESTSUDOERS -R /some/where/else root /bin/ls <<'EOF'
root ALL = CHROOT=/some/where/else /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
# Because command_matches() uses the per-rule CHROOT, this results in
# an unmatched rule instead of a matched rule that is rejected later.
# This is different from the CWD checking which is performed after
# matching is done.
printf "\nUser cannot override the sudoers chroot:\n"
$TESTSUDOERS -R / root /bin/ls <<'EOF'
root ALL = CHROOT=/some/where/else /bin/ls
EOF
if [ $? -eq 0 ]; then
retval=1
fi
printf "\nUser can chroot if sudoers rule sets chroot to '*':\n"
$TESTSUDOERS -R /usr root /bin/ls <<'EOF'
root ALL = CHROOT=* /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
printf "\nUser can chroot if runchroot Defaults is '*':\n"
$TESTSUDOERS -R /usr root /bin/ls <<'EOF'
Defaults runchroot = "*"
root ALL = /bin/ls
EOF
if [ $? -ne 0 ]; then
retval=$?
fi
exit $retval

View File

@ -112,6 +112,7 @@ main(int argc, char *argv[])
const char *errstr; const char *errstr;
int ch, dflag, exitcode = EXIT_FAILURE; int ch, dflag, exitcode = EXIT_FAILURE;
int validated, status = FOUND; int validated, status = FOUND;
char cwdbuf[PATH_MAX];
time_t now; time_t now;
id_t id; id_t id;
debug_decl(main, SUDOERS_DEBUG_MAIN); debug_decl(main, SUDOERS_DEBUG_MAIN);
@ -140,8 +141,11 @@ main(int argc, char *argv[])
dflag = 0; dflag = 0;
grfile = pwfile = NULL; grfile = pwfile = NULL;
while ((ch = getopt(argc, argv, "+dg:G:h:i:P:p:T:tu:U:")) != -1) { while ((ch = getopt(argc, argv, "+D:dg:G:h:i:P:p:R:T:tu:U:")) != -1) {
switch (ch) { switch (ch) {
case 'D':
user_runcwd = optarg;
break;
case 'd': case 'd':
dflag = 1; dflag = 1;
break; break;
@ -179,6 +183,9 @@ main(int argc, char *argv[])
if (now == -1) if (now == -1)
sudo_fatalx("invalid time: %s", optarg); sudo_fatalx("invalid time: %s", optarg);
break; break;
case 'R':
user_runchroot = optarg;
break;
case 't': case 't':
trace_print = testsudoers_error; trace_print = testsudoers_error;
break; break;
@ -229,6 +236,10 @@ main(int argc, char *argv[])
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
user_base = sudo_basename(user_cmnd); user_base = sudo_basename(user_cmnd);
if (getcwd(cwdbuf, sizeof(cwdbuf)) == NULL)
strlcpy(cwdbuf, "/", sizeof(cwdbuf));
user_cwd = cwdbuf;
if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL)
sudo_fatalx(U_("unknown user %s"), user_name); sudo_fatalx(U_("unknown user %s"), user_name);
@ -342,6 +353,22 @@ main(int argc, char *argv[])
validated = sudoers_lookup(&snl, sudo_user.pw, now, &callbacks, &status, validated = sudoers_lookup(&snl, sudo_user.pw, now, &callbacks, &status,
false); false);
/* Validate user-specified chroot or cwd (if any). */
if (ISSET(validated, VALIDATE_SUCCESS)) {
if (check_user_runchroot() != true) {
printf("\nUser %s is not allowed to change root directory to %s\n",
user_name, user_runchroot);
CLR(validated, VALIDATE_SUCCESS);
SET(validated, VALIDATE_FAILURE);
}
if (check_user_runcwd() != true) {
printf("\nUser %s is not allowed to change directory to %s\n",
user_name, user_runcwd);
CLR(validated, VALIDATE_SUCCESS);
SET(validated, VALIDATE_FAILURE);
}
}
/* /*
* Exit codes: * Exit codes:
* 0 - parsed OK and command matched. * 0 - parsed OK and command matched.