From 63d954d1fc1de27e06eb68f5ab458ff8cacac887 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 1 Aug 2017 16:14:54 -0600 Subject: [PATCH] Replace tty_tickets option with timestamp_type which can be global, ppid or tty. Defaults to tty (no change in behavior). Some users want the ppid behavior. --- INSTALL | 13 ++++--- NEWS | 6 +++ config.h.in | 6 +-- configure | 40 ++++++++++++-------- configure.ac | 29 +++++++++------ doc/sudoers.cat | 55 ++++++++++++++++++++++----- doc/sudoers.man.in | 74 ++++++++++++++++++++++++++++++++----- doc/sudoers.mdoc.in | 69 +++++++++++++++++++++++++++++----- plugins/sudoers/def_data.c | 11 ++++++ plugins/sudoers/def_data.h | 7 +++- plugins/sudoers/def_data.in | 4 ++ plugins/sudoers/defaults.c | 4 +- plugins/sudoers/sudoers.c | 20 ++++++++++ plugins/sudoers/timestamp.c | 68 +++++++++++++++++++--------------- 14 files changed, 308 insertions(+), 98 deletions(-) diff --git a/INSTALL b/INSTALL index 11ac4ea64..6c3216f60 100644 --- a/INSTALL +++ b/INSTALL @@ -615,6 +615,13 @@ Options that set runtime-changeable default values: "-s" flag imply "-H". Sudoers option: set_home + --enable-timestamp-type=TYPE + Set the default time stamp record type. The TYPE may be "global" + (a single record per user), "ppid" (a single record for process + with the same parent process), or "tty" (a separate record for + each login session). The default is "tty". + Sudoers option: timestamp_type + --with-all-insults Include all the insult sets listed below. You must either specify --with-insults or enable insults in the sudoers file for this to @@ -859,12 +866,6 @@ Options that set runtime-changeable default values: again. The default is 5, set this to 0 to always prompt for a password. Sudoers option: timestamp_timeout - --with-tty-tickets=no, --without-tty-tickets - By default, sudo uses a different ticket file for each user/tty combo. - With this option disabled, a single ticket will be used for all - of a user's login sessions. - Sudoers option: tty_tickets - --with-umask=MASK Umask to use when running the root command. The default is 0022. Sudoers option: umask diff --git a/NEWS b/NEWS index 57c4c1242..6d7d7dab4 100644 --- a/NEWS +++ b/NEWS @@ -50,6 +50,12 @@ What's new in Sudo 1.8.21 not be terminated when the I/O logging plugin returned an error to the sudo front-end. + * A new "timestamp_type" sudoers setting has been added that replaces + the "tty_tickets" option. In addition to tty and global time stamp + records, it is now possible to use the parent process ID to restrict + the time stamp to commands run by the same process, usually the shell. + Bug #793 + What's new in Sudo 1.8.20p2 * Fixed a bug parsing /proc/pid/stat on Linux when the process diff --git a/config.h.in b/config.h.in index cfa9108e1..d81e71e27 100644 --- a/config.h.in +++ b/config.h.in @@ -955,9 +955,6 @@ /* Define to 1 if root should not be allowed to use sudo. */ #undef NO_ROOT_SUDO -/* Define to 1 if you want a single ticket file instead of per-tty files. */ -#undef NO_TTY_TICKETS - /* Define if your C preprocessor does not support variadic macros. */ #undef NO_VARIADIC_MACROS @@ -1076,6 +1073,9 @@ /* The number of minutes before sudo asks for a password again. */ #undef TIMEOUT +/* Define to global, ppid or tty to set the default timestamp record type. */ +#undef TIMESTAMP_TYPE + /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME diff --git a/configure b/configure index 01a41e399..42fa05533 100755 --- a/configure +++ b/configure @@ -695,7 +695,7 @@ ldap_conf path_info root_sudo insults -tty_tickets +timestamp_type passwd_tries env_reset env_editor @@ -963,6 +963,7 @@ enable_tmpfiles_d enable_devsearch with_selinux enable_sasl +enable_timestamp_type enable_gss_krb5_ccache_name enable_shared enable_static @@ -1647,6 +1648,8 @@ Optional Features: --enable-devsearch=PATH The colon-delimited path to search for device nodes when determing the tty name. --enable-sasl Enable/disable LDAP SASL support + --timestamp-type=TYPE Set the default time stamp record type to global, + ppid or tty. --enable-gss-krb5-ccache-name Use GSS-API to set the Kerberos V cred cache name --enable-shared[=PKGS] build shared libraries [default=yes] @@ -3090,7 +3093,7 @@ env_editor=off env_reset=on editor=vi passwd_tries=3 -tty_tickets=on +timestamp_type=tty insults=off root_sudo=on path_info=on @@ -5690,30 +5693,19 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: $password_timeout" >&5 $as_echo "$password_timeout" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use per-tty ticket files" >&5 -$as_echo_n "checking whether to use per-tty ticket files... " >&6; } # Check whether --with-tty-tickets was given. if test "${with_tty_tickets+set}" = set; then : withval=$with_tty_tickets; case $with_tty_tickets in - yes) tty_tickets=on + yes) timestamp_type=tty ;; - no) tty_tickets=off + no) timestamp_type=global ;; *) as_fn_error $? "\"--with-tty-tickets does not take an argument.\"" "$LINENO" 5 ;; esac fi -if test "$tty_tickets" = "off"; then - $as_echo "#define NO_TTY_TICKETS 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include insults" >&5 $as_echo_n "checking whether to include insults... " >&6; } @@ -6765,6 +6757,24 @@ $as_echo "$as_me: WARNING: Ignoring unknown argument to --enable-sasl: $enableva fi +# Check whether --enable-timestamp-type was given. +if test "${enable_timestamp_type+set}" = set; then : + enableval=$enable_timestamp_type; case "$enableval" in + global|ppid|tty) + timestamp_type=$enableval + ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring unknown argument to --enable-timestamp-type: $enableval" >&5 +$as_echo "$as_me: WARNING: Ignoring unknown argument to --enable-timestamp-type: $enableval" >&2;} + ;; + esac + +fi + +cat >>confdefs.h <<_ACEOF +#define TIMESTAMP_TYPE $timestamp_type +_ACEOF + + # Check whether --enable-gss_krb5_ccache_name was given. if test "${enable_gss_krb5_ccache_name+set}" = set; then : enableval=$enable_gss_krb5_ccache_name; check_gss_krb5_ccache_name=$enableval diff --git a/configure.ac b/configure.ac index c7898f450..ad9523269 100644 --- a/configure.ac +++ b/configure.ac @@ -127,7 +127,7 @@ AC_SUBST([runas_default]) AC_SUBST([env_editor]) AC_SUBST([env_reset]) AC_SUBST([passwd_tries]) -AC_SUBST([tty_tickets]) +AC_SUBST([timestamp_type]) AC_SUBST([insults]) AC_SUBST([root_sudo]) AC_SUBST([path_info]) @@ -171,7 +171,7 @@ env_editor=off env_reset=on editor=vi passwd_tries=3 -tty_tickets=on +timestamp_type=tty insults=off root_sudo=on path_info=on @@ -1036,22 +1036,15 @@ esac]) AC_DEFINE_UNQUOTED(PASSWORD_TIMEOUT, $password_timeout, [The passwd prompt timeout (in minutes).]) AC_MSG_RESULT($password_timeout) -AC_MSG_CHECKING(whether to use per-tty ticket files) AC_ARG_WITH(tty-tickets, [AS_HELP_STRING([--with-tty-tickets], [use a different ticket file for each tty])], [case $with_tty_tickets in - yes) tty_tickets=on + yes) timestamp_type=tty ;; - no) tty_tickets=off + no) timestamp_type=global ;; *) AC_MSG_ERROR(["--with-tty-tickets does not take an argument."]) ;; esac]) -if test "$tty_tickets" = "off"; then - AC_DEFINE(NO_TTY_TICKETS) - AC_MSG_RESULT(no) -else - AC_MSG_RESULT(yes) -fi AC_MSG_CHECKING(whether to include insults) AC_ARG_WITH(insults, [AS_HELP_STRING([--with-insults], [insult the user for entering an incorrect password])], @@ -1571,6 +1564,18 @@ AC_ARG_ENABLE(sasl, esac ]) +AC_ARG_ENABLE(timestamp-type, +[AS_HELP_STRING([--timestamp-type=TYPE], [Set the default time stamp record type to global, ppid or tty.])], +[ case "$enableval" in + global|ppid|tty) + timestamp_type=$enableval + ;; + *) AC_MSG_WARN([Ignoring unknown argument to --enable-timestamp-type: $enableval]) + ;; + esac +]) +AC_DEFINE_UNQUOTED(TIMESTAMP_TYPE, $timestamp_type) + dnl dnl gss_krb5_ccache_name() may not work on Heimdal so we don't use it by default dnl @@ -4443,7 +4448,7 @@ AH_TEMPLATE(NO_LECTURE, [Define to 1 if you don't want users to get the lecture AH_TEMPLATE(NO_PAM_SESSION, [Define to 1 if you don't want to use sudo's PAM session support.]) AH_TEMPLATE(NO_ROOT_MAILER, [Define to avoid runing the mailer as root.]) AH_TEMPLATE(NO_ROOT_SUDO, [Define to 1 if root should not be allowed to use sudo.]) -AH_TEMPLATE(NO_TTY_TICKETS, [Define to 1 if you want a single ticket file instead of per-tty files.]) +AH_TEMPLATE(TIMESTAMP_TYPE, [Define to global, ppid or tty to set the default timestamp record type.]) AH_TEMPLATE(PC_INSULTS, [Define to 1 to replace politically incorrect insults with less offensive ones.]) AH_TEMPLATE(PREFER_PORTABLE_GETCWD, [Define to 1 to enable replacement getcwd if system getcwd is broken.]) AH_TEMPLATE(SECURE_PATH, [A colon-separated list of directories to override the user's PATH with.]) diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 237c71979..fd111641c 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -91,14 +91,14 @@ DDEESSCCRRIIPPTTIIOONN SUDO_USER. ssuuddooeerrss uses per-user time stamp files for credential caching. Once a - user has been authenticated, a record is written containing the uid that - was used to authenticate, the terminal session ID, and a time stamp + user has been authenticated, a record is written containing the user ID + that was used to authenticate, the terminal session ID, and a time stamp (using a monotonic clock if one is available). The user may then use ssuuddoo without a password for a short period of time (5 minutes unless overridden by the _t_i_m_e_s_t_a_m_p___t_i_m_e_o_u_t option). By default, ssuuddooeerrss uses a - separate record for each tty, which means that a user's login sessions - are authenticated separately. The _t_t_y___t_i_c_k_e_t_s option can be disabled to - force the use of a single time stamp for all of a user's sessions. + separate record for each terminal, which means that a user's login + sessions are authenticated separately. The _t_i_m_e_s_t_a_m_p___t_y_p_e option can be + used to select the type of time stamp record ssuuddooeerrss will use. LLooggggiinngg ssuuddooeerrss can log both successful and unsuccessful attempts (as well as @@ -1436,9 +1436,11 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS tty_tickets If set, users must authenticate on a per-tty basis. With this flag enabled, ssuuddoo will use a separate record - in the time stamp file for each tty. If disabled, a - single record is used for all login sessions. This - flag is _o_n by default. + in the time stamp file for each terminal. If disabled, + a single record is used for all login sessions. + + This option has been superceded by the _t_i_m_e_s_t_a_m_p___t_y_p_e + option. umask_override If set, ssuuddoo will set the umask as specified in the _s_u_d_o_e_r_s file without modification. This makes it @@ -1813,6 +1815,41 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS locale may affect how sudoers is interpreted. Defaults to "C". + timestamp_type ssuuddooeerrss uses per-user time stamp files for credential + caching. The _t_i_m_e_s_t_a_m_p___t_y_p_e option can be used to + specify the type of time stamp record used. It has the + following possible values: + + global A single time stamp record is used for all of a + user's login sessions, regardless of the + terminal or parent process ID. An additional + record is used to serialize password prompts + when ssuuddoo is used multiple times in a pipeline, + but this does not affect authentication. + + ppid A single time stamp record is used for all + processes with the same parent process ID + (usually the shell). Commands run from the + same shell (or other common parent process) + will not require a password for + _t_i_m_e_s_t_a_m_p___t_i_m_e_o_u_t minutes (5 by default). + Commands run via ssuuddoo with a different parent + process ID, for example from a shell script, + will be authenticated separately. + + tty One time stamp record is used for each + terminal, which means that a user's login + sessions are authenticated separately. If no + terminal is present, the behavior is the same + as _p_p_i_d. Commands run from the same terminal + will not require a password for + _t_i_m_e_s_t_a_m_p___t_i_m_e_o_u_t minutes (5 by default). + + The default value is _t_t_y. + + This setting is only supported by version 1.8.21 or + higher. + timestampdir The directory in which ssuuddoo stores its time stamp files. This directory should be cleared when the system reboots. The default is _/_v_a_r_/_r_u_n_/_s_u_d_o_/_t_s. @@ -2831,4 +2868,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or https://www.sudo.ws/license.html for complete details. -Sudo 1.8.21 July 21, 2017 Sudo 1.8.21 +Sudo 1.8.21 August 1, 2017 Sudo 1.8.21 diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 193b2e18e..d52e93d34 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -21,7 +21,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.TH "SUDOERS" "5" "July 21, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDOERS" "5" "August 1, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -216,7 +216,7 @@ file lookup is still done for root, not the user specified by \fBsudoers\fR uses per-user time stamp files for credential caching. Once a user has been authenticated, a record is written -containing the uid that was used to authenticate, the +containing the user ID that was used to authenticate, the terminal session ID, and a time stamp (using a monotonic clock if one is available). The user may then use @@ -229,12 +229,13 @@ option) \&. By default, \fBsudoers\fR -uses a separate record for each tty, which means that +uses a separate record for each terminal, which means that a user's login sessions are authenticated separately. The -\fItty_tickets\fR -option can be disabled to force the use of a -single time stamp for all of a user's sessions. +\fItimestamp_type\fR +option can be used to select the type of time stamp record +\fBsudoers\fR +will use. .SS "Logging" \fBsudoers\fR can log both successful and unsuccessful attempts (as well @@ -3005,11 +3006,12 @@ tty_tickets If set, users must authenticate on a per-tty basis. With this flag enabled, \fBsudo\fR -will use a separate record in the time stamp file for each tty. +will use a separate record in the time stamp file for each terminal. If disabled, a single record is used for all login sessions. -This flag is -\fI@tty_tickets@\fR -by default. +.sp +This option has been superceded by the +\fItimestamp_type\fR +option. .TP 18n umask_override If set, @@ -3629,6 +3631,58 @@ Note that changing the locale may affect how sudoers is interpreted. Defaults to \(Lq\fRC\fR\(Rq. .TP 18n +timestamp_type +\fBsudoers\fR +uses per-user time stamp files for credential caching. +The +\fItimestamp_type\fR +option can be used to specify the type of time stamp record used. +It has the following possible values: +.PP +.RS 18n +.PD 0 +.TP 8n +global +A single time stamp record is used for all of a user's login sessions, +regardless of the terminal or parent process ID. +An additional record is used to serialize password prompts when +\fBsudo\fR +is used multiple times in a pipeline, but this does not affect authentication. +.PD +.TP 8n +ppid +A single time stamp record is used for all processes with the same parent +process ID (usually the shell). +Commands run from the same shell (or other common parent process) +will not require a password for +\fItimestamp_timeout\fR +minutes +(\fR@timeout@\fR +by default) +\&. +Commands run via +\fBsudo\fR +with a different parent process ID, for example from a shell script, +will be authenticated separately. +.TP 8n +tty +One time stamp record is used for each terminal, +which means that a user's login sessions are authenticated separately. +If no terminal is present, the behavior is the same as +\fIppid\fR. +Commands run from the same terminal will not require a password for +\fItimestamp_timeout\fR +minutes +(\fR@timeout@\fR +by default) +\&. +.PP +The default value is +\fI@timestamp_type@\fR. +.sp +This setting is only supported by version 1.8.21 or higher. +.RE +.TP 18n timestampdir The directory in which \fBsudo\fR diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index 532adfa8a..8506961bd 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -19,7 +19,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.Dd July 21, 2017 +.Dd August 1, 2017 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -204,7 +204,7 @@ file lookup is still done for root, not the user specified by .Nm sudoers uses per-user time stamp files for credential caching. Once a user has been authenticated, a record is written -containing the uid that was used to authenticate, the +containing the user ID that was used to authenticate, the terminal session ID, and a time stamp (using a monotonic clock if one is available). The user may then use @@ -218,12 +218,13 @@ option .Pc . By default, .Nm sudoers -uses a separate record for each tty, which means that +uses a separate record for each terminal, which means that a user's login sessions are authenticated separately. The -.Em tty_tickets -option can be disabled to force the use of a -single time stamp for all of a user's sessions. +.Em timestamp_type +option can be used to select the type of time stamp record +.Nm sudoers +will use. .Ss Logging .Nm sudoers can log both successful and unsuccessful attempts (as well @@ -2823,11 +2824,12 @@ by default. If set, users must authenticate on a per-tty basis. With this flag enabled, .Nm sudo -will use a separate record in the time stamp file for each tty. +will use a separate record in the time stamp file for each terminal. If disabled, a single record is used for all login sessions. -This flag is -.Em @tty_tickets@ -by default. +.Pp +This option has been superceded by the +.Em timestamp_type +option. .It umask_override If set, .Nm sudo @@ -3396,6 +3398,53 @@ sending email. Note that changing the locale may affect how sudoers is interpreted. Defaults to .Dq Li C . +.It timestamp_type +.Nm sudoers +uses per-user time stamp files for credential caching. +The +.Em timestamp_type +option can be used to specify the type of time stamp record used. +It has the following possible values: +.Bl -tag -width 6n +.It global +A single time stamp record is used for all of a user's login sessions, +regardless of the terminal or parent process ID. +An additional record is used to serialize password prompts when +.Nm sudo +is used multiple times in a pipeline, but this does not affect authentication. +.It ppid +A single time stamp record is used for all processes with the same parent +process ID (usually the shell). +Commands run from the same shell (or other common parent process) +will not require a password for +.Em timestamp_timeout +minutes +.Po +.Li @timeout@ +by default +.Pc . +Commands run via +.Nm sudo +with a different parent process ID, for example from a shell script, +will be authenticated separately. +.It tty +One time stamp record is used for each terminal, +which means that a user's login sessions are authenticated separately. +If no terminal is present, the behavior is the same as +.Em ppid . +Commands run from the same terminal will not require a password for +.Em timestamp_timeout +minutes +.Po +.Li @timeout@ +by default +.Pc . +.El +.Pp +The default value is +.Em @timestamp_type@ . +.Pp +This setting is only supported by version 1.8.21 or higher. .It timestampdir The directory in which .Nm sudo diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index a8bdbef72..dae695471 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -28,6 +28,13 @@ static struct def_values def_data_fdexec[] = { { NULL, 0 }, }; +static struct def_values def_data_timestamp_type[] = { + { "global", global }, + { "ppid", ppid }, + { "tty", tty }, + { NULL, 0 }, +}; + struct sudo_defs_types sudo_defs_table[] = { { "syslog", T_LOGFAC|T_BOOL, @@ -469,6 +476,10 @@ struct sudo_defs_types sudo_defs_table[] = { "syslog_pid", T_FLAG, N_("Include the process ID when logging via syslog"), NULL, + }, { + "timestamp_type", T_TUPLE, + N_("Type of authentication timestamp record: %s"), + def_data_timestamp_type, }, { NULL, 0, NULL } diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 2df8e7735..78f126d24 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -218,6 +218,8 @@ #define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag) #define I_SYSLOG_PID 109 #define def_syslog_pid (sudo_defs_table[I_SYSLOG_PID].sd_un.flag) +#define I_TIMESTAMP_TYPE 110 +#define def_timestamp_type (sudo_defs_table[I_TIMESTAMP_TYPE].sd_un.tuple) enum def_tuple { never, @@ -225,5 +227,8 @@ enum def_tuple { always, any, all, - digest_only + digest_only, + global, + ppid, + tty }; diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index a4f499713..f61dc8eb6 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -344,3 +344,7 @@ iolog_flush syslog_pid T_FLAG "Include the process ID when logging via syslog" +timestamp_type + T_TUPLE + "Type of authentication timestamp record: %s" + global ppid tty diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 0675d9acb..ab2e7cfd3 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -498,9 +498,6 @@ init_defaults(void) #ifdef SEND_MAIL_WHEN_NOT_OK def_mail_no_perms = true; #endif -#ifndef NO_TTY_TICKETS - def_tty_tickets = true; -#endif #ifndef NO_LECTURE def_lecture = once; #endif @@ -534,6 +531,7 @@ init_defaults(void) #ifdef UMASK_OVERRIDE def_umask_override = true; #endif + def_timestamp_type = TIMESTAMP_TYPE; if ((def_iolog_file = strdup("%{seq}")) == NULL) goto oom; if ((def_iolog_dir = strdup(_PATH_SUDO_IO_LOGDIR)) == NULL) diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 7b2fe9cd8..9e2447977 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -71,6 +71,7 @@ static char *find_editor(int nfiles, char **files, int *argc_out, char ***argv_out); static bool cb_fqdn(const union sudo_defs_val *); static bool cb_runas_default(const union sudo_defs_val *); +static bool cb_tty_tickets(const union sudo_defs_val *); static int set_cmnd(void); static int create_admin_success_flag(void); static bool init_vars(char * const *); @@ -760,6 +761,9 @@ init_vars(char * const envp[]) /* Set iolog_mode callback. */ sudo_defs_table[I_IOLOG_MODE].callback = cb_iolog_mode; + /* Set tty_tickets callback. */ + sudo_defs_table[I_TTY_TICKETS].callback = cb_tty_tickets; + /* It is now safe to use log_warningx() and set_perms() */ if (unknown_user) { log_warningx(SLOG_SEND_MAIL, N_("unknown uid: %u"), @@ -1209,6 +1213,22 @@ cb_runas_default(const union sudo_defs_val *sd_un) debug_return_bool(true); } +/* + * Callback for runas_default sudoers setting. + */ +static bool +cb_tty_tickets(const union sudo_defs_val *sd_un) +{ + debug_decl(cb_tty_tickets, SUDOERS_DEBUG_PLUGIN) + + /* Convert tty_tickets -> timestamp_type */ + if (sd_un->flag) + def_timestamp_type = tty; + else + def_timestamp_type = global; + debug_return_bool(true); +} + /* * Cleanup hook for sudo_fatal()/sudo_fatalx() */ diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index d0d73a947..1def3d47a 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -312,15 +312,15 @@ ts_write(int fd, const char *fname, struct timestamp_entry *entry, off_t offset) * based on auth user pw. Does not set the time stamp. */ static void -ts_fill4(struct timestamp_entry *entry, struct passwd *pw, int flags, bool tty_tickets) +ts_init_key(struct timestamp_entry *entry, struct passwd *pw, int flags, + enum def_tuple ticket_type) { struct stat sb; - debug_decl(ts_fill4, SUDOERS_DEBUG_AUTH) + debug_decl(ts_init_key, SUDOERS_DEBUG_AUTH) memset(entry, 0, sizeof(*entry)); entry->version = TS_VERSION; entry->size = sizeof(*entry); - entry->type = TS_GLOBAL; /* may be overriden below */ entry->flags = flags; if (pw != NULL) { entry->auth_uid = pw->pw_uid; @@ -328,31 +328,38 @@ ts_fill4(struct timestamp_entry *entry, struct passwd *pw, int flags, bool tty_t entry->flags |= TS_ANYUID; } entry->sid = user_sid; - if (tty_tickets) { + switch (ticket_type) { + case tty: if (user_ttypath != NULL && stat(user_ttypath, &sb) == 0) { /* tty-based time stamp */ entry->type = TS_TTY; entry->u.ttydev = sb.st_rdev; - } else { - /* ppid-based time stamp */ - entry->type = TS_PPID; - entry->u.ppid = getppid(); + break; } + /* FALLTHROUGH */ + case ppid: + /* ppid-based time stamp */ + entry->type = TS_PPID; + entry->u.ppid = getppid(); + break; + default: + /* global time stamp */ + entry->type = TS_GLOBAL; + break; } debug_return; } static void -ts_fill(struct timestamp_entry *entry, struct passwd *pw, int flags) -{ - ts_fill4(entry, pw, flags, def_tty_tickets); -} - -static void -ts_fill_tty(struct timestamp_entry *entry, struct passwd *pw, int flags) +ts_init_key_nonglobal(struct timestamp_entry *entry, struct passwd *pw, int flags) { - ts_fill4(entry, pw, flags, true); + /* + * Even if the timestamp type is global we still want to do per-tty + * or per-ppid locking so sudo works predictably in a pipeline. + */ + ts_init_key(entry, pw, flags, + def_timestamp_type != global ? def_timestamp_type : tty); } /* @@ -602,13 +609,15 @@ timestamp_lock(void *vcookie, struct passwd *pw) debug_return_bool(false); } - /* Search for a tty-based record or append a new one. */ + /* Search for a tty/ppid-based record or append a new one. */ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "searching for tty time stamp record"); - ts_fill_tty(&cookie->key, pw, TS_DISABLED); + "searching for %s time stamp record", + def_timestamp_type == ppid ? "ppid" : "tty"); + ts_init_key_nonglobal(&cookie->key, pw, TS_DISABLED); if (ts_find_record(cookie->fd, &cookie->key, &entry)) { sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "found existing tty time stamp record"); + "found existing %s time stamp record", + def_timestamp_type == ppid ? "ppid" : "tty"); lock_pos = lseek(cookie->fd, 0, SEEK_CUR) - (off_t)entry.size; } else { sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, @@ -618,19 +627,16 @@ timestamp_lock(void *vcookie, struct passwd *pw) debug_return_bool(false); } sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "tty time stamp position is %lld", (long long)lock_pos); + "%s time stamp position is %lld", + def_timestamp_type == ppid ? "ppid" : "tty", (long long)lock_pos); - if (def_tty_tickets) { - /* For tty tickets the tty lock is the same as the record lock. */ - cookie->pos = lock_pos; - cookie->locked = true; - } else { + if (def_timestamp_type == global) { /* - * For non-tty tickets we use a separate record lock that we + * For global tickets we use a separate record lock that we * cannot hold long-term since it is shared between all ttys. */ cookie->locked = false; - cookie->key.type = TS_GLOBAL; /* find a non-tty record */ + cookie->key.type = TS_GLOBAL; /* find a global record */ if (lseek(cookie->fd, 0, SEEK_SET) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, @@ -648,6 +654,10 @@ timestamp_lock(void *vcookie, struct passwd *pw) if (ts_write(cookie->fd, cookie->fname, &cookie->key, -1) == -1) debug_return_bool(false); } + } else { + /* For tty/ppid tickets the tty lock is the same as the record lock. */ + cookie->pos = lock_pos; + cookie->locked = true; } /* Unlock the TS_LOCKEXCL record. */ @@ -872,7 +882,7 @@ timestamp_remove(bool unlink_it) /* * Find matching entries and invalidate them. */ - ts_fill(&key, NULL, 0); + ts_init_key(&key, NULL, 0, def_timestamp_type); while (ts_find_record(fd, &key, &entry)) { /* Back up and disable the entry. */ if (!ISSET(entry.flags, TS_DISABLED)) { -- 2.40.0