View | Details | Raw Unified | Return to bug 1330 | Differences between
and this patch

Collapse All | Expand All

(-)openssh-5.5p1.orig/clientloop.c (-3 / +63 lines)
Lines 145-150 static volatile sig_atomic_t received_si Link Here
145
/* Flag indicating whether the user's terminal is in non-blocking mode. */
145
/* Flag indicating whether the user's terminal is in non-blocking mode. */
146
static int in_non_blocking_mode = 0;
146
static int in_non_blocking_mode = 0;
147
147
148
/* Time when backgrounded control master using ControlPersist should exit */
149
static time_t control_persist_exit_time = 0;
150
148
/* Common data for the client loop code. */
151
/* Common data for the client loop code. */
149
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
152
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
150
static int escape_char1;	/* Escape character. (proto1 only) */
153
static int escape_char1;	/* Escape character. (proto1 only) */
Lines 251-256 get_current_time(void) Link Here
251
	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
254
	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
252
}
255
}
253
256
257
/*
258
 * Sets control_persist_exit_time to the absolute time when the
259
 * backgrounded control master should exit due to expiry of the
260
 * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
261
 * control master process, or if there is no ControlPersist timeout.
262
 */
263
static void
264
set_control_persist_exit_time(void)
265
{
266
	if (muxserver_sock == -1 || !options.control_persist
267
	    || options.control_persist_timeout == 0)
268
		/* not using a ControlPersist timeout */
269
		control_persist_exit_time = 0;
270
	else if (channel_still_open())
271
		/* some client connections are still open */
272
		control_persist_exit_time = 0;
273
	else if (control_persist_exit_time <= 0) {
274
		/* a client connection has recently closed */
275
		time_t now = time(NULL);
276
277
		control_persist_exit_time = now +
278
			(time_t)options.control_persist_timeout;
279
	}
280
	/* else we are already counting down to the timeout */
281
}
282
254
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
283
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
255
void
284
void
256
client_x11_get_proto(const char *display, const char *xauth_path,
285
client_x11_get_proto(const char *display, const char *xauth_path,
Lines 524-529 client_wait_until_can_do_something(fd_se Link Here
524
    int *maxfdp, u_int *nallocp, int rekeying)
553
    int *maxfdp, u_int *nallocp, int rekeying)
525
{
554
{
526
	struct timeval tv, *tvp;
555
	struct timeval tv, *tvp;
556
	time_t now;
557
	int timeout_secs;
527
	int ret;
558
	int ret;
528
559
529
	/* Add any selections by the channel mechanism. */
560
	/* Add any selections by the channel mechanism. */
Lines 567-579 client_wait_until_can_do_something(fd_se Link Here
567
	/*
598
	/*
568
	 * Wait for something to happen.  This will suspend the process until
599
	 * Wait for something to happen.  This will suspend the process until
569
	 * some selected descriptor can be read, written, or has some other
600
	 * some selected descriptor can be read, written, or has some other
570
	 * event pending.
601
	 * event pending, or a timeout expires.
571
	 */
602
	 */
572
603
573
	if (options.server_alive_interval == 0 || !compat20)
604
	now = time(NULL);
605
	timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
606
	if (options.server_alive_interval > 0 && compat20)
607
		timeout_secs = MIN(timeout_secs,
608
			options.server_alive_interval);
609
	set_control_persist_exit_time();
610
	if (control_persist_exit_time > 0) {
611
		timeout_secs = MIN(timeout_secs,
612
			control_persist_exit_time - now);
613
		if (timeout_secs < 0)
614
			timeout_secs = 0;
615
	}
616
	if (timeout_secs == INT_MAX)
574
		tvp = NULL;
617
		tvp = NULL;
575
	else {
618
	else {
576
		tv.tv_sec = options.server_alive_interval;
619
		tv.tv_sec = timeout_secs;
577
		tv.tv_usec = 0;
620
		tv.tv_usec = 0;
578
		tvp = &tv;
621
		tvp = &tv;
579
	}
622
	}
Lines 1469-1474 client_loop(int have_pty, int escape_cha Link Here
1469
		 */
1512
		 */
1470
		if (FD_ISSET(connection_out, writeset))
1513
		if (FD_ISSET(connection_out, writeset))
1471
			packet_write_poll();
1514
			packet_write_poll();
1515
1516
		/*
1517
		 * If we are a backgrounded control master, and the
1518
		 * timeout has expired without any active client
1519
		 * connections, then quit.
1520
		 */
1521
		if (muxserver_sock != -1 && options.control_persist
1522
		    && options.control_persist_timeout > 0
1523
		    && control_persist_exit_time > 0)
1524
		{
1525
			time_t now = time(NULL);
1526
1527
			if (now >= control_persist_exit_time) {
1528
				debug("ControlPersist timeout expired");
1529
				break;
1530
			}
1531
		}
1472
	}
1532
	}
1473
	if (readset)
1533
	if (readset)
1474
		xfree(readset);
1534
		xfree(readset);
(-)openssh-5.5p1.orig/readconf.c (-1 / +33 lines)
Lines 128-134 typedef enum { Link Here
128
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
128
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
129
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
130
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
130
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
131
	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
131
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
132
	oHashKnownHosts,
132
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
133
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
133
	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
134
	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
134
	oDeprecated, oUnsupported
135
	oDeprecated, oUnsupported
Lines 224-229 static struct { Link Here
224
	{ "sendenv", oSendEnv },
225
	{ "sendenv", oSendEnv },
225
	{ "controlpath", oControlPath },
226
	{ "controlpath", oControlPath },
226
	{ "controlmaster", oControlMaster },
227
	{ "controlmaster", oControlMaster },
228
	{ "controlpersist", oControlPersist },
227
	{ "hashknownhosts", oHashKnownHosts },
229
	{ "hashknownhosts", oHashKnownHosts },
228
	{ "tunnel", oTunnel },
230
	{ "tunnel", oTunnel },
229
	{ "tunneldevice", oTunnelDevice },
231
	{ "tunneldevice", oTunnelDevice },
Lines 866-871 parse_int: Link Here
866
			*intptr = value;
868
			*intptr = value;
867
		break;
869
		break;
868
870
871
	case oControlPersist:
872
		/* no/false/yes/true, or a time spec */
873
		intptr = &options->control_persist;
874
		arg = strdelim(&s);
875
		if (!arg || *arg == '\0')
876
			fatal("%.200s line %d: Missing ControlPersist"
877
			    " argument.", filename, linenum);
878
		value = 0;	/* To avoid compiler warning... */
879
		value2 = 0;	/* timeout */
880
		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
881
			value = 0;
882
		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
883
			value = 1;
884
		else if ((value2 = convtime(arg)) >= 0)
885
			value = 1;
886
		else
887
			fatal("%.200s line %d: Bad ControlPersist argument.",
888
			    filename, linenum);
889
		if (*activep && *intptr == -1) {
890
			*intptr = value;
891
			options->control_persist_timeout = value2;
892
		}
893
		break;
894
869
	case oHashKnownHosts:
895
	case oHashKnownHosts:
870
		intptr = &options->hash_known_hosts;
896
		intptr = &options->hash_known_hosts;
871
		goto parse_flag;
897
		goto parse_flag;
Lines 1064-1069 initialize_options(Options * options) Link Here
1064
	options->num_send_env = 0;
1090
	options->num_send_env = 0;
1065
	options->control_path = NULL;
1091
	options->control_path = NULL;
1066
	options->control_master = -1;
1092
	options->control_master = -1;
1093
	options->control_persist = -1;
1094
	options->control_persist_timeout = 0;
1067
	options->hash_known_hosts = -1;
1095
	options->hash_known_hosts = -1;
1068
	options->tun_open = -1;
1096
	options->tun_open = -1;
1069
	options->tun_local = -1;
1097
	options->tun_local = -1;
Lines 1197-1202 fill_default_options(Options * options) Link Here
1197
		options->server_alive_count_max = 3;
1225
		options->server_alive_count_max = 3;
1198
	if (options->control_master == -1)
1226
	if (options->control_master == -1)
1199
		options->control_master = 0;
1227
		options->control_master = 0;
1228
	if (options->control_persist == -1) {
1229
		options->control_persist = 0;
1230
		options->control_persist_timeout = 0;
1231
	}
1200
	if (options->hash_known_hosts == -1)
1232
	if (options->hash_known_hosts == -1)
1201
		options->hash_known_hosts = 0;
1233
		options->hash_known_hosts = 0;
1202
	if (options->tun_open == -1)
1234
	if (options->tun_open == -1)
(-)openssh-5.5p1.orig/readconf.h (+2 lines)
Lines 112-117 typedef struct { Link Here
112
112
113
	char	*control_path;
113
	char	*control_path;
114
	int	control_master;
114
	int	control_master;
115
	int     control_persist; /* ControlPersist flag */
116
	int     control_persist_timeout; /* ControlPersist timeout (seconds) */
115
117
116
	int	hash_known_hosts;
118
	int	hash_known_hosts;
117
119
(-)openssh-5.5p1.orig/ssh.c (-3 / +42 lines)
Lines 730-735 main(int ac, char **av) Link Here
730
		fatal("No ControlPath specified for \"-O\" command");
730
		fatal("No ControlPath specified for \"-O\" command");
731
	if (options.control_path != NULL)
731
	if (options.control_path != NULL)
732
		muxclient(options.control_path);
732
		muxclient(options.control_path);
733
		/* If muxclient() can connect to a master socket,
734
		 * then it doesn't return. */
733
735
734
	timeout_ms = options.connection_timeout * 1000;
736
	timeout_ms = options.connection_timeout * 1000;
735
737
Lines 1263-1268 ssh_session2(void) Link Here
1263
	/* XXX should be pre-session */
1265
	/* XXX should be pre-session */
1264
	ssh_init_forwarding();
1266
	ssh_init_forwarding();
1265
1267
1268
	/* Start listening for multiplex clients */
1269
	muxserver_listen();
1270
1271
 	/*
1272
 	 * If we are the control master, and if control_persist is set,
1273
 	 * then move the master into the background, and make the
1274
 	 * foreground process a client of the backgrounded master.
1275
 	 */
1276
 	if (options.control_persist && muxserver_sock != -1) {
1277
 		pid_t childpid;
1278
 
1279
 		childpid = fork();
1280
		if (childpid < 0) {
1281
 			fatal("fork() failed");
1282
 		} else if (childpid == 0) {
1283
 			/*
1284
 			 * This is the child.  Set some variables to let
1285
 			 * it continue continue operating as the control
1286
 			 * master in the background.
1287
 			 */
1288
 			debug("backgrounding control master");
1289
 			fork_after_authentication_flag = 1;
1290
 			stdin_null_flag = 1;
1291
 			no_shell_flag = 1;
1292
 			no_tty_flag = 1;
1293
 			tty_flag = 0;
1294
 		} else {
1295
 			/*
1296
 			 * This is the foreground process.  Make it a
1297
 			 * client of the newly-backgrounded control
1298
 			 * master.  muxclient() doesn't return
1299
 			 * unless it fails.
1300
 			 */
1301
 			close(muxserver_sock);
1302
 			muxserver_sock = -1;
1303
 			muxclient(options.control_path);
1304
 			fatal("Failed to connect to new control master");
1305
 		}
1306
 	}
1307
1266
	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1308
	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1267
		id = ssh_session2_open();
1309
		id = ssh_session2_open();
1268
1310
Lines 1281-1289 ssh_session2(void) Link Here
1281
	    options.permit_local_command)
1323
	    options.permit_local_command)
1282
		ssh_local_cmd(options.local_command);
1324
		ssh_local_cmd(options.local_command);
1283
1325
1284
	/* Start listening for multiplex clients */
1285
	muxserver_listen();
1286
1287
	/* If requested, let ssh continue in the background. */
1326
	/* If requested, let ssh continue in the background. */
1288
	if (fork_after_authentication_flag) {
1327
	if (fork_after_authentication_flag) {
1289
		fork_after_authentication_flag = 0;
1328
		fork_after_authentication_flag = 0;
(-)openssh-5.5p1.orig/ssh_config.5 (+22 lines)
Lines 319-324 It is recommended that any Link Here
319
used for opportunistic connection sharing include
319
used for opportunistic connection sharing include
320
at least %h, %p, and %r.
320
at least %h, %p, and %r.
321
This ensures that shared connections are uniquely identified.
321
This ensures that shared connections are uniquely identified.
322
.It Cm ControlPersist
323
When used in conjunction with
324
.Cm ControlMaster ,
325
specifies that the master connection should remain open
326
in the background (waiting for future client connections)
327
after the initial client connection has been closed.
328
If set to
329
.Dq no ,
330
then the master connection will not be placed into the background,
331
and will close as soon as the initial client connection is closed.
332
If set to
333
.Dq yes ,
334
then the master connection will remain in the background indefinitely
335
(until killed or closed via a mechanism such as the
336
.Xr ssh 1
337
.Dq Fl O No exit
338
option).
339
If set to a time in seconds, or a time in any of the formats documented in
340
.Xr sshd_config 5 ,
341
then the backgrounded master connection will automatically terminate
342
after it has remained idle (with no client connections) for the
343
specified time.
322
.It Cm DynamicForward
344
.It Cm DynamicForward
323
Specifies that a TCP port on the local machine be forwarded
345
Specifies that a TCP port on the local machine be forwarded
324
over the secure channel, and the application
346
over the secure channel, and the application

Return to bug 1330