Volker Diels-Grabsch
2021-Feb-21 03:11 UTC
[PATCH] Add ssh_config equivalents of -N, -n and -f
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 ----<<<((()))>>>---- -------------- next part -------------- A non-text attachment was scrubbed... Name: 1_add_option_NoShell_for_flag_N.patch Type: text/x-diff Size: 6934 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210221/b030f572/attachment.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: 2_add_option_StdinNull_for_flag_n.patch Type: text/x-diff Size: 7587 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210221/b030f572/attachment-0001.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: 3_remove_dead_variable_ono_shell_flag.patch Type: text/x-diff Size: 926 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210221/b030f572/attachment-0002.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: 4_add_option_ForkAfterAuthentication_for_flag_f.patch Type: text/x-diff Size: 8313 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210221/b030f572/attachment-0003.bin>
Volker Diels-Grabsch
2021-Feb-26 00:46 UTC
[PATCH] Add ssh_config equivalents of -N, -n and -f
Dear OpenSSH developers, For your convenience, I also created a pull request: * https://github.com/openssh/openssh-portable/pull/231 Best regards, Volker Volker Diels-Grabsch wrote:> 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 at njh.eu> > 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 at njh.eu> > 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 at njh.eu> > 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 at njh.eu> > 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-- Volker Diels-Grabsch ----<<<((()))>>>----