summaryrefslogtreecommitdiff
path: root/modules/pam_unix
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2019-10-31 12:26:31 +0100
committerTomáš Mráz <t8m@users.noreply.github.com>2020-02-18 11:14:27 +0100
commitf5adefa106e28c92dd73dbabac12bad667ef7b8f (patch)
tree3193ef03dfdb94021de12695b5a6d7be1a69c6f7 /modules/pam_unix
parentf07a873240de53e07897d4ef9d1d3fd0c28fe7bb (diff)
pam_unix: add nullresetok option to allow reset blank passwords
Adding nullresetok to auth phase of pam_unix module will allow users with blank password to authenticate in order to immediatelly change their password even if nullok is not set. This allows to have blank password authentication disabled but still allows administrator to create new user accounts with expired blank password that must be change on the first login.
Diffstat (limited to 'modules/pam_unix')
-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);