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