[PATCH] Add ssh_config equivalents of -N, -n and -f

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



Dear OpenSSH developers,

I kindly ask you to review the attached set of patches which
introduce ssh_config equivalents of the flags -N, -n and -f in
a straight forward way:

* NoShell for -N

* StdinNull for -n

* ForkAfterAuthentication for -f

The ssh_config names were derived directly from the internal flag
names, e.g. no_shell_flag was moved to option.no_shell and hence
the ssh_config name became NoShell.  The man pages ssh(1) and
ssh_config(5) are adjusted accordingly.

As a final remark, I noticed that the variable ono_shell_flag (not to
be confused with no_shell_flag) is only assigned once and never used.
So I assume this is dead code and I'm proposing a patch to remove it.


Regards,
Volker

-- 
Volker Diels-Grabsch
----<<<((()))>>>----
commit cc8f234a71985b6c5a2b4b2323c74db3725cc41b
Author: Volker Diels-Grabsch <v@xxxxxx>
Date:   Sun Feb 21 00:47:05 2021 +0100

    Add ssh_config option NoShell with same behavior as -N

diff --git a/clientloop.c b/clientloop.c
index 60b46d1..21b9c54 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -118,9 +118,6 @@ extern Options options;
 /* Flag indicating that stdin should be redirected from /dev/null. */
 extern int stdin_null_flag;
 
-/* Flag indicating that no shell has been requested */
-extern int no_shell_flag;
-
 /* Flag indicating that ssh should daemonise after authentication is complete */
 extern int fork_after_authentication_flag;
 
@@ -1434,7 +1431,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
 	 * exit status to be returned.  In that case, clear error code if the
 	 * connection was deliberately terminated at this end.
 	 */
-	if (no_shell_flag && received_signal == SIGTERM) {
+	if (options.no_shell && received_signal == SIGTERM) {
 		received_signal = 0;
 		exit_status = 0;
 	}
@@ -2439,7 +2436,7 @@ client_stop_mux(void)
 	 * If we are in persist mode, or don't have a shell, signal that we
 	 * should close when all active channels are closed.
 	 */
-	if (options.control_persist || no_shell_flag) {
+	if (options.control_persist || options.no_shell) {
 		session_closed = 1;
 		setproctitle("[stopped mux]");
 	}
diff --git a/readconf.c b/readconf.c
index 554efd7..cdbb298 100644
--- a/readconf.c
+++ b/readconf.c
@@ -166,7 +166,8 @@ typedef enum {
 	oTunnel, oTunnelDevice,
 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
 	oVisualHostKey,
-	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
+	oKexAlgorithms, oIPQoS, oRequestTTY, oNoShell,
+	oIgnoreUnknown, oProxyUseFdpass,
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
@@ -294,6 +295,7 @@ static struct {
 	{ "kexalgorithms", oKexAlgorithms },
 	{ "ipqos", oIPQoS },
 	{ "requesttty", oRequestTTY },
+	{ "noshell", oNoShell },
 	{ "proxyusefdpass", oProxyUseFdpass },
 	{ "canonicaldomains", oCanonicalDomains },
 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
@@ -1694,6 +1696,10 @@ parse_keytypes:
 		multistate_ptr = multistate_requesttty;
 		goto parse_multistate;
 
+	case oNoShell:
+		intptr = &options->no_shell;
+		goto parse_flag;
+
 	case oIgnoreUnknown:
 		charptr = &options->ignored_unknown;
 		goto parse_string;
@@ -2050,6 +2056,7 @@ initialize_options(Options * options)
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
 	options->request_tty = -1;
+	options->no_shell = -1;
 	options->proxy_use_fdpass = -1;
 	options->ignored_unknown = NULL;
 	options->num_canonical_domains = 0;
@@ -2230,6 +2237,8 @@ fill_default_options(Options * options)
 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
 	if (options->request_tty == -1)
 		options->request_tty = REQUEST_TTY_AUTO;
+	if (options->no_shell == -1)
+		options->no_shell = 0;
 	if (options->proxy_use_fdpass == -1)
 		options->proxy_use_fdpass = 0;
 	if (options->canonicalize_max_dots == -1)
@@ -2788,6 +2797,7 @@ dump_client_config(Options *o, const char *host)
 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
+	dump_cfg_fmtint(oNoShell, o->no_shell);
 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
diff --git a/readconf.h b/readconf.h
index d6a1555..50261ee 100644
--- a/readconf.h
+++ b/readconf.h
@@ -143,6 +143,7 @@ typedef struct {
 	int	visual_host_key;
 
 	int	request_tty;
+	int	no_shell;
 
 	int	proxy_use_fdpass;
 
diff --git a/ssh.1 b/ssh.1
index 5553178..ac06025 100644
--- a/ssh.1
+++ b/ssh.1
@@ -425,6 +425,11 @@ keyword for more information.
 .It Fl N
 Do not execute a remote command.
 This is useful for just forwarding ports.
+Refer to the description of
+.Cm NoShell
+in
+.Xr ssh_config 5
+for details.
 .Pp
 .It Fl n
 Redirects stdin from
diff --git a/ssh.c b/ssh.c
index f34ca0d..ae8144e 100644
--- a/ssh.c
+++ b/ssh.c
@@ -126,9 +126,6 @@ int debug_flag = 0;
 /* Flag indicating whether a tty should be requested */
 int tty_flag = 0;
 
-/* don't exec a shell */
-int no_shell_flag = 0;
-
 /*
  * Flag indicating that nothing should be read from stdin.  This can be set
  * on the command line.
@@ -933,7 +930,7 @@ main(int ac, char **av)
 				exit(255);
 			}
 			options.request_tty = REQUEST_TTY_NO;
-			no_shell_flag = 1;
+			options.no_shell = 1;
 			break;
 		case 'q':
 			options.log_level = SYSLOG_LEVEL_QUIET;
@@ -1036,7 +1033,7 @@ main(int ac, char **av)
 #endif
 			break;
 		case 'N':
-			no_shell_flag = 1;
+			options.no_shell = 1;
 			options.request_tty = REQUEST_TTY_NO;
 			break;
 		case 'T':
@@ -1349,7 +1346,7 @@ main(int ac, char **av)
 
 	/* Cannot fork to background if no command. */
 	if (fork_after_authentication_flag && sshbuf_len(command) == 0 &&
-	    options.remote_command == NULL && !no_shell_flag)
+	    options.remote_command == NULL && !options.no_shell)
 		fatal("Cannot fork into background without a command "
 		    "to execute.");
 
@@ -2065,7 +2062,7 @@ ssh_session2_open(struct ssh *ssh)
 	debug3("%s: channel_new: %d", __func__, c->self);
 
 	channel_send_open(ssh, c->self);
-	if (!no_shell_flag)
+	if (!options.no_shell)
 		channel_register_open_confirm(ssh, c->self,
 		    ssh_session2_setup, NULL);
 
@@ -2114,11 +2111,11 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 	 */
 	if (options.control_persist && muxserver_sock != -1) {
 		ostdin_null_flag = stdin_null_flag;
-		ono_shell_flag = no_shell_flag;
+		ono_shell_flag = options.no_shell;
 		orequest_tty = options.request_tty;
 		otty_flag = tty_flag;
 		stdin_null_flag = 1;
-		no_shell_flag = 1;
+		options.no_shell = 1;
 		tty_flag = 0;
 		if (!fork_after_authentication_flag)
 			need_controlpersist_detach = 1;
@@ -2131,7 +2128,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 	if (options.control_persist && muxserver_sock == -1)
 		ssh_init_stdio_forwarding(ssh);
 
-	if (!no_shell_flag)
+	if (!options.no_shell)
 		id = ssh_session2_open(ssh);
 	else {
 		ssh_packet_set_interactive(ssh,
diff --git a/ssh_config.5 b/ssh_config.5
index 6be1f1a..5a9ee10 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1222,6 +1222,16 @@ The argument to this keyword must be
 or
 .Cm no
 (the default).
+.It Cm NoShell
+Do not execute a remote command.
+This is useful for just forwarding ports.
+The argument to this keyword must be
+.Cm yes
+(same as the
+.Fl N
+option) or
+.Cm no
+(the default).
 .It Cm NumberOfPasswordPrompts
 Specifies the number of password prompts before giving up.
 The argument to this keyword must be an integer.
commit fb21e68322281f4640841fb4f0d8f0589ccd6266
Author: Volker Diels-Grabsch <v@xxxxxx>
Date:   Sun Feb 21 02:49:54 2021 +0100

    Add ssh_config option StdinNull with same behavior as -n

diff --git a/clientloop.c b/clientloop.c
index 21b9c54..690b776 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -115,9 +115,6 @@
 /* import options */
 extern Options options;
 
-/* Flag indicating that stdin should be redirected from /dev/null. */
-extern int stdin_null_flag;
-
 /* Flag indicating that ssh should daemonise after authentication is complete */
 extern int fork_after_authentication_flag;
 
diff --git a/mux.c b/mux.c
index 376f0d7..84d7467 100644
--- a/mux.c
+++ b/mux.c
@@ -71,7 +71,6 @@
 /* from ssh.c */
 extern int tty_flag;
 extern Options options;
-extern int stdin_null_flag;
 extern char *host;
 extern int subsystem_flag;
 extern struct sshbuf *command;
@@ -1913,7 +1912,7 @@ mux_client_request_session(int fd)
 
 	ssh_signal(SIGPIPE, SIG_IGN);
 
-	if (stdin_null_flag) {
+	if (options.stdin_null) {
 		if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
 			fatal("open(/dev/null): %s", strerror(errno));
 		if (dup2(devnull, STDIN_FILENO) == -1)
@@ -2148,7 +2147,7 @@ mux_client_request_stdio_fwd(int fd)
 
 	ssh_signal(SIGPIPE, SIG_IGN);
 
-	if (stdin_null_flag) {
+	if (options.stdin_null) {
 		if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
 			fatal("open(/dev/null): %s", strerror(errno));
 		if (dup2(devnull, STDIN_FILENO) == -1)
diff --git a/readconf.c b/readconf.c
index cdbb298..88e6408 100644
--- a/readconf.c
+++ b/readconf.c
@@ -166,7 +166,7 @@ typedef enum {
 	oTunnel, oTunnelDevice,
 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
 	oVisualHostKey,
-	oKexAlgorithms, oIPQoS, oRequestTTY, oNoShell,
+	oKexAlgorithms, oIPQoS, oRequestTTY, oNoShell, oStdinNull,
 	oIgnoreUnknown, oProxyUseFdpass,
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
@@ -296,6 +296,7 @@ static struct {
 	{ "ipqos", oIPQoS },
 	{ "requesttty", oRequestTTY },
 	{ "noshell", oNoShell },
+	{ "stdinnull", oStdinNull },
 	{ "proxyusefdpass", oProxyUseFdpass },
 	{ "canonicaldomains", oCanonicalDomains },
 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
@@ -1700,6 +1701,10 @@ parse_keytypes:
 		intptr = &options->no_shell;
 		goto parse_flag;
 
+	case oStdinNull:
+		intptr = &options->stdin_null;
+		goto parse_flag;
+
 	case oIgnoreUnknown:
 		charptr = &options->ignored_unknown;
 		goto parse_string;
@@ -2057,6 +2062,7 @@ initialize_options(Options * options)
 	options->ip_qos_bulk = -1;
 	options->request_tty = -1;
 	options->no_shell = -1;
+	options->stdin_null = -1;
 	options->proxy_use_fdpass = -1;
 	options->ignored_unknown = NULL;
 	options->num_canonical_domains = 0;
@@ -2239,6 +2245,8 @@ fill_default_options(Options * options)
 		options->request_tty = REQUEST_TTY_AUTO;
 	if (options->no_shell == -1)
 		options->no_shell = 0;
+	if (options->stdin_null == -1)
+		options->stdin_null = 0;
 	if (options->proxy_use_fdpass == -1)
 		options->proxy_use_fdpass = 0;
 	if (options->canonicalize_max_dots == -1)
@@ -2798,6 +2806,7 @@ dump_client_config(Options *o, const char *host)
 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
 	dump_cfg_fmtint(oNoShell, o->no_shell);
+	dump_cfg_fmtint(oStdinNull, o->stdin_null);
 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
diff --git a/readconf.h b/readconf.h
index 50261ee..5de3e62 100644
--- a/readconf.h
+++ b/readconf.h
@@ -144,6 +144,7 @@ typedef struct {
 
 	int	request_tty;
 	int	no_shell;
+	int	stdin_null;
 
 	int	proxy_use_fdpass;
 
diff --git a/ssh.1 b/ssh.1
index ac06025..c8d8489 100644
--- a/ssh.1
+++ b/ssh.1
@@ -451,6 +451,11 @@ program will be put in the background.
 needs to ask for a password or passphrase; see also the
 .Fl f
 option.)
+Refer to the description of
+.Cm StdinNull
+in
+.Xr ssh_config 5
+for details.
 .Pp
 .It Fl O Ar ctl_cmd
 Control an active connection multiplexing master process.
diff --git a/ssh.c b/ssh.c
index ae8144e..dd5195e 100644
--- a/ssh.c
+++ b/ssh.c
@@ -126,12 +126,6 @@ int debug_flag = 0;
 /* Flag indicating whether a tty should be requested */
 int tty_flag = 0;
 
-/*
- * Flag indicating that nothing should be read from stdin.  This can be set
- * on the command line.
- */
-int stdin_null_flag = 0;
-
 /*
  * Flag indicating that the current process should be backgrounded and
  * a new mux-client launched in the foreground for ControlPersist.
@@ -734,11 +728,11 @@ main(int ac, char **av)
 			options.address_family = AF_INET6;
 			break;
 		case 'n':
-			stdin_null_flag = 1;
+			options.stdin_null = 1;
 			break;
 		case 'f':
 			fork_after_authentication_flag = 1;
-			stdin_null_flag = 1;
+			options.stdin_null = 1;
 			break;
 		case 'x':
 			options.forward_x11 = 0;
@@ -1366,7 +1360,7 @@ main(int ac, char **av)
 	    (muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
 		tty_flag = 0;
 	/* Do not allocate a tty if stdin is not a tty. */
-	if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+	if ((!isatty(fileno(stdin)) || options.stdin_null) &&
 	    options.request_tty != REQUEST_TTY_FORCE) {
 		if (tty_flag)
 			logit("Pseudo-terminal will not be allocated because "
@@ -1712,7 +1706,7 @@ control_persist_detach(void)
 	default:
 		/* Parent: set up mux client to connect to backgrounded master */
 		debug2("%s: background process is %ld", __func__, (long)pid);
-		stdin_null_flag = ostdin_null_flag;
+		options.stdin_null = ostdin_null_flag;
 		options.request_tty = orequest_tty;
 		tty_flag = otty_flag;
 		close(muxserver_sock);
@@ -2029,7 +2023,7 @@ ssh_session2_open(struct ssh *ssh)
 	Channel *c;
 	int window, packetmax, in, out, err;
 
-	if (stdin_null_flag) {
+	if (options.stdin_null) {
 		in = open(_PATH_DEVNULL, O_RDONLY);
 	} else {
 		in = dup(STDIN_FILENO);
@@ -2110,11 +2104,11 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 	 * async rfwd replies have been received for ExitOnForwardFailure).
 	 */
 	if (options.control_persist && muxserver_sock != -1) {
-		ostdin_null_flag = stdin_null_flag;
+		ostdin_null_flag = options.stdin_null;
 		ono_shell_flag = options.no_shell;
 		orequest_tty = options.request_tty;
 		otty_flag = tty_flag;
-		stdin_null_flag = 1;
+		options.stdin_null = 1;
 		options.no_shell = 1;
 		tty_flag = 0;
 		if (!fork_after_authentication_flag)
diff --git a/ssh_config.5 b/ssh_config.5
index 5a9ee10..345626d 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1584,6 +1584,33 @@ be sent to the server.
 Similarly to
 .Cm SendEnv ,
 the server must be prepared to accept the environment variable.
+.It Cm StdinNull
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+This must be used when
+.Nm ssh
+is run in the background.
+A common trick is to use this to run X11 programs on a remote machine.
+For example,
+.Ic ssh shadows.cs.hut.fi emacs &
+will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.Nm ssh
+program will be put in the background.
+(This does not work if
+.Nm ssh
+needs to ask for a password or passphrase; see also the
+.Fl f
+option.)
+The argument to this keyword must be
+.Cm yes
+(same as the
+.Fl n
+option) or
+.Cm no
+(the default).
 .It Cm StreamLocalBindMask
 Sets the octal file creation mode mask
 .Pq umask
commit 626845489dd712ee25cec79d255aaf61c1cc629e
Author: Volker Diels-Grabsch <v@xxxxxx>
Date:   Sun Feb 21 03:18:49 2021 +0100

    Remove dead variable ono_shell_flag which is set once but never used

diff --git a/ssh.c b/ssh.c
index dd5195e..8533763 100644
--- a/ssh.c
+++ b/ssh.c
@@ -133,7 +133,7 @@ int tty_flag = 0;
 int need_controlpersist_detach = 0;
 
 /* Copies of flags for ControlPersist foreground mux-client */
-int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
+int ostdin_null_flag, otty_flag, orequest_tty;
 
 /*
  * Flag indicating that ssh should fork after authentication.  This is useful
@@ -2105,7 +2105,6 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 	 */
 	if (options.control_persist && muxserver_sock != -1) {
 		ostdin_null_flag = options.stdin_null;
-		ono_shell_flag = options.no_shell;
 		orequest_tty = options.request_tty;
 		otty_flag = tty_flag;
 		options.stdin_null = 1;
commit 869c8b5108dc413afffd7f8520c1075137cc015c
Author: Volker Diels-Grabsch <v@xxxxxx>
Date:   Sun Feb 21 03:11:37 2021 +0100

    Add ssh_config option ForkAfterAuthentication with same behavior as -f

diff --git a/clientloop.c b/clientloop.c
index 690b776..34ba047 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -115,9 +115,6 @@
 /* import options */
 extern Options options;
 
-/* Flag indicating that ssh should daemonise after authentication is complete */
-extern int fork_after_authentication_flag;
-
 /* Control socket */
 extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
 
@@ -1255,7 +1252,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
 			fatal("%s pledge(): %s", __func__, strerror(errno));
 
 	} else if (!option_clear_or_none(options.proxy_command) ||
-	    fork_after_authentication_flag) {
+	    options.fork_after_authentication) {
 		debug("pledge: proc");
 		if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
 			fatal("%s pledge(): %s", __func__, strerror(errno));
diff --git a/readconf.c b/readconf.c
index 88e6408..c00c3bb 100644
--- a/readconf.c
+++ b/readconf.c
@@ -167,7 +167,7 @@ typedef enum {
 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
 	oVisualHostKey,
 	oKexAlgorithms, oIPQoS, oRequestTTY, oNoShell, oStdinNull,
-	oIgnoreUnknown, oProxyUseFdpass,
+	oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
@@ -297,6 +297,7 @@ static struct {
 	{ "requesttty", oRequestTTY },
 	{ "noshell", oNoShell },
 	{ "stdinnull", oStdinNull },
+	{ "forkafterauthentication", oForkAfterAuthentication },
 	{ "proxyusefdpass", oProxyUseFdpass },
 	{ "canonicaldomains", oCanonicalDomains },
 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
@@ -1705,6 +1706,10 @@ parse_keytypes:
 		intptr = &options->stdin_null;
 		goto parse_flag;
 
+	case oForkAfterAuthentication:
+		intptr = &options->fork_after_authentication;
+		goto parse_flag;
+
 	case oIgnoreUnknown:
 		charptr = &options->ignored_unknown;
 		goto parse_string;
@@ -2063,6 +2068,7 @@ initialize_options(Options * options)
 	options->request_tty = -1;
 	options->no_shell = -1;
 	options->stdin_null = -1;
+	options->fork_after_authentication = -1;
 	options->proxy_use_fdpass = -1;
 	options->ignored_unknown = NULL;
 	options->num_canonical_domains = 0;
@@ -2247,6 +2253,8 @@ fill_default_options(Options * options)
 		options->no_shell = 0;
 	if (options->stdin_null == -1)
 		options->stdin_null = 0;
+	if (options->fork_after_authentication == -1)
+		options->fork_after_authentication = 0;
 	if (options->proxy_use_fdpass == -1)
 		options->proxy_use_fdpass = 0;
 	if (options->canonicalize_max_dots == -1)
@@ -2807,6 +2815,7 @@ dump_client_config(Options *o, const char *host)
 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
 	dump_cfg_fmtint(oNoShell, o->no_shell);
 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
+	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
diff --git a/readconf.h b/readconf.h
index 5de3e62..dd76aa5 100644
--- a/readconf.h
+++ b/readconf.h
@@ -145,6 +145,7 @@ typedef struct {
 	int	request_tty;
 	int	no_shell;
 	int	stdin_null;
+	int	fork_after_authentication;
 
 	int	proxy_use_fdpass;
 
diff --git a/ssh.1 b/ssh.1
index c8d8489..3f9cd05 100644
--- a/ssh.1
+++ b/ssh.1
@@ -259,6 +259,11 @@ then a client started with
 .Fl f
 will wait for all remote port forwards to be successfully established
 before placing itself in the background.
+Refer to the description of
+.Cm ForkAfterAuthentication
+in
+.Xr ssh_config 5
+for details.
 .Pp
 .It Fl G
 Causes
diff --git a/ssh.c b/ssh.c
index 8533763..5e2bfe3 100644
--- a/ssh.c
+++ b/ssh.c
@@ -135,13 +135,6 @@ int need_controlpersist_detach = 0;
 /* Copies of flags for ControlPersist foreground mux-client */
 int ostdin_null_flag, otty_flag, orequest_tty;
 
-/*
- * Flag indicating that ssh should fork after authentication.  This is useful
- * so that the passphrase can be entered manually, and then ssh goes to the
- * background.
- */
-int fork_after_authentication_flag = 0;
-
 /*
  * General data structure for command line options and options configurable
  * in configuration files.  See readconf.h.
@@ -731,7 +724,7 @@ main(int ac, char **av)
 			options.stdin_null = 1;
 			break;
 		case 'f':
-			fork_after_authentication_flag = 1;
+			options.fork_after_authentication = 1;
 			options.stdin_null = 1;
 			break;
 		case 'x':
@@ -1339,7 +1332,7 @@ main(int ac, char **av)
 		fatal("Cannot execute command-line and remote command.");
 
 	/* Cannot fork to background if no command. */
-	if (fork_after_authentication_flag && sshbuf_len(command) == 0 &&
+	if (options.fork_after_authentication && sshbuf_len(command) == 0 &&
 	    options.remote_command == NULL && !options.no_shell)
 		fatal("Cannot fork into background without a command "
 		    "to execute.");
@@ -1741,7 +1734,7 @@ fork_postauth(void)
 	if (need_controlpersist_detach)
 		control_persist_detach();
 	debug("forking to background");
-	fork_after_authentication_flag = 0;
+	options.fork_after_authentication = 0;
 	if (daemon(1, 1) == -1)
 		fatal("daemon() failed: %.200s", strerror(errno));
 	if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
@@ -1765,7 +1758,7 @@ forwarding_success(void)
 		return;
 	if (--forward_confirms_pending == 0) {
 		debug("%s: all expected forwarding replies received", __func__);
-		if (fork_after_authentication_flag)
+		if (options.fork_after_authentication)
 			fork_postauth();
 	} else {
 		debug2("%s: %d expected forwarding replies remaining",
@@ -2110,9 +2103,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 		options.stdin_null = 1;
 		options.no_shell = 1;
 		tty_flag = 0;
-		if (!fork_after_authentication_flag)
+		if (!options.fork_after_authentication)
 			need_controlpersist_detach = 1;
-		fork_after_authentication_flag = 1;
+		options.fork_after_authentication = 1;
 	}
 	/*
 	 * ControlPersist mux listen socket setup failed, attempt the
@@ -2168,7 +2161,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
 	 * If requested and we are not interested in replies to remote
 	 * forwarding requests, then let ssh continue in the background.
 	 */
-	if (fork_after_authentication_flag) {
+	if (options.fork_after_authentication) {
 		if (options.exit_on_forward_failure &&
 		    options.num_remote_forwards > 0) {
 			debug("deferring postauth fork until remote forward "
diff --git a/ssh_config.5 b/ssh_config.5
index 345626d..34bb56a 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -682,6 +682,45 @@ Valid options are:
 and
 .Cm sha256
 (the default).
+.It Cm ForkAfterAuthentication
+Requests
+.Nm ssh
+to go to background just before command execution.
+This is useful if
+.Nm ssh
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies the
+.Cm StdinNull
+configuration option being set to
+.Dq yes .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm ,
+which is the same as
+.Ic ssh host xterm
+if the
+.Cm ForkAfterAuthentication
+configuration option is set to
+.Dq yes .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with the
+.Cm ForkAfterAuthentication
+configuration option being set to
+.Dq yes
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+The argument to this keyword must be
+.Cm yes
+(same as the
+.Fl f
+option) or
+.Cm no
+(the default).
 .It Cm ForwardAgent
 Specifies whether the connection to the authentication agent (if any)
 will be forwarded to the remote machine.
@@ -1602,8 +1641,8 @@ program will be put in the background.
 (This does not work if
 .Nm ssh
 needs to ask for a password or passphrase; see also the
-.Fl f
-option.)
+.Cm ForkAfterAuthentication
+configuration option.)
 The argument to this keyword must be
 .Cm yes
 (same as the
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux