From fef69e615d5b2c81c85977fbdb4fa11c47ef45b5 Mon Sep 17 00:00:00 2001 From: djm Date: Fri, 23 Jul 2021 04:04:52 +0000 Subject: [PATCH] Add a ForkAfterAuthentication ssh_config(5) counterpart to the ssh(1) -f flag. Last part of GHPR231 from Volker Diels-Grabsch. ok dtucker --- usr.bin/ssh/clientloop.c | 7 ++----- usr.bin/ssh/readconf.c | 13 +++++++++++-- usr.bin/ssh/readconf.h | 3 ++- usr.bin/ssh/ssh.1 | 8 +++++++- usr.bin/ssh/ssh.c | 23 ++++++++-------------- usr.bin/ssh/ssh_config.5 | 41 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index 1e1fb8e3273..70d5df18516 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.368 2021/07/23 04:00:59 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.369 2021/07/23 04:04:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -108,9 +108,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 */ @@ -1232,7 +1229,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, fatal_f("pledge(): %s", 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_f("pledge(): %s", strerror(errno)); diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c index 316ed5ab3a9..4062b3006f9 100644 --- a/usr.bin/ssh/readconf.c +++ b/usr.bin/ssh/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.360 2021/07/23 04:00:59 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.361 2021/07/23 04:04:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -154,7 +154,7 @@ typedef enum { oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, - oIgnoreUnknown, oProxyUseFdpass, + oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, @@ -286,6 +286,7 @@ static struct { { "requesttty", oRequestTTY }, { "sessiontype", oSessionType }, { "stdinnull", oStdinNull }, + { "forkafterauthentication", oForkAfterAuthentication }, { "proxyusefdpass", oProxyUseFdpass }, { "canonicaldomains", oCanonicalDomains }, { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, @@ -1945,6 +1946,10 @@ parse_pubkey_algos: 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; @@ -2369,6 +2374,7 @@ initialize_options(Options * options) options->request_tty = -1; options->session_type = -1; options->stdin_null = -1; + options->fork_after_authentication = -1; options->proxy_use_fdpass = -1; options->ignored_unknown = NULL; options->num_canonical_domains = 0; @@ -2557,6 +2563,8 @@ fill_default_options(Options * options) options->session_type = SESSION_TYPE_DEFAULT; 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) @@ -3231,6 +3239,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oRequestTTY, o->request_tty); dump_cfg_fmtint(oSessionType, o->session_type); 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/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h index 08ca9e7a7d6..f7d53b06760 100644 --- a/usr.bin/ssh/readconf.h +++ b/usr.bin/ssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.143 2021/07/23 04:00:59 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.144 2021/07/23 04:04:52 djm Exp $ */ /* * Author: Tatu Ylonen @@ -148,6 +148,7 @@ typedef struct { int request_tty; int session_type; int stdin_null; + int fork_after_authentication; int proxy_use_fdpass; diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1 index b31175ffeb3..46ad55ad498 100644 --- a/usr.bin/ssh/ssh.1 +++ b/usr.bin/ssh/ssh.1 @@ -33,7 +33,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.423 2021/07/23 04:00:59 djm Exp $ +.\" $OpenBSD: ssh.1,v 1.424 2021/07/23 04:04:52 djm Exp $ .Dd $Mdocdate: July 23 2021 $ .Dt SSH 1 .Os @@ -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 @@ -508,6 +513,7 @@ For full details of the options listed below, and their possible values, see .It EscapeChar .It ExitOnForwardFailure .It FingerprintHash +.It ForkAfterAuthentication .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index 0b86ab881f4..5b577b6fef5 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.563 2021/07/23 04:00:59 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.564 2021/07/23 04:04:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -119,13 +119,6 @@ int need_controlpersist_detach = 0; /* Copies of flags for ControlPersist foreground mux-client */ int ostdin_null_flag, osession_type, 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. @@ -694,7 +687,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': @@ -1303,7 +1296,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.session_type != SESSION_TYPE_NONE) fatal("Cannot fork into background without a command " @@ -1731,7 +1724,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 (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) @@ -1745,7 +1738,7 @@ forwarding_success(void) return; if (--forward_confirms_pending == 0) { debug_f("all expected forwarding replies received"); - if (fork_after_authentication_flag) + if (options.fork_after_authentication) fork_postauth(); } else { debug2_f("%d expected forwarding replies remaining", @@ -2124,11 +2117,11 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) options.stdin_null = 1; options.session_type = SESSION_TYPE_NONE; tty_flag = 0; - if (!fork_after_authentication_flag && + if (!options.fork_after_authentication && (osession_type != SESSION_TYPE_NONE || options.stdio_forward_host != NULL)) need_controlpersist_detach = 1; - fork_after_authentication_flag = 1; + options.fork_after_authentication = 1; } /* * ControlPersist mux listen socket setup failed, attempt the @@ -2175,7 +2168,7 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) * 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/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5 index 3464bb0c6f2..2bb93d097e2 100644 --- a/usr.bin/ssh/ssh_config.5 +++ b/usr.bin/ssh/ssh_config.5 @@ -33,7 +33,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.358 2021/07/23 04:00:59 djm Exp $ +.\" $OpenBSD: ssh_config.5,v 1.359 2021/07/23 04:04:52 djm Exp $ .Dd $Mdocdate: July 23 2021 $ .Dt SSH_CONFIG 5 .Os @@ -676,6 +676,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. -- 2.20.1