external/openssh: update to 6.8p1.

In preparation for some updates to external/openssh to make it work with
BoringSSL, this change updates the code to a recent version. The current
version (5.9p1) is coming up on four years old now.

  * Confirmed that f5c67b478bef9992de9e9ec91ce10af4f6205e0d matches
    OpenSSH 5.9p1 exactly (save for the removal of the scard
    subdirectory).

  * Downloaded openssh-6.8p1.tar.gz (SHA256:
    3ff64ce73ee124480b5bf767b9830d7d3c03bbcb6abe716b78f0192c37ce160e)
    and verified with PGP signature. (I've verified Damien's key in
    person previously.)

  * Applied changes between f5c67b478bef9992de9e9ec91ce10af4f6205e0d and
    OpenSSH 5.9p1 to 6.8p1 and updated the build as best I can. The
    ugliest change is probably the duplication of umac.c to umac128.c
    because Android conditionally compiles that file twice. See the
    comment in those files.

Change-Id: I63cb07a8118afb5a377f116087a0882914cea486
diff --git a/mux.c b/mux.c
index add0e26..f3faaee 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.50 2015/01/20 23:14:00 deraadt Exp $ */
 /*
  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
  *
@@ -33,7 +33,6 @@
 #include "includes.h"
 
 #include <sys/types.h>
-#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -63,10 +62,6 @@
 # include <util.h>
 #endif
 
-#ifdef HAVE_LIBUTIL_H
-# include <libutil.h>
-#endif
-
 #include "openbsd-compat/sys-queue.h"
 #include "xmalloc.h"
 #include "log.h"
@@ -109,6 +104,11 @@
 	u_int rid;
 };
 
+/* Context for stdio fwd open confirmation callback */
+struct mux_stdio_confirm_ctx {
+	u_int rid;
+};
+
 /* Context for global channel callback */
 struct mux_channel_confirm_ctx {
 	u_int cid;	/* channel id */
@@ -161,6 +161,7 @@
 #define MUX_FWD_DYNAMIC 3
 
 static void mux_session_confirm(int, int, void *);
+static void mux_stdio_confirm(int, int, void *);
 
 static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
 static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
@@ -223,7 +224,8 @@
 			    __func__, c->self, c->remote_id);
 		c->remote_id = -1;
 		sc->ctl_chan = -1;
-		if (sc->type != SSH_CHANNEL_OPEN) {
+		if (sc->type != SSH_CHANNEL_OPEN &&
+		    sc->type != SSH_CHANNEL_OPENING) {
 			debug2("%s: channel %d: not open", __func__, sc->self);
 			chan_mark_dead(sc);
 		} else {
@@ -290,13 +292,13 @@
 		char *value = buffer_get_string_ret(m, NULL);
 
 		if (name == NULL || value == NULL) {
-			if (name != NULL)
-				xfree(name);
+			free(name);
+			free(value);
 			goto malf;
 		}
 		debug2("Unrecognised slave extension \"%s\"", name);
-		xfree(name);
-		xfree(value);
+		free(name);
+		free(value);
 	}
 	state->hello_rcvd = 1;
 	return 0;
@@ -316,6 +318,8 @@
 	cctx->term = NULL;
 	cctx->rid = rid;
 	cmd = reserved = NULL;
+	cctx->env = NULL;
+	env_len = 0;
 	if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
 	    buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
 	    buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
@@ -325,28 +329,25 @@
 	    (cctx->term = buffer_get_string_ret(m, &len)) == NULL ||
 	    (cmd = buffer_get_string_ret(m, &len)) == NULL) {
  malf:
-		if (cmd != NULL)
-			xfree(cmd);
-		if (reserved != NULL)
-			xfree(reserved);
-		if (cctx->term != NULL)
-			xfree(cctx->term);
+		free(cmd);
+		free(reserved);
+		for (j = 0; j < env_len; j++)
+			free(cctx->env[j]);
+		free(cctx->env);
+		free(cctx->term);
+		free(cctx);
 		error("%s: malformed message", __func__);
 		return -1;
 	}
-	xfree(reserved);
+	free(reserved);
 	reserved = NULL;
 
-	cctx->env = NULL;
-	env_len = 0;
 	while (buffer_len(m) > 0) {
 #define MUX_MAX_ENV_VARS	4096
-		if ((cp = buffer_get_string_ret(m, &len)) == NULL) {
-			xfree(cmd);
+		if ((cp = buffer_get_string_ret(m, &len)) == NULL)
 			goto malf;
-		}
 		if (!env_permitted(cp)) {
-			xfree(cp);
+			free(cp);
 			continue;
 		}
 		cctx->env = xrealloc(cctx->env, env_len + 2,
@@ -367,7 +368,7 @@
 
 	buffer_init(&cctx->cmd);
 	buffer_append(&cctx->cmd, cmd, strlen(cmd));
-	xfree(cmd);
+	free(cmd);
 	cmd = NULL;
 
 	/* Gather fds from client */
@@ -378,12 +379,11 @@
 			for (j = 0; j < i; j++)
 				close(new_fd[j]);
 			for (j = 0; j < env_len; j++)
-				xfree(cctx->env[j]);
-			if (env_len > 0)
-				xfree(cctx->env);
-			xfree(cctx->term);
+				free(cctx->env[j]);
+			free(cctx->env);
+			free(cctx->term);
 			buffer_free(&cctx->cmd);
-			xfree(cctx);
+			free(cctx);
 
 			/* prepare reply */
 			buffer_put_int(r, MUX_S_FAILURE);
@@ -408,13 +408,14 @@
 		close(new_fd[0]);
 		close(new_fd[1]);
 		close(new_fd[2]);
-		xfree(cctx->term);
+		free(cctx->term);
 		if (env_len != 0) {
 			for (i = 0; i < env_len; i++)
-				xfree(cctx->env[i]);
-			xfree(cctx->env);
+				free(cctx->env[i]);
+			free(cctx->env);
 		}
 		buffer_free(&cctx->cmd);
+		free(cctx);
 		return 0;
 	}
 
@@ -513,29 +514,33 @@
 }
 
 static char *
-format_forward(u_int ftype, Forward *fwd)
+format_forward(u_int ftype, struct Forward *fwd)
 {
 	char *ret;
 
 	switch (ftype) {
 	case MUX_FWD_LOCAL:
 		xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
+		    (fwd->listen_path != NULL) ? fwd->listen_path :
 		    (fwd->listen_host == NULL) ?
-		    (options.gateway_ports ? "*" : "LOCALHOST") :
+		    (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
 		    fwd->listen_host, fwd->listen_port,
+		    (fwd->connect_path != NULL) ? fwd->connect_path :
 		    fwd->connect_host, fwd->connect_port);
 		break;
 	case MUX_FWD_DYNAMIC:
 		xasprintf(&ret, "dynamic forward %.200s:%d -> *",
 		    (fwd->listen_host == NULL) ?
-		    (options.gateway_ports ? "*" : "LOCALHOST") :
+		    (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
 		     fwd->listen_host, fwd->listen_port);
 		break;
 	case MUX_FWD_REMOTE:
 		xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
+		    (fwd->listen_path != NULL) ? fwd->listen_path :
 		    (fwd->listen_host == NULL) ?
 		    "LOCALHOST" : fwd->listen_host,
 		    fwd->listen_port,
+		    (fwd->connect_path != NULL) ? fwd->connect_path :
 		    fwd->connect_host, fwd->connect_port);
 		break;
 	default:
@@ -555,14 +560,18 @@
 }
 
 static int
-compare_forward(Forward *a, Forward *b)
+compare_forward(struct Forward *a, struct Forward *b)
 {
 	if (!compare_host(a->listen_host, b->listen_host))
 		return 0;
+	if (!compare_host(a->listen_path, b->listen_path))
+		return 0;
 	if (a->listen_port != b->listen_port)
 		return 0;
 	if (!compare_host(a->connect_host, b->connect_host))
 		return 0;
+	if (!compare_host(a->connect_path, b->connect_path))
+		return 0;
 	if (a->connect_port != b->connect_port)
 		return 0;
 
@@ -574,7 +583,7 @@
 {
 	struct mux_channel_confirm_ctx *fctx = ctxt;
 	char *failmsg = NULL;
-	Forward *rfwd;
+	struct Forward *rfwd;
 	Channel *c;
 	Buffer out;
 
@@ -591,7 +600,8 @@
 	rfwd = &options.remote_forwards[fctx->fid];
 	debug("%s: %s for: listen %d, connect %s:%d", __func__,
 	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
-	    rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
+	    rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
+	    rfwd->connect_host, rfwd->connect_port);
 	if (type == SSH2_MSG_REQUEST_SUCCESS) {
 		if (rfwd->listen_port == 0) {
 			rfwd->allocated_port = packet_get_int();
@@ -601,21 +611,29 @@
 			buffer_put_int(&out, MUX_S_REMOTE_PORT);
 			buffer_put_int(&out, fctx->rid);
 			buffer_put_int(&out, rfwd->allocated_port);
+			channel_update_permitted_opens(rfwd->handle,
+			   rfwd->allocated_port);
 		} else {
 			buffer_put_int(&out, MUX_S_OK);
 			buffer_put_int(&out, fctx->rid);
 		}
 		goto out;
 	} else {
-		xasprintf(&failmsg, "remote port forwarding failed for "
-		    "listen port %d", rfwd->listen_port);
+		if (rfwd->listen_port == 0)
+			channel_update_permitted_opens(rfwd->handle, -1);
+		if (rfwd->listen_path != NULL)
+			xasprintf(&failmsg, "remote port forwarding failed for "
+			    "listen path %s", rfwd->listen_path);
+		else
+			xasprintf(&failmsg, "remote port forwarding failed for "
+			    "listen port %d", rfwd->listen_port);
 	}
  fail:
 	error("%s: %s", __func__, failmsg);
 	buffer_put_int(&out, MUX_S_FAILURE);
 	buffer_put_int(&out, fctx->rid);
 	buffer_put_cstring(&out, failmsg);
-	xfree(failmsg);
+	free(failmsg);
  out:
 	buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
 	buffer_free(&out);
@@ -627,30 +645,45 @@
 static int
 process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
 {
-	Forward fwd;
+	struct Forward fwd;
 	char *fwd_desc = NULL;
+	char *listen_addr, *connect_addr;
 	u_int ftype;
+	u_int lport, cport;
 	int i, ret = 0, freefwd = 1;
 
-	fwd.listen_host = fwd.connect_host = NULL;
+	/* XXX - lport/cport check redundant */
 	if (buffer_get_int_ret(&ftype, m) != 0 ||
-	    (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
-	    buffer_get_int_ret(&fwd.listen_port, m) != 0 ||
-	    (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
-	    buffer_get_int_ret(&fwd.connect_port, m) != 0) {
+	    (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
+	    buffer_get_int_ret(&lport, m) != 0 ||
+	    (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
+	    buffer_get_int_ret(&cport, m) != 0 ||
+	    (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
+	    (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
 		error("%s: malformed message", __func__);
 		ret = -1;
 		goto out;
 	}
+	if (*listen_addr == '\0') {
+		free(listen_addr);
+		listen_addr = NULL;
+	}
+	if (*connect_addr == '\0') {
+		free(connect_addr);
+		connect_addr = NULL;
+	}
 
-	if (*fwd.listen_host == '\0') {
-		xfree(fwd.listen_host);
-		fwd.listen_host = NULL;
-	}
-	if (*fwd.connect_host == '\0') {
-		xfree(fwd.connect_host);
-		fwd.connect_host = NULL;
-	}
+	memset(&fwd, 0, sizeof(fwd));
+	fwd.listen_port = lport;
+	if (fwd.listen_port == PORT_STREAMLOCAL)
+		fwd.listen_path = listen_addr;
+	else
+		fwd.listen_host = listen_addr;
+	fwd.connect_port = cport;
+	if (fwd.connect_port == PORT_STREAMLOCAL)
+		fwd.connect_path = connect_addr;
+	else
+		fwd.connect_host = connect_addr;
 
 	debug2("%s: channel %d: request %s", __func__, c->self,
 	    (fwd_desc = format_forward(ftype, &fwd)));
@@ -659,27 +692,30 @@
 	    ftype != MUX_FWD_DYNAMIC) {
 		logit("%s: invalid forwarding type %u", __func__, ftype);
  invalid:
-		if (fwd.listen_host)
-			xfree(fwd.listen_host);
-		if (fwd.connect_host)
-			xfree(fwd.connect_host);
+		free(listen_addr);
+		free(connect_addr);
 		buffer_put_int(r, MUX_S_FAILURE);
 		buffer_put_int(r, rid);
 		buffer_put_cstring(r, "Invalid forwarding request");
 		return 0;
 	}
-	if (fwd.listen_port >= 65536) {
+	if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
+		logit("%s: streamlocal and dynamic forwards "
+		    "are mutually exclusive", __func__);
+		goto invalid;
+	}
+	if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
 		logit("%s: invalid listen port %u", __func__,
 		    fwd.listen_port);
 		goto invalid;
 	}
-	if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC &&
-	    ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
+	if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
+	    || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
 		logit("%s: invalid connect port %u", __func__,
 		    fwd.connect_port);
 		goto invalid;
 	}
-	if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) {
+	if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
 		logit("%s: missing connect host", __func__);
 		goto invalid;
 	}
@@ -730,9 +766,8 @@
 	}
 
 	if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
-		if (channel_setup_local_fwd_listener(fwd.listen_host,
-		    fwd.listen_port, fwd.connect_host, fwd.connect_port,
-		    options.gateway_ports) < 0) {
+		if (!channel_setup_local_fwd_listener(&fwd,
+		    &options.fwd_opts)) {
  fail:
 			logit("slave-requested %s failed", fwd_desc);
 			buffer_put_int(r, MUX_S_FAILURE);
@@ -745,8 +780,8 @@
 	} else {
 		struct mux_channel_confirm_ctx *fctx;
 
-		if (channel_request_remote_forwarding(fwd.listen_host,
-		    fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
+		fwd.handle = channel_request_remote_forwarding(&fwd);
+		if (fwd.handle < 0)
 			goto fail;
 		add_remote_forward(&options, &fwd);
 		fctx = xcalloc(1, sizeof(*fctx));
@@ -763,13 +798,12 @@
 	buffer_put_int(r, MUX_S_OK);
 	buffer_put_int(r, rid);
  out:
-	if (fwd_desc != NULL)
-		xfree(fwd_desc);
+	free(fwd_desc);
 	if (freefwd) {
-		if (fwd.listen_host != NULL)
-			xfree(fwd.listen_host);
-		if (fwd.connect_host != NULL)
-			xfree(fwd.connect_host);
+		free(fwd.listen_host);
+		free(fwd.listen_path);
+		free(fwd.connect_host);
+		free(fwd.connect_path);
 	}
 	return ret;
 }
@@ -777,46 +811,112 @@
 static int
 process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
 {
-	Forward fwd;
+	struct Forward fwd, *found_fwd;
 	char *fwd_desc = NULL;
+	const char *error_reason = NULL;
+	char *listen_addr = NULL, *connect_addr = NULL;
 	u_int ftype;
-	int ret = 0;
+	int i, ret = 0;
+	u_int lport, cport;
 
-	fwd.listen_host = fwd.connect_host = NULL;
 	if (buffer_get_int_ret(&ftype, m) != 0 ||
-	    (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
-	    buffer_get_int_ret(&fwd.listen_port, m) != 0 ||
-	    (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
-	    buffer_get_int_ret(&fwd.connect_port, m) != 0) {
+	    (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
+	    buffer_get_int_ret(&lport, m) != 0 ||
+	    (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
+	    buffer_get_int_ret(&cport, m) != 0 ||
+	    (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
+	    (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
 		error("%s: malformed message", __func__);
 		ret = -1;
 		goto out;
 	}
 
-	if (*fwd.listen_host == '\0') {
-		xfree(fwd.listen_host);
-		fwd.listen_host = NULL;
+	if (*listen_addr == '\0') {
+		free(listen_addr);
+		listen_addr = NULL;
 	}
-	if (*fwd.connect_host == '\0') {
-		xfree(fwd.connect_host);
-		fwd.connect_host = NULL;
+	if (*connect_addr == '\0') {
+		free(connect_addr);
+		connect_addr = NULL;
 	}
 
-	debug2("%s: channel %d: request %s", __func__, c->self,
+	memset(&fwd, 0, sizeof(fwd));
+	fwd.listen_port = lport;
+	if (fwd.listen_port == PORT_STREAMLOCAL)
+		fwd.listen_path = listen_addr;
+	else
+		fwd.listen_host = listen_addr;
+	fwd.connect_port = cport;
+	if (fwd.connect_port == PORT_STREAMLOCAL)
+		fwd.connect_path = connect_addr;
+	else
+		fwd.connect_host = connect_addr;
+
+	debug2("%s: channel %d: request cancel %s", __func__, c->self,
 	    (fwd_desc = format_forward(ftype, &fwd)));
 
-	/* XXX implement this */
-	buffer_put_int(r, MUX_S_FAILURE);
-	buffer_put_int(r, rid);
-	buffer_put_cstring(r, "unimplemented");
+	/* make sure this has been requested */
+	found_fwd = NULL;
+	switch (ftype) {
+	case MUX_FWD_LOCAL:
+	case MUX_FWD_DYNAMIC:
+		for (i = 0; i < options.num_local_forwards; i++) {
+			if (compare_forward(&fwd,
+			    options.local_forwards + i)) {
+				found_fwd = options.local_forwards + i;
+				break;
+			}
+		}
+		break;
+	case MUX_FWD_REMOTE:
+		for (i = 0; i < options.num_remote_forwards; i++) {
+			if (compare_forward(&fwd,
+			    options.remote_forwards + i)) {
+				found_fwd = options.remote_forwards + i;
+				break;
+			}
+		}
+		break;
+	}
 
+	if (found_fwd == NULL)
+		error_reason = "port not forwarded";
+	else if (ftype == MUX_FWD_REMOTE) {
+		/*
+		 * This shouldn't fail unless we confused the host/port
+		 * between options.remote_forwards and permitted_opens.
+		 * However, for dynamic allocated listen ports we need
+		 * to use the actual listen port.
+		 */
+		if (channel_request_rforward_cancel(found_fwd) == -1)
+			error_reason = "port not in permitted opens";
+	} else {	/* local and dynamic forwards */
+		/* Ditto */
+		if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
+		    &options.fwd_opts) == -1)
+			error_reason = "port not found";
+	}
+
+	if (error_reason == NULL) {
+		buffer_put_int(r, MUX_S_OK);
+		buffer_put_int(r, rid);
+
+		free(found_fwd->listen_host);
+		free(found_fwd->listen_path);
+		free(found_fwd->connect_host);
+		free(found_fwd->connect_path);
+		found_fwd->listen_host = found_fwd->connect_host = NULL;
+		found_fwd->listen_path = found_fwd->connect_path = NULL;
+		found_fwd->listen_port = found_fwd->connect_port = 0;
+	} else {
+		buffer_put_int(r, MUX_S_FAILURE);
+		buffer_put_int(r, rid);
+		buffer_put_cstring(r, error_reason);
+	}
  out:
-	if (fwd_desc != NULL)
-		xfree(fwd_desc);
-	if (fwd.listen_host != NULL)
-		xfree(fwd.listen_host);
-	if (fwd.connect_host != NULL)
-		xfree(fwd.connect_host);
+	free(fwd_desc);
+	free(listen_addr);
+	free(connect_addr);
 
 	return ret;
 }
@@ -828,19 +928,18 @@
 	char *reserved, *chost;
 	u_int cport, i, j;
 	int new_fd[2];
+	struct mux_stdio_confirm_ctx *cctx;
 
 	chost = reserved = NULL;
 	if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
 	   (chost = buffer_get_string_ret(m, NULL)) == NULL ||
 	    buffer_get_int_ret(&cport, m) != 0) {
-		if (reserved != NULL)
-			xfree(reserved);
-		if (chost != NULL)
-			xfree(chost);
+		free(reserved);
+		free(chost);
 		error("%s: malformed message", __func__);
 		return -1;
 	}
-	xfree(reserved);
+	free(reserved);
 
 	debug2("%s: channel %d: request stdio fwd to %s:%u",
 	    __func__, c->self, chost, cport);
@@ -852,7 +951,7 @@
 			    __func__, i);
 			for (j = 0; j < i; j++)
 				close(new_fd[j]);
-			xfree(chost);
+			free(chost);
 
 			/* prepare reply */
 			buffer_put_int(r, MUX_S_FAILURE);
@@ -876,7 +975,7 @@
  cleanup:
 		close(new_fd[0]);
 		close(new_fd[1]);
-		xfree(chost);
+		free(chost);
 		return 0;
 	}
 
@@ -909,15 +1008,60 @@
 
 	channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
 
-	/* prepare reply */
-	/* XXX defer until channel confirmed */
-	buffer_put_int(r, MUX_S_SESSION_OPENED);
-	buffer_put_int(r, rid);
-	buffer_put_int(r, nc->self);
+	cctx = xcalloc(1, sizeof(*cctx));
+	cctx->rid = rid;
+	channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx);
+	c->mux_pause = 1; /* stop handling messages until open_confirm done */
 
+	/* reply is deferred, sent by mux_session_confirm */
 	return 0;
 }
 
+/* Callback on open confirmation in mux master for a mux stdio fwd session. */
+static void
+mux_stdio_confirm(int id, int success, void *arg)
+{
+	struct mux_stdio_confirm_ctx *cctx = arg;
+	Channel *c, *cc;
+	Buffer reply;
+
+	if (cctx == NULL)
+		fatal("%s: cctx == NULL", __func__);
+	if ((c = channel_by_id(id)) == NULL)
+		fatal("%s: no channel for id %d", __func__, id);
+	if ((cc = channel_by_id(c->ctl_chan)) == NULL)
+		fatal("%s: channel %d lacks control channel %d", __func__,
+		    id, c->ctl_chan);
+
+	if (!success) {
+		debug3("%s: sending failure reply", __func__);
+		/* prepare reply */
+		buffer_init(&reply);
+		buffer_put_int(&reply, MUX_S_FAILURE);
+		buffer_put_int(&reply, cctx->rid);
+		buffer_put_cstring(&reply, "Session open refused by peer");
+		goto done;
+	}
+
+	debug3("%s: sending success reply", __func__);
+	/* prepare reply */
+	buffer_init(&reply);
+	buffer_put_int(&reply, MUX_S_SESSION_OPENED);
+	buffer_put_int(&reply, cctx->rid);
+	buffer_put_int(&reply, c->self);
+
+ done:
+	/* Send reply */
+	buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
+	buffer_free(&reply);
+
+	if (cc->mux_pause <= 0)
+		fatal("%s: mux_pause %d", __func__, cc->mux_pause);
+	cc->mux_pause = 0; /* start processing messages again */
+	c->open_confirm_ctx = NULL;
+	free(cctx);
+}
+
 static int
 process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
 {
@@ -938,7 +1082,7 @@
 	if (mux_listener_channel != NULL) {
 		channel_free(mux_listener_channel);
 		client_stop_mux();
-		xfree(options.control_path);
+		free(options.control_path);
 		options.control_path = NULL;
 		mux_listener_channel = NULL;
 		muxserver_sock = -1;
@@ -957,7 +1101,7 @@
 {
 	struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
 	Buffer in, out;
-	void *ptr;
+	const u_char *ptr;
 	u_int type, rid, have, i;
 	int ret = -1;
 
@@ -1038,7 +1182,7 @@
 	Buffer m;
 	Channel *mux_chan;
 
-	debug3("%s: channel %d: exit message, evitval %d", __func__, c->self,
+	debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
 	    exitval);
 
 	if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
@@ -1080,12 +1224,11 @@
 void
 muxserver_listen(void)
 {
-	struct sockaddr_un addr;
-	socklen_t sun_len;
 	mode_t old_umask;
 	char *orig_control_path = options.control_path;
 	char rbuf[16+1];
 	u_int i, r;
+	int oerrno;
 
 	if (options.control_path == NULL ||
 	    options.control_master == SSHCTL_MASTER_NO)
@@ -1110,24 +1253,12 @@
 	xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
 	debug3("%s: temporary control path %s", __func__, options.control_path);
 
-	memset(&addr, '\0', sizeof(addr));
-	addr.sun_family = AF_UNIX;
-	sun_len = offsetof(struct sockaddr_un, sun_path) +
-	    strlen(options.control_path) + 1;
-
-	if (strlcpy(addr.sun_path, options.control_path,
-	    sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
-		error("ControlPath \"%s\" too long for Unix domain socket",
-		    options.control_path);
-		goto disable_mux_master;
-	}
-
-	if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-		fatal("%s socket(): %s", __func__, strerror(errno));
-
 	old_umask = umask(0177);
-	if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) {
-		if (errno == EINVAL || errno == EADDRINUSE) {
+	muxserver_sock = unix_listener(options.control_path, 64, 0);
+	oerrno = errno;
+	umask(old_umask);
+	if (muxserver_sock < 0) {
+		if (oerrno == EINVAL || oerrno == EADDRINUSE) {
 			error("ControlSocket %s already exists, "
 			    "disabling multiplexing", options.control_path);
  disable_mux_master:
@@ -1135,17 +1266,16 @@
 				close(muxserver_sock);
 				muxserver_sock = -1;
 			}
-			xfree(options.control_path);
+			free(orig_control_path);
+			free(options.control_path);
 			options.control_path = NULL;
 			options.control_master = SSHCTL_MASTER_NO;
 			return;
-		} else
-			fatal("%s bind(): %s", __func__, strerror(errno));
+		} else {
+			/* unix_listener() logs the error */
+			cleanup_exit(255);
+		}
 	}
-	umask(old_umask);
-
-	if (listen(muxserver_sock, 64) == -1)
-		fatal("%s listen(): %s", __func__, strerror(errno));
 
 	/* Now atomically "move" the mux socket into position */
 	if (link(options.control_path, orig_control_path) != 0) {
@@ -1156,12 +1286,11 @@
 		}
 		error("ControlSocket %s already exists, disabling multiplexing",
 		    orig_control_path);
-		xfree(orig_control_path);
 		unlink(options.control_path);
 		goto disable_mux_master;
 	}
 	unlink(options.control_path);
-	xfree(options.control_path);
+	free(options.control_path);
 	options.control_path = orig_control_path;
 
 	set_nonblock(muxserver_sock);
@@ -1246,13 +1375,13 @@
 	cc->mux_pause = 0; /* start processing messages again */
 	c->open_confirm_ctx = NULL;
 	buffer_free(&cctx->cmd);
-	xfree(cctx->term);
+	free(cctx->term);
 	if (cctx->env != NULL) {
 		for (i = 0; cctx->env[i] != NULL; i++)
-			xfree(cctx->env[i]);
-		xfree(cctx->env);
+			free(cctx->env[i]);
+		free(cctx->env);
 	}
-	xfree(cctx);
+	free(cctx);
 }
 
 /* ** Multiplexing client support */
@@ -1376,13 +1505,15 @@
 {
 	Buffer queue;
 	u_int need, have;
-	void *ptr;
+	const u_char *ptr;
 	int oerrno;
 
 	buffer_init(&queue);
 	if (mux_client_read(fd, &queue, 4) != 0) {
 		if ((oerrno = errno) == EPIPE)
-		debug3("%s: read header failed: %s", __func__, strerror(errno));
+			debug3("%s: read header failed: %s", __func__,
+			    strerror(errno));
+		buffer_free(&queue);
 		errno = oerrno;
 		return -1;
 	}
@@ -1390,6 +1521,7 @@
 	if (mux_client_read(fd, &queue, need) != 0) {
 		oerrno = errno;
 		debug3("%s: read body failed: %s", __func__, strerror(errno));
+		buffer_free(&queue);
 		errno = oerrno;
 		return -1;
 	}
@@ -1436,8 +1568,8 @@
 		char *value = buffer_get_string(&m, NULL);
 
 		debug2("Unrecognised master extension \"%s\"", name);
-		xfree(name);
-		xfree(value);
+		free(name);
+		free(value);
 	}
 	buffer_free(&m);
 	return 0;
@@ -1537,25 +1669,35 @@
 }
 
 static int
-mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
+mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
 {
 	Buffer m;
 	char *e, *fwd_desc;
 	u_int type, rid;
 
 	fwd_desc = format_forward(ftype, fwd);
-	debug("Requesting %s", fwd_desc);
-	xfree(fwd_desc);
+	debug("Requesting %s %s",
+	    cancel_flag ? "cancellation of" : "forwarding of", fwd_desc);
+	free(fwd_desc);
 
 	buffer_init(&m);
-	buffer_put_int(&m, MUX_C_OPEN_FWD);
+	buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
 	buffer_put_int(&m, muxclient_request_id);
 	buffer_put_int(&m, ftype);
-	buffer_put_cstring(&m,
-	    fwd->listen_host == NULL ? "" : fwd->listen_host);
+	if (fwd->listen_path != NULL) {
+		buffer_put_cstring(&m, fwd->listen_path);
+	} else {
+		buffer_put_cstring(&m,
+		    fwd->listen_host == NULL ? "" :
+		    (*fwd->listen_host == '\0' ? "*" : fwd->listen_host));
+	}
 	buffer_put_int(&m, fwd->listen_port);
-	buffer_put_cstring(&m,
-	    fwd->connect_host == NULL ? "" : fwd->connect_host);
+	if (fwd->connect_path != NULL) {
+		buffer_put_cstring(&m, fwd->connect_path);
+	} else {
+		buffer_put_cstring(&m,
+		    fwd->connect_host == NULL ? "" : fwd->connect_host);
+	}
 	buffer_put_int(&m, fwd->connect_port);
 
 	if (mux_client_write_packet(fd, &m) != 0)
@@ -1577,6 +1719,8 @@
 	case MUX_S_OK:
 		break;
 	case MUX_S_REMOTE_PORT:
+		if (cancel_flag)
+			fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
 		fwd->allocated_port = buffer_get_int(&m);
 		logit("Allocated port %u for remote forward to %s:%d",
 		    fwd->allocated_port,
@@ -1606,27 +1750,28 @@
 }
 
 static int
-mux_client_request_forwards(int fd)
+mux_client_forwards(int fd, int cancel_flag)
 {
-	int i;
+	int i, ret = 0;
 
-	debug3("%s: requesting forwardings: %d local, %d remote", __func__,
+	debug3("%s: %s forwardings: %d local, %d remote", __func__,
+	    cancel_flag ? "cancel" : "request",
 	    options.num_local_forwards, options.num_remote_forwards);
 
 	/* XXX ExitOnForwardingFailure */
 	for (i = 0; i < options.num_local_forwards; i++) {
-		if (mux_client_request_forward(fd,
+		if (mux_client_forward(fd, cancel_flag,
 		    options.local_forwards[i].connect_port == 0 ?
 		    MUX_FWD_DYNAMIC : MUX_FWD_LOCAL,
 		    options.local_forwards + i) != 0)
-			return -1;
+			ret = -1;
 	}
 	for (i = 0; i < options.num_remote_forwards; i++) {
-		if (mux_client_request_forward(fd, MUX_FWD_REMOTE,
+		if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE,
 		    options.remote_forwards + i) != 0)
-			return -1;
+			ret = -1;
 	}
-	return 0;
+	return ret;
 }
 
 static int
@@ -1862,7 +2007,7 @@
 	case MUX_S_FAILURE:
 		e = buffer_get_string(&m, NULL);
 		buffer_free(&m);
-		fatal("%s: stdio forwarding request failed: %s", __func__, e);
+		fatal("Stdio forwarding request failed: %s", e);
 	default:
 		buffer_free(&m);
 		error("%s: unexpected response from master 0x%08x",
@@ -2014,11 +2159,11 @@
 		fprintf(stderr, "Exit request sent.\r\n");
 		exit(0);
 	case SSHMUX_COMMAND_FORWARD:
-		if (mux_client_request_forwards(sock) != 0)
+		if (mux_client_forwards(sock, 0) != 0)
 			fatal("%s: master forward request failed", __func__);
 		exit(0);
 	case SSHMUX_COMMAND_OPEN:
-		if (mux_client_request_forwards(sock) != 0) {
+		if (mux_client_forwards(sock, 0) != 0) {
 			error("%s: master forward request failed", __func__);
 			return;
 		}
@@ -2031,6 +2176,11 @@
 		mux_client_request_stop_listening(sock);
 		fprintf(stderr, "Stop listening request sent.\r\n");
 		exit(0);
+	case SSHMUX_COMMAND_CANCEL_FWD:
+		if (mux_client_forwards(sock, 1) != 0)
+			error("%s: master cancel forward request failed",
+			    __func__);
+		exit(0);
 	default:
 		fatal("unrecognised muxclient_command %d", muxclient_command);
 	}