summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-12-06 22:38:29 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-12-06 22:38:29 +0000
commit57e200b9764c3d42f2a662cc0a4690b8514b31a0 (patch)
tree796f9bb48d94838528feca40a271d18e5f37cf79
parent6dbb1fbadfc0b9c64b1da80376fe45dc0ad61d0a (diff)
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
-rw-r--r--usr.bin/ssh/auth-options.c41
-rw-r--r--usr.bin/ssh/auth-options.h3
-rw-r--r--usr.bin/ssh/channels.c42
-rw-r--r--usr.bin/ssh/channels.h4
-rw-r--r--usr.bin/ssh/clientloop.c11
-rw-r--r--usr.bin/ssh/misc.c58
-rw-r--r--usr.bin/ssh/misc.h4
-rw-r--r--usr.bin/ssh/readconf.c52
-rw-r--r--usr.bin/ssh/readconf.h10
-rw-r--r--usr.bin/ssh/scp.c3
-rw-r--r--usr.bin/ssh/servconf.c12
-rw-r--r--usr.bin/ssh/servconf.h4
-rw-r--r--usr.bin/ssh/serverloop.c34
-rw-r--r--usr.bin/ssh/sftp.c3
-rw-r--r--usr.bin/ssh/ssh.120
-rw-r--r--usr.bin/ssh/ssh.c39
-rw-r--r--usr.bin/ssh/ssh_config5
-rw-r--r--usr.bin/ssh/ssh_config.538
-rw-r--r--usr.bin/ssh/sshconnect.c38
-rw-r--r--usr.bin/ssh/sshconnect.h4
-rw-r--r--usr.bin/ssh/sshd.810
-rw-r--r--usr.bin/ssh/sshd_config3
-rw-r--r--usr.bin/ssh/sshd_config.58
23 files changed, 416 insertions, 30 deletions
diff --git a/usr.bin/ssh/auth-options.c b/usr.bin/ssh/auth-options.c
index a85e408359e..54798d9ad5a 100644
--- a/usr.bin/ssh/auth-options.c
+++ b/usr.bin/ssh/auth-options.c
@@ -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
diff --git a/usr.bin/ssh/auth-options.h b/usr.bin/ssh/auth-options.h
index 15fb21255e5..3cd02a71ff0 100644
--- a/usr.bin/ssh/auth-options.h
+++ b/usr.bin/ssh/auth-options.h
@@ -1,4 +1,4 @@
-/* $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);
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c
index e5787e3fdde..b494ba73279 100644
--- a/usr.bin/ssh/channels.c
+++ b/usr.bin/ssh/channels.c
@@ -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"
@@ -1413,6 +1413,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);
}
@@ -1431,6 +1433,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);
len = write(c->wfd, data, dlen);
@@ -1786,6 +1805,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.
@@ -1908,7 +1943,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);
}
diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h
index cd882b46f34..e4989b8828e 100644
--- a/usr.bin/ssh/channels.h
+++ b/usr.bin/ssh/channels.h
@@ -1,4 +1,4 @@
-/* $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>
@@ -111,6 +111,8 @@ struct Channel {
/* filter */
channel_filter_fn *input_filter;
+
+ int datagram; /* keep boundaries */
};
#define CHAN_EXTENDED_IGNORE 0
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
index 001c8f119a9..a97734c3f78 100644
--- a/usr.bin/ssh/clientloop.c
+++ b/usr.bin/ssh/clientloop.c
@@ -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;
}
diff --git a/usr.bin/ssh/misc.c b/usr.bin/ssh/misc.c
index b5721a0c4f8..dc715ac6778 100644
--- a/usr.bin/ssh/misc.c
+++ b/usr.bin/ssh/misc.c
@@ -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"
@@ -188,6 +188,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)
@@ -501,6 +532,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)
{
diff --git a/usr.bin/ssh/misc.h b/usr.bin/ssh/misc.h
index 51541336cf3..ff2ba1b5a7a 100644
--- a/usr.bin/ssh/misc.h
+++ b/usr.bin/ssh/misc.h
@@ -1,4 +1,4 @@
-/* $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);
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
index 8986dba06be..68da34eb1c0 100644
--- a/usr.bin/ssh/readconf.c
+++ b/usr.bin/ssh/readconf.c
@@ -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 }
};
@@ -262,6 +271,7 @@ clear_forwardings(Options *options)
xfree(options->remote_forwards[i].connect_host);
}
options->num_remote_forwards = 0;
+ options->tun_open = 0;
}
/*
@@ -294,7 +304,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;
@@ -551,9 +561,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);
@@ -820,6 +831,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);
@@ -964,6 +1000,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;
}
/*
@@ -1088,6 +1129,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 */
diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h
index 2b9deb9db39..4565b2c2ced 100644
--- a/usr.bin/ssh/readconf.h
+++ b/usr.bin/ssh/readconf.h
@@ -1,4 +1,4 @@
-/* $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
diff --git a/usr.bin/ssh/scp.c b/usr.bin/ssh/scp.c
index a523299a6c4..1b0424f3065 100644
--- a/usr.bin/ssh/scp.c
+++ b/usr.bin/ssh/scp.c
@@ -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"
@@ -229,6 +229,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;
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
index 76e50eb0d8c..307c4d0ef45 100644
--- a/usr.bin/ssh/servconf.c
+++ b/usr.bin/ssh/servconf.c
@@ -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"
@@ -96,6 +96,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;
@@ -219,6 +220,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)
@@ -247,7 +250,7 @@ typedef enum {
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
- sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
+ sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
sUsePrivilegeSeparation,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -338,6 +341,7 @@ static struct {
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
{ "acceptenv", sAcceptEnv },
+ { "permittunnel", sPermitTunnel },
{ NULL, sBadOption }
};
@@ -921,6 +925,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);
diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
index ba9b6680354..3d710a1488a 100644
--- a/usr.bin/ssh/servconf.h
+++ b/usr.bin/ssh/servconf.h
@@ -1,4 +1,4 @@
-/* $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,6 +133,8 @@ typedef struct {
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
+
+ int permit_tun;
} ServerOptions;
void initialize_server_options(ServerOptions *);
diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c
index f31baaadc79..651ba0a3fc9 100644
--- a/usr.bin/ssh/serverloop.c
+++ b/usr.bin/ssh/serverloop.c
@@ -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"
@@ -912,6 +912,36 @@ server_request_direct_tcpip(void)
}
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)
{
Channel *c;
@@ -956,6 +986,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);
diff --git a/usr.bin/ssh/sftp.c b/usr.bin/ssh/sftp.c
index 85418f9d091..eb2b1941c97 100644
--- a/usr.bin/ssh/sftp.c
+++ b/usr.bin/ssh/sftp.c
@@ -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 $");
#include <glob.h>
#include <histedit.h>
@@ -1437,6 +1437,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;
diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1
index dd97a899593..8a55c2f6421 100644
--- a/usr.bin/ssh/ssh.1
+++ b/usr.bin/ssh/ssh.1
@@ -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.
diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
index 9e54226e012..80e33f1ec34 100644
--- a/usr.bin/ssh/ssh.c
+++ b/usr.bin/ssh/ssh.c
@@ -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);
}
@@ -239,7 +239,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;
@@ -335,6 +335,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;
@@ -1047,6 +1055,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);
@@ -1111,6 +1139,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)
diff --git a/usr.bin/ssh/ssh_config b/usr.bin/ssh/ssh_config
index f41bee0a2ed..7bc8762d6b8 100644
--- a/usr.bin/ssh/ssh_config
+++ b/usr.bin/ssh/ssh_config
@@ -1,4 +1,4 @@
-# $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 $
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
@@ -37,3 +37,6 @@
# Cipher 3des
# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
# EscapeChar ~
+# Tunnel no
+# TunnelDevice any:any
+# PermitLocalCommand no
diff --git a/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5
index 13cdee88b82..d1930baab2e 100644
--- a/usr.bin/ssh/ssh_config.5
+++ b/usr.bin/ssh/ssh_config.5
@@ -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_config.5,v 1.64 2005/10/30 08:43:47 jmc Exp $
+.\" $OpenBSD: ssh_config.5,v 1.65 2005/12/06 22:38:27 reyk Exp $
.Dd September 25, 1999
.Dt SSH_CONFIG 5
.Os
@@ -556,6 +556,14 @@ The default is
Specifies the list of methods to use in keyboard-interactive authentication.
Multiple method names must be comma-separated.
The default is to use the server specified list.
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+.Pa /bin/sh .
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
.It Cm LocalForward
Specifies that a TCP/IP port on the local machine be forwarded over
the secure channel to the specified host and port from the remote machine.
@@ -628,6 +636,19 @@ The default is
.It Cm Port
Specifies the port number to connect on the remote host.
Default is 22.
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic ! Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
.It Cm PreferredAuthentications
Specifies the order in which the client should try protocol 2
authentication methods.
@@ -887,6 +908,21 @@ Note that this option must be set to
for
.Cm RhostsRSAAuthentication
with older servers.
+.It Cm Tunnel
+Request starting
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Force a specified
+.Xr tun 4
+device on the client.
+Without this option, the next available device will be used.
.It Cm User
Specifies the user to log in as.
This can be useful when a different user name is used on different machines.
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index a3c1f4b2b8a..263e6eec532 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.170 2005/10/30 08:52:18 djm Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.171 2005/12/06 22:38:27 reyk Exp $");
#include <openssl/bn.h>
@@ -1026,3 +1026,39 @@ warn_changed_key(Key *host_key)
xfree(fp);
}
+
+/*
+ * Execute a local command
+ */
+int
+ssh_local_cmd(const char *args)
+{
+ char *shell;
+ pid_t pid;
+ int status;
+
+ if (!options.permit_local_command ||
+ args == NULL || !*args)
+ return (1);
+
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = _PATH_BSHELL;
+
+ pid = fork();
+ if (pid == 0) {
+ debug3("Executing %s -c \"%s\"", shell, args);
+ execl(shell, shell, "-c", args, (char *)NULL);
+ error("Couldn't execute %s -c \"%s\": %s",
+ shell, args, strerror(errno));
+ _exit(1);
+ } else if (pid == -1)
+ fatal("fork failed: %.100s", strerror(errno));
+ while (waitpid(pid, &status, 0) == -1)
+ if (errno != EINTR)
+ fatal("Couldn't wait for child: %s", strerror(errno));
+
+ if (!WIFEXITED(status))
+ return (1);
+
+ return (WEXITSTATUS(status));
+}
diff --git a/usr.bin/ssh/sshconnect.h b/usr.bin/ssh/sshconnect.h
index 0be30fe695a..e7c7a2b340d 100644
--- a/usr.bin/ssh/sshconnect.h
+++ b/usr.bin/ssh/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.17 2002/06/19 00:27:55 deraadt Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.18 2005/12/06 22:38:28 reyk Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -49,7 +49,7 @@ void ssh_userauth1(const char *, const char *, char *, Sensitive *);
void ssh_userauth2(const char *, const char *, char *, Sensitive *);
void ssh_put_password(char *);
-
+int ssh_local_cmd(const char *);
/*
* Macros to raise/lower permissions.
diff --git a/usr.bin/ssh/sshd.8 b/usr.bin/ssh/sshd.8
index ef3f8d57774..96441e8e66f 100644
--- a/usr.bin/ssh/sshd.8
+++ b/usr.bin/ssh/sshd.8
@@ -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: sshd.8,v 1.208 2005/06/08 03:50:00 djm Exp $
+.\" $OpenBSD: sshd.8,v 1.209 2005/12/06 22:38:28 reyk Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@@ -493,6 +493,12 @@ Multiple
options may be applied separated by commas.
No pattern matching is performed on the specified hostnames,
they must be literal domains or addresses.
+.It Cm tunnel="n"
+Force a
+.Xr tun 4
+device on the server.
+Without this option, the next available device will be used if
+the client requests a tunnel.
.El
.Ss Examples
1024 33 12121...312314325 ylo@foo.bar
@@ -502,6 +508,8 @@ from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23...2334 ylo@niksula
command="dump /home",no-pty,no-port-forwarding 1024 33 23...2323 backup.hut.fi
.Pp
permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23...2323
+.Pp
+tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== reyk@openbsd.org
.Sh SSH_KNOWN_HOSTS FILE FORMAT
The
.Pa /etc/ssh/ssh_known_hosts
diff --git a/usr.bin/ssh/sshd_config b/usr.bin/ssh/sshd_config
index dd57fc14680..9bd072d368a 100644
--- a/usr.bin/ssh/sshd_config
+++ b/usr.bin/ssh/sshd_config
@@ -1,4 +1,4 @@
-# $OpenBSD: sshd_config,v 1.72 2005/07/25 11:59:40 markus Exp $
+# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
@@ -84,6 +84,7 @@
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
+#PermitTunnel no
# no default banner path
#Banner /some/path
diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5
index 42668eb8e9c..a16018334a2 100644
--- a/usr.bin/ssh/sshd_config.5
+++ b/usr.bin/ssh/sshd_config.5
@@ -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: sshd_config.5,v 1.45 2005/09/21 23:36:54 djm Exp $
+.\" $OpenBSD: sshd_config.5,v 1.46 2005/12/06 22:38:28 reyk Exp $
.Dd September 25, 1999
.Dt SSHD_CONFIG 5
.Os
@@ -502,6 +502,12 @@ All other authentication methods are disabled for root.
If this option is set to
.Dq no
root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The default is
+.Dq no .
.It Cm PermitUserEnvironment
Specifies whether
.Pa ~/.ssh/environment