- djm@cvs.openbsd.org 2005/06/08 11:25:09
     [clientloop.c readconf.c readconf.h ssh.c ssh_config.5]
     add ControlMaster=auto/autoask options to support opportunistic
     multiplexing; tested avsm@ and jakob@, ok markus@
diff --git a/ChangeLog b/ChangeLog
index 728026a..35249dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,10 @@
      [ssh-keygen.1 ssh-keygen.c sshd.8]
      increase default rsa/dsa key length from 1024 to 2048 bits;
      ok markus@ deraadt@
+   - djm@cvs.openbsd.org 2005/06/08 11:25:09
+     [clientloop.c readconf.c readconf.h ssh.c ssh_config.5]
+     add ControlMaster=auto/autoask options to support opportunistic
+     multiplexing; tested avsm@ and jakob@, ok markus@
 
 20050609
  - (dtucker) [cipher.c openbsd-compat/Makefile.in
@@ -2706,4 +2710,4 @@
    - (djm) Trim deprecated options from INSTALL. Mention UsePAM
    - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
 
-$Id: ChangeLog,v 1.3818 2005/06/16 03:19:06 djm Exp $
+$Id: ChangeLog,v 1.3819 2005/06/16 03:19:41 djm Exp $
diff --git a/clientloop.c b/clientloop.c
index 1591215..ae4dce8 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.136 2005/03/10 22:01:05 deraadt Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.137 2005/06/08 11:25:09 djm Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -616,13 +616,15 @@
 
 	switch (command) {
 	case SSHMUX_COMMAND_OPEN:
-		if (options.control_master == 2)
+		if (options.control_master == SSHCTL_MASTER_ASK ||
+		    options.control_master == SSHCTL_MASTER_AUTO_ASK)
 			allowed = ask_permission("Allow shared connection "
 			    "to %s? ", host);
 		/* continue below */
 		break;
 	case SSHMUX_COMMAND_TERMINATE:
-		if (options.control_master == 2)
+		if (options.control_master == SSHCTL_MASTER_ASK ||
+		    options.control_master == SSHCTL_MASTER_AUTO_ASK)
 			allowed = ask_permission("Terminate shared connection "
 			    "to %s? ", host);
 		if (allowed)
diff --git a/readconf.c b/readconf.c
index d412208..5ec89e2 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.140 2005/05/16 15:30:51 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.141 2005/06/08 11:25:09 djm Exp $");
 
 #include "ssh.h"
 #include "xmalloc.h"
@@ -796,7 +796,27 @@
 
 	case oControlMaster:
 		intptr = &options->control_master;
-		goto parse_yesnoask;
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing ControlMaster argument.",
+			    filename, linenum);
+		value = 0;	/* To avoid compiler warning... */
+		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+			value = SSHCTL_MASTER_YES;
+		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+			value = SSHCTL_MASTER_NO;
+		else if (strcmp(arg, "auto") == 0)
+			value = SSHCTL_MASTER_AUTO;
+		else if (strcmp(arg, "ask") == 0)
+			value = SSHCTL_MASTER_ASK;
+		else if (strcmp(arg, "autoask") == 0)
+			value = SSHCTL_MASTER_AUTO_ASK;
+		else
+			fatal("%.200s line %d: Bad ControlMaster argument.",
+			    filename, linenum);
+		if (*activep && *intptr == -1)
+			*intptr = value;
+		break;
 
 	case oHashKnownHosts:
 		intptr = &options->hash_known_hosts;
diff --git a/readconf.h b/readconf.h
index de4b4cb..2b9deb9 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: readconf.h,v 1.66 2005/03/01 10:40:27 djm Exp $	*/
+/*	$OpenBSD: readconf.h,v 1.67 2005/06/08 11:25:09 djm Exp $	*/
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -116,6 +116,11 @@
 	int	hash_known_hosts;
 }       Options;
 
+#define SSHCTL_MASTER_NO	0
+#define SSHCTL_MASTER_YES	1
+#define SSHCTL_MASTER_AUTO	2
+#define SSHCTL_MASTER_ASK	3
+#define SSHCTL_MASTER_AUTO_ASK	4
 
 void     initialize_options(Options *);
 void     fill_default_options(Options *);
diff --git a/ssh.c b/ssh.c
index 0871d06..a27c457 100644
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.241 2005/06/06 11:20:36 djm Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.242 2005/06/08 11:25:09 djm Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -386,8 +386,10 @@
 			}
 			break;
 		case 'M':
-			options.control_master =
-			    (options.control_master >= 1) ? 2 : 1;
+			if (options.control_master == SSHCTL_MASTER_YES)
+				options.control_master = SSHCTL_MASTER_ASK;
+			else
+				options.control_master = SSHCTL_MASTER_YES;
 			break;
 		case 'p':
 			options.port = a2port(optarg);
@@ -618,11 +620,8 @@
 	}
 	if (mux_command != 0 && options.control_path == NULL)
 		fatal("No ControlPath specified for \"-O\" command");
-	if (options.control_path != NULL && options.control_master == 0) {
-		if (mux_command == 0)
-			mux_command = SSHMUX_COMMAND_OPEN;
+	if (options.control_path != NULL)
 		control_client(options.control_path);
-	}
 
 	/* Open a connection to the remote host. */
 	if (ssh_connect(host, &hostaddr, options.port,
@@ -1086,9 +1085,12 @@
 	mode_t old_umask;
 	int addr_len;
 
-	if (options.control_path == NULL || options.control_master <= 0)
+	if (options.control_path == NULL ||
+	    options.control_master == SSHCTL_MASTER_NO)
 		return;
 
+	debug("setting up multiplex master socket");
+
 	memset(&addr, '\0', sizeof(addr));
 	addr.sun_family = AF_UNIX;
 	addr_len = offsetof(struct sockaddr_un, sun_path) +
@@ -1299,6 +1301,20 @@
 	extern char **environ;
 	u_int  flags;
 
+	if (mux_command == 0)
+		mux_command = SSHMUX_COMMAND_OPEN;
+
+	switch (options.control_master) {
+	case SSHCTL_MASTER_AUTO:
+	case SSHCTL_MASTER_AUTO_ASK:
+		debug("auto-mux: Trying existing master");
+		/* FALLTHROUGH */
+	case SSHCTL_MASTER_NO:
+		break;
+	default:
+		return;
+	}
+
 	memset(&addr, '\0', sizeof(addr));
 	addr.sun_family = AF_UNIX;
 	addr_len = offsetof(struct sockaddr_un, sun_path) +
diff --git a/ssh_config.5 b/ssh_config.5
index 2afc3c0..a04ffc2 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -34,7 +34,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh_config.5,v 1.55 2005/06/06 11:20:36 djm Exp $
+.\" $OpenBSD: ssh_config.5,v 1.56 2005/06/08 11:25:09 djm Exp $
 .Dd September 25, 1999
 .Dt SSH_CONFIG 5
 .Os
@@ -278,6 +278,17 @@
 can not be opened,
 .Nm ssh
 will continue without connecting to a master instance.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
 .It Cm ControlPath
 Specify the path to the control socket used for connection sharing as described
 in the
@@ -290,6 +301,11 @@
 the port and
 .Ql %r
 by the remote login username.
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+all three of these escape sequences.
+This ensures that shared connections are uniquely identified.
 .It Cm DynamicForward
 Specifies that a TCP/IP port on the local machine be forwarded
 over the secure channel, and the application