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

Collapse All | Expand All

(-)openssh-5.1p1/clientloop.c (-3 / +63 lines)
Lines 142-147 Link Here
142
/* Flag indicating whether the user's terminal is in non-blocking mode. */
142
/* Flag indicating whether the user's terminal is in non-blocking mode. */
143
static int in_non_blocking_mode = 0;
143
static int in_non_blocking_mode = 0;
144
144
145
/* Time when backgrounded control master using ControlPersist should exit */
146
static time_t control_persist_exit_time = 0;
147
145
/* Common data for the client loop code. */
148
/* Common data for the client loop code. */
146
static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
149
static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
147
static int escape_char1;	/* Escape character. (proto1 only) */
150
static int escape_char1;	/* Escape character. (proto1 only) */
Lines 246-251 Link Here
246
	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
249
	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
247
}
250
}
248
251
252
/*
253
 * Sets control_persist_exit_time to the absolute time when the
254
 * backgrounded control master should exit due to expiry of the
255
 * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
256
 * control master process, or if there is no ControlPersist timeout.
257
 */
258
static void
259
set_control_persist_exit_time(void)
260
{
261
	if (muxserver_sock == -1 || !options.control_persist
262
	    || options.control_persist_timeout == 0)
263
		/* not using a ControlPersist timeout */
264
		control_persist_exit_time = 0;
265
	else if (channel_still_open())
266
		/* some client connections are still open */
267
		control_persist_exit_time = 0;
268
	else if (control_persist_exit_time <= 0) {
269
		/* a client connection has recently closed */
270
		time_t now = time(NULL);
271
272
		control_persist_exit_time = now +
273
			(time_t)options.control_persist_timeout;
274
	}
275
	/* else we are already counting down to the timeout */
276
}
277
249
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
278
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
250
void
279
void
251
client_x11_get_proto(const char *display, const char *xauth_path,
280
client_x11_get_proto(const char *display, const char *xauth_path,
Lines 519-524 Link Here
519
    int *maxfdp, u_int *nallocp, int rekeying)
548
    int *maxfdp, u_int *nallocp, int rekeying)
520
{
549
{
521
	struct timeval tv, *tvp;
550
	struct timeval tv, *tvp;
551
	time_t now;
552
	int timeout_secs;
522
	int ret;
553
	int ret;
523
554
524
	/* Add any selections by the channel mechanism. */
555
	/* Add any selections by the channel mechanism. */
Lines 565-577 Link Here
565
	/*
596
	/*
566
	 * Wait for something to happen.  This will suspend the process until
597
	 * Wait for something to happen.  This will suspend the process until
567
	 * some selected descriptor can be read, written, or has some other
598
	 * some selected descriptor can be read, written, or has some other
568
	 * event pending.
599
	 * event pending, or a timeout expires.
569
	 */
600
	 */
570
601
571
	if (options.server_alive_interval == 0 || !compat20)
602
	now = time(NULL);
603
	timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
604
	if (options.server_alive_interval > 0 && compat20)
605
		timeout_secs = MIN(timeout_secs,
606
			options.server_alive_interval);
607
	set_control_persist_exit_time();
608
	if (control_persist_exit_time > 0) {
609
		timeout_secs = MIN(timeout_secs,
610
			control_persist_exit_time - now);
611
		if (timeout_secs < 0)
612
			timeout_secs = 0;
613
	}
614
	if (timeout_secs == INT_MAX)
572
		tvp = NULL;
615
		tvp = NULL;
573
	else {
616
	else {
574
		tv.tv_sec = options.server_alive_interval;
617
		tv.tv_sec = timeout_secs;
575
		tv.tv_usec = 0;
618
		tv.tv_usec = 0;
576
		tvp = &tv;
619
		tvp = &tv;
577
	}
620
	}
Lines 1459-1464 Link Here
1459
		 */
1502
		 */
1460
		if (FD_ISSET(connection_out, writeset))
1503
		if (FD_ISSET(connection_out, writeset))
1461
			packet_write_poll();
1504
			packet_write_poll();
1505
1506
		/*
1507
		 * If we are a backgrounded control master, and the
1508
		 * timeout has expired without any active client
1509
		 * connections, then quit.
1510
		 */
1511
		if (muxserver_sock != -1 && options.control_persist
1512
		    && options.control_persist_timeout > 0
1513
		    && control_persist_exit_time > 0)
1514
		{
1515
			time_t now = time(NULL);
1516
1517
			if (now >= control_persist_exit_time) {
1518
				debug("ControlPersist timeout expired");
1519
				break;
1520
			}
1521
		}
1462
	}
1522
	}
1463
	if (readset)
1523
	if (readset)
1464
		xfree(readset);
1524
		xfree(readset);
(-)openssh-5.1p1/readconf.c (-1 / +33 lines)
Lines 128-134 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,
134
	oVisualHostKey,
134
	oDeprecated, oUnsupported
135
	oDeprecated, oUnsupported
Lines 222-227 Link Here
222
	{ "sendenv", oSendEnv },
223
	{ "sendenv", oSendEnv },
223
	{ "controlpath", oControlPath },
224
	{ "controlpath", oControlPath },
224
	{ "controlmaster", oControlMaster },
225
	{ "controlmaster", oControlMaster },
226
	{ "controlpersist", oControlPersist },
225
	{ "hashknownhosts", oHashKnownHosts },
227
	{ "hashknownhosts", oHashKnownHosts },
226
	{ "tunnel", oTunnel },
228
	{ "tunnel", oTunnel },
227
	{ "tunneldevice", oTunnelDevice },
229
	{ "tunneldevice", oTunnelDevice },
Lines 870-875 Link Here
870
			*intptr = value;
872
			*intptr = value;
871
		break;
873
		break;
872
874
875
	case oControlPersist:
876
		/* no/false/yes/true, or a time spec */
877
		intptr = &options->control_persist;
878
		arg = strdelim(&s);
879
		if (!arg || *arg == '\0')
880
			fatal("%.200s line %d: Missing ControlPersist"
881
			    " argument.", filename, linenum);
882
		value = 0;	/* To avoid compiler warning... */
883
		value2 = 0;	/* timeout */
884
		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
885
			value = 0;
886
		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
887
			value = 1;
888
		else if ((value2 = convtime(arg)) > 0)
889
			value = 1;
890
		else
891
			fatal("%.200s line %d: Bad ControlPersist argument.",
892
			    filename, linenum);
893
		if (*activep && *intptr == -1) {
894
			*intptr = value;
895
			options->control_persist_timeout = value2;
896
		}
897
		break;
898
873
	case oHashKnownHosts:
899
	case oHashKnownHosts:
874
		intptr = &options->hash_known_hosts;
900
		intptr = &options->hash_known_hosts;
875
		goto parse_flag;
901
		goto parse_flag;
Lines 1065-1070 Link Here
1065
	options->num_send_env = 0;
1091
	options->num_send_env = 0;
1066
	options->control_path = NULL;
1092
	options->control_path = NULL;
1067
	options->control_master = -1;
1093
	options->control_master = -1;
1094
	options->control_persist = -1;
1095
	options->control_persist_timeout = 0;
1068
	options->hash_known_hosts = -1;
1096
	options->hash_known_hosts = -1;
1069
	options->tun_open = -1;
1097
	options->tun_open = -1;
1070
	options->tun_local = -1;
1098
	options->tun_local = -1;
Lines 1196-1201 Link Here
1196
		options->server_alive_count_max = 3;
1224
		options->server_alive_count_max = 3;
1197
	if (options->control_master == -1)
1225
	if (options->control_master == -1)
1198
		options->control_master = 0;
1226
		options->control_master = 0;
1227
	if (options->control_persist == -1) {
1228
		options->control_persist = 0;
1229
		options->control_persist_timeout = 0;
1230
	}
1199
	if (options->hash_known_hosts == -1)
1231
	if (options->hash_known_hosts == -1)
1200
		options->hash_known_hosts = 0;
1232
		options->hash_known_hosts = 0;
1201
	if (options->tun_open == -1)
1233
	if (options->tun_open == -1)
(-)openssh-5.1p1/readconf.h (+2 lines)
Lines 111-116 Link Here
111
111
112
	char	*control_path;
112
	char	*control_path;
113
	int	control_master;
113
	int	control_master;
114
	int     control_persist; /* ControlPersist flag */
115
	int     control_persist_timeout; /* ControlPersist timeout (seconds) */
114
116
115
	int	hash_known_hosts;
117
	int	hash_known_hosts;
116
118
(-)openssh-5.1p1/ssh.c (-3 / +42 lines)
Lines 707-712 Link Here
707
		fatal("No ControlPath specified for \"-O\" command");
707
		fatal("No ControlPath specified for \"-O\" command");
708
	if (options.control_path != NULL)
708
	if (options.control_path != NULL)
709
		muxclient(options.control_path);
709
		muxclient(options.control_path);
710
		/* If muxclient() can connect to a master socket,
711
		 * then it doesn't return. */
710
712
711
	timeout_ms = options.connection_timeout * 1000;
713
	timeout_ms = options.connection_timeout * 1000;
712
714
Lines 1196-1201 Link Here
1196
	/* XXX should be pre-session */
1198
	/* XXX should be pre-session */
1197
	ssh_init_forwarding();
1199
	ssh_init_forwarding();
1198
1200
1201
	/* Start listening for multiplex clients */
1202
	muxserver_listen();
1203
1204
 	/*
1205
 	 * If we are the control master, and if control_persist is set,
1206
 	 * then move the master into the background, and make the
1207
 	 * foreground process a client of the backgrounded master.
1208
 	 */
1209
 	if (options.control_persist && muxserver_sock != -1) {
1210
 		pid_t childpid;
1211
 
1212
 		childpid = fork();
1213
		if (childpid < 0) {
1214
 			fatal("fork() failed");
1215
 		} else if (childpid == 0) {
1216
 			/*
1217
 			 * This is the child.  Set some variables to let
1218
 			 * it continue continue operating as the control
1219
 			 * master in the background.
1220
 			 */
1221
 			debug("backgrounding control master");
1222
 			fork_after_authentication_flag = 1;
1223
 			stdin_null_flag = 1;
1224
 			no_shell_flag = 1;
1225
 			no_tty_flag = 1;
1226
 			tty_flag = 0;
1227
 		} else {
1228
 			/*
1229
 			 * This is the foreground process.  Make it a
1230
 			 * client of the newly-backgrounded control
1231
 			 * master.  muxclient() doesn't return
1232
 			 * unless it fails.
1233
 			 */
1234
 			close(muxserver_sock);
1235
 			muxserver_sock = -1;
1236
 			muxclient(options.control_path);
1237
 			fatal("Failed to connect to new control master");
1238
 		}
1239
 	}
1240
1199
	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1241
	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1200
		id = ssh_session2_open();
1242
		id = ssh_session2_open();
1201
1243
Lines 1213-1221 Link Here
1213
	    options.permit_local_command)
1255
	    options.permit_local_command)
1214
		ssh_local_cmd(options.local_command);
1256
		ssh_local_cmd(options.local_command);
1215
1257
1216
	/* Start listening for multiplex clients */
1217
	muxserver_listen();
1218
1219
	/* If requested, let ssh continue in the background. */
1258
	/* If requested, let ssh continue in the background. */
1220
	if (fork_after_authentication_flag) {
1259
	if (fork_after_authentication_flag) {
1221
		fork_after_authentication_flag = 0;
1260
		fork_after_authentication_flag = 0;
(-)openssh-5.1p1/ssh_config.5 (+22 lines)
Lines 319-324 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