# new option UsePAMCheckLocks to enforce checking for locked accounts while
# UsePAM is used
# bnc#708678, FATE#312033
diff -Ndpru10 openssh-5.1p1/auth.c openssh-5.1p1/auth.c
--- openssh-5.1p1/auth.c	2011-08-18 17:02:18.872063586 +0200
+++ openssh-5.1p1/auth.c	2011-08-18 19:13:34.151833392 +0200
@@ -99,41 +99,41 @@ allowed_user(struct passwd * pw)
 	u_int i;
 #ifdef USE_SHADOW
 	struct spwd *spw = NULL;
 #endif
 
 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
 	if (!pw || !pw->pw_name)
 		return 0;
 
 #ifdef USE_SHADOW
-	if (!options.use_pam)
+	if (!options.use_pam || options.use_pam_check_locks)
 		spw = getspnam(pw->pw_name);
 #ifdef HAS_SHADOW_EXPIRE
 	if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
 		return 0;
 #endif /* HAS_SHADOW_EXPIRE */
 #endif /* USE_SHADOW */
 
 	/* grab passwd field for locked account check */
 	passwd = pw->pw_passwd;
 #ifdef USE_SHADOW
 	if (spw != NULL)
 #ifdef USE_LIBIAF
 		passwd = get_iaf_password(pw);
 #else
 		passwd = spw->sp_pwdp;
 #endif /* USE_LIBIAF */
 #endif
 
 	/* check for locked account */
-	if (!options.use_pam && passwd && *passwd) {
+	if ((!options.use_pam || options.use_pam_check_locks) && passwd && *passwd) {
 		int locked = 0;
 
 #ifdef LOCKED_PASSWD_STRING
 		if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
 			 locked = 1;
 #endif
 #ifdef LOCKED_PASSWD_PREFIX
 		if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
 		    strlen(LOCKED_PASSWD_PREFIX)) == 0)
 			 locked = 1;
diff -Ndpru10 openssh-5.1p1/servconf.c openssh-5.1p1/servconf.c
--- openssh-5.1p1/servconf.c	2011-08-18 17:02:18.927063702 +0200
+++ openssh-5.1p1/servconf.c	2011-08-18 19:16:06.569088881 +0200
@@ -51,20 +51,21 @@ extern Buffer cfg;
 
 /* Initializes the server options to their default values. */
 
 void
 initialize_server_options(ServerOptions *options)
 {
 	memset(options, 0, sizeof(*options));
 
 	/* Portable-specific options */
 	options->use_pam = -1;
+	options->use_pam_check_locks = -1;
 
 	/* Standard Options */
 	options->num_ports = 0;
 	options->ports_from_cmdline = 0;
 	options->listen_addrs = NULL;
 	options->address_family = -1;
 	options->num_host_key_files = 0;
 	options->pid_file = NULL;
 	options->server_key_bits = -1;
 	options->login_grace_time = -1;
@@ -131,20 +132,22 @@ initialize_server_options(ServerOptions
 	options->authorized_keys_command = NULL;
 	options->authorized_keys_command_runas = NULL;
 }
 
 void
 fill_default_server_options(ServerOptions *options)
 {
 	/* Portable-specific options */
 	if (options->use_pam == -1)
 		options->use_pam = 0;
+	if (options->use_pam_check_locks == -1)
+		options->use_pam_check_locks = 0;
 
 	/* Standard Options */
 	if (options->protocol == SSH_PROTO_UNKNOWN)
 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
 	if (options->num_host_key_files == 0) {
 		/* fill default hostkeys for protocols */
 		if (options->protocol & SSH_PROTO_1)
 			options->host_key_files[options->num_host_key_files++] =
 			    _PATH_HOST_KEY_FILE;
 		if (options->protocol & SSH_PROTO_2) {
@@ -276,21 +279,21 @@ fill_default_server_options(ServerOption
 		options->compression = 0;
 	}
 #endif
 
 }
 
 /* Keyword tokens. */
 typedef enum {
 	sBadOption,		/* == unknown option */
 	/* Portable-specific options */
-	sUsePAM,
+	sUsePAM, sUsePAMChecklocks,
 	/* Standard Options */
 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
 	sPermitRootLogin, sLogFacility, sLogLevel,
 	sRhostsRSAAuthentication, sRSAAuthentication,
 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 	sKerberosGetAFSToken,
 	sKerberosTgtPassing, sChallengeResponseAuthentication,
 	sPasswordAuthentication, sKbdInteractiveAuthentication,
 	sListenAddress, sAddressFamily,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
@@ -317,22 +320,24 @@ typedef enum {
 
 /* Textual representation of the tokens. */
 static struct {
 	const char *name;
 	ServerOpCodes opcode;
 	u_int flags;
 } keywords[] = {
 	/* Portable-specific options */
 #ifdef USE_PAM
 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
+	{ "usepamchecklocks", sUsePAMChecklocks, SSHCFG_GLOBAL },
 #else
 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
+	{ "usepamchecklocks", sUnsupported, SSHCFG_GLOBAL },
 #endif
 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
 	/* Standard Options */
 	{ "port", sPort, SSHCFG_GLOBAL },
 	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
 	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },		/* alias */
 	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
 	{ "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
 	{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
 	{ "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
@@ -679,20 +684,23 @@ process_server_config_line(ServerOptions
 				arg = strdelim(&cp);
 			return 0;
 		}
 	}
 
 	switch (opcode) {
 	/* Portable-specific options */
 	case sUsePAM:
 		intptr = &options->use_pam;
 		goto parse_flag;
+	case sUsePAMChecklocks:
+		intptr = &options->use_pam_check_locks;
+		goto parse_flag;
 
 	/* Standard Options */
 	case sBadOption:
 		return -1;
 	case sPort:
 		/* ignore ports from configfile if cmdline specifies ports */
 		if (options->ports_from_cmdline)
 			return 0;
 		if (options->listen_addrs != NULL)
 			fatal("%s line %d: ports must be specified before "
diff -Ndpru10 openssh-5.1p1/servconf.h openssh-5.1p1/servconf.h
--- openssh-5.1p1/servconf.h	2011-08-18 17:02:18.928063704 +0200
+++ openssh-5.1p1/servconf.h	2011-08-18 19:23:50.919872468 +0200
@@ -137,20 +137,21 @@ typedef struct {
 					 * for this many intervals above,
 					 * disconnect the session
 					 */
 
 	char   *authorized_keys_file;	/* File containing public keys */
 	char   *authorized_keys_file2;
 
 	char   *adm_forced_command;
 
 	int	use_pam;		/* Enable auth via PAM */
+	int	use_pam_check_locks;	/* internally check for locked accounts even when using PAM */
 
 	int	permit_tun;
 
 	int	num_permitted_opens;
 
 	char   *chroot_directory;
 	char   *authorized_keys_command;
 	char   *authorized_keys_command_runas;
 }       ServerOptions;
 
diff -Ndpru10 openssh-5.1p1/sshd_config.0 openssh-5.1p1/sshd_config.0
--- openssh-5.1p1/sshd_config.0	2011-08-18 17:02:18.928063704 +0200
+++ openssh-5.1p1/sshd_config.0	2011-08-23 23:29:22.823974687 +0200
@@ -547,20 +547,28 @@ DESCRIPTION
              dition to PAM account and session module processing for all au-
              thentication types.
 
              Because PAM challenge-response authentication usually serves an
              equivalent role to password authentication, you should disable
              either PasswordAuthentication or ChallengeResponseAuthentication.
 
              If UsePAM is enabled, you will not be able to run sshd(8) as a
              non-root user.  The default is ``no''.
 
+     UsePAMCheckLocks
+             When set to ``yes'', the checks whether the account has been
+             locked with `passwd -l' are performed even when PAM authentication
+             is enabled via UsePAM.  This is to ensure that it is not possible
+             to log in with e.g. a public key (in such a case PAM is used only
+             to set up the session and some PAM modules will not check whether
+             the account is locked in this scenario). The default is ``no''.
+
      UsePrivilegeSeparation
              Specifies whether sshd(8) separates privileges by creating an un-
              privileged child process to deal with incoming network traffic.
              After successful authentication, another process will be created
              that has the privilege of the authenticated user.  The goal of
              privilege separation is to prevent privilege escalation by con-
              taining any corruption within the unprivileged processes.  The
              default is ``yes''.
 
      X11DisplayOffset
diff -Ndpru10 openssh-5.1p1/sshd_config.5 openssh-5.1p1/sshd_config.5
--- openssh-5.1p1/sshd_config.5	2011-08-18 17:02:18.928063704 +0200
+++ openssh-5.1p1/sshd_config.5	2011-08-23 23:29:34.010982645 +0200
@@ -928,20 +928,32 @@ role to password authentication, you sho
 or
 .Cm ChallengeResponseAuthentication.
 .Pp
 If
 .Cm UsePAM
 is enabled, you will not be able to run
 .Xr sshd 8
 as a non-root user.
 The default is
 .Dq no .
+.It Cm UsePAMCheckLocks
+When set to 
+.Dq yes
+, the checks whether the account has been locked with
+.Pa passwd -l
+are performed even when PAM authentication is enabled via 
+.Cm UsePAM .
+This is to ensure that it is not possible to log in with e.g. a
+public key (in such a case PAM is used only to set up the session and some PAM
+modules will not check whether the account is locked in this scenario). The
+default is 
+.Dq no .
 .It Cm UsePrivilegeSeparation
 Specifies whether
 .Xr sshd 8
 separates privileges by creating an unprivileged child process
 to deal with incoming network traffic.
 After successful authentication, another process will be created that has
 the privilege of the authenticated user.
 The goal of privilege separation is to prevent privilege
 escalation by containing any corruption within the unprivileged processes.
 The default is
