aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/pam_unix/pam_unix.8.xml13
-rw-r--r--modules/pam_unix/pam_unix_acct.c26
-rw-r--r--modules/pam_unix/support.c47
-rw-r--r--modules/pam_unix/support.h7
4 files changed, 67 insertions, 26 deletions
diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
index 93a01c89..607ec85c 100644
--- a/modules/pam_unix/pam_unix.8.xml
+++ b/modules/pam_unix/pam_unix.8.xml
@@ -165,6 +165,19 @@
</varlistentry>
<varlistentry>
<term>
+ <option>nullresetok</option>
+ </term>
+ <listitem>
+ <para>
+ Allow users to authenticate with blank password if password reset
+ is enforced even if <option>nullok</option> is not set. If password
+ reset is not required and <option>nullok</option> is not set the
+ authentication with blank password will be denied.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<option>try_first_pass</option>
</term>
<listitem>
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index 36f68eff..0c5dff96 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -192,8 +192,6 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
const void *void_uname;
const char *uname;
int retval, daysleft;
- struct spwd *spent;
- struct passwd *pwent;
char buf[256];
D(("called."));
@@ -210,29 +208,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_USER_UNKNOWN;
}
- retval = get_account_info(pamh, uname, &pwent, &spent);
- if (retval == PAM_USER_UNKNOWN) {
- pam_syslog(pamh, LOG_ERR,
- "could not identify user (from getpwnam(%s))",
- uname);
- return retval;
- }
-
- if (retval == PAM_SUCCESS && spent == NULL)
- return PAM_SUCCESS;
-
- if (retval == PAM_UNIX_RUN_HELPER) {
- retval = _unix_run_verify_binary(pamh, ctrl, uname, &daysleft);
- if (retval == PAM_AUTHINFO_UNAVAIL &&
- on(UNIX_BROKEN_SHADOW, ctrl))
- return PAM_SUCCESS;
- } else if (retval != PAM_SUCCESS) {
- if (on(UNIX_BROKEN_SHADOW,ctrl))
- return PAM_SUCCESS;
- else
- return retval;
- } else
- retval = check_shadow_expiry(pamh, spent, &daysleft);
+ retval = _unix_verify_user(pamh, ctrl, uname, &daysleft);
if (on(UNIX_NO_PASS_EXPIRY, ctrl)) {
const void *pretval = NULL;
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index 33761840..6a840a26 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -595,6 +595,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name
{
struct passwd *pwd = NULL;
char *salt = NULL;
+ int daysleft;
int retval;
D(("called"));
@@ -605,6 +606,15 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name
* else (CG)
*/
+ if (on(UNIX_NULLRESETOK, ctrl)) {
+ retval = _unix_verify_user(pamh, ctrl, name, &daysleft);
+ if (retval == PAM_NEW_AUTHTOK_REQD) {
+ /* password reset is enforced, allow authentication with empty password */
+ pam_syslog(pamh, LOG_DEBUG, "user [%s] has expired blank password, enabling nullok", name);
+ set(UNIX__NULLOK, ctrl);
+ }
+ }
+
if (on(UNIX__NONULL, ctrl))
return 0; /* will fail but don't let on yet */
@@ -796,6 +806,43 @@ cleanup:
return retval;
}
+int
+_unix_verify_user(pam_handle_t *pamh,
+ unsigned long long ctrl,
+ const char *name,
+ int *daysleft)
+{
+ int retval;
+ struct spwd *spent;
+ struct passwd *pwent;
+
+ retval = get_account_info(pamh, name, &pwent, &spent);
+ if (retval == PAM_USER_UNKNOWN) {
+ pam_syslog(pamh, LOG_ERR,
+ "could not identify user (from getpwnam(%s))",
+ name);
+ return retval;
+ }
+
+ if (retval == PAM_SUCCESS && spent == NULL)
+ return PAM_SUCCESS;
+
+ if (retval == PAM_UNIX_RUN_HELPER) {
+ retval = _unix_run_verify_binary(pamh, ctrl, name, daysleft);
+ if (retval == PAM_AUTHINFO_UNAVAIL &&
+ on(UNIX_BROKEN_SHADOW, ctrl))
+ return PAM_SUCCESS;
+ } else if (retval != PAM_SUCCESS) {
+ if (on(UNIX_BROKEN_SHADOW,ctrl))
+ return PAM_SUCCESS;
+ else
+ return retval;
+ } else
+ retval = check_shadow_expiry(pamh, spent, daysleft);
+
+ return retval;
+}
+
/* ****************************************************************** *
* Copyright (c) Jan Rękorajski 1999.
* Copyright (c) Andrew G. Morgan 1996-8.
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index e02c05e0..19754dc1 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -100,8 +100,9 @@ typedef struct {
#define UNIX_DES 30 /* DES, default */
#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */
#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */
+#define UNIX_NULLRESETOK 33 /* allow empty password if password reset is enforced */
/* -------------- */
-#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */
#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl))
@@ -143,6 +144,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1},
/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1},
/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1},
+/* UNIX_NULLRESETOK */ {"nullresetok", _ALL_ON_, 020000000000, 0},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
@@ -171,6 +173,9 @@ extern int _unix_blankpasswd(pam_handle_t *pamh, unsigned long long ctrl,
extern int _unix_verify_password(pam_handle_t * pamh, const char *name,
const char *p, unsigned long long ctrl);
+extern int _unix_verify_user(pam_handle_t *pamh, unsigned long long ctrl,
+ const char *name, int *daysleft);
+
extern int _unix_run_verify_binary(pam_handle_t *pamh,
unsigned long long ctrl,
const char *user, int *daysleft);