Test for locked account in auth.c (bug #442).

Darren Tucker dtucker at zip.com.au
Sun Jan 12 21:59:52 EST 2003


Darren Tucker wrote:
> This patch adds handling of those cases (and takes into account the IRIX
> cases as described by Herbert Lewis) and adds a paragraph to sshd.8
> describing what happens.

Hi All.
	Peter Stuge pointed out a missing "||" in the previous patch and I
found that the regression tests no longer run on Solaris (using shadow
support).  This probably applies to any shadow platform.

	The regression failure is when the tests are not running as root. 
Previously, the shadow expiry tests were:

	spw = getspwnam(pw->pw_name);
	if (spw != NULL) {
		[expiry tests]

so if sshd was not running as root, getspwnam failed and the tests were
skipped.  Now, it's

        spw = getspnam(pw->pw_name);
        if (!spw)
                return 0;

so allowed_user fails rather that just skipping the tests.  The new
locked account tests have a similar problem.

-- 
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
-------------- next part --------------
Index: auth.c
===================================================================
RCS file: /cvs/openssh/auth.c,v
retrieving revision 1.66
diff -u -r1.66 auth.c
--- auth.c	9 Jan 2003 04:04:28 -0000	1.66
+++ auth.c	12 Jan 2003 10:45:52 -0000
@@ -72,7 +72,7 @@
 allowed_user(struct passwd * pw)
 {
 	struct stat st;
-	const char *hostname = NULL, *ipaddr = NULL, *passwd;
+	const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
 	char *shell;
 	int i;
 #ifdef WITH_AIXAUTHENTICATE
@@ -92,15 +92,21 @@
 	/* Grab the password for locked account checking */
 #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
 	spw = getspnam(pw->pw_name);
-	if (!spw)
-		return 0;
-	passwd = spw->sp_pwdp;
+	if (spw)
+		passwd = spw->sp_pwdp;
 #else
 	passwd = pw->pw_passwd;
 #endif
 
 	/* check for locked account */
-	if (strcmp(passwd, "*LK*") == 0 || passwd[0] == '!') {
+	if (passwd && (strcmp(passwd, "*LK*") == 0 ||	/* Solaris,IRIX */
+	    strcmp(passwd, "*") == 0 ||			/* HP-UX,Tru64 */
+	    strstr(passwd, "Nologin") ||		/* Tru64 */
+#ifdef __osf
+	    /* Tru64 but we also want to allow "passwordless" accounts */
+	    (passwd[0] == '*' && strcmp(passwd, "*NP*") != 0) ||
+#endif
+	    passwd[0] == '!')) {			/* Redhat */
 		log("User %.100s not allowed because account is locked",
 		    pw->pw_name);
 		return 0;
@@ -109,31 +115,33 @@
 #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
     !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
 #define	DAY		(24L * 60 * 60) /* 1 day in seconds */
-	today = time(NULL) / DAY;
-	debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
-	    " sp_max %d", (int)today, (int)spw->sp_expire,
-	    (int)spw->sp_lstchg, (int)spw->sp_max);
-
-	/*
-	 * We assume account and password expiration occurs the
-	 * day after the day specified.
-	 */
-	if (spw->sp_expire != -1 && today > spw->sp_expire) {
-		log("Account %.100s has expired", pw->pw_name);
-		return 0;
-	}
-
-	if (spw->sp_lstchg == 0) {
-		log("User %.100s password has expired (root forced)",
-		    pw->pw_name);
-		return 0;
-	}
-
-	if (spw->sp_max != -1 &&
-	    today > spw->sp_lstchg + spw->sp_max) {
-		log("User %.100s password has expired (password aged)",
-		    pw->pw_name);
-		return 0;
+	if (spw) {
+		today = time(NULL) / DAY;
+		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
+		    " sp_max %d", (int)today, (int)spw->sp_expire,
+		    (int)spw->sp_lstchg, (int)spw->sp_max);
+
+		/*
+		 * We assume account and password expiration occurs the
+		 * day after the day specified.
+		 */
+		if (spw->sp_expire != -1 && today > spw->sp_expire) {
+			log("Account %.100s has expired", pw->pw_name);
+			return 0;
+		}
+
+		if (spw->sp_lstchg == 0) {
+			log("User %.100s password has expired (root forced)",
+			    pw->pw_name);
+			return 0;
+		}
+
+		if (spw->sp_max != -1 &&
+		    today > spw->sp_lstchg + spw->sp_max) {
+			log("User %.100s password has expired (password aged)",
+			    pw->pw_name);
+			return 0;
+		}
 	}
 #endif
 
Index: sshd.8
===================================================================
RCS file: /cvs/openssh/sshd.8,v
retrieving revision 1.150
diff -u -r1.150 sshd.8
--- sshd.8	25 Sep 2002 02:20:54 -0000	1.150
+++ sshd.8	12 Jan 2003 10:45:53 -0000
@@ -112,6 +112,30 @@
 authentication, RSA challenge-response authentication, or password
 based authentication.
 .Pp
+Regardless of the authentication type, the account is checked to
+ensure that it is accessible.  An account is not accessible if it is
+locked, listed in
+.Cm DenyUsers
+or its group is listed in
+.Cm DenyGroups
+\&.  An account is considered locked if the passwd entry equals
+.Ql \&*LK\&*
+or
+.Ql \&*
+, contains the string
+.Ql Nologin
+, or has a leading
+.Ql \&!
+(or, on Tru64, a
+.Ql \&*
+) character.  If there is a requirement to disable password authentication
+for the account while allowing still public-key, then the passwd field
+should be set to something other than these values (eg
+.Ql NP
+or
+.Ql \&*NP\&*
+).
+.Pp
 Rhosts authentication is normally disabled
 because it is fundamentally insecure, but can be enabled in the server
 configuration file if desired.


More information about the openssh-unix-dev mailing list