From 3bfce30a8585fd6c4aee659d2013044eb1a55fbb Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 6 Aug 2009 00:04:14 +0000 Subject: [PATCH] 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. --- Makefile.in | 8 +- aclocal.m4 | 27 +- compat.h | 1 + config.h.in | 3 + configure | 220 +++++++++++++++- configure.in | 7 +- def_data.c | 4 + def_data.h | 2 + def_data.in | 3 + gram.c | 669 +++++++++++++++++++++++++------------------------ gram.h | 20 +- gram.y | 12 +- parse.c | 9 + parse.h | 2 +- pathnames.h.in | 8 + sudo.c | 27 +- sudo.h | 2 + term.c | 77 ++++++ tgetpass.c | 4 +- 19 files changed, 754 insertions(+), 351 deletions(-) diff --git a/Makefile.in b/Makefile.in index f665b2cb6..f0eed2a8e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ 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 \ - 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 \ 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 \ @@ -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 \ getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ - interfaces.o lbuf.o logging.o parse.o pwutil.o set_perms.o \ - sudo.o sudo_edit.o sudo_nss.o term.o tgetpass.o + interfaces.o lbuf.o logging.o parse.o pwutil.o script.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 \ find_path.o pwutil.o @@ -285,6 +285,8 @@ pwutil.o: $(srcdir)/pwutil.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c redblack.o: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h $(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) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/set_perms.c sigaction.o: $(srcdir)/sigaction.c $(srcdir)/compat.h diff --git a/aclocal.m4 b/aclocal.m4 index 1a6d99049..f333ed30e 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -134,7 +134,8 @@ fi ])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 AC_DEFUN(SUDO_TIMEDIR, [AC_MSG_CHECKING(for timestamp file location) if test -n "$with_timedir"; then @@ -156,6 +157,30 @@ else fi ])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 SUDO_CHECK_TYPE(TYPE, DEFAULT) dnl XXX - should require the check for unistd.h... diff --git a/compat.h b/compat.h index 6851bde88..7cededc65 100644 --- a/compat.h +++ b/compat.h @@ -198,6 +198,7 @@ int isblank __P((int)); # define SA_ONSTACK SV_ONSTACK # define SA_RESTART SV_INTERRUPT /* opposite effect */ # define SA_RESETHAND SV_RESETHAND +# define SA_NOCLDSTOP SV_NOCLDSTOP # define sa_handler sv_handler # define sa_mask sv_mask # define sa_flags sv_flags diff --git a/config.h.in b/config.h.in index 18698f4f9..62f2a3902 100644 --- a/config.h.in +++ b/config.h.in @@ -318,6 +318,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETGROUP_H +/* Define to 1 if you have the `openpty' function. */ +#undef HAVE_OPENPTY + /* Define to 1 if you use NRL OPIE. */ #undef HAVE_OPIE diff --git a/configure b/configure index 1d45b2118..cb4dd8a82 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # 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 . # @@ -724,8 +724,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.7.2' -PACKAGE_STRING='sudo 1.7.2' +PACKAGE_VERSION='1.7.3' +PACKAGE_STRING='sudo 1.7.3' PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/' # 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. # This message is too long to be a string in the A/UX 3.1 sh. 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]... @@ -1481,7 +1481,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.7.2:";; + short | recursive ) echo "Configuration of sudo 1.7.3:";; esac cat <<\_ACEOF @@ -1683,7 +1683,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.7.2 +sudo configure 1.7.3 generated by GNU Autoconf 2.61 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 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 $ $0 $@ @@ -15921,6 +15921,172 @@ fi 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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` @@ -23997,6 +24163,42 @@ EOF timedir="/usr/adm/sudo" 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 <&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 yes|maybe) @@ -24462,7 +24664,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. 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 CONFIG_FILES = $CONFIG_FILES @@ -24511,7 +24713,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -sudo config.status 1.7.2 +sudo config.status 1.7.3 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.in b/configure.in index e33e343b0..a1d35bf2a 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl $Sudo$ dnl dnl Copyright (c) 1994-1996,1998-2009 Todd C. Miller 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) dnl 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 \ strftime setrlimit initgroups getgroups fstat gettimeofday \ 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) SUDO_FUNC_PUTENV_CONST if test -z "$SKIP_SETRESUID"; then @@ -2543,6 +2547,7 @@ dnl Check for log file and timestamp locations dnl SUDO_LOGFILE SUDO_TIMEDIR +SUDO_SESSDIR dnl dnl Use passwd (and secureware) auth modules? diff --git a/def_data.c b/def_data.c index 8498464db..2ba2be773 100644 --- a/def_data.c +++ b/def_data.c @@ -314,6 +314,10 @@ struct sudo_defs_types sudo_defs_table[] = { "umask_override", T_FLAG, "The umask specified in sudoers will override the user's, even if it is more permissive", NULL, + }, { + "script", T_FLAG, + "Log a transcript of the command being run", + NULL, }, { NULL, 0, NULL } diff --git a/def_data.h b/def_data.h index bccfd160b..a8dadb4f8 100644 --- a/def_data.h +++ b/def_data.h @@ -144,6 +144,8 @@ #define I_FAST_GLOB 71 #define def_umask_override (sudo_defs_table[72].sd_un.flag) #define I_UMASK_OVERRIDE 72 +#define def_script (sudo_defs_table[73].sd_un.flag) +#define I_SCRIPT 73 enum def_tupple { never, diff --git a/def_data.in b/def_data.in index 625c14097..cb31693e1 100644 --- a/def_data.in +++ b/def_data.in @@ -232,3 +232,6 @@ fast_glob umask_override T_FLAG "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" diff --git a/gram.c b/gram.c index 1f0117e2b..e10c43dde 100644 --- a/gram.c +++ b/gram.c @@ -19,7 +19,7 @@ static char yyrcsid[] #define YYPREFIX "yy" #line 2 "gram.y" /* - * Copyright (c) 1996, 1998-2005, 2007-2008 + * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -166,15 +166,17 @@ typedef union { #define EXEC 272 #define SETENV 273 #define NOSETENV 274 -#define ALL 275 -#define COMMENT 276 -#define HOSTALIAS 277 -#define CMNDALIAS 278 -#define USERALIAS 279 -#define RUNASALIAS 280 -#define ERROR 281 -#define TYPE 282 -#define ROLE 283 +#define SCRIPT 275 +#define NOSCRIPT 276 +#define ALL 277 +#define COMMENT 278 +#define HOSTALIAS 279 +#define CMNDALIAS 280 +#define USERALIAS 281 +#define RUNASALIAS 282 +#define ERROR 283 +#define TYPE 284 +#define ROLE 285 #define YYERRCODE 256 #if defined(__cplusplus) || defined(__STDC__) const short yylhs[] = @@ -187,11 +189,11 @@ short yylhs[] = 3, 3, 3, 20, 20, 19, 10, 10, 8, 8, 8, 8, 8, 2, 2, 1, 6, 6, 23, 24, 22, 22, 22, 22, 22, 17, 17, 18, 18, 18, - 21, 21, 21, 21, 21, 21, 21, 5, 5, 5, - 28, 28, 31, 9, 9, 29, 29, 32, 7, 7, - 30, 30, 33, 27, 27, 34, 13, 13, 11, 11, - 12, 12, 12, 12, 12, 16, 16, 14, 14, 15, - 15, 15, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 5, + 5, 5, 28, 28, 31, 9, 9, 29, 29, 32, + 7, 7, 30, 30, 33, 27, 27, 34, 13, 13, + 11, 11, 12, 12, 12, 12, 12, 16, 16, 14, + 14, 15, 15, 15, }; #if defined(__cplusplus) || defined(__STDC__) const short yylen[] = @@ -204,11 +206,11 @@ short yylen[] = 3, 3, 3, 1, 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, 3, 4, 1, 2, 3, 3, 0, 1, 1, 2, 2, 0, 3, 1, 3, 2, - 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 1, 3, 3, 1, 3, 1, 3, 3, 1, 3, - 1, 3, 3, 1, 3, 3, 1, 3, 1, 2, - 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, - 1, 1, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 3, 3, 1, 3, 1, 3, 3, + 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, + 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, + 2, 1, 1, 1, }; #if defined(__cplusplus) || defined(__STDC__) const short yydefred[] = @@ -216,21 +218,21 @@ const short yydefred[] = short yydefred[] = #endif { 0, - 0, 81, 83, 84, 85, 0, 0, 0, 0, 0, - 82, 5, 0, 0, 0, 0, 0, 0, 77, 79, + 0, 83, 85, 86, 87, 0, 0, 0, 0, 0, + 84, 5, 0, 0, 0, 0, 0, 0, 79, 81, 0, 0, 3, 6, 0, 0, 17, 0, 29, 32, - 31, 33, 30, 0, 27, 0, 64, 0, 0, 60, - 59, 58, 0, 37, 69, 0, 0, 0, 61, 0, - 0, 66, 0, 0, 74, 0, 0, 71, 80, 0, + 31, 33, 30, 0, 27, 0, 66, 0, 0, 62, + 61, 60, 0, 37, 71, 0, 0, 0, 63, 0, + 0, 68, 0, 0, 76, 0, 0, 73, 82, 0, 0, 24, 0, 4, 0, 0, 0, 20, 0, 28, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 78, 0, 0, 21, 22, - 23, 18, 65, 70, 0, 62, 0, 67, 0, 75, - 0, 72, 0, 34, 0, 0, 25, 0, 0, 0, - 0, 0, 0, 51, 0, 0, 90, 92, 91, 0, - 86, 88, 0, 0, 47, 35, 0, 0, 0, 44, - 45, 89, 0, 0, 40, 39, 52, 53, 54, 55, - 56, 57, 36, 87, + 0, 0, 0, 0, 0, 80, 0, 0, 21, 22, + 23, 18, 67, 72, 0, 64, 0, 69, 0, 77, + 0, 74, 0, 34, 0, 0, 25, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 92, 94, 93, 0, + 88, 90, 0, 0, 47, 35, 0, 0, 0, 44, + 45, 91, 0, 0, 40, 39, 52, 53, 54, 55, + 56, 57, 58, 59, 36, 89, }; #if defined(__cplusplus) || defined(__STDC__) const short yydgoto[] = @@ -248,232 +250,238 @@ const short yysindex[] = #else short yysindex[] = #endif - { 405, - -266, 0, 0, 0, 0, -9, 463, 510, 510, -2, - 0, 0, -243, -218, -215, -211, -225, 0, 0, 0, - -28, 405, 0, 0, -36, -210, 0, 4, 0, 0, - 0, 0, 0, -231, 0, -33, 0, -25, -25, 0, - 0, 0, -240, 0, 0, -21, -6, -1, 0, 2, - 6, 0, 7, 8, 0, 9, 11, 0, 0, 510, - -22, 0, 13, 0, -203, -201, -198, 0, -9, 0, - 463, 4, 4, 4, 0, -2, 4, 463, -243, -2, - -218, 510, -215, 510, -211, 0, 27, 463, 0, 0, - 0, 0, 0, 0, 28, 0, 30, 0, 31, 0, - 31, 0, 141, 0, 32, -262, 0, -27, -16, 36, - 27, 18, 19, 0, -200, -202, 0, 0, 0, -217, - 0, 0, 39, -27, 0, 0, -177, -175, 250, 0, - 0, 0, -27, 39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,}; + { -26, + -272, 0, 0, 0, 0, -16, 481, 485, 485, -31, + 0, 0, -237, -232, -228, -227, -238, 0, 0, 0, + 417, -26, 0, 0, -2, -217, 0, 7, 0, 0, + 0, 0, 0, -223, 0, -28, 0, -25, -25, 0, + 0, 0, -248, 0, 0, -11, -14, -6, 0, -3, + -5, 0, -1, 4, 0, 2, 6, 0, 0, 485, + -17, 0, 8, 0, -198, -196, -195, 0, -16, 0, + 481, 7, 7, 7, 0, -31, 7, 481, -237, -31, + -232, 485, -228, 485, -227, 0, 29, 481, 0, 0, + 0, 0, 0, 0, 26, 0, 30, 0, 31, 0, + 31, 0, 457, 0, 32, -270, 0, -30, -8, 36, + 29, 11, 12, 0, -206, -205, 0, 0, 0, -245, + 0, 0, 35, -30, 0, 0, -182, -180, 453, 0, + 0, 0, -30, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,}; #if defined(__cplusplus) || defined(__STDC__) const short yyrindex[] = #else short yyrindex[] = #endif - { 90, + { 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 91, 0, 0, 1, 0, 0, 156, 0, 0, + 0, 89, 0, 0, 1, 0, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, - 206, 0, 0, 237, 0, 0, 274, 0, 0, 0, - 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, - 0, 326, 352, 378, 0, 0, 430, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -29, 0, 0, 0, - 0, 0, 0, 0, 26, 0, 52, 0, 78, 0, - 104, 0, 0, 0, 130, 442, 0, 0, 51, 0, - -29, 0, 0, 0, 461, 485, 0, 0, 0, 0, - 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,}; + 0, 0, 0, 0, 0, 0, 0, 190, 0, 0, + 217, 0, 0, 244, 0, 0, 271, 0, 0, 0, + 0, 0, 298, 0, 0, 0, 0, 0, 0, 0, + 0, 325, 352, 379, 0, 0, 406, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 432, 0, 0, 0, + 0, 0, 0, 0, 28, 0, 55, 0, 82, 0, + 109, 0, 0, 0, 136, 480, 0, 0, 49, 0, + 432, 0, 0, 0, 507, 534, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,}; #if defined(__cplusplus) || defined(__STDC__) const short yygindex[] = #else short yygindex[] = #endif { 0, - -18, 0, 29, 15, 56, -73, 16, 63, -5, 34, - 40, 84, 5, -31, -17, -15, 0, 0, 24, 0, - 0, 0, -10, -8, 0, 92, 0, 0, 0, 0, - 37, 38, 33, 41, + -18, 0, 25, 10, 52, -72, 16, 63, -7, 27, + 39, 83, 3, -32, -15, -22, 0, 0, 15, 0, + 0, 0, -12, -4, 0, 85, 0, 0, 0, 0, + 33, 37, 23, 34, }; -#define YYTABLESIZE 785 +#define YYTABLESIZE 811 #if defined(__cplusplus) || defined(__STDC__) const short yytable[] = #else short yytable[] = #endif - { 26, - 19, 36, 94, 46, 34, 120, 66, 26, 67, 24, - 71, 26, 38, 39, 47, 60, 40, 41, 60, 112, - 113, 71, 76, 26, 65, 63, 29, 60, 30, 31, - 43, 32, 2, 19, 42, 3, 4, 5, 87, 50, - 117, 124, 53, 33, 19, 118, 56, 69, 68, 11, - 72, 68, 73, 74, 78, 143, 79, 119, 63, 89, - 77, 90, 80, 81, 91, 83, 103, 82, 85, 84, - 88, 71, 95, 76, 60, 111, 125, 76, 127, 128, - 113, 112, 133, 63, 68, 135, 99, 136, 101, 1, - 2, 48, 126, 50, 49, 97, 70, 92, 75, 86, - 59, 144, 132, 73, 93, 131, 130, 109, 134, 68, - 76, 107, 0, 64, 0, 96, 0, 102, 98, 0, - 0, 0, 0, 100, 0, 0, 0, 0, 0, 26, - 0, 0, 0, 0, 0, 76, 73, 0, 0, 0, + { 36, + 19, 43, 120, 94, 26, 24, 17, 26, 40, 41, + 38, 39, 117, 112, 113, 71, 26, 118, 60, 2, + 47, 26, 3, 4, 5, 50, 71, 65, 42, 53, + 56, 119, 76, 19, 29, 60, 30, 31, 11, 32, + 66, 68, 67, 87, 19, 72, 78, 73, 74, 124, + 69, 79, 81, 33, 70, 77, 145, 80, 65, 82, + 65, 83, 84, 85, 89, 88, 90, 91, 103, 71, + 95, 127, 128, 76, 60, 111, 125, 112, 133, 113, + 135, 78, 136, 1, 99, 65, 101, 70, 2, 48, + 50, 49, 126, 92, 75, 97, 70, 93, 86, 59, + 146, 134, 107, 131, 132, 109, 64, 102, 75, 0, + 130, 96, 70, 0, 78, 0, 100, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, - 0, 73, 26, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 26, 12, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, - 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, - 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 25, 0, 46, 46, 29, - 117, 30, 31, 25, 32, 118, 8, 25, 10, 46, - 46, 46, 46, 46, 46, 46, 33, 119, 0, 25, - 0, 0, 46, 46, 40, 41, 19, 0, 19, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 8, - 0, 0, 42, 11, 0, 19, 19, 19, 19, 19, - 19, 63, 43, 63, 0, 0, 63, 63, 63, 63, - 63, 63, 63, 63, 0, 0, 0, 0, 0, 7, - 63, 63, 63, 63, 63, 63, 11, 68, 0, 68, - 0, 0, 68, 68, 68, 68, 68, 68, 68, 68, - 0, 0, 0, 0, 0, 15, 68, 68, 68, 68, - 68, 68, 7, 76, 0, 76, 0, 0, 76, 76, - 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, - 0, 13, 76, 76, 76, 76, 76, 76, 15, 73, - 0, 73, 0, 0, 73, 73, 73, 73, 73, 73, - 73, 73, 0, 0, 0, 0, 0, 14, 73, 73, - 73, 73, 73, 73, 13, 26, 0, 26, 0, 0, - 26, 26, 26, 26, 26, 26, 26, 26, 2, 0, - 0, 3, 4, 5, 26, 26, 26, 26, 26, 26, - 14, 12, 0, 12, 0, 11, 12, 12, 12, 12, - 12, 12, 12, 12, 0, 0, 0, 0, 0, 16, - 12, 12, 12, 12, 12, 12, 9, 17, 9, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, - 9, 10, 16, 10, 0, 0, 10, 10, 10, 10, - 10, 10, 10, 10, 41, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, - 0, 0, 8, 42, 8, 34, 0, 8, 8, 8, - 8, 8, 8, 8, 8, 0, 40, 41, 0, 0, - 0, 8, 8, 8, 8, 8, 8, 43, 137, 138, - 139, 140, 141, 142, 42, 0, 0, 0, 0, 11, - 0, 11, 0, 0, 11, 11, 11, 11, 11, 11, - 11, 11, 17, 0, 0, 0, 0, 0, 11, 11, - 11, 11, 11, 11, 0, 7, 0, 7, 0, 0, - 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 26, 0, 0, 0, 78, + 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 75, 0, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 0, 0, 26, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 9, 0, 0, 40, 41, 117, 0, 1, + 25, 2, 118, 25, 3, 4, 5, 6, 7, 8, + 9, 10, 25, 8, 0, 42, 119, 25, 0, 10, + 11, 12, 13, 14, 15, 16, 19, 0, 19, 0, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 0, + 11, 0, 0, 0, 0, 0, 8, 19, 19, 19, + 19, 19, 19, 65, 0, 65, 0, 0, 65, 65, + 65, 65, 65, 65, 65, 65, 0, 7, 0, 0, + 0, 0, 0, 11, 65, 65, 65, 65, 65, 65, + 70, 0, 70, 0, 0, 70, 70, 70, 70, 70, + 70, 70, 70, 0, 15, 0, 0, 0, 0, 0, + 7, 70, 70, 70, 70, 70, 70, 78, 0, 78, + 0, 0, 78, 78, 78, 78, 78, 78, 78, 78, + 0, 13, 0, 0, 0, 0, 0, 15, 78, 78, + 78, 78, 78, 78, 75, 0, 75, 0, 0, 75, + 75, 75, 75, 75, 75, 75, 75, 0, 14, 0, + 0, 0, 0, 0, 13, 75, 75, 75, 75, 75, + 75, 26, 0, 26, 0, 0, 26, 26, 26, 26, + 26, 26, 26, 26, 0, 16, 0, 0, 0, 0, + 0, 14, 26, 26, 26, 26, 26, 26, 12, 0, + 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, + 12, 0, 0, 0, 0, 0, 0, 0, 16, 12, + 12, 12, 12, 12, 12, 9, 0, 9, 0, 34, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 60, 0, 0, 0, 46, 0, 9, 9, 9, 9, + 9, 9, 10, 0, 10, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 43, 0, 0, 0, 17, + 0, 0, 0, 10, 10, 10, 10, 10, 10, 8, + 0, 8, 0, 0, 8, 8, 8, 8, 8, 8, + 8, 8, 41, 34, 108, 0, 0, 17, 0, 0, + 8, 8, 8, 8, 8, 8, 11, 0, 11, 0, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 42, + 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, + 11, 11, 11, 7, 0, 7, 0, 0, 7, 7, + 7, 7, 7, 7, 7, 7, 43, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, - 0, 15, 0, 15, 0, 0, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, - 15, 15, 15, 15, 15, 15, 0, 13, 0, 13, + 15, 0, 15, 0, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 13, 0, 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, - 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, - 13, 13, 0, 14, 0, 14, 0, 0, 14, 14, - 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, - 0, 0, 14, 14, 14, 14, 14, 14, 0, 0, - 1, 0, 2, 0, 0, 3, 4, 5, 6, 7, - 8, 9, 10, 0, 0, 0, 0, 0, 0, 11, - 12, 13, 14, 15, 16, 16, 0, 16, 0, 0, - 16, 16, 16, 16, 16, 16, 16, 16, 41, 41, - 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, - 41, 41, 41, 41, 41, 41, 41, 42, 42, 0, - 29, 0, 30, 31, 0, 32, 0, 0, 0, 42, - 42, 42, 42, 42, 42, 42, 0, 33, 0, 0, - 0, 43, 43, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, + 13, 13, 13, 13, 14, 0, 14, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 16, 0, 16, 0, 0, 16, 16, 16, 16, + 16, 16, 16, 16, 29, 0, 30, 31, 0, 32, + 0, 0, 16, 16, 16, 16, 16, 16, 46, 46, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 40, + 41, 0, 0, 0, 2, 46, 46, 3, 4, 5, + 0, 137, 138, 139, 140, 141, 142, 143, 144, 42, + 0, 0, 0, 11, 0, 0, 41, 41, 29, 0, + 30, 31, 2, 32, 0, 3, 4, 5, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 33, 0, 0, + 0, 11, 0, 42, 42, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, + 43, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, + 43, }; #if defined(__cplusplus) || defined(__STDC__) const short yycheck[] = #else short yycheck[] = #endif - { 33, - 0, 7, 76, 33, 33, 33, 43, 33, 45, 276, - 44, 33, 8, 9, 258, 44, 257, 258, 44, 282, - 283, 44, 44, 33, 61, 0, 258, 44, 260, 261, - 33, 263, 258, 33, 275, 261, 262, 263, 61, 258, - 258, 58, 258, 275, 44, 263, 258, 44, 259, 275, - 36, 0, 38, 39, 61, 129, 58, 275, 33, 263, - 46, 263, 61, 58, 263, 58, 40, 61, 58, 61, - 58, 44, 78, 44, 44, 44, 41, 0, 61, 61, - 283, 282, 44, 58, 33, 263, 82, 263, 84, 0, - 0, 41, 111, 41, 41, 80, 34, 69, 43, 60, - 17, 133, 120, 0, 71, 116, 115, 103, 124, 58, - 33, 88, -1, 22, -1, 79, -1, 85, 81, -1, - -1, -1, -1, 83, -1, -1, -1, -1, -1, 0, - -1, -1, -1, -1, -1, 58, 33, -1, -1, -1, + { 7, + 0, 33, 33, 76, 33, 278, 33, 33, 257, 258, + 8, 9, 258, 284, 285, 44, 33, 263, 44, 258, + 258, 33, 261, 262, 263, 258, 44, 0, 277, 258, + 258, 277, 44, 33, 258, 44, 260, 261, 277, 263, + 43, 259, 45, 61, 44, 36, 61, 38, 39, 58, + 44, 58, 58, 277, 0, 46, 129, 61, 61, 61, + 33, 58, 61, 58, 263, 58, 263, 263, 40, 44, + 78, 61, 61, 44, 44, 44, 41, 284, 44, 285, + 263, 0, 263, 0, 82, 58, 84, 33, 0, 41, + 41, 41, 111, 69, 43, 80, 34, 71, 60, 17, + 133, 124, 88, 116, 120, 103, 22, 85, 0, -1, + 115, 79, 58, -1, 33, -1, 83, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, - -1, 58, 33, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, - 0, -1, -1, -1, -1, -1, -1, 58, 33, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, - -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 259, -1, 257, 258, 258, - 258, 260, 261, 259, 263, 263, 0, 259, 33, 269, - 270, 271, 272, 273, 274, 275, 275, 275, -1, 259, - -1, -1, 282, 283, 257, 258, 256, -1, 258, -1, - -1, 261, 262, 263, 264, 265, 266, 267, 268, 33, - -1, -1, 275, 0, -1, 275, 276, 277, 278, 279, - 280, 256, 33, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, 268, -1, -1, -1, -1, -1, 0, - 275, 276, 277, 278, 279, 280, 33, 256, -1, 258, - -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, - -1, -1, -1, -1, -1, 0, 275, 276, 277, 278, - 279, 280, 33, 256, -1, 258, -1, -1, 261, 262, - 263, 264, 265, 266, 267, 268, -1, -1, -1, -1, - -1, 0, 275, 276, 277, 278, 279, 280, 33, 256, - -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, - 267, 268, -1, -1, -1, -1, -1, 0, 275, 276, - 277, 278, 279, 280, 33, 256, -1, 258, -1, -1, - 261, 262, 263, 264, 265, 266, 267, 268, 258, -1, - -1, 261, 262, 263, 275, 276, 277, 278, 279, 280, - 33, 256, -1, 258, -1, 275, 261, 262, 263, 264, - 265, 266, 267, 268, -1, -1, -1, -1, -1, 0, - 275, 276, 277, 278, 279, 280, 256, 33, 258, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, 58, + -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, 58, -1, 33, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, 58, -1, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, -1, 33, -1, -1, 257, 258, 258, -1, 256, + 259, 258, 263, 259, 261, 262, 263, 264, 265, 266, + 267, 268, 259, 0, -1, 277, 277, 259, -1, 33, + 277, 278, 279, 280, 281, 282, 256, -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, -1, - -1, -1, -1, -1, -1, 275, 276, 277, 278, 279, - 280, 256, 33, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, 268, 33, -1, -1, -1, -1, -1, - 275, 276, 277, 278, 279, 280, -1, -1, -1, -1, - -1, -1, 256, 33, 258, 33, -1, 261, 262, 263, - 264, 265, 266, 267, 268, -1, 257, 258, -1, -1, - -1, 275, 276, 277, 278, 279, 280, 33, 269, 270, - 271, 272, 273, 274, 275, -1, -1, -1, -1, 256, - -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, - 267, 268, 33, -1, -1, -1, -1, -1, 275, 276, - 277, 278, 279, 280, -1, 256, -1, 258, -1, -1, - 261, 262, 263, 264, 265, 266, 267, 268, -1, -1, - -1, -1, -1, -1, 275, 276, 277, 278, 279, 280, - -1, 256, -1, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, 268, -1, -1, -1, -1, -1, -1, - 275, 276, 277, 278, 279, 280, -1, 256, -1, 258, + 0, -1, -1, -1, -1, -1, 33, 277, 278, 279, + 280, 281, 282, 256, -1, 258, -1, -1, 261, 262, + 263, 264, 265, 266, 267, 268, -1, 0, -1, -1, + -1, -1, -1, 33, 277, 278, 279, 280, 281, 282, + 256, -1, 258, -1, -1, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 0, -1, -1, -1, -1, -1, + 33, 277, 278, 279, 280, 281, 282, 256, -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, - -1, -1, -1, -1, -1, -1, 275, 276, 277, 278, - 279, 280, -1, 256, -1, 258, -1, -1, 261, 262, - 263, 264, 265, 266, 267, 268, -1, -1, -1, -1, - -1, -1, 275, 276, 277, 278, 279, 280, -1, -1, + -1, 0, -1, -1, -1, -1, -1, 33, 277, 278, + 279, 280, 281, 282, 256, -1, 258, -1, -1, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 0, -1, + -1, -1, -1, -1, 33, 277, 278, 279, 280, 281, + 282, 256, -1, 258, -1, -1, 261, 262, 263, 264, + 265, 266, 267, 268, -1, 0, -1, -1, -1, -1, + -1, 33, 277, 278, 279, 280, 281, 282, 256, -1, + 258, -1, -1, 261, 262, 263, 264, 265, 266, 267, + 268, -1, -1, -1, -1, -1, -1, -1, 33, 277, + 278, 279, 280, 281, 282, 256, -1, 258, -1, 33, + 261, 262, 263, 264, 265, 266, 267, 268, -1, -1, + 44, -1, -1, -1, 33, -1, 277, 278, 279, 280, + 281, 282, 256, -1, 258, -1, -1, 261, 262, 263, + 264, 265, 266, 267, 268, 33, -1, -1, -1, 33, + -1, -1, -1, 277, 278, 279, 280, 281, 282, 256, + -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, + 267, 268, 33, 33, 58, -1, -1, 33, -1, -1, + 277, 278, 279, 280, 281, 282, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, 267, 268, 33, + -1, -1, -1, -1, -1, -1, -1, 277, 278, 279, + 280, 281, 282, 256, -1, 258, -1, -1, 261, 262, + 263, 264, 265, 266, 267, 268, 33, -1, -1, -1, + -1, -1, -1, -1, 277, 278, 279, 280, 281, 282, 256, -1, 258, -1, -1, 261, 262, 263, 264, 265, - 266, 267, 268, -1, -1, -1, -1, -1, -1, 275, - 276, 277, 278, 279, 280, 256, -1, 258, -1, -1, - 261, 262, 263, 264, 265, 266, 267, 268, 257, 258, - -1, -1, -1, -1, 275, 276, 277, 278, 279, 280, - 269, 270, 271, 272, 273, 274, 275, 257, 258, -1, - 258, -1, 260, 261, -1, 263, -1, -1, -1, 269, - 270, 271, 272, 273, 274, 275, -1, 275, -1, -1, - -1, 257, 258, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 269, 270, 271, 272, 273, 274, 275, - -1, -1, -1, -1, -1, -1, -1, 258, -1, -1, - 261, 262, 263, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 275, + 266, 267, 268, -1, -1, -1, -1, -1, -1, -1, + -1, 277, 278, 279, 280, 281, 282, 256, -1, 258, + -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, + -1, -1, -1, -1, -1, -1, -1, -1, 277, 278, + 279, 280, 281, 282, 256, -1, 258, -1, -1, 261, + 262, 263, 264, 265, 266, 267, 268, -1, -1, -1, + -1, -1, -1, -1, -1, 277, 278, 279, 280, 281, + 282, 256, -1, 258, -1, -1, 261, 262, 263, 264, + 265, 266, 267, 268, 258, -1, 260, 261, -1, 263, + -1, -1, 277, 278, 279, 280, 281, 282, 257, 258, + -1, -1, -1, 277, -1, -1, -1, -1, -1, -1, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 257, + 258, -1, -1, -1, 258, 284, 285, 261, 262, 263, + -1, 269, 270, 271, 272, 273, 274, 275, 276, 277, + -1, -1, -1, 277, -1, -1, 257, 258, 258, -1, + 260, 261, 258, 263, -1, 261, 262, 263, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 277, -1, -1, + -1, 277, -1, 257, 258, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 269, 270, 271, 272, 273, + 274, 275, 276, 277, -1, -1, -1, -1, -1, -1, + 257, 258, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 269, 270, 271, 272, 273, 274, 275, 276, + 277, }; #define YYFINAL 18 #ifndef YYDEBUG #define YYDEBUG 0 #endif -#define YYMAXTOKEN 283 +#define YYMAXTOKEN 285 #if YYDEBUG #if defined(__cplusplus) || defined(__STDC__) const char * const yyname[] = @@ -490,8 +498,9 @@ char *yyname[] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, "COMMAND","ALIAS","DEFVAR","NTWKADDR","NETGROUP","USERGROUP","WORD","DEFAULTS", "DEFAULTS_HOST","DEFAULTS_USER","DEFAULTS_RUNAS","DEFAULTS_CMND","NOPASSWD", -"PASSWD","NOEXEC","EXEC","SETENV","NOSETENV","ALL","COMMENT","HOSTALIAS", -"CMNDALIAS","USERALIAS","RUNASALIAS","ERROR","TYPE","ROLE", +"PASSWD","NOEXEC","EXEC","SETENV","NOSETENV","SCRIPT","NOSCRIPT","ALL", +"COMMENT","HOSTALIAS","CMNDALIAS","USERALIAS","RUNASALIAS","ERROR","TYPE", +"ROLE", }; #if defined(__cplusplus) || defined(__STDC__) const char * const yyrule[] = @@ -556,6 +565,8 @@ char *yyrule[] = "cmndtag : cmndtag EXEC", "cmndtag : cmndtag SETENV", "cmndtag : cmndtag NOSETENV", +"cmndtag : cmndtag SCRIPT", +"cmndtag : cmndtag NOSCRIPT", "cmnd : ALL", "cmnd : ALIAS", "cmnd : COMMAND", @@ -618,7 +629,7 @@ short *yyss; short *yysslim; YYSTYPE *yyvs; int yystacksize; -#line 590 "gram.y" +#line 600 "gram.y" static struct defaults * new_default(var, val, op) char *var; @@ -809,7 +820,7 @@ init_parser(path, quiet) sudolineno = 1; verbose = !quiet; } -#line 761 "y.tab.c" +#line 772 "y.tab.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -1015,127 +1026,127 @@ yyreduce: switch (yyn) { case 1: -#line 188 "gram.y" +#line 190 "gram.y" { ; } break; case 5: -#line 196 "gram.y" +#line 198 "gram.y" { ; } break; case 6: -#line 199 "gram.y" +#line 201 "gram.y" { yyerrok; } break; case 7: -#line 202 "gram.y" +#line 204 "gram.y" { add_userspec(yyvsp[-1].member, yyvsp[0].privilege); } break; case 8: -#line 205 "gram.y" +#line 207 "gram.y" { ; } break; case 9: -#line 208 "gram.y" +#line 210 "gram.y" { ; } break; case 10: -#line 211 "gram.y" +#line 213 "gram.y" { ; } break; case 11: -#line 214 "gram.y" +#line 216 "gram.y" { ; } break; case 12: -#line 217 "gram.y" +#line 219 "gram.y" { add_defaults(DEFAULTS, NULL, yyvsp[0].defaults); } break; case 13: -#line 220 "gram.y" +#line 222 "gram.y" { add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults); } break; case 14: -#line 223 "gram.y" +#line 225 "gram.y" { add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults); } break; case 15: -#line 226 "gram.y" +#line 228 "gram.y" { add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults); } break; case 16: -#line 229 "gram.y" +#line 231 "gram.y" { add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults); } break; case 18: -#line 235 "gram.y" +#line 237 "gram.y" { list_append(yyvsp[-2].defaults, yyvsp[0].defaults); yyval.defaults = yyvsp[-2].defaults; } break; case 19: -#line 241 "gram.y" +#line 243 "gram.y" { yyval.defaults = new_default(yyvsp[0].string, NULL, TRUE); } break; case 20: -#line 244 "gram.y" +#line 246 "gram.y" { yyval.defaults = new_default(yyvsp[0].string, NULL, FALSE); } break; case 21: -#line 247 "gram.y" +#line 249 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, TRUE); } break; case 22: -#line 250 "gram.y" +#line 252 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+'); } break; case 23: -#line 253 "gram.y" +#line 255 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-'); } break; case 25: -#line 259 "gram.y" +#line 261 "gram.y" { list_append(yyvsp[-2].privilege, yyvsp[0].privilege); yyval.privilege = yyvsp[-2].privilege; } break; case 26: -#line 265 "gram.y" +#line 267 "gram.y" { struct privilege *p = emalloc(sizeof(*p)); list2tq(&p->hostlist, yyvsp[-2].member); @@ -1146,51 +1157,51 @@ case 26: } break; case 27: -#line 275 "gram.y" +#line 277 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 28: -#line 279 "gram.y" +#line 281 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 29: -#line 285 "gram.y" +#line 287 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 30: -#line 288 "gram.y" +#line 290 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 31: -#line 291 "gram.y" +#line 293 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; case 32: -#line 294 "gram.y" +#line 296 "gram.y" { yyval.member = new_member(yyvsp[0].string, NTWKADDR); } break; case 33: -#line 297 "gram.y" +#line 299 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; case 35: -#line 303 "gram.y" +#line 305 "gram.y" { list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec); #ifdef HAVE_SELINUX @@ -1208,6 +1219,8 @@ case 35: if (yyvsp[0].cmndspec->tags.setenv == UNSPEC && yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED) yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv; + if (yyvsp[0].cmndspec->tags.script == UNSPEC) + yyvsp[0].cmndspec->tags.script = yyvsp[0].cmndspec->prev->tags.script; if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) && tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) && (!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) || @@ -1219,7 +1232,7 @@ case 35: } break; case 36: -#line 331 "gram.y" +#line 335 "gram.y" { struct cmndspec *cs = emalloc(sizeof(*cs)); if (yyvsp[-3].runas != NULL) { @@ -1246,80 +1259,80 @@ case 36: } break; case 37: -#line 357 "gram.y" +#line 361 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 38: -#line 361 "gram.y" +#line 365 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 39: -#line 367 "gram.y" +#line 371 "gram.y" { yyval.string = yyvsp[0].string; } break; case 40: -#line 372 "gram.y" +#line 376 "gram.y" { yyval.string = yyvsp[0].string; } break; case 41: -#line 377 "gram.y" +#line 381 "gram.y" { yyval.seinfo.role = NULL; yyval.seinfo.type = NULL; } break; case 42: -#line 381 "gram.y" +#line 385 "gram.y" { yyval.seinfo.role = yyvsp[0].string; yyval.seinfo.type = NULL; } break; case 43: -#line 385 "gram.y" +#line 389 "gram.y" { yyval.seinfo.type = yyvsp[0].string; yyval.seinfo.role = NULL; } break; case 44: -#line 389 "gram.y" +#line 393 "gram.y" { yyval.seinfo.role = yyvsp[-1].string; yyval.seinfo.type = yyvsp[0].string; } break; case 45: -#line 393 "gram.y" +#line 397 "gram.y" { yyval.seinfo.type = yyvsp[-1].string; yyval.seinfo.role = yyvsp[0].string; } break; case 46: -#line 399 "gram.y" +#line 403 "gram.y" { yyval.runas = NULL; } break; case 47: -#line 402 "gram.y" +#line 406 "gram.y" { yyval.runas = yyvsp[-1].runas; } break; case 48: -#line 407 "gram.y" +#line 411 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[0].member; @@ -1327,7 +1340,7 @@ case 48: } break; case 49: -#line 412 "gram.y" +#line 416 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[-2].member; @@ -1335,7 +1348,7 @@ case 49: } break; case 50: -#line 417 "gram.y" +#line 421 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = NULL; @@ -1343,61 +1356,73 @@ case 50: } break; case 51: -#line 424 "gram.y" +#line 428 "gram.y" { - yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = UNSPEC; + yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = yyval.tag.script = UNSPEC; } break; case 52: -#line 427 "gram.y" +#line 431 "gram.y" { yyval.tag.nopasswd = TRUE; } break; case 53: -#line 430 "gram.y" +#line 434 "gram.y" { yyval.tag.nopasswd = FALSE; } break; case 54: -#line 433 "gram.y" +#line 437 "gram.y" { yyval.tag.noexec = TRUE; } break; case 55: -#line 436 "gram.y" +#line 440 "gram.y" { yyval.tag.noexec = FALSE; } break; case 56: -#line 439 "gram.y" +#line 443 "gram.y" { yyval.tag.setenv = TRUE; } break; case 57: -#line 442 "gram.y" +#line 446 "gram.y" { yyval.tag.setenv = FALSE; } break; case 58: -#line 447 "gram.y" +#line 449 "gram.y" { - yyval.member = new_member(NULL, ALL); + yyval.tag.script = TRUE; } break; case 59: -#line 450 "gram.y" +#line 452 "gram.y" { - yyval.member = new_member(yyvsp[0].string, ALIAS); + yyval.tag.script = FALSE; } break; case 60: -#line 453 "gram.y" +#line 457 "gram.y" +{ + yyval.member = new_member(NULL, ALL); + } +break; +case 61: +#line 460 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, ALIAS); + } +break; +case 62: +#line 463 "gram.y" { struct sudo_command *c = emalloc(sizeof(*c)); c->cmnd = yyvsp[0].command.cmnd; @@ -1405,8 +1430,8 @@ case 60: yyval.member = new_member((char *)c, COMMAND); } break; -case 63: -#line 465 "gram.y" +case 65: +#line 475 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) { @@ -1415,15 +1440,15 @@ case 63: } } break; -case 65: -#line 475 "gram.y" +case 67: +#line 485 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; -case 68: -#line 485 "gram.y" +case 70: +#line 495 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) { @@ -1432,15 +1457,15 @@ case 68: } } break; -case 70: -#line 495 "gram.y" +case 72: +#line 505 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; -case 73: -#line 505 "gram.y" +case 75: +#line 515 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) { @@ -1449,8 +1474,8 @@ case 73: } } break; -case 76: -#line 518 "gram.y" +case 78: +#line 528 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) { @@ -1459,97 +1484,97 @@ case 76: } } break; -case 78: -#line 528 "gram.y" +case 80: +#line 538 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; -case 79: -#line 534 "gram.y" +case 81: +#line 544 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; -case 80: -#line 538 "gram.y" +case 82: +#line 548 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; -case 81: -#line 544 "gram.y" +case 83: +#line 554 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; -case 82: -#line 547 "gram.y" +case 84: +#line 557 "gram.y" { yyval.member = new_member(NULL, ALL); } break; -case 83: -#line 550 "gram.y" +case 85: +#line 560 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; -case 84: -#line 553 "gram.y" +case 86: +#line 563 "gram.y" { yyval.member = new_member(yyvsp[0].string, USERGROUP); } break; -case 85: -#line 556 "gram.y" +case 87: +#line 566 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; -case 87: -#line 562 "gram.y" +case 89: +#line 572 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; -case 88: -#line 568 "gram.y" +case 90: +#line 578 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; -case 89: -#line 572 "gram.y" +case 91: +#line 582 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; -case 90: -#line 578 "gram.y" +case 92: +#line 588 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; -case 91: -#line 581 "gram.y" +case 93: +#line 591 "gram.y" { yyval.member = new_member(NULL, ALL); } break; -case 92: -#line 584 "gram.y" +case 94: +#line 594 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; -#line 1501 "y.tab.c" +#line 1526 "y.tab.c" } yyssp -= yym; yystate = *yyssp; diff --git a/gram.h b/gram.h index 8f054916a..c71c897e6 100644 --- a/gram.h +++ b/gram.h @@ -16,15 +16,17 @@ #define EXEC 272 #define SETENV 273 #define NOSETENV 274 -#define ALL 275 -#define COMMENT 276 -#define HOSTALIAS 277 -#define CMNDALIAS 278 -#define USERALIAS 279 -#define RUNASALIAS 280 -#define ERROR 281 -#define TYPE 282 -#define ROLE 283 +#define SCRIPT 275 +#define NOSCRIPT 276 +#define ALL 277 +#define COMMENT 278 +#define HOSTALIAS 279 +#define CMNDALIAS 280 +#define USERALIAS 281 +#define RUNASALIAS 282 +#define ERROR 283 +#define TYPE 284 +#define ROLE 285 #ifndef YYSTYPE_DEFINED #define YYSTYPE_DEFINED typedef union { diff --git a/gram.y b/gram.y index 628ae01a6..8d7eeef14 100644 --- a/gram.y +++ b/gram.y @@ -146,6 +146,8 @@ yyerror(s) %token EXEC /* don't preload dummy execve() */ %token SETENV /* user may set environment for cmnd */ %token NOSETENV /* user may not set environment */ +%token SCRIPT /* log a transcript of the cmnd */ +%token NOSCRIPT /* don't log a transcript of the cmnd */ %token ALL /* ALL keyword */ %token COMMENT /* comment and/or carriage return */ %token HOSTALIAS /* Host_Alias keyword */ @@ -317,6 +319,8 @@ cmndspeclist : cmndspec if ($3->tags.setenv == UNSPEC && $3->prev->tags.setenv != IMPLIED) $3->tags.setenv = $3->prev->tags.setenv; + if ($3->tags.script == UNSPEC) + $3->tags.script = $3->prev->tags.script; if ((tq_empty(&$3->runasuserlist) && tq_empty(&$3->runasgrouplist)) && (!tq_empty(&$3->prev->runasuserlist) || @@ -422,7 +426,7 @@ runaslist : userlist { ; cmndtag : /* empty */ { - $$.nopasswd = $$.noexec = $$.setenv = UNSPEC; + $$.nopasswd = $$.noexec = $$.setenv = $$.script = UNSPEC; } | cmndtag NOPASSWD { $$.nopasswd = TRUE; @@ -442,6 +446,12 @@ cmndtag : /* empty */ { | cmndtag NOSETENV { $$.setenv = FALSE; } + | cmndtag SCRIPT { + $$.script = TRUE; + } + | cmndtag NOSCRIPT { + $$.script = FALSE; + } ; cmnd : ALL { diff --git a/parse.c b/parse.c index 5e8ac2fc0..0b9b23510 100644 --- a/parse.c +++ b/parse.c @@ -254,6 +254,8 @@ sudo_file_lookup(nss, validated, pwflag) def_noexec = tags->noexec; if (tags->setenv != UNSPEC) def_setenv = tags->setenv; + if (tags->script != UNSPEC) + def_script = tags->script; } } else if (match == DENY) { SET(validated, VALIDATE_NOT_OK); @@ -295,6 +297,11 @@ sudo_file_append_cmnd(cs, tags, lbuf) "PASSWD: ", NULL); 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; print_member(lbuf, m->name, m->type, m->negated, CMNDALIAS); @@ -316,6 +323,7 @@ sudo_file_display_priv_short(pw, us, lbuf) tags.noexec = UNSPEC; tags.setenv = UNSPEC; tags.nopasswd = UNSPEC; + tags.script = UNSPEC; lbuf_append(lbuf, " ", NULL); tq_foreach_fwd(&priv->cmndlist, cs) { if (cs != tq_first(&priv->cmndlist)) @@ -367,6 +375,7 @@ sudo_file_display_priv_long(pw, us, lbuf) tags.noexec = UNSPEC; tags.setenv = UNSPEC; tags.nopasswd = UNSPEC; + tags.script = UNSPEC; lbuf_print(lbuf); /* force a newline */ lbuf_append(lbuf, "Sudoers entry:", NULL); lbuf_print(lbuf); diff --git a/parse.h b/parse.h index e0049e245..a33b79043 100644 --- a/parse.h +++ b/parse.h @@ -45,7 +45,7 @@ struct cmndtag { __signed char nopasswd; __signed char noexec; __signed char setenv; - __signed char extra; + __signed char script; }; /* diff --git a/pathnames.h.in b/pathnames.h.in index 6cc18b787..4166c7f9c 100644 --- a/pathnames.h.in +++ b/pathnames.h.in @@ -68,6 +68,14 @@ #undef _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 * /var/log/sudo.log if /var/log exists, else /var/adm/sudo.log. diff --git a/sudo.c b/sudo.c index e32146729..ebe947d77 100644 --- a/sudo.c +++ b/sudo.c @@ -165,6 +165,10 @@ static struct sudo_nss_list *snl; extern char *optarg; extern int optind; +/* XXX - script.c */ +extern int script_fds[5]; +extern void term_restore __P((int)); + int main(argc, argv, envp) int argc; @@ -498,6 +502,10 @@ main(argc, argv, envp) /* Must audit before uid change. */ audit_success(NewArgv); + /* Open tty as needed */ + if (def_script) + script_setup(); + /* Become specified user or root if executing a command. */ if (ISSET(sudo_mode, MODE_RUN)) set_perms(PERM_FULL_RUNAS); @@ -540,7 +548,16 @@ main(argc, argv, envp) sudo_endpwent(); 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 if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) { @@ -548,11 +565,15 @@ main(argc, argv, envp) exit(0); } else { #ifdef HAVE_SELINUX + /* XXX - script support */ if (is_selinux_enabled() > 0 && user_role != NULL) selinux_exec(user_role, user_type, NewArgv, ISSET(sudo_mode, MODE_LOGIN_SHELL)); #endif - execv(safe_cmnd, NewArgv); + if (def_script) + script_execv(safe_cmnd, NewArgv); + else + execv(safe_cmnd, NewArgv); } #else exit(0); @@ -1446,6 +1467,8 @@ cleanup(gotsignal) sudo_endpwent(); sudo_endgrent(); } + if (def_script) + term_restore(STDIN_FILENO); } static void diff --git a/sudo.h b/sudo.h index 30537c0cc..4557f7f12 100644 --- a/sudo.h +++ b/sudo.h @@ -324,6 +324,8 @@ void selinux_exec __P((char *, char *, char **, int)); #ifdef HAVE_GETUSERATTR void aix_setlimits __P((char *)); #endif +int script_execv __P((const char *, char * const *)); +void script_setup __P((void)); YY_DECL; /* Only provide extern declarations outside of sudo.c. */ diff --git a/term.c b/term.c index 234c9dec3..301b396b6 100644 --- a/term.c +++ b/term.c @@ -132,9 +132,32 @@ term_noecho(fd) } #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) + int term_raw(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) return(0); @@ -156,11 +179,42 @@ term_raw(fd) 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 */ int term_raw(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) return(0); @@ -177,4 +231,27 @@ term_raw(fd) 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 diff --git a/tgetpass.c b/tgetpass.c index 3d0b73598..8ebc8f198 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -68,7 +68,7 @@ static char *sudo_askpass __P((const char *)); extern int term_restore __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. @@ -120,7 +120,7 @@ restart: (void) sigaction(SIGTTOU, &sa, &savettou); if (def_pwfeedback) - neednl = term_raw(input); + neednl = term_cbreak(input); else neednl = term_noecho(input); -- 2.40.0