From 43953173e4ea404b291fe7c76ab0c70da103e363 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 17 Apr 2024 19:30:11 -0600 Subject: [PATCH] Add pam_silent sudoers option. Inspired by PR #368 GitHub issue #216 --- docs/sudoers.man.in | 18 ++++- docs/sudoers.mdoc.in | 17 ++++- plugins/sudoers/auth/pam.c | 2 +- plugins/sudoers/def_data.c | 4 ++ plugins/sudoers/def_data.h | 130 ++++++++++++++++++------------------ plugins/sudoers/def_data.in | 3 + plugins/sudoers/defaults.c | 1 + 7 files changed, 108 insertions(+), 67 deletions(-) diff --git a/docs/sudoers.man.in b/docs/sudoers.man.in index e8e68303d5..ed570c1375 100644 --- a/docs/sudoers.man.in +++ b/docs/sudoers.man.in @@ -25,7 +25,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.TH "SUDOERS" "@mansectform@" "December 19, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDOERS" "@mansectform@" "April 17, 2024" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -3816,6 +3816,22 @@ by default. .sp This setting is only supported by version 1.8.8 or higher. .TP 18n +pam_silent +If set, PAM authentication will be performed in silent mode. +This prevents PAM authentication modules from generating output. +In some cases, this may suppress important information about why +authentication failed. +For example, PAM modules such as +\fIpam_faillock\fR +will only display a warning if +\fIpam_silent\fR +is disabled. +This flag is +\fIon\fR +by default. +.sp +This setting is only supported by version 1.8.16 or higher. +.TP 18n passprompt_override If set, the prompt specified by \fIpassprompt\fR diff --git a/docs/sudoers.mdoc.in b/docs/sudoers.mdoc.in index 8ec5c32ae9..7c609f2c7d 100644 --- a/docs/sudoers.mdoc.in +++ b/docs/sudoers.mdoc.in @@ -25,7 +25,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.Dd December 19, 2023 +.Dd April 17, 2024 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -3615,6 +3615,21 @@ This flag is by default. .Pp This setting is only supported by version 1.8.8 or higher. +.It pam_silent +If set, PAM authentication will be performed in silent mode. +This prevents PAM authentication modules from generating output. +In some cases, this may suppress important information about why +authentication failed. +For example, PAM modules such as +.Em pam_faillock +will only display a warning if +.Em pam_silent +is disabled. +This flag is +.Em on +by default. +.Pp +This setting is only supported by version 1.8.16 or higher. .It passprompt_override If set, the prompt specified by .Em passprompt diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index e8d17856a8..3b678bf4d4 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -318,7 +318,7 @@ sudo_pam_verify(const struct sudoers_context *ctx, struct passwd *pw, } /* PAM_SILENT prevents the authentication service from generating output. */ - *pam_status = pam_authenticate(pamh, PAM_SILENT); + *pam_status = pam_authenticate(pamh, def_pam_silent ? PAM_SILENT : 0); /* Restore def_prompt, the passed-in prompt may be freed later. */ def_prompt = PASSPROMPT; diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index b8c1212d24..b90a722d40 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -439,6 +439,10 @@ struct sudo_defs_types sudo_defs_table[] = { "pam_acct_mgmt", T_FLAG, N_("Perform PAM account validation management"), NULL, + }, { + "pam_silent", T_FLAG, + N_("Do not allow PAM authentication modules to generate output"), + NULL, }, { "maxseq", T_STR, N_("Maximum I/O log sequence number: %s"), diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 5c244a45c9..79af80cc39 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -194,133 +194,135 @@ #define def_pam_session (sudo_defs_table[I_PAM_SESSION].sd_un.flag) #define I_PAM_ACCT_MGMT 96 #define def_pam_acct_mgmt (sudo_defs_table[I_PAM_ACCT_MGMT].sd_un.flag) -#define I_MAXSEQ 97 +#define I_PAM_SILENT 97 +#define def_pam_silent (sudo_defs_table[I_PAM_SILENT].sd_un.flag) +#define I_MAXSEQ 98 #define def_maxseq (sudo_defs_table[I_MAXSEQ].sd_un.str) -#define I_USE_NETGROUPS 98 +#define I_USE_NETGROUPS 99 #define def_use_netgroups (sudo_defs_table[I_USE_NETGROUPS].sd_un.flag) -#define I_SUDOEDIT_CHECKDIR 99 +#define I_SUDOEDIT_CHECKDIR 100 #define def_sudoedit_checkdir (sudo_defs_table[I_SUDOEDIT_CHECKDIR].sd_un.flag) -#define I_SUDOEDIT_FOLLOW 100 +#define I_SUDOEDIT_FOLLOW 101 #define def_sudoedit_follow (sudo_defs_table[I_SUDOEDIT_FOLLOW].sd_un.flag) -#define I_ALWAYS_QUERY_GROUP_PLUGIN 101 +#define I_ALWAYS_QUERY_GROUP_PLUGIN 102 #define def_always_query_group_plugin (sudo_defs_table[I_ALWAYS_QUERY_GROUP_PLUGIN].sd_un.flag) -#define I_NETGROUP_TUPLE 102 +#define I_NETGROUP_TUPLE 103 #define def_netgroup_tuple (sudo_defs_table[I_NETGROUP_TUPLE].sd_un.flag) -#define I_IGNORE_AUDIT_ERRORS 103 +#define I_IGNORE_AUDIT_ERRORS 104 #define def_ignore_audit_errors (sudo_defs_table[I_IGNORE_AUDIT_ERRORS].sd_un.flag) -#define I_IGNORE_IOLOG_ERRORS 104 +#define I_IGNORE_IOLOG_ERRORS 105 #define def_ignore_iolog_errors (sudo_defs_table[I_IGNORE_IOLOG_ERRORS].sd_un.flag) -#define I_IGNORE_LOGFILE_ERRORS 105 +#define I_IGNORE_LOGFILE_ERRORS 106 #define def_ignore_logfile_errors (sudo_defs_table[I_IGNORE_LOGFILE_ERRORS].sd_un.flag) -#define I_MATCH_GROUP_BY_GID 106 +#define I_MATCH_GROUP_BY_GID 107 #define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag) -#define I_SYSLOG_MAXLEN 107 +#define I_SYSLOG_MAXLEN 108 #define def_syslog_maxlen (sudo_defs_table[I_SYSLOG_MAXLEN].sd_un.uival) -#define I_IOLOG_USER 108 +#define I_IOLOG_USER 109 #define def_iolog_user (sudo_defs_table[I_IOLOG_USER].sd_un.str) -#define I_IOLOG_GROUP 109 +#define I_IOLOG_GROUP 110 #define def_iolog_group (sudo_defs_table[I_IOLOG_GROUP].sd_un.str) -#define I_IOLOG_MODE 110 +#define I_IOLOG_MODE 111 #define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode) -#define I_FDEXEC 111 +#define I_FDEXEC 112 #define def_fdexec (sudo_defs_table[I_FDEXEC].sd_un.tuple) -#define I_IGNORE_UNKNOWN_DEFAULTS 112 +#define I_IGNORE_UNKNOWN_DEFAULTS 113 #define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag) -#define I_COMMAND_TIMEOUT 113 +#define I_COMMAND_TIMEOUT 114 #define def_command_timeout (sudo_defs_table[I_COMMAND_TIMEOUT].sd_un.ival) -#define I_USER_COMMAND_TIMEOUTS 114 +#define I_USER_COMMAND_TIMEOUTS 115 #define def_user_command_timeouts (sudo_defs_table[I_USER_COMMAND_TIMEOUTS].sd_un.flag) -#define I_IOLOG_FLUSH 115 +#define I_IOLOG_FLUSH 116 #define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag) -#define I_SYSLOG_PID 116 +#define I_SYSLOG_PID 117 #define def_syslog_pid (sudo_defs_table[I_SYSLOG_PID].sd_un.flag) -#define I_TIMESTAMP_TYPE 117 +#define I_TIMESTAMP_TYPE 118 #define def_timestamp_type (sudo_defs_table[I_TIMESTAMP_TYPE].sd_un.tuple) -#define I_AUTHFAIL_MESSAGE 118 +#define I_AUTHFAIL_MESSAGE 119 #define def_authfail_message (sudo_defs_table[I_AUTHFAIL_MESSAGE].sd_un.str) -#define I_CASE_INSENSITIVE_USER 119 +#define I_CASE_INSENSITIVE_USER 120 #define def_case_insensitive_user (sudo_defs_table[I_CASE_INSENSITIVE_USER].sd_un.flag) -#define I_CASE_INSENSITIVE_GROUP 120 +#define I_CASE_INSENSITIVE_GROUP 121 #define def_case_insensitive_group (sudo_defs_table[I_CASE_INSENSITIVE_GROUP].sd_un.flag) -#define I_LOG_ALLOWED 121 +#define I_LOG_ALLOWED 122 #define def_log_allowed (sudo_defs_table[I_LOG_ALLOWED].sd_un.flag) -#define I_LOG_DENIED 122 +#define I_LOG_DENIED 123 #define def_log_denied (sudo_defs_table[I_LOG_DENIED].sd_un.flag) -#define I_LOG_SERVERS 123 +#define I_LOG_SERVERS 124 #define def_log_servers (sudo_defs_table[I_LOG_SERVERS].sd_un.list) -#define I_LOG_SERVER_TIMEOUT 124 +#define I_LOG_SERVER_TIMEOUT 125 #define def_log_server_timeout (sudo_defs_table[I_LOG_SERVER_TIMEOUT].sd_un.ival) -#define I_LOG_SERVER_KEEPALIVE 125 +#define I_LOG_SERVER_KEEPALIVE 126 #define def_log_server_keepalive (sudo_defs_table[I_LOG_SERVER_KEEPALIVE].sd_un.flag) -#define I_LOG_SERVER_CABUNDLE 126 +#define I_LOG_SERVER_CABUNDLE 127 #define def_log_server_cabundle (sudo_defs_table[I_LOG_SERVER_CABUNDLE].sd_un.str) -#define I_LOG_SERVER_PEER_CERT 127 +#define I_LOG_SERVER_PEER_CERT 128 #define def_log_server_peer_cert (sudo_defs_table[I_LOG_SERVER_PEER_CERT].sd_un.str) -#define I_LOG_SERVER_PEER_KEY 128 +#define I_LOG_SERVER_PEER_KEY 129 #define def_log_server_peer_key (sudo_defs_table[I_LOG_SERVER_PEER_KEY].sd_un.str) -#define I_LOG_SERVER_VERIFY 129 +#define I_LOG_SERVER_VERIFY 130 #define def_log_server_verify (sudo_defs_table[I_LOG_SERVER_VERIFY].sd_un.flag) -#define I_RUNAS_ALLOW_UNKNOWN_ID 130 +#define I_RUNAS_ALLOW_UNKNOWN_ID 131 #define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag) -#define I_RUNAS_CHECK_SHELL 131 +#define I_RUNAS_CHECK_SHELL 132 #define def_runas_check_shell (sudo_defs_table[I_RUNAS_CHECK_SHELL].sd_un.flag) -#define I_PAM_RUSER 132 +#define I_PAM_RUSER 133 #define def_pam_ruser (sudo_defs_table[I_PAM_RUSER].sd_un.flag) -#define I_PAM_RHOST 133 +#define I_PAM_RHOST 134 #define def_pam_rhost (sudo_defs_table[I_PAM_RHOST].sd_un.flag) -#define I_RUNCWD 134 +#define I_RUNCWD 135 #define def_runcwd (sudo_defs_table[I_RUNCWD].sd_un.str) -#define I_RUNCHROOT 135 +#define I_RUNCHROOT 136 #define def_runchroot (sudo_defs_table[I_RUNCHROOT].sd_un.str) -#define I_LOG_FORMAT 136 +#define I_LOG_FORMAT 137 #define def_log_format (sudo_defs_table[I_LOG_FORMAT].sd_un.tuple) -#define I_SELINUX 137 +#define I_SELINUX 138 #define def_selinux (sudo_defs_table[I_SELINUX].sd_un.flag) -#define I_ADMIN_FLAG 138 +#define I_ADMIN_FLAG 139 #define def_admin_flag (sudo_defs_table[I_ADMIN_FLAG].sd_un.str) -#define I_INTERCEPT 139 +#define I_INTERCEPT 140 #define def_intercept (sudo_defs_table[I_INTERCEPT].sd_un.flag) -#define I_LOG_SUBCMDS 140 +#define I_LOG_SUBCMDS 141 #define def_log_subcmds (sudo_defs_table[I_LOG_SUBCMDS].sd_un.flag) -#define I_LOG_EXIT_STATUS 141 +#define I_LOG_EXIT_STATUS 142 #define def_log_exit_status (sudo_defs_table[I_LOG_EXIT_STATUS].sd_un.flag) -#define I_INTERCEPT_AUTHENTICATE 142 +#define I_INTERCEPT_AUTHENTICATE 143 #define def_intercept_authenticate (sudo_defs_table[I_INTERCEPT_AUTHENTICATE].sd_un.flag) -#define I_INTERCEPT_ALLOW_SETID 143 +#define I_INTERCEPT_ALLOW_SETID 144 #define def_intercept_allow_setid (sudo_defs_table[I_INTERCEPT_ALLOW_SETID].sd_un.flag) -#define I_RLIMIT_AS 144 +#define I_RLIMIT_AS 145 #define def_rlimit_as (sudo_defs_table[I_RLIMIT_AS].sd_un.str) -#define I_RLIMIT_CORE 145 +#define I_RLIMIT_CORE 146 #define def_rlimit_core (sudo_defs_table[I_RLIMIT_CORE].sd_un.str) -#define I_RLIMIT_CPU 146 +#define I_RLIMIT_CPU 147 #define def_rlimit_cpu (sudo_defs_table[I_RLIMIT_CPU].sd_un.str) -#define I_RLIMIT_DATA 147 +#define I_RLIMIT_DATA 148 #define def_rlimit_data (sudo_defs_table[I_RLIMIT_DATA].sd_un.str) -#define I_RLIMIT_FSIZE 148 +#define I_RLIMIT_FSIZE 149 #define def_rlimit_fsize (sudo_defs_table[I_RLIMIT_FSIZE].sd_un.str) -#define I_RLIMIT_LOCKS 149 +#define I_RLIMIT_LOCKS 150 #define def_rlimit_locks (sudo_defs_table[I_RLIMIT_LOCKS].sd_un.str) -#define I_RLIMIT_MEMLOCK 150 +#define I_RLIMIT_MEMLOCK 151 #define def_rlimit_memlock (sudo_defs_table[I_RLIMIT_MEMLOCK].sd_un.str) -#define I_RLIMIT_NOFILE 151 +#define I_RLIMIT_NOFILE 152 #define def_rlimit_nofile (sudo_defs_table[I_RLIMIT_NOFILE].sd_un.str) -#define I_RLIMIT_NPROC 152 +#define I_RLIMIT_NPROC 153 #define def_rlimit_nproc (sudo_defs_table[I_RLIMIT_NPROC].sd_un.str) -#define I_RLIMIT_RSS 153 +#define I_RLIMIT_RSS 154 #define def_rlimit_rss (sudo_defs_table[I_RLIMIT_RSS].sd_un.str) -#define I_RLIMIT_STACK 154 +#define I_RLIMIT_STACK 155 #define def_rlimit_stack (sudo_defs_table[I_RLIMIT_STACK].sd_un.str) -#define I_NONINTERACTIVE_AUTH 155 +#define I_NONINTERACTIVE_AUTH 156 #define def_noninteractive_auth (sudo_defs_table[I_NONINTERACTIVE_AUTH].sd_un.flag) -#define I_LOG_PASSWORDS 156 +#define I_LOG_PASSWORDS 157 #define def_log_passwords (sudo_defs_table[I_LOG_PASSWORDS].sd_un.flag) -#define I_PASSPROMPT_REGEX 157 +#define I_PASSPROMPT_REGEX 158 #define def_passprompt_regex (sudo_defs_table[I_PASSPROMPT_REGEX].sd_un.list) -#define I_INTERCEPT_TYPE 158 +#define I_INTERCEPT_TYPE 159 #define def_intercept_type (sudo_defs_table[I_INTERCEPT_TYPE].sd_un.tuple) -#define I_INTERCEPT_VERIFY 159 +#define I_INTERCEPT_VERIFY 160 #define def_intercept_verify (sudo_defs_table[I_INTERCEPT_VERIFY].sd_un.flag) -#define I_APPARMOR_PROFILE 160 +#define I_APPARMOR_PROFILE 161 #define def_apparmor_profile (sudo_defs_table[I_APPARMOR_PROFILE].sd_un.str) enum def_tuple { diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index 4d627e64b6..e96d36deb2 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -304,6 +304,9 @@ pam_session pam_acct_mgmt T_FLAG "Perform PAM account validation management" +pam_silent + T_FLAG + "Do not allow PAM authentication modules to generate output" maxseq T_STR "Maximum I/O log sequence number: %s" diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 34c5d1d83f..d410db6857 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -661,6 +661,7 @@ init_defaults(void) def_set_utmp = true; def_pam_acct_mgmt = true; def_pam_setcred = true; + def_pam_silent = true; def_syslog_maxlen = MAXSYSLOGLEN; def_case_insensitive_user = true; def_case_insensitive_group = true;