--- old/usr/src/cmd/ssh/sshd/altprivsep.c	2016-08-16 20:42:17.101797039 -0400
+++ /dev/null	2016-08-16 20:42:17.000000000 -0400
@@ -1,1187 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-
-#include <pwd.h>
-
-#include "includes.h"
-#include "atomicio.h"
-#include "auth.h"
-#include "bufaux.h"
-#include "buffer.h"
-#include "cipher.h"
-#include "compat.h"
-#include "dispatch.h"
-#include "getput.h"
-#include "kex.h"
-#include "log.h"
-#include "mac.h"
-#include "packet.h"
-#include "uidswap.h"
-#include "ssh2.h"
-#include "sshlogin.h"
-#include "xmalloc.h"
-#include "altprivsep.h"
-#include "canohost.h"
-#include "engine.h"
-#include "servconf.h"
-
-#ifdef HAVE_BSM
-#include "bsmaudit.h"
-adt_session_data_t *ah = NULL;
-#endif /* HAVE_BSM */
-
-#ifdef GSSAPI
-#include "ssh-gss.h"
-extern Gssctxt *xxx_gssctxt;
-#endif /* GSSAPI */
-
-extern Kex *xxx_kex;
-extern u_char *session_id2;
-extern int session_id2_len;
-
-static Buffer to_monitor;
-static Buffer from_monitor;
-
-/*
- * Sun's Alternative Privilege Separation basics:
- *
- * Abstract
- * --------
- *
- * sshd(1M) fork()s and drops privs in the child while retaining privs
- * in the parent (a.k.a., the monitor).  The unprivileged sshd and the
- * monitor talk over a pipe using a simple protocol.
- *
- * The monitor protocol is all about having the monitor carry out the
- * only operations that require privileges OR access to privileged
- * resources.  These are: utmpx/wtmpx record keeping, auditing, and
- * SSHv2 re-keying.
- *
- * Re-Keying
- * ---------
- *
- * Re-keying is the only protocol version specific aspect of sshd in
- * which the monitor gets involved.
- *
- * The monitor processes all SSHv2 re-key protocol packets, but the
- * unprivileged sshd process does the transport layer crypto for those
- * packets.
- *
- * The monitor and its unprivileged sshd child process treat
- * SSH_MSG_NEWKEYS SSH2 messages specially: a) the monitor does not call
- * set_newkeys(), but b) the child asks the monitor for the set of
- * negotiated algorithms, key, IV and what not for the relevant
- * transport direction and then calls set_newkeys().
- *
- * Monitor Protocol
- * ----------------
- *
- * Monitor IPC message formats are similar to SSHv2 messages, minus
- * compression, encryption, padding and MACs:
- *
- *  - 4 octet message length
- *  - message data
- *     - 1 octet message type
- *     - message data
- *
- * In broad strokes:
- *
- *  - IPC: pipe, exit(2)/wait4(2)
- *
- *  - threads: the monitor and child are single-threaded
- *
- *  - monitor main loop: a variant of server_loop2(), for re-keying only
- *  - unpriv child main loop: server_loop2(), as usual
- *
- *  - protocol:
- *     - key exchange packets are always forwarded as is to the monitor
- *     - newkeys, record_login(), record_logout() are special packets
- *     using the packet type range reserved for local extensions
- *
- *  - the child drops privs and runs like a normal sshd, except that it
- *  sets dispatch handlers for key exchange packets that forward the
- *  packets to the monitor
- *
- * Event loops:
- *
- *  - all monitor protocols are synchronous: because the SSHv2 rekey
- *  protocols are synchronous and because the other monitor operations
- *  are synchronous (or have no replies),
- *
- *  - server_loop2() is modified to check the monitor pipe for rekey
- *  packets to forward to the client
- *
- *  - and dispatch handlers are set, upon receipt of KEXINIT (and reset
- *  when NEWKEYS is sent out) to forward incoming rekey packets to the
- *  monitor.
- *
- *  - the monitor runs an event loop not unlike server_loop2() and runs
- *  key exchanges almost exactly as a pre-altprivsep sshd would
- *
- *  - unpriv sshd exit -> monitor cleanup (including audit logout) and exit
- *
- *  - fatal() in monitor -> forcibly shutdown() socket and kill/wait for
- *  child (so that the audit event for the logout better reflects
- *  reality -- i.e., logged out means logged out, but for bg jobs)
- *
- * Message formats:
- *
- *  - key exchange packets/replies forwarded "as is"
- *
- *  - all other monitor requests are sent as SSH2_PRIV_MSG_ALTPRIVSEP and have a
- *  sub-type identifier (one octet)
- *  - private request sub-types include:
- *     - get new shared secret from last re-key
- *     - record login  (utmpx/wtmpx), request data contains three arguments:
- *     pid, ttyname, program name
- *     - record logout (utmpx/wtmpx), request data contains one argument: pid
- *
- * Reply sub-types include:
- *
- *  - NOP (for record_login/logout)
- *  - new shared secret from last re-key
- */
-
-static int aps_started = 0;
-static int is_monitor = 0;
-
-static pid_t monitor_pid, child_pid;
-static int pipe_fds[2];
-static int pipe_fd = -1;
-static Buffer input_pipe, output_pipe; /* for pipe I/O */
-
-static Authctxt *xxx_authctxt;
-
-/* Monitor functions */
-extern void aps_monitor_loop(Authctxt *authctxt, pid_t child_pid);
-static void aps_record_login(void);
-static void aps_record_logout(void);
-static void aps_start_rekex(void);
-Authctxt *aps_read_auth_context(void);
-
-/* main functions for handling the monitor */
-static pid_t	altprivsep_start_monitor(Authctxt **authctxt);
-static void	altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid);
-static int	altprivsep_started(void);
-static int	altprivsep_is_monitor(void);
-
-/* calls _to_ monitor from unprivileged process */
-static void	altprivsep_get_newkeys(enum kex_modes mode);
-
-/* monitor-side fatal_cleanup callbacks */
-static void	altprivsep_shutdown_sock(void *arg);
-
-/* Altprivsep packet utilities for communication with the monitor */
-static void	altprivsep_packet_start(u_char);
-static int	altprivsep_packet_send(void);
-static int	altprivsep_fwd_packet(u_char type);
-
-static int	altprivsep_packet_read(void);
-static void	altprivsep_packet_read_expect(int type);
-
-static void	altprivsep_packet_put_char(int ch);
-static void	altprivsep_packet_put_int(u_int value);
-static void	altprivsep_packet_put_cstring(const char *str);
-static void	altprivsep_packet_put_raw(const void *buf, u_int len);
-
-static u_int	 altprivsep_packet_get_char(void);
-static void	*altprivsep_packet_get_raw(u_int *length_ptr);
-static void	*altprivsep_packet_get_string(u_int *length_ptr);
-
-Kex		*prepare_for_ssh2_kex(void);
-
-/*
- * Start monitor from privileged sshd process.
- *
- * Return values are like fork(2); the parent is the monitor.  The caller should
- * fatal() on error.
- *
- * Note that the monitor waits until the still privileged child finishes the
- * authentication. The child drops its privileges after the authentication.
- */
-static pid_t
-altprivsep_start_monitor(Authctxt **authctxt)
-{
-	pid_t pid;
-	int junk;
-
-	if (aps_started)
-		fatal("Monitor startup failed: missing state");
-
-	buffer_init(&output_pipe);
-	buffer_init(&input_pipe);
-
-	if (pipe(pipe_fds) != 0) {
-		error("Monitor startup failure: could not create pipes: %s",
-			strerror(errno));
-		return (-1);
-	}
-
-	(void) fcntl(pipe_fds[0], F_SETFD, FD_CLOEXEC);
-	(void) fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC);
-
-	monitor_pid = getpid();
-
-	if ((pid = fork()) > 0) {
-		/*
-		 * From now on, all debug messages from monitor will have prefix
-		 * "monitor "
-		 */
-		set_log_txt_prefix("monitor ");
-		(void) prepare_for_ssh2_kex();
-		packet_set_server();
-		/* parent */
-		child_pid = pid;
-
-		debug2("Monitor pid %ld, unprivileged child pid %ld",
-			monitor_pid, child_pid);
-
-		(void) close(pipe_fds[1]);
-		pipe_fd = pipe_fds[0];
-
-		/*
-		 * Signal readiness of the monitor and then read the
-		 * authentication context from the child.
-		 */
-		(void) write(pipe_fd, &pid, sizeof (pid));
-		packet_set_monitor(pipe_fd);
-		xxx_authctxt = *authctxt = aps_read_auth_context();
-
-		if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0)
-			error("fcntl O_NONBLOCK: %.100s", strerror(errno));
-
-		aps_started = 1;
-		is_monitor = 1;
-
-		debug2("Monitor started");
-
-		return (pid);
-	}
-
-	if (pid < 0) {
-		debug2("Monitor startup failure: could not fork unprivileged"
-			" process:  %s", strerror(errno));
-		return (pid);
-	}
-
-	/* this is the child that will later drop privileges */
-
-	/* note that Solaris has bi-directional pipes so one pipe is enough */
-	(void) close(pipe_fds[0]);
-	pipe_fd = pipe_fds[1];
-
-	/* wait for monitor to be ready */
-	debug2("Waiting for monitor");
-	(void) read(pipe_fd, &junk, sizeof (junk));
-	debug2("Monitor signalled readiness");
-
-	buffer_init(&to_monitor);
-	buffer_init(&from_monitor);
-
-	/* AltPrivSep interfaces are set up */
-	aps_started = 1;
-	return (pid);
-}
-
-int
-altprivsep_get_pipe_fd(void)
-{
-	return (pipe_fd);
-}
-
-/*
- * This function is used in the unprivileged child for all packets in the range
- * between SSH2_MSG_KEXINIT and SSH2_MSG_TRANSPORT_MAX.
- */
-void
-altprivsep_rekey(int type, u_int32_t seq, void *ctxt)
-{
-	Kex *kex = (Kex *)ctxt;
-
-	if (kex == NULL)
-		fatal("Missing key exchange context in unprivileged process");
-
-	if (type != SSH2_MSG_NEWKEYS) {
-		debug2("Forwarding re-key packet (%d) to monitor", type);
-		if (!altprivsep_fwd_packet(type))
-			fatal("altprivsep_rekey: Monitor not responding");
-	}
-
-	/* tell server_loop2() that we're re-keying */
-	kex->done = 0;
-
-	/* NEWKEYS is special: get the new keys for client->server direction */
-	if (type == SSH2_MSG_NEWKEYS) {
-		debug2("received SSH2_MSG_NEWKEYS packet - "
-		    "getting new inbound keys from the monitor");
-		altprivsep_get_newkeys(MODE_IN);
-		kex->done = 1;
-	}
-}
-
-void
-altprivsep_process_input(fd_set *rset)
-{
-	void	*data;
-	int	 type;
-	u_int	 dlen;
-
-	if (pipe_fd == -1)
-		return;
-
-	if (!FD_ISSET(pipe_fd, rset))
-		return;
-
-	debug2("reading from pipe to monitor (%d)", pipe_fd);
-	if ((type = altprivsep_packet_read()) == -1)
-		fatal("altprivsep_process_input: Monitor not responding");
-
-	if (!compat20)
-		return; /* shouldn't happen! but be safe */
-
-	if (type == 0)
-		return;	/* EOF -- nothing to do here */
-
-	if (type >= SSH2_MSG_MAX)
-		fatal("Received garbage from monitor");
-
-	debug2("Read packet type %d from pipe to monitor", (u_int)type);
-
-	if (type == SSH2_PRIV_MSG_ALTPRIVSEP)
-		return; /* shouldn't happen! */
-
-	/* NEWKEYS is special: get the new keys for server->client direction */
-	if (type == SSH2_MSG_NEWKEYS) {
-		debug2("forwarding SSH2_MSG_NEWKEYS packet we got from monitor to "
-		    "the client");
-		packet_start(SSH2_MSG_NEWKEYS);
-		packet_send();
-		debug2("getting new outbound keys from the monitor");
-		altprivsep_get_newkeys(MODE_OUT);
-		return;
-	}
-
-	data = altprivsep_packet_get_raw(&dlen);
-
-	packet_start((u_char)type);
-
-	if (data != NULL && dlen > 0)
-		packet_put_raw(data, dlen);
-
-	packet_send();
-}
-
-static void
-altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid)
-{
-	aps_monitor_loop(authctxt, child_pid);
-}
-
-static int
-altprivsep_started(void)
-{
-	return (aps_started);
-}
-
-static int
-altprivsep_is_monitor(void)
-{
-	return (is_monitor);
-}
-
-/*
- * A fatal cleanup function to forcibly shutdown the connection socket
- */
-static void
-altprivsep_shutdown_sock(void *arg)
-{
-	int sock;
-
-	if (arg == NULL)
-		return;
-
-	sock = *(int *)arg;
-
-	(void) shutdown(sock, SHUT_RDWR);
-}
-
-/* Calls _to_ monitor from unprivileged process */
-static int
-altprivsep_fwd_packet(u_char type)
-{
-	u_int len;
-	void  *data;
-
-	altprivsep_packet_start(type);
-	data = packet_get_raw(&len);
-	altprivsep_packet_put_raw(data, len);
-
-	/* packet_send()s any replies from the monitor to the client */
-	return (altprivsep_packet_send());
-}
-
-extern Newkeys *current_keys[MODE_MAX];
-
-/* To be called from packet.c:set_newkeys() before referencing current_keys */
-static void
-altprivsep_get_newkeys(enum kex_modes mode)
-{
-	Newkeys	*newkeys;
-	Comp	*comp;
-	Enc	*enc;
-	Mac	*mac;
-	u_int	 len;
-
-	if (!altprivsep_started())
-		return;
-
-	if (altprivsep_is_monitor())
-		return; /* shouldn't happen */
-
-	/* request new keys */
-	altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	altprivsep_packet_put_char(APS_MSG_NEWKEYS_REQ);
-	altprivsep_packet_put_int((u_int)mode);
-	altprivsep_packet_send();
-	altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-	if (altprivsep_packet_get_char() != APS_MSG_NEWKEYS_REP)
-		fatal("Received garbage from monitor during re-keying");
-
-	newkeys = xmalloc(sizeof (*newkeys));
-	memset(newkeys, 0, sizeof (*newkeys));
-
-	enc = &newkeys->enc;
-	mac = &newkeys->mac;
-	comp = &newkeys->comp;
-
-	/* Cipher name, key, IV */
-	enc->name = altprivsep_packet_get_string(NULL);
-	if ((enc->cipher = cipher_by_name(enc->name)) == NULL)
-		fatal("Monitor negotiated an unknown cipher during re-key");
-
-	enc->key = altprivsep_packet_get_string(&enc->key_len);
-	enc->iv = altprivsep_packet_get_string(&enc->block_size);
-
-	/* MAC name */
-	mac->name = altprivsep_packet_get_string(NULL);
-	if (mac_setup(mac, mac->name) < 0)
-		fatal("Monitor negotiated an unknown MAC algorithm "
-			"during re-key");
-
-	mac->key = altprivsep_packet_get_string(&len);
-	if (len > mac->key_len)
-		fatal("%s: bad mac key length: %d > %d", __func__, len,
-			mac->key_len);
-
-	/* Compression algorithm name */
-	comp->name = altprivsep_packet_get_string(NULL);
-	if (strcmp(comp->name, "zlib") != 0 && strcmp(comp->name, "none") != 0)
-		fatal("Monitor negotiated an unknown compression "
-			"algorithm during re-key");
-
-	comp->type = 0;
-	comp->enabled = 0; /* forces compression re-init, as per-spec */
-	if (strcmp(comp->name, "zlib") == 0)
-		comp->type = 1;
-
-	/*
-	 * Now install new keys
-	 *
-	 * For now abuse kex.c/packet.c non-interfaces.  Someday, when
-	 * the many internal interfaces are parametrized, made reentrant
-	 * and thread-safe, made more consistent, and when necessary-but-
-	 * currently-missing interfaces are added then this bit of
-	 * ugliness can be revisited.
-	 *
-	 * The ugliness is in the set_newkeys(), its name and the lack
-	 * of a (Newkeys *) parameter, which forces us to pass the
-	 * newkeys through current_keys[mode].  But this saves us some
-	 * lines of code for now, though not comments.
-	 *
-	 * Also, we've abused, in the code above, knowledge of what
-	 * set_newkeys() expects the current_keys[mode] to contain.
-	 */
-	current_keys[mode] = newkeys;
-	set_newkeys(mode);
-
-}
-
-void
-altprivsep_record_login(pid_t pid, const char *ttyname)
-{
-	altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	altprivsep_packet_put_char(APS_MSG_RECORD_LOGIN);
-	altprivsep_packet_put_int(pid);
-	altprivsep_packet_put_cstring(ttyname);
-	altprivsep_packet_send();
-	altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-}
-
-void
-altprivsep_record_logout(pid_t pid)
-{
-	altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	altprivsep_packet_put_char(APS_MSG_RECORD_LOGOUT);
-	altprivsep_packet_put_int(pid);
-	altprivsep_packet_send();
-	altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-}
-
-void
-altprivsep_start_rekex(void)
-{
-	altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	altprivsep_packet_put_char(APS_MSG_START_REKEX);
-	altprivsep_packet_send();
-	altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-}
-
-/*
- * The monitor needs some information that its child learns during the
- * authentication process. Since the child was forked before the key exchange
- * and authentication started it must send some context to the monitor after the
- * authentication is finished. Less obvious part - monitor needs the session ID
- * since it is used in the key generation process after the key (re-)exchange is
- * finished.
- */
-void
-altprivsep_send_auth_context(Authctxt *authctxt)
-{
-	debug("sending auth context to the monitor");
-	altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	altprivsep_packet_put_char(APS_MSG_AUTH_CONTEXT);
-	altprivsep_packet_put_int(authctxt->pw->pw_uid);
-	altprivsep_packet_put_int(authctxt->pw->pw_gid);
-	altprivsep_packet_put_cstring(authctxt->pw->pw_name);
-	altprivsep_packet_put_raw(session_id2, session_id2_len);
-	debug("will send %d bytes of auth context to the monitor",
-	    buffer_len(&to_monitor));
-	altprivsep_packet_send();
-	altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-}
-
-static void aps_send_newkeys(void);
-
-/* Monitor side dispatch handler for SSH2_PRIV_MSG_ALTPRIVSEP */
-/* ARGSUSED */
-void
-aps_input_altpriv_msg(int type, u_int32_t seq, void *ctxt)
-{
-	u_char req_type;
-
-	req_type = packet_get_char();
-
-	switch (req_type) {
-	case APS_MSG_NEWKEYS_REQ:
-		aps_send_newkeys();
-		break;
-	case APS_MSG_RECORD_LOGIN:
-		aps_record_login();
-		break;
-	case APS_MSG_RECORD_LOGOUT:
-		aps_record_logout();
-		break;
-	case APS_MSG_START_REKEX:
-		aps_start_rekex();
-		break;
-	default:
-		break;
-	}
-}
-
-/* Monitor-side handlers for APS_MSG_* */
-static
-void
-aps_send_newkeys(void)
-{
-	Newkeys *newkeys;
-	Enc *enc;
-	Mac *mac;
-	Comp *comp;
-	enum kex_modes mode;
-
-	/* get direction for which newkeys are wanted */
-	mode = (enum kex_modes) packet_get_int();
-	packet_check_eom();
-
-	/* get those newkeys */
-	newkeys = kex_get_newkeys(mode);
-	enc = &newkeys->enc;
-	mac = &newkeys->mac;
-	comp = &newkeys->comp;
-
-	/*
-	 * Negotiated algorithms, client->server and server->client, for
-	 * cipher, mac and compression.
-	 */
-	packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	packet_put_char(APS_MSG_NEWKEYS_REP);
-	packet_put_cstring(enc->name);
-	packet_put_string(enc->key, enc->key_len);
-	packet_put_string(enc->iv, enc->block_size);
-	packet_put_cstring(mac->name);
-	packet_put_string(mac->key, mac->key_len);
-	packet_put_cstring(comp->name);
-
-	packet_send();
-	free_keys(newkeys);
-}
-
-struct _aps_login_rec {
-	pid_t			lr_pid;
-	char			*lr_tty;
-	struct _aps_login_rec	*next;
-};
-
-typedef struct _aps_login_rec aps_login_rec;
-
-static aps_login_rec *aps_login_list = NULL;
-
-static
-void
-aps_record_login(void)
-{
-	aps_login_rec	*new_rec;
-	struct stat	 sbuf;
-	size_t		 proc_path_len;
-	char		*proc_path;
-
-	new_rec = xmalloc(sizeof (aps_login_rec));
-	memset(new_rec, 0, sizeof (aps_login_rec));
-
-	new_rec->lr_pid = packet_get_int();
-	new_rec->lr_tty = packet_get_string(NULL);
-
-	proc_path_len = snprintf(NULL, 0, "/proc/%d", new_rec->lr_pid);
-	proc_path = xmalloc(proc_path_len + 1);
-	(void) snprintf(proc_path, proc_path_len + 1, "/proc/%d",
-			new_rec->lr_pid);
-
-	if (stat(proc_path, &sbuf) ||
-	    sbuf.st_uid != xxx_authctxt->pw->pw_uid ||
-	    stat(new_rec->lr_tty, &sbuf) < 0 ||
-	    sbuf.st_uid != xxx_authctxt->pw->pw_uid) {
-		debug2("Spurious record_login request from unprivileged sshd");
-		xfree(proc_path);
-		xfree(new_rec->lr_tty);
-		xfree(new_rec);
-		return;
-	}
-
-	/* Insert new record on list */
-	new_rec->next = aps_login_list;
-	aps_login_list = new_rec;
-
-	record_login(new_rec->lr_pid, new_rec->lr_tty, NULL,
-		xxx_authctxt->user);
-
-	packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	packet_send();
-
-	xfree(proc_path);
-}
-
-static
-void
-aps_record_logout(void)
-{
-	aps_login_rec	**p, *q;
-	pid_t		 pid;
-
-	pid = packet_get_int();
-	packet_check_eom();
-
-	for (p = &aps_login_list; *p != NULL; p = &q->next) {
-		q = *p;
-		if (q->lr_pid == pid) {
-			record_logout(q->lr_pid, q->lr_tty, NULL,
-				xxx_authctxt->user);
-
-			/* dequeue */
-			*p = q->next;
-			xfree(q->lr_tty);
-			xfree(q);
-			break;
-		}
-	}
-
-	packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	packet_send();
-}
-
-static
-void
-aps_start_rekex(void)
-{
-	/*
-	 * Send confirmation. We could implement it without that but it doesn't
-	 * bring any harm to do that and we are consistent with other subtypes
-	 * of our private SSH2_PRIV_MSG_ALTPRIVSEP message type.
-	 */
-	packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	packet_send();
-
-	/*
-	 * KEX_INIT message could be the one that reached the limit. In that
-	 * case, it was already forwarded to us from the unnprivileged child,
-	 * and maybe even acted upon. Obviously we must not send another
-	 * KEX_INIT message.
-	 */
-	if (!(xxx_kex->flags & KEX_INIT_SENT))
-		kex_send_kexinit(xxx_kex);
-	else
-		debug2("rekeying already in progress");
-}
-
-/*
- * This is the monitor side of altprivsep_send_auth_context().
- */
-Authctxt *
-aps_read_auth_context(void)
-{
-	unsigned char *tmp;
-	Authctxt *authctxt;
-	
-	/*
-	 * After the successful authentication we get the context. Getting
-	 * end-of-file means that authentication failed and we can exit as well.
-	 */
-	debug("reading the context from the child");
-	packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
-	debug3("got SSH2_PRIV_MSG_ALTPRIVSEP");
-	if (packet_get_char() != APS_MSG_AUTH_CONTEXT) {
-		fatal("APS_MSG_AUTH_CONTEXT message subtype expected.");
-	}
-
-	authctxt = xcalloc(1, sizeof(Authctxt));
-	authctxt->pw = xcalloc(1, sizeof(struct passwd));
-
-	/* uid_t and gid_t are integers (UNIX spec) */
-	authctxt->pw->pw_uid = packet_get_int();
-	authctxt->pw->pw_gid = packet_get_int();
-	authctxt->pw->pw_name = packet_get_string(NULL);
-	authctxt->user = xstrdup(authctxt->pw->pw_name);
-	debug3("uid/gid/username %d/%d/%s", authctxt->pw->pw_uid,
-	    authctxt->pw->pw_gid, authctxt->user);
-	session_id2 = (unsigned char *)packet_get_raw((unsigned int*)&session_id2_len);
-
-	/* we don't have this for SSH1. In that case, session_id2_len is 0. */
-	if (session_id2_len > 0) {
-		tmp = (unsigned char *)xmalloc(session_id2_len);
-		memcpy(tmp, session_id2, session_id2_len);
-		session_id2 = tmp;
-		debug3("read session ID (%d B)", session_id2_len);
-		xxx_kex->session_id = tmp;
-		xxx_kex->session_id_len = session_id2_len;
-	}
-	debug("finished reading the context");
-
-	/* send confirmation */
-	packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
-	packet_send();
-
-	return (authctxt);
-}
-
-
-/* Utilities for communication with the monitor */
-static void
-altprivsep_packet_start(u_char type)
-{
-	buffer_clear(&to_monitor);
-	buffer_put_char(&to_monitor, type);
-}
-
-static void
-altprivsep_packet_put_char(int ch)
-{
-	buffer_put_char(&to_monitor, ch);
-}
-
-static void
-altprivsep_packet_put_int(u_int value)
-{
-	buffer_put_int(&to_monitor, value);
-}
-
-static void
-altprivsep_packet_put_cstring(const char *str)
-{
-	buffer_put_cstring(&to_monitor, str);
-}
-
-static void
-altprivsep_packet_put_raw(const void *buf, u_int len)
-{
-	buffer_append(&to_monitor, buf, len);
-}
-
-/*
- * Send a monitor packet to the monitor.  This function is blocking.
- *
- * Returns -1 if the monitor pipe has been closed earlier, fatal()s if
- * there's any other problems.
- */
-static int
-altprivsep_packet_send(void)
-{
-	ssize_t len;
-	u_int32_t plen;	/* packet length */
-	u_char	plen_buf[sizeof (plen)];
-	u_char padlen;	/* padding length */
-	fd_set *setp;
-	int err;
-
-	if (pipe_fd == -1)
-		return (-1);
-
-	if ((plen = buffer_len(&to_monitor)) == 0)
-		return (0);
-
-	/*
-	 * We talk the SSHv2 binary packet protocol to the monitor,
-	 * using the none cipher, mac and compression algorithms.
-	 *
-	 * But, interestingly, the none cipher has a block size of 8
-	 * bytes, thus we must pad the packet.
-	 *
-	 * Also, encryption includes the packet length, so the padding
-	 * must account for that field.  I.e., (sizeof (packet length) +
-	 * sizeof (padding length) + packet length + padding length) %
-	 * block_size must == 0.
-	 *
-	 * Also, there must be at least four (4) bytes of padding.
-	 */
-	padlen = (8 - ((plen + sizeof (plen) + sizeof (padlen)) % 8)) % 8;
-	if (padlen < 4)
-		padlen += 8;
-
-	/* packet length counts padding and padding length field */
-	plen += padlen + sizeof (padlen);
-
-	PUT_32BIT(plen_buf, plen);
-
-	setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
-	memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
-	FD_SET(pipe_fd, setp);
-
-	while (select(pipe_fd + 1, NULL, setp, NULL, NULL) == -1) {
-		if (errno == EAGAIN || errno == EINTR)
-			continue;
-		else
-			goto pipe_gone;
-	}
-
-	xfree(setp);
-
-	/* packet length field */
-	len = atomicio(write, pipe_fd, plen_buf, sizeof (plen));
-
-	if (len != sizeof (plen))
-		goto pipe_gone;
-
-	/* padding length field */
-	len = atomicio(write, pipe_fd, &padlen, sizeof (padlen));
-
-	if (len != sizeof (padlen))
-		goto pipe_gone;
-
-	len = atomicio(write, pipe_fd, buffer_ptr(&to_monitor), plen - 1);
-
-	if (len != (plen - 1))
-		goto pipe_gone;
-
-	buffer_clear(&to_monitor);
-
-	return (1);
-
-pipe_gone:
-	
-	err = errno;
-
-	(void) close(pipe_fd);
-
-	pipe_fd = -1;
-
-	fatal("altprvsep_packet_send: Monitor not responding: %.100s",
-	    strerror(err));
-
-	/* NOTREACHED */
-	return (0);
-}
-
-/*
- * Read a monitor packet from the monitor.  This function is blocking.
- */
-static int
-altprivsep_packet_read(void)
-{
-	ssize_t len = -1;
-	u_int32_t plen;
-	u_char plen_buf[sizeof (plen)];
-	u_char padlen;
-	fd_set *setp;
-	int err;
-
-	if (pipe_fd == -1)
-		return (-1);
-
-	setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
-	memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
-	FD_SET(pipe_fd, setp);
-
-	while (select(pipe_fd + 1, setp, NULL, NULL, NULL) == -1) {
-		if (errno == EAGAIN || errno == EINTR)
-			continue;
-		else
-			goto pipe_gone;
-	}
-
-	xfree(setp);
-
-	/* packet length field */
-	len = atomicio(read, pipe_fd, plen_buf, sizeof (plen));
-
-	plen = GET_32BIT(plen_buf);
-
-	if (len != sizeof (plen))
-		goto pipe_gone;
-
-	/* padding length field */
-	len = atomicio(read, pipe_fd, &padlen, sizeof (padlen));
-
-	if (len != sizeof (padlen))
-		goto pipe_gone;
-
-	plen -= sizeof (padlen);
-
-	buffer_clear(&from_monitor);
-	buffer_append_space(&from_monitor, plen);
-
-	/* packet data + padding */
-	len = atomicio(read, pipe_fd, buffer_ptr(&from_monitor), plen);
-
-	if (len != plen)
-		goto pipe_gone;
-
-	/* remove padding */
-	if (padlen > 0)
-		buffer_consume_end(&from_monitor, padlen);
-
-	/* packet type */
-	return (buffer_get_char(&from_monitor));
-
-pipe_gone:
-
-	err = errno;
-
-	(void) close(pipe_fd);
-
-	pipe_fd = -1;
-
-	if (len < 0)
-		fatal("altpriv_packet_read: Monitor not responding %.100s",
-		    strerror(err));
-
-	debug2("Monitor pipe closed by monitor");
-	return (0);
-}
-
-static void
-altprivsep_packet_read_expect(int expected)
-{
-	int type;
-
-	type = altprivsep_packet_read();
-
-	if (type <= 0)
-		fatal("altprivsep_packet_read_expect: Monitor not responding");
-
-	if (type != expected)
-		fatal("Protocol error in privilege separation; expected "
-			"packet type %d, got %d", expected, type);
-}
-
-static u_int
-altprivsep_packet_get_char(void)
-{
-	return (buffer_get_char(&from_monitor));
-}
-void
-*altprivsep_packet_get_raw(u_int *length_ptr)
-{
-	if (length_ptr != NULL)
-		*length_ptr = buffer_len(&from_monitor);
-
-	return (buffer_ptr(&from_monitor));
-}
-void
-*altprivsep_packet_get_string(u_int *length_ptr)
-{
-	return (buffer_get_string(&from_monitor, length_ptr));
-}
-
-/*
- * Start and execute the code for the monitor which never returns from this
- * function. The child will return and continue in the caller.
- */
-void
-altprivsep_start_and_do_monitor(int use_engine, int inetd, int newsock,
-	int statup_pipe)
-{
-	pid_t aps_child;
-	Authctxt *authctxt;
-
-	/*
-	 * The monitor will packet_close() in packet_set_monitor() called from
-	 * altprivsep_start_monitor() below to clean up the socket stuff before
-	 * it switches to pipes for communication to the child. The socket fd is
-	 * closed there so we must dup it here - monitor needs that socket to
-	 * shutdown the connection in case of any problem; see comments below.
-	 * Note that current newsock was assigned to connection_(in|out) which
-	 * are the variables used in packet_close() to close the communication
-	 * socket.
-	 */
-	newsock = dup(newsock);
-
-	if ((aps_child = altprivsep_start_monitor(&authctxt)) == -1)
-		fatal("Monitor could not be started.");
-
-	if (aps_child > 0) {
-		/* ALTPRIVSEP Monitor */
-
-		/*
-		 * The ALTPRIVSEP monitor here does:
-		 *
-		 *  - record keeping and auditing
-		 *  - PAM cleanup
-		 */
-
-		/* this is for MaxStartups and the child takes care of that */
-		(void) close(statup_pipe);
-		(void) pkcs11_engine_load(use_engine);
-
-		/*
-		 * If the monitor fatal()s it will audit/record a logout, so
-		 * we'd better do something to really mean it: shutdown the
-		 * socket but leave the child alone -- it's been disconnected
-		 * and we hope it exits, but killing any pid from a privileged
-		 * monitor could be dangerous.
-		 *
-		 * NOTE: Order matters -- these fatal cleanups must come before
-		 * the audit logout fatal cleanup as these functions are called
-		 * in LIFO.
-		 */
-		fatal_add_cleanup((void (*)(void *))altprivsep_shutdown_sock,
-			(void *)&newsock);
-
-		if (compat20) {
-			debug3("Recording SSHv2 session login in wtmpx");
-			/*
-			 * record_login() relies on connection_in to be the
-			 * socket to get the peer address. The problem is that
-			 * connection_in had to be set to the pipe descriptor in
-			 * altprivsep_start_monitor(). It's not nice but the
-			 * easiest way to get the peer's address is to
-			 * temporarily set connection_in to the socket's file
-			 * descriptor.
-			 */
-			packet_set_fds(inetd == 1 ? -1 : newsock, 0);
-			record_login(getpid(), NULL, "sshd", authctxt->user);
-			packet_set_fds(0, 1);
-		}
-
-#ifdef HAVE_BSM
-		/* Initialize the group list, audit sometimes needs it. */
-		if (initgroups(authctxt->pw->pw_name,
-		    authctxt->pw->pw_gid) < 0) {
-			perror("initgroups");
-			exit (1);
-		}
-
-		/*
-		 * The monitor process fork()ed before the authentication
-		 * process started so at this point we have an unaudited
-		 * context.  Thus we need to obtain the audit session data
-		 * from the authentication process (aps_child) which will
-		 * have the correct audit context for the user logging in.
-		 * To do so we pass along the process-ID of the aps_child
-		 * process so that it is referenced for this audit session
-		 * rather than referencing the monitor's unaudited context.
-		 */
-		audit_sshd_login(&ah, aps_child);
-
-		fatal_add_cleanup((void (*)(void *))audit_sshd_logout,
-		    (void *)&ah);
-#endif /* HAVE_BSM */
-
-#ifdef GSSAPI
-		fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds,
-			(void *)&xxx_gssctxt);
-#endif /* GSSAPI */
-
-		altprivsep_do_monitor(authctxt, aps_child);
-
-		/* If we got here the connection is dead. */
-		fatal_remove_cleanup((void (*)(void *))altprivsep_shutdown_sock,
-			(void *)&newsock);
-
-		if (compat20) {
-			debug3("Recording SSHv2 session logout in wtmpx");
-			record_logout(getpid(), NULL, "sshd", authctxt->user);
-		}
-
-		/*
-		 * Make sure the socket is closed. The monitor can't call
-		 * packet_close here as it's done a packet_set_connection()
-		 * with the pipe to the child instead of the socket.
-		 */
-		(void) shutdown(newsock, SHUT_RDWR);
-
-#ifdef GSSAPI
-		fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds,
-			&xxx_gssctxt);
-		ssh_gssapi_cleanup_creds(xxx_gssctxt);
-		ssh_gssapi_server_mechs(NULL); /* release cached mechs list */
-#endif /* GSSAPI */
-
-#ifdef HAVE_BSM
-		fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah);
-		audit_sshd_logout(&ah);
-#endif /* HAVE_BSM */
-
-		exit(0);
-	} else {
-		/*
-		 * This is the child, close the dup()ed file descriptor for a
-		 * socket. It's not needed in the child.
-		 */
-		close(newsock);
-	}
-}
