upstream commit

Expose devices allocated for tun/tap forwarding.

At the client, the device may be obtained from a new %T expansion
for LocalCommand.

At the server, the allocated devices will be listed in a
SSH_TUNNEL variable exposed to the environment of any user sessions
started after the tunnel forwarding was established.

ok markus

Upstream-ID: e61e53f8ae80566e9ddc0d67a5df5bdf2f3c9f9e
This commit is contained in:
djm@openbsd.org 2017-10-23 05:08:00 +00:00 committed by Damien Miller
parent 887669ef03
commit b7548b12a6
11 changed files with 133 additions and 77 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.305 2017/09/19 04:24:22 djm Exp $ */ /* $OpenBSD: clientloop.c,v 1.306 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -1601,12 +1601,13 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
return c; return c;
} }
int char *
client_request_tun_fwd(struct ssh *ssh, int tun_mode, client_request_tun_fwd(struct ssh *ssh, int tun_mode,
int local_tun, int remote_tun) int local_tun, int remote_tun)
{ {
Channel *c; Channel *c;
int fd; int fd;
char *ifname = NULL;
if (tun_mode == SSH_TUNMODE_NO) if (tun_mode == SSH_TUNMODE_NO)
return 0; return 0;
@ -1614,10 +1615,11 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode,
debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
/* Open local tunnel device */ /* Open local tunnel device */
if ((fd = tun_open(local_tun, tun_mode)) == -1) { if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) {
error("Tunnel device open failed."); error("Tunnel device open failed.");
return -1; return NULL;
} }
debug("Tunnel forwarding using interface %s", ifname);
c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
@ -1638,7 +1640,7 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode,
packet_put_int(remote_tun); packet_put_int(remote_tun);
packet_send(); packet_send();
return 0; return ifname;
} }
/* XXXX move to generic input handler */ /* XXXX move to generic input handler */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.34 2017/09/12 06:32:07 djm Exp $ */ /* $OpenBSD: clientloop.h,v 1.35 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -46,7 +46,7 @@ int client_x11_get_proto(struct ssh *, const char *, const char *,
void client_global_request_reply_fwd(int, u_int32_t, void *); void client_global_request_reply_fwd(int, u_int32_t, void *);
void client_session2_setup(struct ssh *, int, int, int, void client_session2_setup(struct ssh *, int, int, int,
const char *, struct termios *, int, Buffer *, char **); const char *, struct termios *, int, Buffer *, char **);
int client_request_tun_fwd(struct ssh *, int, int, int); char *client_request_tun_fwd(struct ssh *, int, int, int);
void client_stop_mux(void); void client_stop_mux(void);
/* Escape filter for protocol 2 sessions */ /* Escape filter for protocol 2 sessions */

12
misc.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.114 2017/10/21 23:06:24 millert Exp $ */ /* $OpenBSD: misc.c,v 1.115 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -964,16 +964,19 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
} }
int int
tun_open(int tun, int mode) tun_open(int tun, int mode, char **ifname)
{ {
#if defined(CUSTOM_SYS_TUN_OPEN) #if defined(CUSTOM_SYS_TUN_OPEN)
return (sys_tun_open(tun, mode)); return (sys_tun_open(tun, mode, ifname));
#elif defined(SSH_TUN_OPENBSD) #elif defined(SSH_TUN_OPENBSD)
struct ifreq ifr; struct ifreq ifr;
char name[100]; char name[100];
int fd = -1, sock; int fd = -1, sock;
const char *tunbase = "tun"; const char *tunbase = "tun";
if (ifname != NULL)
*ifname = NULL;
if (mode == SSH_TUNMODE_ETHERNET) if (mode == SSH_TUNMODE_ETHERNET)
tunbase = "tap"; tunbase = "tap";
@ -1020,6 +1023,9 @@ tun_open(int tun, int mode)
} }
} }
if (ifname != NULL)
*ifname = xstrdup(ifr.ifr_name);
close(sock); close(sock);
return fd; return fd;

4
misc.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.64 2017/10/21 23:06:24 millert Exp $ */ /* $OpenBSD: misc.h,v 1.65 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -87,7 +87,7 @@ void replacearg(arglist *, u_int, char *, ...)
__attribute__((format(printf, 3, 4))); __attribute__((format(printf, 3, 4)));
void freeargs(arglist *); void freeargs(arglist *);
int tun_open(int, int); int tun_open(int, int, char **);
/* Common definitions for ssh tunnel device forwarding */ /* Common definitions for ssh tunnel device forwarding */
#define SSH_TUNMODE_NO 0x00 #define SSH_TUNMODE_NO 0x00

View File

@ -56,12 +56,15 @@
#include <linux/if_tun.h> #include <linux/if_tun.h>
int int
sys_tun_open(int tun, int mode) sys_tun_open(int tun, int mode, char **ifname)
{ {
struct ifreq ifr; struct ifreq ifr;
int fd = -1; int fd = -1;
const char *name = NULL; const char *name = NULL;
if (ifname != NULL)
*ifname = NULL;
if ((fd = open("/dev/net/tun", O_RDWR)) == -1) { if ((fd = open("/dev/net/tun", O_RDWR)) == -1) {
debug("%s: failed to open tunnel control interface: %s", debug("%s: failed to open tunnel control interface: %s",
__func__, strerror(errno)); __func__, strerror(errno));
@ -99,6 +102,9 @@ sys_tun_open(int tun, int mode)
else else
debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd); debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd);
if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)))
goto failed;
return (fd); return (fd);
failed: failed:
@ -116,13 +122,16 @@ sys_tun_open(int tun, int mode)
#endif #endif
int int
sys_tun_open(int tun, int mode) sys_tun_open(int tun, int mode, char **ifname)
{ {
struct ifreq ifr; struct ifreq ifr;
char name[100]; char name[100];
int fd = -1, sock, flag; int fd = -1, sock, flag;
const char *tunbase = "tun"; const char *tunbase = "tun";
if (ifname != NULL)
*ifname = NULL;
if (mode == SSH_TUNMODE_ETHERNET) { if (mode == SSH_TUNMODE_ETHERNET) {
#ifdef SSH_TUN_NO_L2 #ifdef SSH_TUN_NO_L2
debug("%s: no layer 2 tunnelling support", __func__); debug("%s: no layer 2 tunnelling support", __func__);
@ -180,6 +189,9 @@ sys_tun_open(int tun, int mode)
goto failed; goto failed;
} }
if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)))
goto failed;
close(sock); close(sock);
return (fd); return (fd);

View File

@ -22,7 +22,7 @@ struct ssh;
#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) #if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
# define CUSTOM_SYS_TUN_OPEN # define CUSTOM_SYS_TUN_OPEN
int sys_tun_open(int, int); int sys_tun_open(int, int, char **);
#endif #endif
#if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF) #if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.198 2017/09/12 06:35:32 djm Exp $ */ /* $OpenBSD: serverloop.c,v 1.199 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -99,6 +99,9 @@ static volatile sig_atomic_t received_sigterm = 0;
/* prototypes */ /* prototypes */
static void server_init_dispatch(void); static void server_init_dispatch(void);
/* requested tunnel forwarding interface(s), shared with session.c */
char *tun_fwd_ifnames = NULL;
/* /*
* we write to this pipe if a SIGCHLD is caught in order to avoid * we write to this pipe if a SIGCHLD is caught in order to avoid
* the race between select() and child_terminated * the race between select() and child_terminated
@ -519,6 +522,7 @@ server_request_tun(struct ssh *ssh)
Channel *c = NULL; Channel *c = NULL;
int mode, tun; int mode, tun;
int sock; int sock;
char *tmp, *ifname = NULL;
mode = packet_get_int(); mode = packet_get_int();
switch (mode) { switch (mode) {
@ -541,9 +545,10 @@ server_request_tun(struct ssh *ssh)
goto done; goto done;
tun = forced_tun_device; tun = forced_tun_device;
} }
sock = tun_open(tun, mode); sock = tun_open(tun, mode, &ifname);
if (sock < 0) if (sock < 0)
goto done; goto done;
debug("Tunnel forwarding using interface %s", ifname);
c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1; c->datagram = 1;
@ -553,6 +558,19 @@ server_request_tun(struct ssh *ssh)
sys_tun_outfilter, NULL, NULL); sys_tun_outfilter, NULL, NULL);
#endif #endif
/*
* Update the list of names exposed to the session
* XXX remove these if the tunnels are closed (won't matter
* much if they are already in the environment though)
*/
tmp = tun_fwd_ifnames;
xasprintf(&tun_fwd_ifnames, "%s%s%s",
tun_fwd_ifnames == NULL ? "" : tun_fwd_ifnames,
tun_fwd_ifnames == NULL ? "" : ",",
ifname);
free(tmp);
free(ifname);
done: done:
if (c == NULL) if (c == NULL)
packet_send_debug("Failed to open the tunnel device."); packet_send_debug("Failed to open the tunnel device.");

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.292 2017/09/12 06:32:07 djm Exp $ */ /* $OpenBSD: session.c,v 1.293 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -140,6 +140,7 @@ extern u_int utmp_len;
extern int startup_pipe; extern int startup_pipe;
extern void destroy_sensitive_data(void); extern void destroy_sensitive_data(void);
extern Buffer loginmsg; extern Buffer loginmsg;
char *tun_fwd_ifnames; /* serverloop.c */
/* original command from peer. */ /* original command from peer. */
const char *original_command = NULL; const char *original_command = NULL;
@ -1066,6 +1067,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
free(laddr); free(laddr);
child_set_env(&env, &envsize, "SSH_CONNECTION", buf); child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
if (tun_fwd_ifnames != NULL)
child_set_env(&env, &envsize, "SSH_TUNNEL", tun_fwd_ifnames);
if (auth_info_file != NULL) if (auth_info_file != NULL)
child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file); child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file);
if (s->ttyfd != -1) if (s->ttyfd != -1)

9
ssh.1
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh.1,v 1.386 2017/10/21 23:06:24 millert Exp $ .\" $OpenBSD: ssh.1,v 1.387 2017/10/23 05:08:00 djm Exp $
.Dd $Mdocdate: October 21 2017 $ .Dd $Mdocdate: October 23 2017 $
.Dt SSH 1 .Dt SSH 1
.Os .Os
.Sh NAME .Sh NAME
@ -1395,6 +1395,11 @@ This is set to the name of the tty (path to the device) associated
with the current shell or command. with the current shell or command.
If the current session has no tty, If the current session has no tty,
this variable is not set. this variable is not set.
.It Ev SSH_TUNNEL
Optionally set by
.Xr sshd 8
to contain the interface names assigned if tunnel forwarding was
requested by the client.
.It Ev SSH_USER_AUTH .It Ev SSH_USER_AUTH
Optionally set by Optionally set by
.Xr sshd 8 , .Xr sshd 8 ,

108
ssh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.465 2017/10/21 23:06:24 millert Exp $ */ /* $OpenBSD: ssh.c,v 1.466 2017/10/23 05:08:00 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -168,6 +168,10 @@ char *config = NULL;
*/ */
char *host; char *host;
/* 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;
/* socket address the host resolves to */ /* socket address the host resolves to */
struct sockaddr_storage hostaddr; struct sockaddr_storage hostaddr;
@ -208,8 +212,8 @@ usage(void)
exit(255); exit(255);
} }
static int ssh_session2(struct ssh *); static int ssh_session2(struct ssh *, struct passwd *);
static void load_public_identity_files(void); static void load_public_identity_files(struct passwd *);
static void main_sigchld_handler(int); static void main_sigchld_handler(int);
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
@ -456,14 +460,14 @@ resolve_canonicalize(char **hostp, int port)
* file if the user specifies a config file on the command line. * file if the user specifies a config file on the command line.
*/ */
static void static void
process_config_files(const char *host_arg, struct passwd *pw, int post_canon) process_config_files(const char *host_name, struct passwd *pw, int post_canon)
{ {
char buf[PATH_MAX]; char buf[PATH_MAX];
int r; int r;
if (config != NULL) { if (config != NULL) {
if (strcasecmp(config, "none") != 0 && if (strcasecmp(config, "none") != 0 &&
!read_config_file(config, pw, host, host_arg, &options, !read_config_file(config, pw, host, host_name, &options,
SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0))) SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
fatal("Can't open user config file %.100s: " fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno)); "%.100s", config, strerror(errno));
@ -471,13 +475,13 @@ process_config_files(const char *host_arg, struct passwd *pw, int post_canon)
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE); _PATH_SSH_USER_CONFFILE);
if (r > 0 && (size_t)r < sizeof(buf)) if (r > 0 && (size_t)r < sizeof(buf))
(void)read_config_file(buf, pw, host, host_arg, (void)read_config_file(buf, pw, host, host_name,
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
(post_canon ? SSHCONF_POSTCANON : 0)); (post_canon ? SSHCONF_POSTCANON : 0));
/* Read systemwide configuration file after user config. */ /* Read systemwide configuration file after user config. */
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
host, host_arg, &options, host, host_name, &options,
post_canon ? SSHCONF_POSTCANON : 0); post_canon ? SSHCONF_POSTCANON : 0);
} }
} }
@ -511,9 +515,8 @@ main(int ac, char **av)
struct ssh *ssh = NULL; struct ssh *ssh = NULL;
int i, r, opt, exit_status, use_syslog, direct, timeout_ms; int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
int config_test = 0, opt_terminated = 0; int config_test = 0, opt_terminated = 0;
char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile; char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; char cname[NI_MAXHOST];
char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex;
struct stat st; struct stat st;
struct passwd *pw; struct passwd *pw;
extern int optind, optreset; extern int optind, optreset;
@ -1203,6 +1206,7 @@ main(int ac, char **av)
if (options.user == NULL) if (options.user == NULL)
options.user = xstrdup(pw->pw_name); options.user = xstrdup(pw->pw_name);
/* Set up strings used to percent_expand() arguments */
if (gethostname(thishost, sizeof(thishost)) == -1) if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno)); fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost)); strlcpy(shorthost, thishost, sizeof(shorthost));
@ -1220,24 +1224,11 @@ main(int ac, char **av)
ssh_digest_free(md); ssh_digest_free(md);
conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
if (options.local_command != NULL) { /*
debug3("expanding LocalCommand: %s", options.local_command); * Expand tokens in arguments. NB. LocalCommand is expanded later,
cp = options.local_command; * after port-forwarding is set up, so it may pick up any local
options.local_command = percent_expand(cp, * tunnel interface name allocated.
"C", conn_hash_hex, */
"L", shorthost,
"d", pw->pw_dir,
"h", host,
"l", thishost,
"n", host_arg,
"p", portstr,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
free(cp);
}
if (options.remote_command != NULL) { if (options.remote_command != NULL) {
debug3("expanding RemoteCommand: %s", options.remote_command); debug3("expanding RemoteCommand: %s", options.remote_command);
cp = options.remote_command; cp = options.remote_command;
@ -1256,7 +1247,6 @@ main(int ac, char **av)
free(cp); free(cp);
buffer_append(&command, options.remote_command, buffer_append(&command, options.remote_command,
strlen(options.remote_command)); strlen(options.remote_command));
} }
if (options.control_path != NULL) { if (options.control_path != NULL) {
@ -1427,7 +1417,7 @@ main(int ac, char **av)
} }
} }
/* load options.identity_files */ /* load options.identity_files */
load_public_identity_files(); load_public_identity_files(pw);
/* optionally set the SSH_AUTHSOCKET_ENV_NAME varibale */ /* optionally set the SSH_AUTHSOCKET_ENV_NAME varibale */
if (options.identity_agent && if (options.identity_agent &&
@ -1491,7 +1481,7 @@ main(int ac, char **av)
} }
skip_connect: skip_connect:
exit_status = ssh_session2(ssh); exit_status = ssh_session2(ssh, pw);
packet_close(); packet_close();
if (options.control_path != NULL && muxserver_sock != -1) if (options.control_path != NULL && muxserver_sock != -1)
@ -1650,7 +1640,7 @@ ssh_init_stdio_forwarding(struct ssh *ssh)
} }
static void static void
ssh_init_forwarding(struct ssh *ssh) ssh_init_forwarding(struct ssh *ssh, char **ifname)
{ {
int success = 0; int success = 0;
int i; int i;
@ -1708,8 +1698,9 @@ ssh_init_forwarding(struct ssh *ssh)
/* Initiate tunnel forwarding. */ /* Initiate tunnel forwarding. */
if (options.tun_open != SSH_TUNMODE_NO) { if (options.tun_open != SSH_TUNMODE_NO) {
if (client_request_tun_fwd(ssh, options.tun_open, if ((*ifname = client_request_tun_fwd(ssh,
options.tun_local, options.tun_remote) == -1) { options.tun_open, options.tun_local,
options.tun_remote)) == NULL) {
if (options.exit_on_forward_failure) if (options.exit_on_forward_failure)
fatal("Could not request tunnel forwarding."); fatal("Could not request tunnel forwarding.");
else else
@ -1824,14 +1815,35 @@ ssh_session2_open(struct ssh *ssh)
} }
static int static int
ssh_session2(struct ssh *ssh) ssh_session2(struct ssh *ssh, struct passwd *pw)
{ {
int id = -1; int id = -1;
char *cp, *tun_fwd_ifname = NULL;
/* XXX should be pre-session */ /* XXX should be pre-session */
if (!options.control_persist) if (!options.control_persist)
ssh_init_stdio_forwarding(ssh); ssh_init_stdio_forwarding(ssh);
ssh_init_forwarding(ssh);
ssh_init_forwarding(ssh, &tun_fwd_ifname);
if (options.local_command != NULL) {
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
options.local_command = percent_expand(cp,
"C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
"l", thishost,
"n", host_arg,
"p", portstr,
"r", options.user,
"u", pw->pw_name,
"T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
(char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
free(cp);
}
/* Start listening for multiplex clients */ /* Start listening for multiplex clients */
if (!packet_get_mux()) if (!packet_get_mux())
@ -1907,12 +1919,10 @@ ssh_session2(struct ssh *ssh)
/* Loads all IdentityFile and CertificateFile keys */ /* Loads all IdentityFile and CertificateFile keys */
static void static void
load_public_identity_files(void) load_public_identity_files(struct passwd *pw)
{ {
char *filename, *cp, thishost[NI_MAXHOST]; char *filename, *cp;
char *pwdir = NULL, *pwname = NULL;
struct sshkey *public; struct sshkey *public;
struct passwd *pw;
int i; int i;
u_int n_ids, n_certs; u_int n_ids, n_certs;
char *identity_files[SSH_MAX_IDENTITY_FILES]; char *identity_files[SSH_MAX_IDENTITY_FILES];
@ -1951,11 +1961,6 @@ load_public_identity_files(void)
#endif /* ENABLE_PKCS11 */ #endif /* ENABLE_PKCS11 */
if ((pw = getpwuid(original_real_uid)) == NULL) if ((pw = getpwuid(original_real_uid)) == NULL)
fatal("load_public_identity_files: getpwuid failed"); fatal("load_public_identity_files: getpwuid failed");
pwname = xstrdup(pw->pw_name);
pwdir = xstrdup(pw->pw_dir);
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("load_public_identity_files: gethostname: %s",
strerror(errno));
for (i = 0; i < options.num_identity_files; i++) { for (i = 0; i < options.num_identity_files; i++) {
if (n_ids >= SSH_MAX_IDENTITY_FILES || if (n_ids >= SSH_MAX_IDENTITY_FILES ||
strcasecmp(options.identity_files[i], "none") == 0) { strcasecmp(options.identity_files[i], "none") == 0) {
@ -1965,8 +1970,8 @@ load_public_identity_files(void)
} }
cp = tilde_expand_filename(options.identity_files[i], cp = tilde_expand_filename(options.identity_files[i],
original_real_uid); original_real_uid);
filename = percent_expand(cp, "d", pwdir, filename = percent_expand(cp, "d", pw->pw_dir,
"u", pwname, "l", thishost, "h", host, "u", pw->pw_name, "l", thishost, "h", host,
"r", options.user, (char *)NULL); "r", options.user, (char *)NULL);
free(cp); free(cp);
public = key_load_public(filename, NULL); public = key_load_public(filename, NULL);
@ -2011,8 +2016,8 @@ load_public_identity_files(void)
for (i = 0; i < options.num_certificate_files; i++) { for (i = 0; i < options.num_certificate_files; i++) {
cp = tilde_expand_filename(options.certificate_files[i], cp = tilde_expand_filename(options.certificate_files[i],
original_real_uid); original_real_uid);
filename = percent_expand(cp, "d", pwdir, filename = percent_expand(cp, "d", pw->pw_dir,
"u", pwname, "l", thishost, "h", host, "u", pw->pw_name, "l", thishost, "h", host,
"r", options.user, (char *)NULL); "r", options.user, (char *)NULL);
free(cp); free(cp);
@ -2045,11 +2050,6 @@ load_public_identity_files(void)
memcpy(options.certificate_files, memcpy(options.certificate_files,
certificate_files, sizeof(certificate_files)); certificate_files, sizeof(certificate_files));
memcpy(options.certificates, certificates, sizeof(certificates)); memcpy(options.certificates, certificates, sizeof(certificates));
explicit_bzero(pwname, strlen(pwname));
free(pwname);
explicit_bzero(pwdir, strlen(pwdir));
free(pwdir);
} }
static void static void

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh_config.5,v 1.260 2017/10/21 23:06:24 millert Exp $ .\" $OpenBSD: ssh_config.5,v 1.261 2017/10/23 05:08:00 djm Exp $
.Dd $Mdocdate: October 21 2017 $ .Dd $Mdocdate: October 23 2017 $
.Dt SSH_CONFIG 5 .Dt SSH_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -1713,6 +1713,16 @@ The original remote hostname, as given on the command line.
The remote port. The remote port.
.It %r .It %r
The remote username. The remote username.
.It \&%T
The local
.Xr tun 4
or
.Xr tap 4
network interface assigned if
.Cm Tunnel
forwarding was requested, or
.Cm NONE
otherwise.
.It %u .It %u
The local username. The local username.
.El .El
@ -1735,7 +1745,7 @@ and
accept the tokens %%, %d, %h, %l, %r, and %u. accept the tokens %%, %d, %h, %l, %r, and %u.
.Pp .Pp
.Cm LocalCommand .Cm LocalCommand
accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, %T, and %u.
.Pp .Pp
.Cm ProxyCommand .Cm ProxyCommand
accepts the tokens %%, %h, %p, and %r. accepts the tokens %%, %h, %p, and %r.