[PATCH] Do PAM chauthtok via keyboard-interactive.

Darren Tucker dtucker at zip.com.au
Mon Dec 8 00:41:47 EST 2003


Hi All.
	Attached is another patch that attempts to do pam_chauthtok() via SSH2
keyboard-interactive authentication.  It now passes the results from the
authentication thread back to the monitor (based on a suggestion from
djm).

	Because of this, it doesn't call do_pam_account twice and consequently
now works on AIX 5.2, which the previous version didn't.  I haven't tested
it on any other platforms yet, but there were few other changes so it
should still work (famous last words :-)

	I would be interested to know if it works with unusual PAM configurations
or platforms other than those I can test on.

-- 
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-pam.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth-pam.c,v
retrieving revision 1.84
diff -u -p -r1.84 auth-pam.c
--- auth-pam.c	21 Nov 2003 12:56:47 -0000	1.84
+++ auth-pam.c	7 Dec 2003 13:23:38 -0000
@@ -53,6 +53,7 @@ RCSID("$Id: auth-pam.c,v 1.84 2003/11/21
 
 extern ServerOptions options;
 extern Buffer loginmsg;
+extern int compat20;
 
 #define __unused
 
@@ -118,6 +119,7 @@ static int sshpam_authenticated = 0;
 static int sshpam_new_authtok_reqd = 0;
 static int sshpam_session_open = 0;
 static int sshpam_cred_established = 0;
+static int sshpam_account_status = -1;
 static char **sshpam_env = NULL;
 
 struct pam_ctxt {
@@ -144,6 +146,21 @@ pam_getenvlist(pam_handle_t *pamh)
 }
 #endif
 
+void
+pam_password_change_required(int reqd)
+{
+	sshpam_new_authtok_reqd = reqd;
+	if (reqd) {
+		no_port_forwarding_flag |= 2;
+		no_agent_forwarding_flag |= 2;
+		no_x11_forwarding_flag |= 2;
+	} else {
+		no_port_forwarding_flag &= ~2;
+		no_agent_forwarding_flag &= ~2;
+		no_x11_forwarding_flag &= ~2;
+
+	}
+}
 /* Import regular and PAM environment from subprocess */
 static void
 import_environments(Buffer *b)
@@ -152,6 +169,13 @@ import_environments(Buffer *b)
 	u_int i, num_env;
 	int err;
 
+	/* Import variables set by do_pam_account */
+	sshpam_account_status = buffer_get_int(b);
+	sshpam_new_authtok_reqd = buffer_get_int(b);
+
+	if (sshpam_new_authtok_reqd == 1)
+		pam_password_change_required(1);
+
 	/* Import environment from subprocess */
 	num_env = buffer_get_int(b);
 	sshpam_env = xmalloc((num_env + 1) * sizeof(*sshpam_env));
@@ -290,9 +314,28 @@ sshpam_thread(void *ctxtp)
 	sshpam_err = pam_authenticate(sshpam_handle, 0);
 	if (sshpam_err != PAM_SUCCESS)
 		goto auth_fail;
+
+	if (compat20) {
+		if (do_pam_account()) {
+		       if (sshpam_new_authtok_reqd) {
+				sshpam_err = pam_chauthtok(sshpam_handle,
+				    PAM_CHANGE_EXPIRED_AUTHTOK);
+				if (sshpam_err != PAM_SUCCESS)
+					goto auth_fail;
+				pam_password_change_required(0);
+			}
+		} else {
+			goto auth_fail;
+		}
+	}
+
 	buffer_put_cstring(&buffer, "OK");
 
 #ifndef USE_POSIX_THREADS
+	/* Export variables set by do_pam_account */
+	buffer_put_int(&buffer, sshpam_account_status);
+	buffer_put_int(&buffer, sshpam_new_authtok_reqd);
+
 	/* Export any environment strings set in child */
 	for(i = 0; environ[i] != NULL; i++)
 		; /* Count */
@@ -611,22 +654,22 @@ finish_pam(void)
 u_int
 do_pam_account(void)
 {
+	if (sshpam_account_status != -1)
+		return (sshpam_account_status);
+
 	sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
 	debug3("%s: pam_acct_mgmt = %d", __func__, sshpam_err);
-
-	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD)
-		return (0);
-
-	if (sshpam_err == PAM_NEW_AUTHTOK_REQD) {
-		sshpam_new_authtok_reqd = 1;
-
-		/* Prevent forwardings until password changed */
-		no_port_forwarding_flag |= 2;
-		no_agent_forwarding_flag |= 2;
-		no_x11_forwarding_flag |= 2;
+	
+	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
+		sshpam_account_status = 0;
+		return (sshpam_account_status);
 	}
 
-	return (1);
+	if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
+		pam_password_change_required(1);
+
+	sshpam_account_status = 1;
+	return (sshpam_account_status);
 }
 
 void


More information about the openssh-unix-dev mailing list