summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--auth-options.c41
-rw-r--r--auth-options.h3
-rw-r--r--channels.c42
-rw-r--r--channels.h4
-rw-r--r--clientloop.c11
-rw-r--r--misc.c58
-rw-r--r--misc.h4
-rw-r--r--readconf.c52
-rw-r--r--readconf.h10
-rw-r--r--scp.c3
-rw-r--r--servconf.c12
-rw-r--r--servconf.h5
-rw-r--r--serverloop.c34
-rw-r--r--sftp.c3
-rw-r--r--ssh.120
-rw-r--r--ssh.c39
-rw-r--r--ssh_config5
-rw-r--r--ssh_config.538
-rw-r--r--sshconnect.c38
-rw-r--r--sshconnect.h4
-rw-r--r--sshd.810
-rw-r--r--sshd_config3
-rw-r--r--sshd_config.58
24 files changed, 433 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index d187f2aa..96ed9a05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 $
diff --git a/auth-options.c b/auth-options.c
index a85e4083..54798d9a 100644
--- a/auth-options.c
+++ b/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/auth-options.h b/auth-options.h
index 15fb2125..3cd02a71 100644
--- a/auth-options.h
+++ b/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/channels.c b/channels.c
index 9607717c..b4fd89f9 100644
--- a/channels.c
+++ b/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"
@@ -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);
}
diff --git a/channels.h b/channels.h
index 7e1cc7c5..743a2065 100644
--- a/channels.h
+++ b/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>
@@ -112,6 +112,8 @@ struct Channel {
/* filter */
channel_filter_fn *input_filter;
+
+ int datagram; /* keep boundaries */
};
#define CHAN_EXTENDED_IGNORE 0
diff --git a/clientloop.c b/clientloop.c
index 001c8f11..a97734c3 100644
--- a/clientloop.c
+++ b/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/misc.c b/misc.c
index 27b947f0..9b23e2c3 100644
--- a/misc.c
+++ b/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"
@@ -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)
{
diff --git a/misc.h b/misc.h
index 51541336..ff2ba1b5 100644
--- a/misc.h
+++ b/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/readconf.c b/readconf.c
index cf27a9f4..b6aad9d8 100644
--- a/readconf.c
+++ b/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 }
};
@@ -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 */
diff --git a/readconf.h b/readconf.h
index 2b9deb9d..4565b2c2 100644
--- a/readconf.h
+++ b/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/scp.c b/scp.c
index a19021f8..5dced6ce 100644
--- a/scp.c
+++ b/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"
@@ -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;
diff --git a/servconf.c b/servconf.c
index 9e420a52..91a0ced2 100644
--- a/servconf.c
+++ b/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"
@@ -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);
diff --git a/servconf.h b/servconf.h
index f7e56d52..ab82c8f5 100644
--- a/servconf.h
+++ b/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,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 *);
diff --git a/serverloop.c b/serverloop.c
index 03376bac..199f7696 100644
--- a/serverloop.c
+++ b/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"
@@ -914,6 +914,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;
@@ -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);
diff --git a/sftp.c b/sftp.c
index ff3223ad..24f6dc53 100644
--- a/sftp.c
+++ b/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 $");
#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;
diff --git a/ssh.1 b/ssh.1
index dd97a899..8a55c2f6 100644
--- a/ssh.1
+++ b/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/ssh.c b/ssh.c
index 2227755c..8a4a0e4c 100644
--- a/ssh.c
+++ b/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);
}
@@ -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)
diff --git a/ssh_config b/ssh_config
index f41bee0a..7bc8762d 100644
--- a/ssh_config
+++ b/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/ssh_config.5 b/ssh_config.5
index 13cdee88..d1930baa 100644
--- a/ssh_config.5
+++ b/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