First cut at session logging for sudo. Still need to write get_pty()

for Unix 98 and old-style BSD ptys.  Also needs documentation and
general cleanup.
This commit is contained in:
Todd C. Miller
2009-08-06 00:04:14 +00:00
parent 334c19a405
commit 3bfce30a85
19 changed files with 788 additions and 385 deletions

View File

@@ -106,7 +106,7 @@ SRCS = aix.c alias.c alloc.c audit.c bsm_audit.c check.c closefrom.c \
def_data.c defaults.c env.c error.c fileops.c find_path.c fnmatch.c \ def_data.c defaults.c env.c error.c fileops.c find_path.c fnmatch.c \
getcwd.c getprogname.c getspwuid.c gettime.c glob.c goodpath.c gram.c \ getcwd.c getprogname.c getspwuid.c gettime.c glob.c goodpath.c gram.c \
gram.y interfaces.c isblank.c lbuf.c ldap.c list.c logging.c match.c \ gram.y interfaces.c isblank.c lbuf.c ldap.c list.c logging.c match.c \
mkstemp.c memrchr.c parse.c pwutil.c set_perms.c sigaction.c \ mkstemp.c memrchr.c parse.c pwutil.c script.c set_perms.c sigaction.c \
snprintf.c strcasecmp.c strerror.c strlcat.c strlcpy.c sudo.c \ snprintf.c strcasecmp.c strerror.c strlcat.c strlcpy.c sudo.c \
sudo_noexec.c sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c \ sudo_noexec.c sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c \
toke.c toke.l tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \ toke.c toke.l tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \
@@ -131,8 +131,8 @@ COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o list.o match.o \
SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ audit.o check.o env.o \ SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ audit.o check.o env.o \
getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ getspwuid.o gettime.o goodpath.o fileops.o find_path.o \
interfaces.o lbuf.o logging.o parse.o pwutil.o set_perms.o \ interfaces.o lbuf.o logging.o parse.o pwutil.o script.o \
sudo.o sudo_edit.o sudo_nss.o term.o tgetpass.o set_perms.o sudo.o sudo_edit.o sudo_nss.o term.o tgetpass.o
VISUDO_OBJS = $(COMMON_OBJS) visudo.o fileops.o gettime.o goodpath.o \ VISUDO_OBJS = $(COMMON_OBJS) visudo.o fileops.o gettime.o goodpath.o \
find_path.o pwutil.o find_path.o pwutil.o
@@ -285,6 +285,8 @@ pwutil.o: $(srcdir)/pwutil.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c
redblack.o: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h redblack.o: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/redblack.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/redblack.c
script.o: $(srcdir)/script.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/script.c
set_perms.o: $(srcdir)/set_perms.c $(SUDODEP) set_perms.o: $(srcdir)/set_perms.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/set_perms.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/set_perms.c
sigaction.o: $(srcdir)/sigaction.c $(srcdir)/compat.h sigaction.o: $(srcdir)/sigaction.c $(srcdir)/compat.h

27
aclocal.m4 vendored
View File

@@ -134,7 +134,8 @@ fi
])dnl ])dnl
dnl dnl
dnl Where the log file goes, use /var/log if it exists, else /{var,usr}/adm dnl Where the timestamp files go, use /var/run/sudo if /var/run exists,
dnl else /{var,usr}/adm/sudo
dnl dnl
AC_DEFUN(SUDO_TIMEDIR, [AC_MSG_CHECKING(for timestamp file location) AC_DEFUN(SUDO_TIMEDIR, [AC_MSG_CHECKING(for timestamp file location)
if test -n "$with_timedir"; then if test -n "$with_timedir"; then
@@ -156,6 +157,30 @@ else
fi fi
])dnl ])dnl
dnl
dnl Where the session files go, use /var/log/sudo-session if /var/log exists,
dnl else /{var,usr}/adm/sudo-session
dnl
AC_DEFUN(SUDO_SESSDIR, [AC_MSG_CHECKING(for session file location)
if test -n "$with_sessdir"; then
AC_MSG_RESULT($with_sessdir)
SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SESSDIR, "$with_sessdir")
sessdir="$with_sessdir"
elif test -d "/var/log"; then
AC_MSG_RESULT(/var/log/sudo-session)
SUDO_DEFINE(_PATH_SUDO_SESSDIR, "/var/log/sudo-session")
sessdir="/var/log/sudo-session"
elif test -d "/var/adm"; then
AC_MSG_RESULT(/var/adm/sudo-session)
SUDO_DEFINE(_PATH_SUDO_SESSDIR, "/var/adm/sudo-session")
sessdir="/var/adm/sudo-session"
else
AC_MSG_RESULT(/usr/adm/sudo-session)
SUDO_DEFINE(_PATH_SUDO_SESSDIR, "/usr/adm/sudo-session")
sessdir="/usr/adm/sudo-session"
fi
])dnl
dnl dnl
dnl SUDO_CHECK_TYPE(TYPE, DEFAULT) dnl SUDO_CHECK_TYPE(TYPE, DEFAULT)
dnl XXX - should require the check for unistd.h... dnl XXX - should require the check for unistd.h...

View File

@@ -198,6 +198,7 @@ int isblank __P((int));
# define SA_ONSTACK SV_ONSTACK # define SA_ONSTACK SV_ONSTACK
# define SA_RESTART SV_INTERRUPT /* opposite effect */ # define SA_RESTART SV_INTERRUPT /* opposite effect */
# define SA_RESETHAND SV_RESETHAND # define SA_RESETHAND SV_RESETHAND
# define SA_NOCLDSTOP SV_NOCLDSTOP
# define sa_handler sv_handler # define sa_handler sv_handler
# define sa_mask sv_mask # define sa_mask sv_mask
# define sa_flags sv_flags # define sa_flags sv_flags

View File

@@ -318,6 +318,9 @@
/* Define to 1 if you have the <netgroup.h> header file. */ /* Define to 1 if you have the <netgroup.h> header file. */
#undef HAVE_NETGROUP_H #undef HAVE_NETGROUP_H
/* Define to 1 if you have the `openpty' function. */
#undef HAVE_OPENPTY
/* Define to 1 if you use NRL OPIE. */ /* Define to 1 if you use NRL OPIE. */
#undef HAVE_OPIE #undef HAVE_OPIE

220
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for sudo 1.7.2. # Generated by GNU Autoconf 2.61 for sudo 1.7.3.
# #
# Report bugs to <http://www.sudo.ws/bugs/>. # Report bugs to <http://www.sudo.ws/bugs/>.
# #
@@ -724,8 +724,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='sudo' PACKAGE_NAME='sudo'
PACKAGE_TARNAME='sudo' PACKAGE_TARNAME='sudo'
PACKAGE_VERSION='1.7.2' PACKAGE_VERSION='1.7.3'
PACKAGE_STRING='sudo 1.7.2' PACKAGE_STRING='sudo 1.7.3'
PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/' PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/'
# Factoring default headers for most tests. # Factoring default headers for most tests.
@@ -1416,7 +1416,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures sudo 1.7.2 to adapt to many kinds of systems. \`configure' configures sudo 1.7.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1481,7 +1481,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of sudo 1.7.2:";; short | recursive ) echo "Configuration of sudo 1.7.3:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1683,7 +1683,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
sudo configure 1.7.2 sudo configure 1.7.3
generated by GNU Autoconf 2.61 generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1697,7 +1697,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by sudo $as_me 1.7.2, which was It was created by sudo $as_me 1.7.3, which was
generated by GNU Autoconf 2.61. Invocation command line was generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@ $ $0 $@
@@ -15921,6 +15921,172 @@ fi
done done
for ac_func in openpty
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $ac_func innocuous_$ac_func
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $ac_func
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$ac_func || defined __stub___$ac_func
choke me
#endif
int
main ()
{
return $ac_func ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext &&
$as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
if test `eval echo '${'$as_ac_var'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
else
{ echo "$as_me:$LINENO: checking for openpty in -lutil" >&5
echo $ECHO_N "checking for openpty in -lutil... $ECHO_C" >&6; }
if test "${ac_cv_lib_util_openpty+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lutil $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char openpty ();
int
main ()
{
return openpty ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext &&
$as_test_x conftest$ac_exeext; then
ac_cv_lib_util_openpty=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_util_openpty=no
fi
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ echo "$as_me:$LINENO: result: $ac_cv_lib_util_openpty" >&5
echo "${ECHO_T}$ac_cv_lib_util_openpty" >&6; }
if test $ac_cv_lib_util_openpty = yes; then
SUDO_LIBS="${SUDO_LIBS} -lutil"
cat >>confdefs.h <<\_ACEOF
#define HAVE_OPENPTY 1
_ACEOF
fi
fi
done
for ac_func in unsetenv for ac_func in unsetenv
do do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -23997,6 +24163,42 @@ EOF
timedir="/usr/adm/sudo" timedir="/usr/adm/sudo"
fi fi
{ echo "$as_me:$LINENO: checking for session file location" >&5
echo $ECHO_N "checking for session file location... $ECHO_C" >&6; }
if test -n "$with_sessdir"; then
{ echo "$as_me:$LINENO: result: $with_sessdir" >&5
echo "${ECHO_T}$with_sessdir" >&6; }
cat >>confdefs.h <<EOF
#define _PATH_SUDO_SESSDIR "$with_sessdir"
EOF
sessdir="$with_sessdir"
elif test -d "/var/log"; then
{ echo "$as_me:$LINENO: result: /var/log/sudo-session" >&5
echo "${ECHO_T}/var/log/sudo-session" >&6; }
cat >>confdefs.h <<\EOF
#define _PATH_SUDO_SESSDIR "/var/log/sudo-session"
EOF
sessdir="/var/log/sudo-session"
elif test -d "/var/adm"; then
{ echo "$as_me:$LINENO: result: /var/adm/sudo-session" >&5
echo "${ECHO_T}/var/adm/sudo-session" >&6; }
cat >>confdefs.h <<\EOF
#define _PATH_SUDO_SESSDIR "/var/adm/sudo-session"
EOF
sessdir="/var/adm/sudo-session"
else
{ echo "$as_me:$LINENO: result: /usr/adm/sudo-session" >&5
echo "${ECHO_T}/usr/adm/sudo-session" >&6; }
cat >>confdefs.h <<\EOF
#define _PATH_SUDO_SESSDIR "/usr/adm/sudo-session"
EOF
sessdir="/usr/adm/sudo-session"
fi
case "$with_passwd" in case "$with_passwd" in
yes|maybe) yes|maybe)
@@ -24462,7 +24664,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by sudo $as_me 1.7.2, which was This file was extended by sudo $as_me 1.7.3, which was
generated by GNU Autoconf 2.61. Invocation command line was generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -24511,7 +24713,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
sudo config.status 1.7.2 sudo config.status 1.7.3
configured by $0, generated by GNU Autoconf 2.61, configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

View File

@@ -4,7 +4,7 @@ dnl $Sudo$
dnl dnl
dnl Copyright (c) 1994-1996,1998-2009 Todd C. Miller <Todd.Miller@courtesan.com> dnl Copyright (c) 1994-1996,1998-2009 Todd C. Miller <Todd.Miller@courtesan.com>
dnl dnl
AC_INIT([sudo], [1.7.2], [http://www.sudo.ws/bugs/], [sudo]) AC_INIT([sudo], [1.7.3], [http://www.sudo.ws/bugs/], [sudo])
AC_CONFIG_HEADER(config.h pathnames.h) AC_CONFIG_HEADER(config.h pathnames.h)
dnl dnl
dnl This won't work before AC_INIT dnl This won't work before AC_INIT
@@ -1837,6 +1837,10 @@ AC_FUNC_GETGROUPS
AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \ AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \
strftime setrlimit initgroups getgroups fstat gettimeofday \ strftime setrlimit initgroups getgroups fstat gettimeofday \
setlocale getaddrinfo setsid setenv) setlocale getaddrinfo setsid setenv)
AC_CHECK_FUNCS(openpty, [], [AC_CHECK_LIB(util, openpty, [
SUDO_LIBS="${SUDO_LIBS} -lutil"
AC_DEFINE(HAVE_OPENPTY)
])])
AC_CHECK_FUNCS(unsetenv, SUDO_FUNC_UNSETENV_VOID) AC_CHECK_FUNCS(unsetenv, SUDO_FUNC_UNSETENV_VOID)
SUDO_FUNC_PUTENV_CONST SUDO_FUNC_PUTENV_CONST
if test -z "$SKIP_SETRESUID"; then if test -z "$SKIP_SETRESUID"; then
@@ -2543,6 +2547,7 @@ dnl Check for log file and timestamp locations
dnl dnl
SUDO_LOGFILE SUDO_LOGFILE
SUDO_TIMEDIR SUDO_TIMEDIR
SUDO_SESSDIR
dnl dnl
dnl Use passwd (and secureware) auth modules? dnl Use passwd (and secureware) auth modules?

View File

@@ -314,6 +314,10 @@ struct sudo_defs_types sudo_defs_table[] = {
"umask_override", T_FLAG, "umask_override", T_FLAG,
"The umask specified in sudoers will override the user's, even if it is more permissive", "The umask specified in sudoers will override the user's, even if it is more permissive",
NULL, NULL,
}, {
"script", T_FLAG,
"Log a transcript of the command being run",
NULL,
}, { }, {
NULL, 0, NULL NULL, 0, NULL
} }

View File

@@ -144,6 +144,8 @@
#define I_FAST_GLOB 71 #define I_FAST_GLOB 71
#define def_umask_override (sudo_defs_table[72].sd_un.flag) #define def_umask_override (sudo_defs_table[72].sd_un.flag)
#define I_UMASK_OVERRIDE 72 #define I_UMASK_OVERRIDE 72
#define def_script (sudo_defs_table[73].sd_un.flag)
#define I_SCRIPT 73
enum def_tupple { enum def_tupple {
never, never,

View File

@@ -232,3 +232,6 @@ fast_glob
umask_override umask_override
T_FLAG T_FLAG
"The umask specified in sudoers will override the user's, even if it is more permissive" "The umask specified in sudoers will override the user's, even if it is more permissive"
script
T_FLAG
"Log a transcript of the command being run"

737
gram.c

File diff suppressed because it is too large Load Diff

20
gram.h
View File

@@ -16,15 +16,17 @@
#define EXEC 272 #define EXEC 272
#define SETENV 273 #define SETENV 273
#define NOSETENV 274 #define NOSETENV 274
#define ALL 275 #define SCRIPT 275
#define COMMENT 276 #define NOSCRIPT 276
#define HOSTALIAS 277 #define ALL 277
#define CMNDALIAS 278 #define COMMENT 278
#define USERALIAS 279 #define HOSTALIAS 279
#define RUNASALIAS 280 #define CMNDALIAS 280
#define ERROR 281 #define USERALIAS 281
#define TYPE 282 #define RUNASALIAS 282
#define ROLE 283 #define ERROR 283
#define TYPE 284
#define ROLE 285
#ifndef YYSTYPE_DEFINED #ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED #define YYSTYPE_DEFINED
typedef union { typedef union {

12
gram.y
View File

@@ -146,6 +146,8 @@ yyerror(s)
%token <tok> EXEC /* don't preload dummy execve() */ %token <tok> EXEC /* don't preload dummy execve() */
%token <tok> SETENV /* user may set environment for cmnd */ %token <tok> SETENV /* user may set environment for cmnd */
%token <tok> NOSETENV /* user may not set environment */ %token <tok> NOSETENV /* user may not set environment */
%token <tok> SCRIPT /* log a transcript of the cmnd */
%token <tok> NOSCRIPT /* don't log a transcript of the cmnd */
%token <tok> ALL /* ALL keyword */ %token <tok> ALL /* ALL keyword */
%token <tok> COMMENT /* comment and/or carriage return */ %token <tok> COMMENT /* comment and/or carriage return */
%token <tok> HOSTALIAS /* Host_Alias keyword */ %token <tok> HOSTALIAS /* Host_Alias keyword */
@@ -317,6 +319,8 @@ cmndspeclist : cmndspec
if ($3->tags.setenv == UNSPEC && if ($3->tags.setenv == UNSPEC &&
$3->prev->tags.setenv != IMPLIED) $3->prev->tags.setenv != IMPLIED)
$3->tags.setenv = $3->prev->tags.setenv; $3->tags.setenv = $3->prev->tags.setenv;
if ($3->tags.script == UNSPEC)
$3->tags.script = $3->prev->tags.script;
if ((tq_empty(&$3->runasuserlist) && if ((tq_empty(&$3->runasuserlist) &&
tq_empty(&$3->runasgrouplist)) && tq_empty(&$3->runasgrouplist)) &&
(!tq_empty(&$3->prev->runasuserlist) || (!tq_empty(&$3->prev->runasuserlist) ||
@@ -422,7 +426,7 @@ runaslist : userlist {
; ;
cmndtag : /* empty */ { cmndtag : /* empty */ {
$$.nopasswd = $$.noexec = $$.setenv = UNSPEC; $$.nopasswd = $$.noexec = $$.setenv = $$.script = UNSPEC;
} }
| cmndtag NOPASSWD { | cmndtag NOPASSWD {
$$.nopasswd = TRUE; $$.nopasswd = TRUE;
@@ -442,6 +446,12 @@ cmndtag : /* empty */ {
| cmndtag NOSETENV { | cmndtag NOSETENV {
$$.setenv = FALSE; $$.setenv = FALSE;
} }
| cmndtag SCRIPT {
$$.script = TRUE;
}
| cmndtag NOSCRIPT {
$$.script = FALSE;
}
; ;
cmnd : ALL { cmnd : ALL {

View File

@@ -254,6 +254,8 @@ sudo_file_lookup(nss, validated, pwflag)
def_noexec = tags->noexec; def_noexec = tags->noexec;
if (tags->setenv != UNSPEC) if (tags->setenv != UNSPEC)
def_setenv = tags->setenv; def_setenv = tags->setenv;
if (tags->script != UNSPEC)
def_script = tags->script;
} }
} else if (match == DENY) { } else if (match == DENY) {
SET(validated, VALIDATE_NOT_OK); SET(validated, VALIDATE_NOT_OK);
@@ -295,6 +297,11 @@ sudo_file_append_cmnd(cs, tags, lbuf)
"PASSWD: ", NULL); "PASSWD: ", NULL);
tags->nopasswd = cs->tags.nopasswd; tags->nopasswd = cs->tags.nopasswd;
} }
if (TAG_CHANGED(script)) {
lbuf_append(lbuf, cs->tags.script ? "SCRIPT: " :
"NOSCRIPT: ", NULL);
tags->script = cs->tags.script;
}
m = cs->cmnd; m = cs->cmnd;
print_member(lbuf, m->name, m->type, m->negated, print_member(lbuf, m->name, m->type, m->negated,
CMNDALIAS); CMNDALIAS);
@@ -316,6 +323,7 @@ sudo_file_display_priv_short(pw, us, lbuf)
tags.noexec = UNSPEC; tags.noexec = UNSPEC;
tags.setenv = UNSPEC; tags.setenv = UNSPEC;
tags.nopasswd = UNSPEC; tags.nopasswd = UNSPEC;
tags.script = UNSPEC;
lbuf_append(lbuf, " ", NULL); lbuf_append(lbuf, " ", NULL);
tq_foreach_fwd(&priv->cmndlist, cs) { tq_foreach_fwd(&priv->cmndlist, cs) {
if (cs != tq_first(&priv->cmndlist)) if (cs != tq_first(&priv->cmndlist))
@@ -367,6 +375,7 @@ sudo_file_display_priv_long(pw, us, lbuf)
tags.noexec = UNSPEC; tags.noexec = UNSPEC;
tags.setenv = UNSPEC; tags.setenv = UNSPEC;
tags.nopasswd = UNSPEC; tags.nopasswd = UNSPEC;
tags.script = UNSPEC;
lbuf_print(lbuf); /* force a newline */ lbuf_print(lbuf); /* force a newline */
lbuf_append(lbuf, "Sudoers entry:", NULL); lbuf_append(lbuf, "Sudoers entry:", NULL);
lbuf_print(lbuf); lbuf_print(lbuf);

View File

@@ -45,7 +45,7 @@ struct cmndtag {
__signed char nopasswd; __signed char nopasswd;
__signed char noexec; __signed char noexec;
__signed char setenv; __signed char setenv;
__signed char extra; __signed char script;
}; };
/* /*

View File

@@ -68,6 +68,14 @@
#undef _PATH_SUDO_TIMEDIR #undef _PATH_SUDO_TIMEDIR
#endif /* _PATH_SUDO_TIMEDIR */ #endif /* _PATH_SUDO_TIMEDIR */
/*
* Where to put the session files. Defaults to /var/log/sudo-session,
* /var/adm/sudo-session or /usr/adm/sudo-session depending on what exists.
*/
#ifndef _PATH_SUDO_SESSDIR
#undef _PATH_SUDO_SESSDIR
#endif /* _PATH_SUDO_SESSDIR */
/* /*
* Where to put the sudo log file when logging to a file. Defaults to * Where to put the sudo log file when logging to a file. Defaults to
* /var/log/sudo.log if /var/log exists, else /var/adm/sudo.log. * /var/log/sudo.log if /var/log exists, else /var/adm/sudo.log.

27
sudo.c
View File

@@ -165,6 +165,10 @@ static struct sudo_nss_list *snl;
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
/* XXX - script.c */
extern int script_fds[5];
extern void term_restore __P((int));
int int
main(argc, argv, envp) main(argc, argv, envp)
int argc; int argc;
@@ -498,6 +502,10 @@ main(argc, argv, envp)
/* Must audit before uid change. */ /* Must audit before uid change. */
audit_success(NewArgv); audit_success(NewArgv);
/* Open tty as needed */
if (def_script)
script_setup();
/* Become specified user or root if executing a command. */ /* Become specified user or root if executing a command. */
if (ISSET(sudo_mode, MODE_RUN)) if (ISSET(sudo_mode, MODE_RUN))
set_perms(PERM_FULL_RUNAS); set_perms(PERM_FULL_RUNAS);
@@ -540,7 +548,16 @@ main(argc, argv, envp)
sudo_endpwent(); sudo_endpwent();
sudo_endgrent(); sudo_endgrent();
closefrom(def_closefrom); /* Move pty master/slave to low numbered fd and close the rest. */
fd = def_closefrom;
if (def_script) {
int i;
for (i = 0; i < 5; i++) {
dup2(script_fds[i], fd);
script_fds[i] = fd++;
}
}
closefrom(fd);
#ifndef PROFILING #ifndef PROFILING
if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) { if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) {
@@ -548,11 +565,15 @@ main(argc, argv, envp)
exit(0); exit(0);
} else { } else {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
/* XXX - script support */
if (is_selinux_enabled() > 0 && user_role != NULL) if (is_selinux_enabled() > 0 && user_role != NULL)
selinux_exec(user_role, user_type, NewArgv, selinux_exec(user_role, user_type, NewArgv,
ISSET(sudo_mode, MODE_LOGIN_SHELL)); ISSET(sudo_mode, MODE_LOGIN_SHELL));
#endif #endif
execv(safe_cmnd, NewArgv); if (def_script)
script_execv(safe_cmnd, NewArgv);
else
execv(safe_cmnd, NewArgv);
} }
#else #else
exit(0); exit(0);
@@ -1446,6 +1467,8 @@ cleanup(gotsignal)
sudo_endpwent(); sudo_endpwent();
sudo_endgrent(); sudo_endgrent();
} }
if (def_script)
term_restore(STDIN_FILENO);
} }
static void static void

2
sudo.h
View File

@@ -324,6 +324,8 @@ void selinux_exec __P((char *, char *, char **, int));
#ifdef HAVE_GETUSERATTR #ifdef HAVE_GETUSERATTR
void aix_setlimits __P((char *)); void aix_setlimits __P((char *));
#endif #endif
int script_execv __P((const char *, char * const *));
void script_setup __P((void));
YY_DECL; YY_DECL;
/* Only provide extern declarations outside of sudo.c. */ /* Only provide extern declarations outside of sudo.c. */

77
term.c
View File

@@ -132,9 +132,32 @@ term_noecho(fd)
} }
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
int int
term_raw(fd) term_raw(fd)
int fd; int fd;
{
struct termios term;
if (!changed && tcgetattr(fd, &oterm) != 0)
return(0);
(void) memcpy(&term, &oterm, sizeof(term));
/* Set terminal to raw mode */
term.c_iflag &= ~(BRKINT|ICRNL|IGNCR|INLCR|IXON|PARMRK);
term.c_oflag &= ~OPOST;
term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) == 0) {
changed = 1;
return(1);
}
return(0);
}
int
term_cbreak(fd)
int fd;
{ {
if (!changed && tcgetattr(fd, &oterm) != 0) if (!changed && tcgetattr(fd, &oterm) != 0)
return(0); return(0);
@@ -156,11 +179,42 @@ term_raw(fd)
return(0); return(0);
} }
int
term_copy(src, dst)
int src;
int dst;
{
struct termios tt;
if (tcgetattr(src, &tt) != 0)
return(0);
if (tcsetattr(dst, TCSAFLUSH, &tt) != 0)
return(0);
return(1);
}
#else /* SGTTY */ #else /* SGTTY */
int int
term_raw(fd) term_raw(fd)
int fd; int fd;
{
if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0)
return(0);
(void) memcpy(&term, &oterm, sizeof(term));
/* Set terminal to raw mode */
CLR(term.c_lflag, ECHO);
SET(term.sg_flags, RAW);
if (ioctl(fd, TIOCSETP, &term) == 0) {
changed = 1;
return(1);
}
return(0);
}
int
term_cbreak(fd)
int fd;
{ {
if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0) if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0)
return(0); return(0);
@@ -177,4 +231,27 @@ term_raw(fd)
return(0); return(0);
} }
int
term_copy(src, dst)
int src;
int dst;
{
struct sgttyb b;
struct tchars tc;
struct ltchars lc;
int l, lb;
if (ioctl(src, TIOCGETP, &b) != 0 || ioctl(src, TIOCGETC, &tc) != 0 ||
ioctl(src, TIOCGETD, &l) != 0 || ioctl(src, TIOCGLTC, &lc) != 0 ||
ioctl(src, TIOCLGET, &lb)) {
return(0);
}
if (ioctl(dst, TIOCSETP, &b) != 0 || ioctl(dst, TIOCSETC, &tc) != 0 ||
ioctl(dst, TIOCSLTC, &lc) != 0 || ioctl(dst, TIOCLSET, &lb) != 0 ||
ioctl(dst, TIOCSETD, &l) != 0) {
return(0);
}
return(1);
}
#endif #endif

View File

@@ -68,7 +68,7 @@ static char *sudo_askpass __P((const char *));
extern int term_restore __P((int)); extern int term_restore __P((int));
extern int term_noecho __P((int)); extern int term_noecho __P((int));
extern int term_raw __P((int)); extern int term_cbreak __P((int));
/* /*
* Like getpass(3) but with timeout and echo flags. * Like getpass(3) but with timeout and echo flags.
@@ -120,7 +120,7 @@ restart:
(void) sigaction(SIGTTOU, &sa, &savettou); (void) sigaction(SIGTTOU, &sa, &savettou);
if (def_pwfeedback) if (def_pwfeedback)
neednl = term_raw(input); neednl = term_cbreak(input);
else else
neednl = term_noecho(input); neednl = term_noecho(input);