From 805175efc90d81d3dc7700e4c823a3210337ebe0 Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Wed, 10 Apr 2024 01:08:47 +0200 Subject: [PATCH] Add pam_silent configuration setting This commit adds a boolean setting 'pam_silent' that controls whether sudo will pass PAM_SILENT to pam_authenticate(). The default for this setting is 'true'. When this setting is set to 'false', pam messages such as faillock lockout message will be displayed, which is not the case for the default. --- examples/sudo.conf.in | 10 ++++++++++ include/sudo_conf.h | 2 ++ lib/util/sudo_conf.c | 26 ++++++++++++++++++++++++++ lib/util/util.exp.in | 1 + plugins/sudoers/auth/pam.c | 2 +- 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/examples/sudo.conf.in b/examples/sudo.conf.in index 2187457e81..5d1ef8486c 100644 --- a/examples/sudo.conf.in +++ b/examples/sudo.conf.in @@ -116,6 +116,16 @@ # #Set probe_interfaces false +# +# PAM verbosity: +# Set pam_silent true|false +# +# By default, sudo will call PAM's authentication in silent mode to reduce +# messages printed on the terminal. This can however hide potentially +# important messages such as the account lockout messages by pam_faillock. +# +#Set pam_silent true + # # Sudo debug files: # Debug program /path/to/debug_log subsystem@priority[,subsyste@priority] diff --git a/include/sudo_conf.h b/include/sudo_conf.h index 866e47de3a..acd3a6284f 100644 --- a/include/sudo_conf.h +++ b/include/sudo_conf.h @@ -75,6 +75,7 @@ sudo_dso_public struct plugin_info_list *sudo_conf_plugins_v1(void); sudo_dso_public bool sudo_conf_disable_coredump_v1(void); sudo_dso_public bool sudo_conf_developer_mode_v1(void); sudo_dso_public bool sudo_conf_probe_interfaces_v1(void); +sudo_dso_public bool sudo_conf_pam_silent_v1(void); sudo_dso_public int sudo_conf_group_source_v1(void); sudo_dso_public int sudo_conf_max_groups_v1(void); sudo_dso_public void sudo_conf_clear_paths_v1(void); @@ -90,6 +91,7 @@ sudo_dso_public void sudo_conf_clear_paths_v1(void); #define sudo_conf_disable_coredump() sudo_conf_disable_coredump_v1() #define sudo_conf_developer_mode() sudo_conf_developer_mode_v1() #define sudo_conf_probe_interfaces() sudo_conf_probe_interfaces_v1() +#define sudo_conf_pam_silent() sudo_conf_pam_silent_v1() #define sudo_conf_group_source() sudo_conf_group_source_v1() #define sudo_conf_max_groups() sudo_conf_max_groups_v1() #define sudo_conf_clear_paths() sudo_conf_clear_paths_v1() diff --git a/lib/util/sudo_conf.c b/lib/util/sudo_conf.c index be22e45051..b34cecfa3c 100644 --- a/lib/util/sudo_conf.c +++ b/lib/util/sudo_conf.c @@ -79,6 +79,7 @@ struct sudo_conf_settings { bool updated; bool disable_coredump; bool probe_interfaces; + bool pam_silent; int group_source; int max_groups; }; @@ -100,12 +101,14 @@ static int set_var_disable_coredump(const char *entry, const char *conf_file, un static int set_var_group_source(const char *entry, const char *conf_file, unsigned int); static int set_var_max_groups(const char *entry, const char *conf_file, unsigned int); static int set_var_probe_interfaces(const char *entry, const char *conf_file, unsigned int); +static int set_var_pam_silent(const char *entry, const char *conf_file, unsigned int); static struct sudo_conf_table sudo_conf_var_table[] = { { "disable_coredump", sizeof("disable_coredump") - 1, set_var_disable_coredump }, { "group_source", sizeof("group_source") - 1, set_var_group_source }, { "max_groups", sizeof("max_groups") - 1, set_var_max_groups }, { "probe_interfaces", sizeof("probe_interfaces") - 1, set_var_probe_interfaces }, + { "pam_silent", sizeof("pam_silent") - 1, set_var_pam_silent }, { NULL } }; @@ -142,6 +145,7 @@ static struct sudo_conf_table sudo_conf_var_table[] = { false, /* updated */ \ true, /* disable_coredump */ \ true, /* probe_interfaces */ \ + true, /* pam_silent */ \ GROUP_SOURCE_DEFAULT, /* group_source */ \ -1 /* max_groups */ \ } @@ -461,6 +465,22 @@ set_var_probe_interfaces(const char *strval, const char *conf_file, debug_return_int(true); } +static int +set_var_pam_silent(const char *strval, const char *conf_file, + unsigned int lineno) +{ + int val = sudo_strtobool(strval); + debug_decl(set_var_pam_silent, SUDO_DEBUG_UTIL); + + if (val == -1) { + sudo_warnx(U_("invalid value for %s \"%s\" in %s, line %u"), + "pam_silent", strval, conf_file, lineno); + debug_return_int(false); + } + sudo_conf_data.settings.pam_silent = val; + debug_return_int(true); +} + const char * sudo_conf_askpass_path_v1(void) { @@ -590,6 +610,12 @@ sudo_conf_probe_interfaces_v1(void) return sudo_conf_data.settings.probe_interfaces; } +bool +sudo_conf_pam_silent_v1(void) +{ + return sudo_conf_data.settings.pam_silent; +} + /* * Free dynamically allocated parts of sudo_conf_data and * reset to initial values. diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in index ca9dcede21..17c2dea3e9 100644 --- a/lib/util/util.exp.in +++ b/lib/util/util.exp.in @@ -15,6 +15,7 @@ sudo_conf_noexec_path_v1 sudo_conf_plugin_dir_path_v1 sudo_conf_plugins_v1 sudo_conf_probe_interfaces_v1 +sudo_conf_pam_silent_v1 sudo_conf_read_v1 sudo_conf_sesh_path_v1 sudo_debug_deregister_v1 diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index e8d17856a8..f6b96a3e38 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, sudo_conf_pam_silent() ? PAM_SILENT : 0); /* Restore def_prompt, the passed-in prompt may be freed later. */ def_prompt = PASSPROMPT;