- markus@cvs.openbsd.org 2003/09/23 20:17:11
     [Makefile.in auth1.c auth2.c auth.c auth.h auth-krb5.c canohost.c
     cleanup.c clientloop.c fatal.c gss-serv.c log.c log.h monitor.c monitor.h
     monitor_wrap.c monitor_wrap.h packet.c serverloop.c session.c session.h
     ssh-agent.c sshd.c]
     replace fatal_cleanup() and linked list of fatal callbacks with static
     cleanup_exit() function.  re-refine cleanup_exit() where appropriate,
     allocate sshd's authctxt eary to allow simpler cleanup in sshd.
     tested by many, ok deraadt@
diff --git a/sshd.c b/sshd.c
index 4b3ff0d..5c27112 100644
--- a/sshd.c
+++ b/sshd.c
@@ -42,7 +42,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.277 2003/09/19 11:33:09 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.278 2003/09/23 20:17:11 markus Exp $");
 
 #include <openssl/dh.h>
 #include <openssl/bn.h>
@@ -204,6 +204,9 @@
 /* message to be displayed after login */
 Buffer loginmsg;
 
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
 /* Prototypes for various functions defined later in this file. */
 void destroy_sensitive_data(void);
 void demote_sensitive_data(void);
@@ -375,7 +378,7 @@
 	    strlen(server_version_string))
 	    != strlen(server_version_string)) {
 		logit("Could not write ident string to %s", get_remote_ipaddr());
-		fatal_cleanup();
+		cleanup_exit(255);
 	}
 
 	/* Read other sides version identification. */
@@ -384,7 +387,7 @@
 		if (atomicio(read, sock_in, &buf[i], 1) != 1) {
 			logit("Did not receive identification string from %s",
 			    get_remote_ipaddr());
-			fatal_cleanup();
+			cleanup_exit(255);
 		}
 		if (buf[i] == '\r') {
 			buf[i] = 0;
@@ -414,7 +417,7 @@
 		close(sock_out);
 		logit("Bad protocol version identification '%.100s' from %s",
 		    client_version_string, get_remote_ipaddr());
-		fatal_cleanup();
+		cleanup_exit(255);
 	}
 	debug("Client protocol version %d.%d; client software version %.100s",
 	    remote_major, remote_minor, remote_version);
@@ -424,13 +427,13 @@
 	if (datafellows & SSH_BUG_PROBE) {
 		logit("probed from %s with %s.  Don't panic.",
 		    get_remote_ipaddr(), client_version_string);
-		fatal_cleanup();
+		cleanup_exit(255);
 	}
 
 	if (datafellows & SSH_BUG_SCANNER) {
 		logit("scanned from %s with %s.  Don't panic.",
 		    get_remote_ipaddr(), client_version_string);
-		fatal_cleanup();
+		cleanup_exit(255);
 	}
 
 	mismatch = 0;
@@ -476,7 +479,7 @@
 		logit("Protocol major versions differ for %s: %.200s vs. %.200s",
 		    get_remote_ipaddr(),
 		    server_version_string, client_version_string);
-		fatal_cleanup();
+		cleanup_exit(255);
 	}
 }
 
@@ -571,10 +574,9 @@
 #endif
 }
 
-static Authctxt *
-privsep_preauth(void)
+static int
+privsep_preauth(Authctxt *authctxt)
 {
-	Authctxt *authctxt = NULL;
 	int status;
 	pid_t pid;
 
@@ -590,7 +592,7 @@
 		debug2("Network child is on pid %ld", (long)pid);
 
 		close(pmonitor->m_recvfd);
-		authctxt = monitor_child_preauth(pmonitor);
+		monitor_child_preauth(authctxt, pmonitor);
 		close(pmonitor->m_sendfd);
 
 		/* Sync memory */
@@ -600,7 +602,7 @@
 		while (waitpid(pid, &status, 0) < 0)
 			if (errno != EINTR)
 				break;
-		return (authctxt);
+		return (1);
 	} else {
 		/* child */
 
@@ -611,17 +613,12 @@
 			privsep_preauth_child();
 		setproctitle("%s", "[net]");
 	}
-	return (NULL);
+	return (0);
 }
 
 static void
 privsep_postauth(Authctxt *authctxt)
 {
-	extern Authctxt *x_authctxt;
-
-	/* XXX - Remote port forwarding */
-	x_authctxt = authctxt;
-
 #ifdef DISABLE_FD_PASSING
 	if (1) {
 #else
@@ -804,8 +801,8 @@
 	int listen_sock, maxfd;
 	int startup_p[2];
 	int startups = 0;
-	Authctxt *authctxt;
 	Key *key;
+	Authctxt *authctxt;
 	int ret, key_used = 0;
 
 #ifdef HAVE_SECUREWARE
@@ -1460,18 +1457,25 @@
         /* prepare buffers to collect authentication messages */
 	buffer_init(&loginmsg);
 
+	/* allocate authentication context */
+	authctxt = xmalloc(sizeof(*authctxt));
+	memset(authctxt, 0, sizeof(*authctxt));
+
+	/* XXX global for cleanup, access from other modules */
+	the_authctxt = authctxt;
+
 	if (use_privsep)
-		if ((authctxt = privsep_preauth()) != NULL)
+		if (privsep_preauth(authctxt) == 1)
 			goto authenticated;
 
 	/* perform the key exchange */
 	/* authenticate user and start session */
 	if (compat20) {
 		do_ssh2_kex();
-		authctxt = do_authentication2();
+		do_authentication2(authctxt);
 	} else {
 		do_ssh1_kex();
-		authctxt = do_authentication();
+		do_authentication(authctxt);
 	}
 	/*
 	 * If we use privilege separation, the unprivileged child transfers
@@ -1494,7 +1498,7 @@
 			destroy_sensitive_data();
 	}
 
-	/* Perform session preparation. */
+	/* Start session. */
 	do_authenticated(authctxt);
 
 	/* The connection has been terminated. */
@@ -1787,3 +1791,12 @@
 #endif
 	debug("KEX done");
 }
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+	if (the_authctxt)
+		do_cleanup(the_authctxt);
+	_exit(i);
+}