Dear OpenSSH developers, I hope you don't mind that I resubmit my patch for OpenSSH. This patch adds a new ssh_config option "ExecRemoteCommand", which is the missing equivalent to the "-N" command line option. For implementation notes, please have a look at the top of the patch. Regards, Volker -- Volker Diels-Grabsch ----<<<((()))>>>----
Author: Volker Diels-Grabsch <v@xxxxxx> Add ssh_config option ExecRemoteCommand which is equivalent to -N The man page of ssh_config is adjusted accordingly. A new flag "option.exec_remote_command" is introduced which replaces the former CLI-only "no_shell_flag", but has the inverse meaning. The "ono_shell_flag" is renamed to "oexec_remote_command" and mirrors "option.exec_remote_command" instead of "no_shell_flag". A potential pitfall is fixed: Until now, the code had to ensure that whenever "no_shell_flag" is set, the "option.request_tty" must be set to "no". Now, this is no longer required. Instead, it is ensured at one central place that the "tty_flag" is always calculated correctly from "option.request_tty" and "option.exec_remote_command". In "clientloop.c" some dead code regarding "no_shell_flag" is removed. diff --git a/clientloop.c b/clientloop.c index 2c44f5d..732638f 100644 --- a/clientloop.c +++ b/clientloop.c @@ -120,9 +120,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; @@ -1739,7 +1736,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) * 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.exec_remote_command && received_signal == SIGTERM) { received_signal = 0; exit_status = 0; } @@ -2712,7 +2709,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.exec_remote_command) { session_closed = 1; setproctitle("[stopped mux]"); } diff --git a/readconf.c b/readconf.c index c177202..7e7e200 100644 --- a/readconf.c +++ b/readconf.c @@ -166,6 +166,7 @@ typedef enum { oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, + oExecRemoteCommand, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, @@ -282,6 +283,7 @@ static struct { { "ipqos", oIPQoS }, { "requesttty", oRequestTTY }, { "proxyusefdpass", oProxyUseFdpass }, + { "execremotecommand", oExecRemoteCommand }, { "canonicaldomains", oCanonicalDomains }, { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, { "canonicalizehostname", oCanonicalizeHostname }, @@ -1547,6 +1549,10 @@ parse_keytypes: intptr = &options->proxy_use_fdpass; goto parse_flag; + case oExecRemoteCommand: + intptr = &options->exec_remote_command; + goto parse_flag; + case oCanonicalDomains: value = options->num_canonical_domains != 0; while ((arg = strdelim(&s)) != NULL && *arg != '\0') { @@ -1847,6 +1853,7 @@ initialize_options(Options * options) options->ip_qos_bulk = -1; options->request_tty = -1; options->proxy_use_fdpass = -1; + options->exec_remote_command = -1; options->ignored_unknown = NULL; options->num_canonical_domains = 0; options->num_permitted_cnames = 0; @@ -2035,6 +2042,8 @@ fill_default_options(Options * options) options->request_tty = REQUEST_TTY_AUTO; if (options->proxy_use_fdpass == -1) options->proxy_use_fdpass = 0; + if (options->exec_remote_command == -1) + options->exec_remote_command = 1; if (options->canonicalize_max_dots == -1) options->canonicalize_max_dots = 1; if (options->canonicalize_fallback_local == -1) @@ -2521,6 +2530,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); dump_cfg_fmtint(oProtocol, o->protocol); dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); + dump_cfg_fmtint(oExecRemoteCommand, o->exec_remote_command); dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); dump_cfg_fmtint(oRequestTTY, o->request_tty); dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication); diff --git a/readconf.h b/readconf.h index cef55f7..7d2b6a8 100644 --- a/readconf.h +++ b/readconf.h @@ -146,6 +146,8 @@ typedef struct { int proxy_use_fdpass; + int exec_remote_command; + int num_canonical_domains; char *canonical_domains[MAX_CANON_DOMAINS]; int canonicalize_hostname; diff --git a/ssh.c b/ssh.c index 03a23fb..fdb1335 100644 --- a/ssh.c +++ b/ssh.c @@ -127,9 +127,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. @@ -143,7 +140,7 @@ int stdin_null_flag = 0; int need_controlpersist_detach = 0; /* Copies of flags for ControlPersist foreground slave */ -int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty; +int ostdin_null_flag, oexec_remote_command, otty_flag, orequest_tty; /* * Flag indicating that ssh should fork after authentication. This is useful @@ -797,8 +794,7 @@ main(int ac, char **av) optarg); exit(255); } - options.request_tty = REQUEST_TTY_NO; - no_shell_flag = 1; + options.exec_remote_command = 0; break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; @@ -905,8 +901,7 @@ main(int ac, char **av) options.compression = 1; break; case 'N': - no_shell_flag = 1; - options.request_tty = REQUEST_TTY_NO; + options.exec_remote_command = 0; break; case 'T': options.request_tty = REQUEST_TTY_NO; @@ -995,7 +990,7 @@ main(int ac, char **av) /* Cannot fork to background if no command. */ if (fork_after_authentication_flag && buffer_len(&command) == 0 && - !no_shell_flag) + options.exec_remote_command) fatal("Cannot fork into background without a command " "to execute."); @@ -1164,6 +1159,8 @@ main(int ac, char **av) /* Force no tty */ if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0) tty_flag = 0; + if (!options.exec_remote_command) + tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if ((!isatty(fileno(stdin)) || stdin_null_flag) && options.request_tty != REQUEST_TTY_FORCE) { @@ -1935,7 +1932,7 @@ ssh_session2_open(void) debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); - if (!no_shell_flag) + if (options.exec_remote_command) channel_register_open_confirm(c->self, ssh_session2_setup, NULL); @@ -1966,11 +1963,11 @@ ssh_session2(void) */ if (options.control_persist && muxserver_sock != -1) { ostdin_null_flag = stdin_null_flag; - ono_shell_flag = no_shell_flag; + oexec_remote_command = options.exec_remote_command; orequest_tty = options.request_tty; otty_flag = tty_flag; stdin_null_flag = 1; - no_shell_flag = 1; + options.exec_remote_command = 0; tty_flag = 0; if (!fork_after_authentication_flag) need_controlpersist_detach = 1; @@ -1983,7 +1980,7 @@ ssh_session2(void) if (options.control_persist && muxserver_sock == -1) ssh_init_stdio_forwarding(); - if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) + if (options.exec_remote_command || (datafellows & SSH_BUG_DUMMYCHAN)) id = ssh_session2_open(); else { packet_set_interactive( diff --git a/ssh_config.5 b/ssh_config.5 index 7630e7b..4962dce 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -706,6 +706,13 @@ followed by a letter, or to disable the escape character entirely (making the connection transparent for binary data). +.It Cm ExecRemoteCommand +Specifies whether to execute a remote command. +This option can be set to +.Dq no +for just forwarding ports. +The default is +.Dq yes . .It Cm ExitOnForwardFailure Specifies whether .Xr ssh 1
_______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev