diff -r bf80034a547d src/auth/auth-settings.c
--- a/src/auth/auth-settings.c	Thu Jan 31 18:27:22 2013 +0200
+++ b/src/auth/auth-settings.c	Thu Jan 31 22:11:31 2013 +0000
@@ -202,6 +202,8 @@
 	DEF(SET_TIME, failure_delay),
 	DEF(SET_UINT, first_valid_uid),
 	DEF(SET_UINT, last_valid_uid),
+        DEF(SET_BOOL, check_nologin),
+        DEF(SET_BOOL, check_homedir),
 
 	DEF(SET_BOOL, verbose),
 	DEF(SET_BOOL, debug),
@@ -241,6 +243,8 @@
 	.failure_delay = 2,
 	.first_valid_uid = 500,
 	.last_valid_uid = 0,
+        .check_nologin = TRUE,
+        .check_homedir = FALSE,
 
 	.verbose = FALSE,
 	.debug = FALSE,
diff -r bf80034a547d src/auth/auth-settings.h
--- a/src/auth/auth-settings.h	Thu Jan 31 18:27:22 2013 +0200
+++ b/src/auth/auth-settings.h	Thu Jan 31 22:11:31 2013 +0000
@@ -40,6 +40,8 @@
 	unsigned int failure_delay;
 	unsigned int first_valid_uid;
 	unsigned int last_valid_uid;
+        bool check_nologin;
+        bool check_homedir;
 
 	bool verbose, debug, debug_passwords;
 	const char *verbose_passwords;
diff -r bf80034a547d src/auth/userdb-passwd.c
--- a/src/auth/userdb-passwd.c	Thu Jan 31 18:27:22 2013 +0200
+++ b/src/auth/userdb-passwd.c	Thu Jan 31 22:11:31 2013 +0000
@@ -10,6 +10,8 @@
 #include "time-util.h"
 #include "userdb-template.h"
 
+#include <sys/stat.h>
+
 #define USER_CACHE_KEY "%u"
 #define PASSWD_SLOW_WARN_MSECS (10*1000)
 #define PASSWD_SLOW_MASTER_WARN_MSECS 50
@@ -76,6 +78,41 @@
 	}
 }
 
+static bool
+passwd_want_pw(struct passwd *pw, const struct auth_settings *set)
+{
+	/* skip entries not in valid UID range.
+	   they're users for daemons and such. */
+	if (pw->pw_uid < (uid_t)set->first_valid_uid)
+                return FALSE;
+	if (pw->pw_uid > (uid_t)set->last_valid_uid && set->last_valid_uid != 0)
+                return FALSE;
+
+        if (set->check_nologin) {
+                /* skip entries that don't have a valid shell.
+                   they're again probably not real users. */
+                if (strcmp(pw->pw_shell, "/bin/false") == 0 ||
+                    strcmp(pw->pw_shell, "/sbin/nologin") == 0 ||
+                    strcmp(pw->pw_shell, "/usr/sbin/nologin") == 0)
+                        return FALSE;
+        }
+
+        if (set->check_homedir) {
+                int err = errno;
+                struct stat st;
+                int ok;
+
+                /* skip users who don't own their homedirs */
+                ok = (stat(pw->pw_dir, &st) >= 0 &&
+                    S_ISDIR(st.st_mode) &&
+                    st.st_uid == pw->pw_uid);
+                errno = err;
+                if (!ok) return FALSE;
+        }
+
+	return TRUE;
+}
+
 static void passwd_lookup(struct auth_request *auth_request,
 			  userdb_callback_t *callback)
 {
@@ -106,6 +143,13 @@
 		return;
 	}
 
+        if (!passwd_want_pw(&pw, auth_request->set)) {
+                auth_request_log_info(auth_request, "passwd",
+                                      "user has bad uid or homedir");
+                callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
+                return;
+        }
+
 	auth_request_set_field(auth_request, "user", pw.pw_name, NULL);
 
 	auth_request_init_userdb_reply(auth_request);
@@ -137,25 +181,6 @@
 	return &ctx->ctx;
 }
 
-static bool
-passwd_iterate_want_pw(struct passwd *pw, const struct auth_settings *set)
-{
-	/* skip entries not in valid UID range.
-	   they're users for daemons and such. */
-	if (pw->pw_uid < (uid_t)set->first_valid_uid)
-		return FALSE;
-	if (pw->pw_uid > (uid_t)set->last_valid_uid && set->last_valid_uid != 0)
-		return FALSE;
-
-	/* skip entries that don't have a valid shell.
-	   they're again probably not real users. */
-	if (strcmp(pw->pw_shell, "/bin/false") == 0 ||
-	    strcmp(pw->pw_shell, "/sbin/nologin") == 0 ||
-	    strcmp(pw->pw_shell, "/usr/sbin/nologin") == 0)
-		return FALSE;
-	return TRUE;
-}
-
 static void passwd_iterate_next(struct userdb_iterate_context *_ctx)
 {
 	struct passwd_userdb_iterate_context *ctx =
@@ -173,7 +198,7 @@
 
 	errno = 0;
 	while ((pw = getpwent()) != NULL) {
-		if (passwd_iterate_want_pw(pw, set)) {
+		if (passwd_want_pw(pw, set)) {
 			_ctx->callback(pw->pw_name, _ctx->context);
 			return;
 		}
