OpenSSH and PAM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



--VbJkn9YxBvnuCH5J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Jul 10, 2002 at 11:38:58AM -0800, Ethan Benson wrote:
> On Wed, Jul 10, 2002 at 11:11:18AM -0400, Matt Miller wrote:
> >     
> > I am running OpenSSH 3.1p1. I did read that the new version of ssh will
> > break PAM if "UsePrivilegeSeparation" is set to "yes" in the
> 
> correct it will, and your version has a exploitable root hole in the
> PAM keyboard interactive bits.
> 
> unfortunatly you get to choose exploitable root hole or no properly
> working passwd expiration in ssh at this point. (passwds will expire
> and ssh will honor that by happily denying access, giving no
> opertunity to pick a new password).

Not really.  PAM keyboard interactive authentication is not relevant
to PAM password changing, and should be disabled (unless there's
another reason to use it).

Then, there's the patch to fix just the vulnerability, without
changing OpenSSH version, in the official OpenSSH advisory (at
http://www.openssh.com/txt/preauth.adv).

Finally, I did a patch to re-enable password changes, without the
nasty side effect which was the reason to disable that code, for the
non-privsep case in the OpenSSH 3.4p1 package in Owl (our distribution,
http://www.openwall.com/Owl/).  The patch is freely available as a
part of Owl (in the native tree).  To this message I've attached just
the two patches relevant to making password changing work again in
3.4p1.  Our OpenSSH package contains many other patches (11 total).

-- 
/sd

--VbJkn9YxBvnuCH5J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="openssh-3.4p1-owl-password-changing.diff"

diff -ur openssh-3.4p1.orig/auth-pam.c openssh-3.4p1/auth-pam.c
--- openssh-3.4p1.orig/auth-pam.c	Wed May  8 06:27:56 2002
+++ openssh-3.4p1/auth-pam.c	Fri Jul  5 23:39:24 2002
@@ -29,6 +29,7 @@
 #include "xmalloc.h"
 #include "log.h"
 #include "auth.h"
+#include "auth-options.h"
 #include "auth-pam.h"
 #include "servconf.h"
 #include "canohost.h"
@@ -36,10 +37,14 @@
 
 extern char *__progname;
 
+extern int use_privsep;
+
 RCSID("$Id: auth-pam.c,v 1.46 2002/05/08 02:27:56 djm Exp $");
 
 #define NEW_AUTHTOK_MSG \
-	"Warning: Your password has expired, please change it now"
+	"Warning: Your password has expired, please change it now."
+#define NEW_AUTHTOK_MSG_PRIVSEP \
+	"Your password has expired, the session cannot proceed."
 
 static int do_pam_conversation(int num_msg, const struct pam_message **msg,
 	struct pam_response **resp, void *appdata_ptr);
@@ -55,7 +60,7 @@
 
 /* states for do_pam_conversation() */
 enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
-/* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */
+/* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
 static int password_change_required = 0;
 /* remember whether the last pam_authenticate() succeeded or not */
 static int was_authenticated = 0;
@@ -254,13 +259,16 @@
 		case PAM_SUCCESS:
 			/* This is what we want */
 			break;
-#if 0
 		case PAM_NEW_AUTHTOK_REQD:
-			message_cat(&__pam_msg, NEW_AUTHTOK_MSG);
+			message_cat(&__pam_msg, use_privsep ?
+			    NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG);
 			/* flag that password change is necessary */
 			password_change_required = 1;
+			/* disallow other functionality for now */
+			no_port_forwarding_flag |= 2;
+			no_agent_forwarding_flag |= 2;
+			no_x11_forwarding_flag |= 2;
 			break;
-#endif
 		default:
 			log("PAM rejected by account configuration[%d]: "
 			    "%.200s", pam_retval, PAM_STRERROR(__pamh, 
@@ -328,7 +336,7 @@
  * Have user change authentication token if pam_acct_mgmt() indicated
  * it was expired.  This needs to be called after an interactive
  * session is established and the user's pty is connected to
- * stdin/stout/stderr.
+ * stdin/stdout/stderr.
  */
 void do_pam_chauthtok(void)
 {
@@ -337,11 +345,23 @@
 	do_pam_set_conv(&conv);
 
 	if (password_change_required) {
+		if (use_privsep)
+			fatal("Password changing is currently unsupported"
+			    " with privilege separation");
 		pamstate = OTHER;
 		pam_retval = pam_chauthtok(__pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
 		if (pam_retval != PAM_SUCCESS)
 			fatal("PAM pam_chauthtok failed[%d]: %.200s",
 			    pam_retval, PAM_STRERROR(__pamh, pam_retval));
+#if 0
+		/* XXX: This would need to be done in the parent process,
+		 * but there's currently no way to pass such request. */
+		no_port_forwarding_flag &= ~2;
+		no_agent_forwarding_flag &= ~2;
+		no_x11_forwarding_flag &= ~2;
+		if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
+			channel_permit_all_opens();
+#endif
 	}
 }
 

--VbJkn9YxBvnuCH5J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="openssh-3.4p1-owl-fatal_cleanups.diff"

diff -ur openssh-3.4p1.orig/auth-pam.c openssh-3.4p1/auth-pam.c
--- openssh-3.4p1.orig/auth-pam.c	Wed May  8 06:27:56 2002
+++ openssh-3.4p1/auth-pam.c	Sat Jul  6 02:42:50 2002
@@ -177,7 +177,7 @@
 {
 	int pam_retval = PAM_SUCCESS;
 
-	if (__pamh && session_opened) {
+	if (__pamh && getpid() == session_opened) {
 		pam_retval = pam_close_session(__pamh, 0);
 		if (pam_retval != PAM_SUCCESS)
 			log("Cannot close PAM session[%d]: %.200s",
@@ -291,7 +291,7 @@
 		fatal("PAM session setup failed[%d]: %.200s",
 		    pam_retval, PAM_STRERROR(__pamh, pam_retval));
 
-	session_opened = 1;
+	session_opened = getpid();
 }
 
 /* Set PAM credentials */
diff -ur openssh-3.4p1.orig/packet.c openssh-3.4p1/packet.c
--- openssh-3.4p1.orig/packet.c	Mon Jun 24 01:49:25 2002
+++ openssh-3.4p1/packet.c	Sat Jul  6 02:39:59 2002
@@ -148,8 +148,6 @@
 		buffer_init(&outgoing_packet);
 		buffer_init(&incoming_packet);
 	}
-	/* Kludge: arrange the close function to be called from fatal(). */
-	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
 }
 
 /* Returns 1 if remote host is connected via socket, 0 if not. */
diff -ur openssh-3.4p1.orig/session.c openssh-3.4p1/session.c
--- openssh-3.4p1.orig/session.c	Wed Jun 26 17:51:06 2002
+++ openssh-3.4p1/session.c	Sat Jul  6 05:24:37 2002
@@ -470,6 +470,8 @@
 
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
+		fatal_remove_cleanup((void (*) (void *)) packet_close, NULL);
+
 		/* Child.  Reinitialize the log since the pid has changed. */
 		log_init(__progname, options.log_level, options.log_facility, log_stderr);
 
@@ -585,6 +587,8 @@
 
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
+		fatal_remove_cleanup(session_pty_cleanup, (void *)s);
+		fatal_remove_cleanup((void (*) (void *)) packet_close, NULL);
 
 		/* Child.  Reinitialize the log because the pid has changed. */
 		log_init(__progname, options.log_level, options.log_facility, log_stderr);
@@ -1593,7 +1597,9 @@
 	 * Add a cleanup function to clear the utmp entry and record logout
 	 * time in case we call fatal() (e.g., the connection gets closed).
 	 */
+	fatal_remove_cleanup((void (*) (void *)) packet_close, NULL);
 	fatal_add_cleanup(session_pty_cleanup, (void *)s);
+	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
 	if (!use_privsep)
 		pty_setowner(s->pw, s->tty);
 
diff -ur openssh-3.4p1.orig/sshd.c openssh-3.4p1/sshd.c
--- openssh-3.4p1.orig/sshd.c	Wed Jun 26 03:24:19 2002
+++ openssh-3.4p1/sshd.c	Sun Jul  7 07:04:55 2002
@@ -303,9 +303,6 @@
 {
 	/* XXX no idea how fix this signal handler */
 
-	/* Close the connection. */
-	packet_close();
-
 	/* Log error and exit. */
 	fatal("Timeout before authentication for %s.", get_remote_ipaddr());
 }
@@ -612,6 +609,8 @@
 		if (getuid() == 0 || geteuid() == 0)
 			privsep_preauth_child();
 		setproctitle("%s", "[net]");
+
+		fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
 	}
 	return (NULL);
 }
@@ -630,6 +629,7 @@
 	if (authctxt->pw->pw_uid == 0 || options.use_login) {
 #endif
 		/* File descriptor passing is broken or root login */
+		fatal_add_cleanup((void (*) (void *))packet_close, NULL);
 		monitor_apply_keystate(pmonitor);
 		use_privsep = 0;
 		return;
@@ -665,6 +665,8 @@
 	/* Drop privileges */
 	do_setusercontext(authctxt->pw);
 
+	fatal_add_cleanup((void (*) (void *))packet_close, NULL);
+
 	/* It is safe now to apply the key state */
 	monitor_apply_keystate(pmonitor);
 }
@@ -1483,9 +1485,11 @@
 
 	packet_set_nonblocking();
 
-	if (use_privsep)
+	if (use_privsep) {
 		if ((authctxt = privsep_preauth()) != NULL)
 			goto authenticated;
+	} else
+		fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
 
 	/* perform the key exchange */
 	/* authenticate user and start session */

--VbJkn9YxBvnuCH5J--





[Index of Archives]     [Fedora Users]     [Kernel]     [Red Hat Install]     [Linux for the blind]     [Gimp]

  Powered by Linux