Commit d27b9471 authored by Damien Miller's avatar Damien Miller

- reyk@cvs.openbsd.org 2005/12/06 22:38:28

     [auth-options.c auth-options.h channels.c channels.h clientloop.c]
     [misc.c misc.h readconf.c readconf.h scp.c servconf.c servconf.h]
     [serverloop.c sftp.c ssh.1 ssh.c ssh_config ssh_config.5 sshconnect.c]
     [sshconnect.h sshd.8 sshd_config sshd_config.5]
     Add support for tun(4) forwarding over OpenSSH, based on an idea and
     initial channel code bits by markus@. This is a simple and easy way to
     use OpenSSH for ad hoc virtual private network connections, e.g.
     administrative tunnels or secure wireless access. It's based on a new
     ssh channel and works similar to the existing TCP forwarding support,
     except that it depends on the tun(4) network interface on both ends of
     the connection for layer 2 or layer 3 tunneling. This diff also adds
     support for LocalCommand in the ssh(1) client.

     ok djm@, markus@, jmc@ (manpages), tested and discussed with others
parent 6dbdb6af
......@@ -7,6 +7,21 @@
[ssh.1]
avoid ambiguities in describing TZ;
ok djm@
- reyk@cvs.openbsd.org 2005/12/06 22:38:28
[auth-options.c auth-options.h channels.c channels.h clientloop.c]
[misc.c misc.h readconf.c readconf.h scp.c servconf.c servconf.h]
[serverloop.c sftp.c ssh.1 ssh.c ssh_config ssh_config.5 sshconnect.c]
[sshconnect.h sshd.8 sshd_config sshd_config.5]
Add support for tun(4) forwarding over OpenSSH, based on an idea and
initial channel code bits by markus@. This is a simple and easy way to
use OpenSSH for ad hoc virtual private network connections, e.g.
administrative tunnels or secure wireless access. It's based on a new
ssh channel and works similar to the existing TCP forwarding support,
except that it depends on the tun(4) network interface on both ends of
the connection for layer 2 or layer 3 tunneling. This diff also adds
support for LocalCommand in the ssh(1) client.
ok djm@, markus@, jmc@ (manpages), tested and discussed with others
20051201
- (djm) [envpass.sh] Remove regress script that was accidentally committed
......@@ -3399,4 +3414,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.4018 2005/12/13 08:25:43 djm Exp $
$Id: ChangeLog,v 1.4019 2005/12/13 08:29:02 djm Exp $
......@@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-options.c,v 1.31 2005/03/10 22:40:38 deraadt Exp $");
RCSID("$OpenBSD: auth-options.c,v 1.32 2005/12/06 22:38:27 reyk Exp $");
#include "xmalloc.h"
#include "match.h"
......@@ -35,6 +35,9 @@ char *forced_command = NULL;
/* "environment=" options. */
struct envstring *custom_environment = NULL;
/* "tunnel=" option. */
int forced_tun_device = -1;
extern ServerOptions options;
void
......@@ -54,6 +57,7 @@ auth_clear_options(void)
xfree(forced_command);
forced_command = NULL;
}
forced_tun_device = -1;
channel_clear_permitted_opens();
auth_debug_reset();
}
......@@ -269,6 +273,41 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
xfree(patterns);
goto next_option;
}
cp = "tunnel=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *tun = NULL;
opts += strlen(cp);
tun = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
tun[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(tun);
forced_tun_device = -1;
goto bad_option;
}
tun[i] = 0;
forced_tun_device = a2tun(tun, NULL);
xfree(tun);
if (forced_tun_device < -1) {
debug("%.100s, line %lu: invalid tun device",
file, linenum);
auth_debug_add("%.100s, line %lu: invalid tun device",
file, linenum);
forced_tun_device = -1;
goto bad_option;
}
auth_debug_add("Forced tun device: %d", forced_tun_device);
opts++;
goto next_option;
}
next_option:
/*
* Skip the comma, and move to the next option
......
/* $OpenBSD: auth-options.h,v 1.12 2002/07/21 18:34:43 stevesk Exp $ */
/* $OpenBSD: auth-options.h,v 1.13 2005/12/06 22:38:27 reyk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -28,6 +28,7 @@ extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern char *forced_command;
extern struct envstring *custom_environment;
extern int forced_tun_device;
int auth_parse_options(struct passwd *, char *, char *, u_long);
void auth_clear_options(void);
......
......@@ -39,7 +39,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.227 2005/10/14 02:29:37 stevesk Exp $");
RCSID("$OpenBSD: channels.c,v 1.228 2005/12/06 22:38:27 reyk Exp $");
#include "ssh.h"
#include "ssh1.h"
......@@ -1414,6 +1414,8 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
debug2("channel %d: filter stops", c->self);
chan_read_failed(c);
}
} else if (c->datagram) {
buffer_put_string(&c->input, buf, len);
} else {
buffer_append(&c->input, buf, len);
}
......@@ -1432,6 +1434,23 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
if (c->wfd != -1 &&
FD_ISSET(c->wfd, writeset) &&
buffer_len(&c->output) > 0) {
if (c->datagram) {
data = buffer_get_string(&c->output, &dlen);
/* ignore truncated writes, datagrams might get lost */
c->local_consumed += dlen + 4;
len = write(c->wfd, data, dlen);
xfree(data);
if (len < 0 && (errno == EINTR || errno == EAGAIN))
return 1;
if (len <= 0) {
if (c->type != SSH_CHANNEL_OPEN)
chan_mark_dead(c);
else
chan_write_failed(c);
return -1;
}
return 1;
}
data = buffer_ptr(&c->output);
dlen = buffer_len(&c->output);
#ifdef _AIX
......@@ -1792,6 +1811,22 @@ channel_output_poll(void)
if ((c->istate == CHAN_INPUT_OPEN ||
c->istate == CHAN_INPUT_WAIT_DRAIN) &&
(len = buffer_len(&c->input)) > 0) {
if (c->datagram) {
if (len > 0) {
u_char *data;
u_int dlen;
data = buffer_get_string(&c->input,
&dlen);
packet_start(SSH2_MSG_CHANNEL_DATA);
packet_put_int(c->remote_id);
packet_put_string(data, dlen);
packet_send();
c->remote_window -= dlen + 4;
xfree(data);
}
continue;
}
/*
* Send some data for the other side over the secure
* connection.
......@@ -1914,7 +1949,10 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
c->local_window -= data_len;
}
packet_check_eom();
buffer_append(&c->output, data, data_len);
if (c->datagram)
buffer_put_string(&c->output, data, data_len);
else
buffer_append(&c->output, data, data_len);
xfree(data);
}
......
/* $OpenBSD: channels.h,v 1.80 2005/10/10 10:23:08 djm Exp $ */
/* $OpenBSD: channels.h,v 1.81 2005/12/06 22:38:27 reyk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -112,6 +112,8 @@ struct Channel {
/* filter */
channel_filter_fn *input_filter;
int datagram; /* keep boundaries */
};
#define CHAN_EXTENDED_IGNORE 0
......
......@@ -59,7 +59,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: clientloop.c,v 1.145 2005/10/30 08:52:17 djm Exp $");
RCSID("$OpenBSD: clientloop.c,v 1.146 2005/12/06 22:38:27 reyk Exp $");
#include "ssh.h"
#include "ssh1.h"
......@@ -914,6 +914,15 @@ process_cmdline(void)
logit(" -Lport:host:hostport Request local forward");
logit(" -Rport:host:hostport Request remote forward");
logit(" -KRhostport Cancel remote forward");
if (!options.permit_local_command)
goto out;
logit(" !args Execute local command");
goto out;
}
if (*s == '!' && options.permit_local_command) {
s++;
ssh_local_cmd(s);
goto out;
}
......
......@@ -24,7 +24,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: misc.c,v 1.35 2005/09/13 23:40:07 djm Exp $");
RCSID("$OpenBSD: misc.c,v 1.36 2005/12/06 22:38:27 reyk Exp $");
#include "misc.h"
#include "log.h"
......@@ -194,6 +194,37 @@ a2port(const char *s)
return port;
}
int
a2tun(const char *s, int *remote)
{
const char *errstr = NULL;
char *sp, *ep;
int tun;
if (remote != NULL) {
*remote = -1;
sp = xstrdup(s);
if ((ep = strchr(sp, ':')) == NULL) {
xfree(sp);
return (a2tun(s, NULL));
}
ep[0] = '\0'; ep++;
*remote = a2tun(ep, NULL);
tun = a2tun(sp, NULL);
xfree(sp);
return (tun);
}
if (strcasecmp(s, "any") == 0)
return (-1);
tun = strtonum(s, 0, INT_MAX, &errstr);
if (errstr != NULL || tun < -1)
return (-2);
return (tun);
}
#define SECONDS 1
#define MINUTES (SECONDS * 60)
#define HOURS (MINUTES * 60)
......@@ -507,6 +538,31 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
return -1;
}
int
tun_open(int tun)
{
char name[100];
int i, fd;
if (tun > -1) {
snprintf(name, sizeof(name), "/dev/tun%d", tun);
if ((fd = open(name, O_RDWR)) >= 0) {
debug("%s: %s: %d", __func__, name, fd);
return (fd);
}
} else {
for (i = 100; i >= 0; i--) {
snprintf(name, sizeof(name), "/dev/tun%d", i);
if ((fd = open(name, O_RDWR)) >= 0) {
debug("%s: %s: %d", __func__, name, fd);
return (fd);
}
}
}
debug("%s: %s failed: %s", __func__, name, strerror(errno));
return (-1);
}
void
sanitise_stdfd(void)
{
......
/* $OpenBSD: misc.h,v 1.26 2005/09/13 23:40:07 djm Exp $ */
/* $OpenBSD: misc.h,v 1.27 2005/12/06 22:38:27 reyk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -20,6 +20,7 @@ int set_nonblock(int);
int unset_nonblock(int);
void set_nodelay(int);
int a2port(const char *);
int a2tun(const char *, int *);
char *hpdelim(char **);
char *cleanhostname(char *);
char *colon(char *);
......@@ -49,3 +50,4 @@ void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
char *read_passphrase(const char *, int);
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
int tun_open(int);
......@@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.143 2005/07/30 02:03:47 djm Exp $");
RCSID("$OpenBSD: readconf.c,v 1.144 2005/12/06 22:38:27 reyk Exp $");
#include "ssh.h"
#include "xmalloc.h"
......@@ -70,6 +70,10 @@ RCSID("$OpenBSD: readconf.c,v 1.143 2005/07/30 02:03:47 djm Exp $");
Cipher none
PasswordAuthentication no
Host vpn.fake.com
Tunnel yes
TunnelDevice 3
# Defaults for various options
Host *
ForwardAgent no
......@@ -107,6 +111,7 @@ typedef enum {
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oDeprecated, oUnsupported
} OpCodes;
......@@ -198,6 +203,10 @@ static struct {
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
{ "hashknownhosts", oHashKnownHosts },
{ "tunnel", oTunnel },
{ "tunneldevice", oTunnelDevice },
{ "localcommand", oLocalCommand },
{ "permitlocalcommand", oPermitLocalCommand },
{ NULL, oBadOption }
};
......@@ -264,6 +273,7 @@ clear_forwardings(Options *options)
xfree(options->remote_forwards[i].connect_host);
}
options->num_remote_forwards = 0;
options->tun_open = 0;
}
/*
......@@ -296,7 +306,7 @@ process_config_line(Options *options, const char *host,
int *activep)
{
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
int opcode, *intptr, value;
int opcode, *intptr, value, value2;
size_t len;
Forward fwd;
......@@ -553,9 +563,10 @@ parse_string:
goto parse_string;
case oProxyCommand:
charptr = &options->proxy_command;
parse_command:
if (s == NULL)
fatal("%.200s line %d: Missing argument.", filename, linenum);
charptr = &options->proxy_command;
len = strspn(s, WHITESPACE "=");
if (*activep && *charptr == NULL)
*charptr = xstrdup(s + len);
......@@ -822,6 +833,31 @@ parse_int:
intptr = &options->hash_known_hosts;
goto parse_flag;
case oTunnel:
intptr = &options->tun_open;
goto parse_flag;
case oTunnelDevice:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
value = a2tun(arg, &value2);
if (value < -1)
fatal("%.200s line %d: Bad tun device.", filename, linenum);
if (*activep) {
options->tun_local = value;
options->tun_remote = value2;
}
break;
case oLocalCommand:
charptr = &options->local_command;
goto parse_command;
case oPermitLocalCommand:
intptr = &options->permit_local_command;
goto parse_flag;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
......@@ -966,6 +1002,11 @@ initialize_options(Options * options)
options->control_path = NULL;
options->control_master = -1;
options->hash_known_hosts = -1;
options->tun_open = -1;
options->tun_local = -1;
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
}
/*
......@@ -1090,6 +1131,11 @@ fill_default_options(Options * options)
options->control_master = 0;
if (options->hash_known_hosts == -1)
options->hash_known_hosts = 0;
if (options->tun_open == -1)
options->tun_open = 0;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
/* options->local_command should not be set by default */
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
......
/* $OpenBSD: readconf.h,v 1.67 2005/06/08 11:25:09 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.68 2005/12/06 22:38:27 reyk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -114,6 +114,14 @@ typedef struct {
int control_master;
int hash_known_hosts;
int tun_open; /* tun(4) */
int tun_local; /* force tun device (optional) */
int tun_remote; /* force tun device (optional) */
char *local_command;
int permit_local_command;
} Options;
#define SSHCTL_MASTER_NO 0
......
......@@ -71,7 +71,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: scp.c,v 1.127 2005/11/12 18:38:15 deraadt Exp $");
RCSID("$OpenBSD: scp.c,v 1.128 2005/12/06 22:38:27 reyk Exp $");
#include "xmalloc.h"
#include "atomicio.h"
......@@ -231,6 +231,7 @@ main(int argc, char **argv)
addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "-x");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
fflag = tflag = 0;
......
......@@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.144 2005/08/06 10:03:12 dtucker Exp $");
RCSID("$OpenBSD: servconf.c,v 1.145 2005/12/06 22:38:27 reyk Exp $");
#include "ssh.h"
#include "log.h"
......@@ -101,6 +101,7 @@ initialize_server_options(ServerOptions *options)
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
options->num_accept_env = 0;
options->permit_tun = -1;
/* Needs to be accessable in many places */
use_privsep = -1;
......@@ -229,6 +230,8 @@ fill_default_server_options(ServerOptions *options)
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
if (options->permit_tun == -1)
options->permit_tun = 0;
/* Turn privilege separation on by default */
if (use_privsep == -1)
......@@ -270,7 +273,7 @@ typedef enum {
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
sUsePrivilegeSeparation,
sDeprecated, sUnsupported
} ServerOpCodes;
......@@ -373,6 +376,7 @@ static struct {
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
{ "acceptenv", sAcceptEnv },
{ "permittunnel", sPermitTunnel },
{ NULL, sBadOption }
};
......@@ -962,6 +966,10 @@ parse_flag:
}
break;
case sPermitTunnel:
intptr = &options->permit_tun;
goto parse_flag;
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
......
/* $OpenBSD: servconf.h,v 1.71 2004/12/23 23:11:00 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.72 2005/12/06 22:38:27 reyk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -133,7 +133,10 @@ typedef struct {
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
int use_pam; /* Enable auth via PAM */
int permit_tun;
} ServerOptions;
void initialize_server_options(ServerOptions *);
......
......@@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: serverloop.c,v 1.121 2005/10/31 11:48:29 djm Exp $");
RCSID("$OpenBSD: serverloop.c,v 1.122 2005/12/06 22:38:27 reyk Exp $");
#include "xmalloc.h"
#include "packet.h"
......@@ -913,6 +913,36 @@ server_request_direct_tcpip(void)
return c;
}
static Channel *
server_request_tun(void)
{
Channel *c = NULL;
int sock, tun;
if (!options.permit_tun) {
packet_send_debug("Server has disabled tunnel device forwarding.");
return NULL;
}
tun = packet_get_int();
if (forced_tun_device != -1) {
if (tun != -1 && forced_tun_device != tun)
goto done;
tun = forced_tun_device;
}
sock = tun_open(tun);
if (sock < 0)
goto done;
c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
done:
if (c == NULL)
packet_send_debug("Failed to open the tunnel device.");
return c;
}
static Channel *
server_request_session(void)
{
......@@ -958,6 +988,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
c = server_request_session();
} else if (strcmp(ctype, "direct-tcpip") == 0) {
c = server_request_direct_tcpip();
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
c = server_request_tun();
}
if (c != NULL) {
debug("server_input_channel_open: confirm %s", ctype);
......
......@@ -16,7 +16,7 @@
#include "includes.h"
RCSID("$OpenBSD: sftp.c,v 1.68 2005/10/31 06:15:04 dtucker Exp $");
RCSID("$OpenBSD: sftp.c,v 1.69 2005/12/06 22:38:27 reyk Exp $");
#ifdef USE_LIBEDIT
#include <histedit.h>
......@@ -1457,6 +1457,7 @@ main(int argc, char **argv)
addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "-oForwardX11 no");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
ll = SYSLOG_LEVEL_INFO;
......
......@@ -34,7 +34,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.214 2005/11/30 11:45:20 jmc Exp $
.\" $OpenBSD: ssh.1,v 1.215 2005/12/06 22:38:27 reyk Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
......@@ -77,6 +77,7 @@
.Sm on
.Oc
.Op Fl S Ar ctl_path
.Op Fl w Ar tunnel : tunnel
.Oo Ar user Ns @ Oc Ns Ar hostname
.Op Ar command
.Sh DESCRIPTION
......@@ -301,6 +302,12 @@ options (see below).
It also allows the cancellation of existing remote port-forwardings
using
.Fl KR Ar hostport .
The
.Ic ! Ar command
allows the user to execute a local command if the
.Ic PermitLocalCommand
option is enabled in
.Xr ssh_config 5 .
Basic help is available, using the
.Fl h
option.
......@@ -747,12 +754,14 @@ For full details of the options listed below, and their possible values, see
.It IdentityFile
.It IdentitiesOnly
.It KbdInteractiveDevices
.It LocalCommand
.It LocalForward
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PermitLocalCommand
.It Port
.It PreferredAuthentications
.It Protocol
......@@ -767,6 +776,8 @@ For full details of the options listed below, and their possible values, see
.It SmartcardDevice
.It StrictHostKeyChecking
.It TCPKeepAlive
.It Tunnel
.It TunnelDevice
.It UsePrivilegedPort
.It User
.It UserKnownHostsFile
......@@ -866,6 +877,13 @@ Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
.It Fl w
Requests a
.Xr tun 4
device on the client and server like the
.Cm Tunnel
directive in
.Xr ssh_config 5 .
.It Fl X
Enables X11 forwarding.
This can also be specified on a per-host basis in a configuration file.
......
......@@ -40,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.254 2005/10/30 08:52:18 djm Exp $");
RCSID("$OpenBSD: ssh.c,v 1.255 2005/12/06 22:38:27 reyk Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
......@@ -162,7 +162,7 @@ usage(void)
" [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
" [user@]hostname [command]\n"
" [-w tunnel:tunnel] [user@]hostname [command]\n"
);
exit(1);
}
......@@ -244,7 +244,7 @@ main(int ac, char **av)
again:
while ((opt = getopt(ac, av,
"1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
"1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XY")) != -1) {
switch (opt) {
case '1':
options.protocol = SSH_PROTO_1;
......@@ -340,6 +340,14 @@ again:
if (opt == 'V')
exit(0);
break;
case 'w':
options.tun_open = 1;
options.tun_local = a2tun(optarg, &options.tun_remote);
if (options.tun_local < -1) {
fprintf(stderr, "Bad tun device '%s'\n", optarg);
exit(1);
}
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
break;
......@@ -1059,6 +1067,26 @@ ssh_session2_setup(int id, void *arg)
packet_send();
}
if (options.tun_open) {
Channel *c;
int fd;
debug("Requesting tun.");
if ((fd = tun_open(options.tun_local)) >= 0) {
c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "tun", 1);
c->datagram = 1;
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("tun@openssh.com");
packet_put_int(c->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
packet_put_int(options.tun_remote);
packet_send();
}
}
client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply);
......@@ -1123,6 +1151,11 @@ ssh_session2(void)
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
id = ssh_session2_open();
/* Execute a local command */
if (options.local_command != NULL &&
options.permit_local_command)
ssh_local_cmd(options.local_command);
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
if (daemon(1, 1) < 0)
......
# $OpenBSD: ssh_config,v 1.20 2005/01/28 09:45:53 dtucker Exp $
# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $