]> andersk Git - openssh.git/commitdiff
- reyk@cvs.openbsd.org 2005/12/06 22:38:28
authordjm <djm>
Tue, 13 Dec 2005 08:29:02 +0000 (08:29 +0000)
committerdjm <djm>
Tue, 13 Dec 2005 08:29:02 +0000 (08:29 +0000)
     [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

24 files changed:
ChangeLog
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

index 4e151eb31676bcf5f15cce6522ab6c62e11e99c7..de534b95f376b3b2635f705a407a6d09078c05bf 100644 (file)
--- 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 
index a85e408359eeb96d866e5ea57c4780ffb25f9213..54798d9ad5a7881448f768eba54e096b5ad51878 100644 (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
index 15fb21255e53d582ac88e3519d1e54f463d962ad..3cd02a71ff0d535ef7d6287a61accf60c66d98b4 100644 (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);
index 9607717cc15dc44b59b37697816423414d11d77b..b4fd89f96c2215fc807708f72c9e3ea0334a3fce 100644 (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);
 }
 
index 7e1cc7c5a3e1e40ca115ec5d0d8cea1c2f9027fd..743a2065e191779fac8d81218efe7014dcc10161 100644 (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
index 001c8f119a997984694034c4fff70570646825ca..a97734c3f788da4ff55bf5dfbeb70308a166c307 100644 (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;
        }
 
diff --git a/misc.c b/misc.c
index 27b947f0c79f54ba0cb6aedc68e231e77cb116dc..9b23e2c379a725685d0d872e857bdb550d371359 100644 (file)
--- 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 51541336cf396ad9e830f19a36102ed3bdc6aad3..ff2ba1b5a7af5d67a0b83e5ada6b005229947b54 100644 (file)
--- 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);
index cf27a9f4107e842b4c642f587fbda3d101631465..b6aad9d8d56cf287774bc1c975ec4a42dc63e2fb 100644 (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 */
index 2b9deb9db393cd9c427c74a88913b86a15aacdb7..4565b2c2cedabd42cc95334be089295a45368135 100644 (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
diff --git a/scp.c b/scp.c
index a19021f853e87d816998225a72d020aae548aea1..5dced6ce4aa008e3bef063711e7a54a5ac7dee99 100644 (file)
--- 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;
index 9e420a527d7b2d2bebb271837d38228eb5e2df9b..91a0ced298a1d1ce171bbcc037871c824b5b88a1 100644 (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);
index f7e56d52105efc895ee8c1e0bd12efd051be91ec..ab82c8f57a683a9904ac107cc724a842f79269bd 100644 (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 *);
index 03376bacf5df99e817f32c8fd1290be449fef328..199f7696d05be9a55dde2cfa41df95c6862836c6 100644 (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);
diff --git a/sftp.c b/sftp.c
index ff3223ad27f2193e094d69500a303c5eb81de6c9..24f6dc5389bacfabcb3cf7fbc8ac83e26e85b295 100644 (file)
--- 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 dd97a89959342fab5fe86b897c829b81f83641dd..8a55c2f6421b7455ad6c4ebbf938063b45e02972 100644 (file)
--- 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 2227755cdfbf2164ea54ab6ce3ac390c15060e0e..8a4a0e4c978770a0dad4328cb6a76917ae1ad518 100644 (file)
--- 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)
index f41bee0a2ed391d6955e830e97f27e85e2c72723..7bc8762d6b8fd3a7ddc39fc39430991dc81dc57c 100644 (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
index 13cdee88b82b2514d15029d352e643f170a0a4a6..d1930baab2e60a0c7746684f471122591e68e9b0 100644 (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.
index 2245a8af647257b5194c7c9d46b10afc95ae3c08..64ffec240c1606f05ccd9c12e671d7b1f7499d2b 100644 (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));
+}
index 0be30fe695aa838ddded6f826798c9a4f50455e6..e7c7a2b340dee3bfad9b772a1c389f8f6070c1b2 100644 (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.
diff --git a/sshd.8 b/sshd.8
index c610f47b8e0f528d05264477626da06e24ccebcb..53eddcdfbdd6402915cde602635c1a1e286cf896 100644 (file)
--- a/sshd.8
+++ b/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
@@ -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
index 1440c05ffcaf1e218c3523eda69626702f0be143..4957dd1a69ecb668cb9d51d7e3647462c9cfeacc 100644 (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
index 45c1c0131478f8bc49d5ba2aa3afa20764fb8a27..3835fcd6289e4cea76e78dac89afe195df9eb25b 100644 (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
This page took 0.177327 seconds and 5 git commands to generate.