From 976550084e98343d57309ebfa99ff145f6a2b71b Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 29 Apr 2019 19:44:13 -0600 Subject: [PATCH] Add pam_acct_mgmt setting to enable/disable PAM account validation. --- doc/sudoers.cat | 13 +++- doc/sudoers.man.in | 15 ++++- doc/sudoers.mdoc.in | 14 ++++- plugins/sudoers/auth/pam.c | 114 ++++++++++++++++++------------------ plugins/sudoers/def_data.c | 4 ++ plugins/sudoers/def_data.h | 50 ++++++++-------- plugins/sudoers/def_data.in | 3 + plugins/sudoers/defaults.c | 1 + 8 files changed, 131 insertions(+), 83 deletions(-) diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 9c4b79f69..b1677d3fc 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -1286,6 +1286,17 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS well as the _P_r_e_v_e_n_t_i_n_g _s_h_e_l_l _e_s_c_a_p_e_s section at the end of this manual. This flag is _o_f_f by default. + pam_acct_mgmt On systems that use PAM for authentication, ssuuddoo will + perform PAM account validation for the invoking user by + default. The actual checks performed depend on which + PAM modules are configured. If enabled, account + validation will be performed regardless of whether or + not a password is required. This flag is _o_n by + default. + + This setting is only supported by version 1.8.28 or + higher. + pam_session On systems that use PAM for authentication, ssuuddoo will create a new PAM session for the command to be run in. Disabling _p_a_m___s_e_s_s_i_o_n may be needed on older PAM @@ -2928,4 +2939,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or https://www.sudo.ws/license.html for complete details. -Sudo 1.8.28 March 4, 2019 Sudo 1.8.28 +Sudo 1.8.28 April 29, 2019 Sudo 1.8.28 diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index d05fbc1fc..551e515f0 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -25,7 +25,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.TH "SUDOERS" "@mansectform@" "March 4, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDOERS" "@mansectform@" "April 29, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -2722,6 +2722,19 @@ This flag is \fIoff\fR by default. .TP 18n +pam_acct_mgmt +On systems that use PAM for authentication, +\fBsudo\fR +will perform PAM account validation for the invoking user by default. +The actual checks performed depend on which PAM modules are configured. +If enabled, account validation will be performed regardless of whether +or not a password is required. +This flag is +\fIon\fR +by default. +.sp +This setting is only supported by version 1.8.28 or higher. +.TP 18n pam_session On systems that use PAM for authentication, \fBsudo\fR diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index 3ff8604ff..e6e1aac2e 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -24,7 +24,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.Dd March 4, 2019 +.Dd April 29, 2019 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -2560,6 +2560,18 @@ section at the end of this manual. This flag is .Em off by default. +.It pam_acct_mgmt +On systems that use PAM for authentication, +.Nm sudo +will perform PAM account validation for the invoking user by default. +The actual checks performed depend on which PAM modules are configured. +If enabled, account validation will be performed regardless of whether +or not a password is required. +This flag is +.Em on +by default. +.Pp +This setting is only supported by version 1.8.28 or higher. .It pam_session On systems that use PAM for authentication, .Nm sudo diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 93fbb500c..54e16bb62 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -313,66 +313,68 @@ sudo_pam_approval(struct passwd *pw, sudo_auth *auth, bool exempt) int *pam_status = (int *) auth->data; debug_decl(sudo_pam_approval, SUDOERS_DEBUG_AUTH) - rc = pam_acct_mgmt(pamh, PAM_SILENT); - switch (rc) { - case PAM_SUCCESS: - break; - case PAM_AUTH_ERR: - log_warningx(0, N_("account validation failure, " - "is your account locked?")); - status = AUTH_FATAL; - break; - case PAM_NEW_AUTHTOK_REQD: - /* Ignore if user is exempt from password restrictions. */ - if (exempt) { - rc = *pam_status; + if (def_pam_acct_mgmt) { + rc = pam_acct_mgmt(pamh, PAM_SILENT); + switch (rc) { + case PAM_SUCCESS: break; - } - /* New password required, try to change it. */ - log_warningx(0, N_("Account or password is " - "expired, reset your password and try again")); - rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); - if (rc == PAM_SUCCESS) + case PAM_AUTH_ERR: + log_warningx(0, N_("account validation failure, " + "is your account locked?")); + status = AUTH_FATAL; break; - if ((s = pam_strerror(pamh, rc)) == NULL) - s = "unknown error"; - log_warningx(0, - N_("unable to change expired password: %s"), s); - status = AUTH_FAILURE; - break; - case PAM_AUTHTOK_EXPIRED: - /* Ignore if user is exempt from password restrictions. */ - if (exempt) { - rc = *pam_status; + case PAM_NEW_AUTHTOK_REQD: + /* Ignore if user is exempt from password restrictions. */ + if (exempt) { + rc = *pam_status; + break; + } + /* New password required, try to change it. */ + log_warningx(0, N_("Account or password is " + "expired, reset your password and try again")); + rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + if (rc == PAM_SUCCESS) + break; + if ((s = pam_strerror(pamh, rc)) == NULL) + s = "unknown error"; + log_warningx(0, + N_("unable to change expired password: %s"), s); + status = AUTH_FAILURE; break; - } - /* Password expired, cannot be updated by user. */ - log_warningx(0, - N_("Password expired, contact your system administrator")); - status = AUTH_FATAL; - break; - case PAM_ACCT_EXPIRED: - log_warningx(0, - N_("Account expired or PAM config lacks an \"account\" " - "section for sudo, contact your system administrator")); - status = AUTH_FATAL; - break; - case PAM_AUTHINFO_UNAVAIL: - case PAM_MAXTRIES: - case PAM_PERM_DENIED: - s = pam_strerror(pamh, rc); - log_warningx(0, N_("PAM account management error: %s"), - s ? s : "unknown error"); - status = AUTH_FAILURE; - break; - default: - s = pam_strerror(pamh, rc); - log_warningx(0, N_("PAM account management error: %s"), - s ? s : "unknown error"); - status = AUTH_FATAL; - break; + case PAM_AUTHTOK_EXPIRED: + /* Ignore if user is exempt from password restrictions. */ + if (exempt) { + rc = *pam_status; + break; + } + /* Password expired, cannot be updated by user. */ + log_warningx(0, + N_("Password expired, contact your system administrator")); + status = AUTH_FATAL; + break; + case PAM_ACCT_EXPIRED: + log_warningx(0, + N_("Account expired or PAM config lacks an \"account\" " + "section for sudo, contact your system administrator")); + status = AUTH_FATAL; + break; + case PAM_AUTHINFO_UNAVAIL: + case PAM_MAXTRIES: + case PAM_PERM_DENIED: + s = pam_strerror(pamh, rc); + log_warningx(0, N_("PAM account management error: %s"), + s ? s : "unknown error"); + status = AUTH_FAILURE; + break; + default: + s = pam_strerror(pamh, rc); + log_warningx(0, N_("PAM account management error: %s"), + s ? s : "unknown error"); + status = AUTH_FATAL; + break; + } + *pam_status = rc; } - *pam_status = rc; debug_return_int(status); } diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index 07e343320..ba5be8dfb 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -397,6 +397,10 @@ struct sudo_defs_types sudo_defs_table[] = { "pam_session", T_FLAG, N_("Create a new PAM session for the command to run in"), NULL, + }, { + "pam_acct_mgmt", T_FLAG, + N_("Perform PAM account validation management"), + NULL, }, { "maxseq", T_UINT, N_("Maximum I/O log sequence number: %u"), diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 65f10c355..b33ba6d93 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -178,53 +178,55 @@ #define def_pam_setcred (sudo_defs_table[I_PAM_SETCRED].sd_un.flag) #define I_PAM_SESSION 89 #define def_pam_session (sudo_defs_table[I_PAM_SESSION].sd_un.flag) -#define I_MAXSEQ 90 +#define I_PAM_ACCT_MGMT 90 +#define def_pam_acct_mgmt (sudo_defs_table[I_PAM_ACCT_MGMT].sd_un.flag) +#define I_MAXSEQ 91 #define def_maxseq (sudo_defs_table[I_MAXSEQ].sd_un.uival) -#define I_USE_NETGROUPS 91 +#define I_USE_NETGROUPS 92 #define def_use_netgroups (sudo_defs_table[I_USE_NETGROUPS].sd_un.flag) -#define I_SUDOEDIT_CHECKDIR 92 +#define I_SUDOEDIT_CHECKDIR 93 #define def_sudoedit_checkdir (sudo_defs_table[I_SUDOEDIT_CHECKDIR].sd_un.flag) -#define I_SUDOEDIT_FOLLOW 93 +#define I_SUDOEDIT_FOLLOW 94 #define def_sudoedit_follow (sudo_defs_table[I_SUDOEDIT_FOLLOW].sd_un.flag) -#define I_ALWAYS_QUERY_GROUP_PLUGIN 94 +#define I_ALWAYS_QUERY_GROUP_PLUGIN 95 #define def_always_query_group_plugin (sudo_defs_table[I_ALWAYS_QUERY_GROUP_PLUGIN].sd_un.flag) -#define I_NETGROUP_TUPLE 95 +#define I_NETGROUP_TUPLE 96 #define def_netgroup_tuple (sudo_defs_table[I_NETGROUP_TUPLE].sd_un.flag) -#define I_IGNORE_AUDIT_ERRORS 96 +#define I_IGNORE_AUDIT_ERRORS 97 #define def_ignore_audit_errors (sudo_defs_table[I_IGNORE_AUDIT_ERRORS].sd_un.flag) -#define I_IGNORE_IOLOG_ERRORS 97 +#define I_IGNORE_IOLOG_ERRORS 98 #define def_ignore_iolog_errors (sudo_defs_table[I_IGNORE_IOLOG_ERRORS].sd_un.flag) -#define I_IGNORE_LOGFILE_ERRORS 98 +#define I_IGNORE_LOGFILE_ERRORS 99 #define def_ignore_logfile_errors (sudo_defs_table[I_IGNORE_LOGFILE_ERRORS].sd_un.flag) -#define I_MATCH_GROUP_BY_GID 99 +#define I_MATCH_GROUP_BY_GID 100 #define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag) -#define I_SYSLOG_MAXLEN 100 +#define I_SYSLOG_MAXLEN 101 #define def_syslog_maxlen (sudo_defs_table[I_SYSLOG_MAXLEN].sd_un.uival) -#define I_IOLOG_USER 101 +#define I_IOLOG_USER 102 #define def_iolog_user (sudo_defs_table[I_IOLOG_USER].sd_un.str) -#define I_IOLOG_GROUP 102 +#define I_IOLOG_GROUP 103 #define def_iolog_group (sudo_defs_table[I_IOLOG_GROUP].sd_un.str) -#define I_IOLOG_MODE 103 +#define I_IOLOG_MODE 104 #define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode) -#define I_FDEXEC 104 +#define I_FDEXEC 105 #define def_fdexec (sudo_defs_table[I_FDEXEC].sd_un.tuple) -#define I_IGNORE_UNKNOWN_DEFAULTS 105 +#define I_IGNORE_UNKNOWN_DEFAULTS 106 #define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag) -#define I_COMMAND_TIMEOUT 106 +#define I_COMMAND_TIMEOUT 107 #define def_command_timeout (sudo_defs_table[I_COMMAND_TIMEOUT].sd_un.ival) -#define I_USER_COMMAND_TIMEOUTS 107 +#define I_USER_COMMAND_TIMEOUTS 108 #define def_user_command_timeouts (sudo_defs_table[I_USER_COMMAND_TIMEOUTS].sd_un.flag) -#define I_IOLOG_FLUSH 108 +#define I_IOLOG_FLUSH 109 #define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag) -#define I_SYSLOG_PID 109 +#define I_SYSLOG_PID 110 #define def_syslog_pid (sudo_defs_table[I_SYSLOG_PID].sd_un.flag) -#define I_TIMESTAMP_TYPE 110 +#define I_TIMESTAMP_TYPE 111 #define def_timestamp_type (sudo_defs_table[I_TIMESTAMP_TYPE].sd_un.tuple) -#define I_AUTHFAIL_MESSAGE 111 +#define I_AUTHFAIL_MESSAGE 112 #define def_authfail_message (sudo_defs_table[I_AUTHFAIL_MESSAGE].sd_un.str) -#define I_CASE_INSENSITIVE_USER 112 +#define I_CASE_INSENSITIVE_USER 113 #define def_case_insensitive_user (sudo_defs_table[I_CASE_INSENSITIVE_USER].sd_un.flag) -#define I_CASE_INSENSITIVE_GROUP 113 +#define I_CASE_INSENSITIVE_GROUP 114 #define def_case_insensitive_group (sudo_defs_table[I_CASE_INSENSITIVE_GROUP].sd_un.flag) enum def_tuple { diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index 99d436008..f9e9716a0 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -283,6 +283,9 @@ pam_setcred pam_session T_FLAG "Create a new PAM session for the command to run in" +pam_acct_mgmt + T_FLAG + "Perform PAM account validation management" maxseq T_UINT "Maximum I/O log sequence number: %u" diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index de161366f..ce4822383 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -641,6 +641,7 @@ init_defaults(void) if ((def_editor = strdup(EDITOR)) == NULL) goto oom; def_set_utmp = true; + def_pam_acct_mgmt = true; def_pam_setcred = true; def_syslog_maxlen = MAXSYSLOGLEN; def_case_insensitive_user = true; -- 2.50.1