diff --git a/ssh.c b/ssh.c index 176085647..98b6ce788 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.526 2020/04/03 06:07:57 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -176,13 +176,6 @@ char *forward_agent_sock_path = NULL; /* Various strings used to to percent_expand() arguments */ static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; static char uidstr[32], *host_arg, *conn_hash_hex; -#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \ - "C", conn_hash_hex, \ - "L", shorthost, \ - "i", uidstr, \ - "l", thishost, \ - "n", host_arg, \ - "p", portstr /* socket address the host resolves to */ struct sockaddr_storage hostaddr; @@ -238,6 +231,34 @@ tilde_expand_paths(char **paths, u_int num_paths) } } +#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \ + "C", conn_hash_hex, \ + "L", shorthost, \ + "i", uidstr, \ + "l", thishost, \ + "n", host_arg, \ + "p", portstr + +/* + * Expands the set of percent_expand options used by the majority of keywords + * in the client that support percent expansion. + * Caller must free returned string. + */ +static char * +default_client_percent_expand(const char *str, const char *homedir, + const char *remhost, const char *remuser, const char *locuser) +{ + return percent_expand(str, + /* values from statics above */ + DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, + /* values from arguments */ + "d", homedir, + "h", remhost, + "r", remuser, + "u", locuser, + (char *)NULL); +} + /* * Attempt to resolve a host name / port to a set of addresses and * optionally return any CNAMEs encountered along the way. @@ -1345,13 +1366,8 @@ main(int ac, char **av) if (options.remote_command != NULL) { debug3("expanding RemoteCommand: %s", options.remote_command); cp = options.remote_command; - options.remote_command = percent_expand(cp, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + options.remote_command = default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); debug3("expanded RemoteCommand: %s", options.remote_command); free(cp); if ((r = sshbuf_put(command, options.remote_command, @@ -1362,25 +1378,15 @@ main(int ac, char **av) if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, getuid()); free(options.control_path); - options.control_path = percent_expand(cp, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + options.control_path = default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); free(cp); } if (options.identity_agent != NULL) { p = tilde_expand_filename(options.identity_agent, getuid()); - cp = percent_expand(p, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + cp = default_client_percent_expand(p, + pw->pw_dir, host, options.user, pw->pw_name); free(p); free(options.identity_agent); options.identity_agent = cp; @@ -1389,18 +1395,59 @@ main(int ac, char **av) if (options.forward_agent_sock_path != NULL) { p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); - cp = percent_expand(p, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + cp = default_client_percent_expand(p, + pw->pw_dir, host, options.user, pw->pw_name); free(p); free(options.forward_agent_sock_path); options.forward_agent_sock_path = cp; } + for (i = 0; i < options.num_local_forwards; i++) { + if (options.local_forwards[i].listen_path != NULL) { + cp = options.local_forwards[i].listen_path; + p = options.local_forwards[i].listen_path = + default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); + if (strcmp(cp, p) != 0) + debug3("expanded LocalForward listen path " + "'%s' -> '%s'", cp, p); + free(cp); + } + if (options.local_forwards[i].connect_path != NULL) { + cp = options.local_forwards[i].connect_path; + p = options.local_forwards[i].connect_path = + default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); + if (strcmp(cp, p) != 0) + debug3("expanded LocalForward connect path " + "'%s' -> '%s'", cp, p); + free(cp); + } + } + + for (i = 0; i < options.num_remote_forwards; i++) { + if (options.remote_forwards[i].listen_path != NULL) { + cp = options.remote_forwards[i].listen_path; + p = options.remote_forwards[i].listen_path = + default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); + if (strcmp(cp, p) != 0) + debug3("expanded RemoteForward listen path " + "'%s' -> '%s'", cp, p); + free(cp); + } + if (options.remote_forwards[i].connect_path != NULL) { + cp = options.remote_forwards[i].connect_path; + p = options.remote_forwards[i].connect_path = + default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); + if (strcmp(cp, p) != 0) + debug3("expanded RemoteForward connect path " + "'%s' -> '%s'", cp, p); + free(cp); + } + } + if (config_test) { dump_client_config(&options, host); exit(0); @@ -2154,13 +2201,8 @@ load_public_identity_files(struct passwd *pw) continue; } cp = tilde_expand_filename(options.identity_files[i], getuid()); - filename = percent_expand(cp, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + filename = default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); free(cp); check_load(sshkey_load_public(filename, &public, NULL), filename, "pubkey"); @@ -2209,13 +2251,8 @@ load_public_identity_files(struct passwd *pw) for (i = 0; i < options.num_certificate_files; i++) { cp = tilde_expand_filename(options.certificate_files[i], getuid()); - filename = percent_expand(cp, - DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, - "d", pw->pw_dir, - "h", host, - "r", options.user, - "u", pw->pw_name, - (char *)NULL); + filename = default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); free(cp); check_load(sshkey_load_public(filename, &public, NULL), diff --git a/ssh_config.5 b/ssh_config.5 index 9d89c13aa..7bbc76aa3 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,8 +33,8 @@ .\" (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.323 2020/04/03 02:27:12 dtucker Exp $ -.Dd $Mdocdate: April 3 2020 $ +.\" $OpenBSD: ssh_config.5,v 1.324 2020/04/10 00:52:07 dtucker Exp $ +.Dd $Mdocdate: April 10 2020 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -1125,12 +1125,15 @@ has been enabled. .It Cm LocalForward Specifies that a TCP port on the local machine be forwarded over the secure channel to the specified host and port from the remote machine. -The first argument must be +The first argument specifies the listener and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on -and the second argument must be -.Ar host : Ns Ar hostport . +or a Unix domain socket path. +The second argument is the destination and may be +.Ar host : Ns Ar hostport +or a Unix domain socket path if the remote host supports it. +.Pp IPv6 addresses can be specified by enclosing addresses in square brackets. Multiple forwardings may be specified, and additional forwardings can be given on the command line. @@ -1149,6 +1152,9 @@ indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. +Unix domain socket paths accept the tokens described in the +.Sx TOKENS +section. .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Xr ssh 1 . @@ -1401,12 +1407,14 @@ the secure channel. The remote port may either be forwarded to a specified host and port from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote client to connect to arbitrary destinations from the local machine. -The first argument must be +The first argument is the listening specification and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on +or, if the remote host supports it, a Unix domain socket path. If forwarding to a specific destination then the second argument must be -.Ar host : Ns Ar hostport , +.Ar host : Ns Ar hostport +or a Unix domain socket path, otherwise if no destination argument is specified then the remote forwarding will be established as a SOCKS proxy. .Pp @@ -1415,6 +1423,9 @@ Multiple forwardings may be specified, and additional forwardings can be given on the command line. Privileged ports can be forwarded only when logging in as root on the remote machine. +Unix domain socket paths accept the tokens described in the +.Sx TOKENS +section. .Pp If the .Ar port @@ -1845,13 +1856,15 @@ otherwise. The local username. .El .Pp -.Cm Match exec , .Cm CertificateFile , .Cm ControlPath , .Cm IdentityAgent , .Cm IdentityFile , +.Cm LocalForward, +.Cm Match exec , +.Cm RemoteCommand , and -.Cm RemoteCommand +.Cm RemoteForward accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u. .Pp .Cm Hostname