[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
This commit is contained in:
Damien Miller 2005-12-13 19:29:02 +11:00
parent 6dbdb6afee
commit d27b947178
24 changed files with 433 additions and 31 deletions

View File

@ -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 $

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

58
misc.c
View File

@ -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)
{

4
misc.h
View File

@ -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);

View File

@ -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 */

View File

@ -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

3
scp.c
View File

@ -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;

View File

@ -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);

View File

@ -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 *);

View File

@ -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);

3
sftp.c
View File

@ -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;

20
ssh.1
View File

@ -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.

39
ssh.c
View 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)

View File

@ -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

View File

@ -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.

View File

@ -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>
@ -1034,3 +1034,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));
}

View File

@ -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.

10
sshd.8
View File

@ -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
@ -518,6 +518,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
@ -527,6 +533,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

View File

@ -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.
@ -96,6 +96,7 @@
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
#PermitTunnel no
# no default banner path
#Banner /some/path

View File

@ -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