]> andersk Git - gssapi-openssh.git/commitdiff
openssh-4.3p2-hpn12.diff
authorjbasney <jbasney>
Wed, 26 Jul 2006 19:24:11 +0000 (19:24 +0000)
committerjbasney <jbasney>
Wed, 26 Jul 2006 19:24:11 +0000 (19:24 +0000)
21 files changed:
openssh/HPN12-README [new file with mode: 0644]
openssh/buffer.h
openssh/channels.c
openssh/channels.h
openssh/clientloop.c
openssh/clientloop.h
openssh/myproposal.h
openssh/readconf.c
openssh/readconf.h
openssh/scp.c
openssh/servconf.c
openssh/servconf.h
openssh/serverloop.c
openssh/session.c
openssh/sftp.c
openssh/ssh.c
openssh/sshconnect.c
openssh/sshconnect2.c
openssh/sshd.c
openssh/sshd_config
openssh/version.h

diff --git a/openssh/HPN12-README b/openssh/HPN12-README
new file mode 100644 (file)
index 0000000..01f46aa
--- /dev/null
@@ -0,0 +1,43 @@
+config options
+
+TcpRcvBuf=[int]KB client
+      set the TCP socket receive buffer to n Kilobytes. It can be set up to the 
+maximum socket size allowed by the system. This is useful in situations where 
+the tcp receive window is set low but the maximum buffer size is set 
+higher (as is typical). This works on a per TCP connection basis. You can also 
+use this to artifically limit the transfer rate of the connection. In these 
+cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. 
+Default is the current system wide tcp receive buffer size.
+
+TcpRcvBufPoll=[yes/no] client/server
+      enable of disable the polling of the tcp receive buffer through the life 
+of the connection. You would want to make sure that this option is enabled 
+for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) 
+default is no.
+
+NoneEnabled=[yes/no] client/server
+      enable or disable the use of the None cipher. Care must always be used 
+when enabling this as it will allow users to send data in the clear. However, 
+it is important to note that authentication information remains encrypted 
+even if this option is enabled. Set to no by default.
+
+NoneSwitch=[yes/no] client
+     Switch the encryption cipher being used to the None cipher after
+authentication takes place. NoneEnabled must be enabled on both the client
+and server side of the connection. When the connection switches to the NONE
+cipher a warning is sent to STDERR. The connection attempt will fail with an
+error if a client requests a NoneSwitch from the server that does not explicitly
+have NoneEnabled set to yes. Note: The NONE cipher cannot be used in
+interactive (shell) sessions and it will fail silently. Set to no by default.
+
+HPNDisabled=[yes/no] client/server
+     In some situations, such as transfers on a local area network, the impact 
+of the HPN code produces a net decrease in performance. In these cases it is 
+helpful to disable the HPN functionality. By default HPNDisabled is set to no. 
+
+HPNBufferSize=[int]KB client/server
+     This is the default buffer size the HPN functionality uses when interacting
+with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf
+option as applied to the internal SSH flow control. This value can range from 
+1KB to 14MB (1-14336). Use of oversized or undersized buffers can cause performance
+problems depending on the length of the network path. The default size of this buffer
index 634b2727b4e7d1310da41747d22056fe84495f42..62e43d1a716fe803e65ddcc9144b5a796aada75b 100644 (file)
@@ -23,9 +23,15 @@ typedef struct {
        u_int    end;           /* Offset of last byte containing data. */
 }       Buffer;
 
-#define        BUFFER_MAX_CHUNK        0x100000
-#define        BUFFER_MAX_LEN          0xa00000
-#define BUFFER_MAX_HPN_LEN     (2<<29)-1
+#define        BUFFER_MAX_CHUNK        0x100000  /*1MB*/
+#define        BUFFER_MAX_LEN          0xa00000  /*10MB*/
+
+/* this value for BUFFER_MAX_HPN_LEN is */
+/* still undersized for the faster networks */
+/* it might make sense to have yet another */
+/* MAX_LEN for 10+GB networks. Something closer to */
+/* 128MB or 192MB -cjr*/
+#define        BUFFER_MAX_HPN_LEN      0x2000000 /*32MB*/
 
 void    buffer_init(Buffer *);
 void    buffer_clear(Buffer *);
index eead4bd94f274ad177701b881b1ca1d5b9646c17..9311643b4ecbb702c599aec099ff5a2a32efea78 100644 (file)
@@ -56,6 +56,7 @@ RCSID("$OpenBSD: channels.c,v 1.232 2006/01/30 12:22:22 reyk Exp $");
 #include "pathnames.h"
 #include "bufaux.h"
 
+
 /* -- channel core */
 
 /*
@@ -745,13 +746,32 @@ channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset)
                FD_SET(c->sock, writeset);
 }
 
+int channel_tcpwinsz () {
+        u_int32_t tcpwinsz = 0;
+        socklen_t optsz = sizeof(tcpwinsz);
+        int ret = -1;
+       if(!packet_connection_is_on_socket()) 
+               return(131072);
+        ret = getsockopt(packet_get_connection_in(),
+                        SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+        if ((ret == 0) && tcpwinsz > BUFFER_MAX_HPN_LEN)
+                          tcpwinsz = BUFFER_MAX_HPN_LEN;
+       debug2("tcpwinsz: %d for connection: %d", tcpwinsz, packet_get_connection_in());
+       return(tcpwinsz);
+}
+
 static void
 channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
 {
        u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
 
        /* check buffer limits */
-       limit = MIN(limit, (BUFFER_MAX_HPN_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF));
+       if (!c->tcpwinsz) 
+               c->tcpwinsz = channel_tcpwinsz();
+       if (c->dynamic_window > 0)
+               c->tcpwinsz = channel_tcpwinsz();
+
+       limit = MIN(limit, 2 * c->tcpwinsz);
 
        if (c->istate == CHAN_INPUT_OPEN &&
            limit > 0 &&
@@ -1616,19 +1636,10 @@ channel_check_window(Channel *c)
            !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
            c->local_window < c->local_window_max/2 &&
            c->local_consumed > 0) {
-               u_int32_t tcpwinsz = 0;
-               socklen_t optsz = sizeof(tcpwinsz);
-               int ret = -1;
-               u_int32_t addition = 0;
-               if (c->dynamic_window) {
-                       ret = getsockopt(packet_get_connection_in(), 
-                               SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
-                       if ((ret == 0) && tcpwinsz > BUFFER_MAX_HPN_LEN) 
-                               tcpwinsz = BUFFER_MAX_HPN_LEN;
-               }
-               if (c->dynamic_window && (ret == 0) && 
-                   (tcpwinsz > c->local_window_max)) {
-                       addition = tcpwinsz - c->local_window_max;
+               u_int addition = 0;
+               /* adjust max window size if we are in a dynamic environment */
+               if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) {
+                       addition = c->tcpwinsz - c->local_window_max;
                        c->local_window_max += addition;
                }
                packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
@@ -2297,7 +2308,8 @@ channel_set_af(int af)
 
 static int
 channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port,
-    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
+    const char *host_to_connect, u_short port_to_connect, int gateway_ports, 
+    int hpn_disabled, int hpn_buffer_size)
 {
        Channel *c;
        int sock, r, success = 0, wildcard = 0, is_client;
@@ -2410,9 +2422,15 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                        continue;
                }
                /* Allocate a channel number for the socket. */
-               c = channel_new("port listener", type, sock, sock, -1,
-                   CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
-                   0, "port listener", 1);
+               /* explicitly test for hpn disabled option. if true use smaller window size */
+               if (hpn_disabled)
+                       c = channel_new("port listener", type, sock, sock, -1,
+                         CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+                         0, "port listener", 1); 
+               else
+                       c = channel_new("port listener", type, sock, sock, -1,
+                         hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+                         0, "port listener", 1); 
                strlcpy(c->path, host, sizeof(c->path));
                c->host_port = port_to_connect;
                c->listening_port = listen_port;
@@ -2449,20 +2467,22 @@ channel_cancel_rport_listener(const char *host, u_short port)
 /* protocol local port fwd, used by ssh (and sshd in v1) */
 int
 channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
-    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
+    const char *host_to_connect, u_short port_to_connect, int gateway_ports, 
+    int hpn_disabled, int hpn_buffer_size)
 {
        return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
            listen_host, listen_port, host_to_connect, port_to_connect,
-           gateway_ports);
+           gateway_ports, hpn_disabled, hpn_buffer_size);
 }
 
 /* protocol v2 remote port fwd, used by sshd */
 int
 channel_setup_remote_fwd_listener(const char *listen_address,
-    u_short listen_port, int gateway_ports)
+    u_short listen_port, int gateway_ports, int hpn_disabled, int hpn_buffer_size)
 {
        return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
-           listen_address, listen_port, NULL, 0, gateway_ports);
+           listen_address, listen_port, NULL, 0, gateway_ports, 
+           hpn_disabled, hpn_buffer_size);
 }
 
 /*
@@ -2571,7 +2591,8 @@ channel_request_rforward_cancel(const char *host, u_short port)
  */
 
 void
-channel_input_port_forward_request(int is_root, int gateway_ports)
+channel_input_port_forward_request(int is_root, int gateway_ports, 
+       int hpn_disabled, int hpn_buffer_size)
 {
        u_short port, host_port;
        char *hostname;
@@ -2596,7 +2617,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports)
 
        /* Initiate forwarding */
        channel_setup_local_fwd_listener(NULL, port, hostname,
-           host_port, gateway_ports);
+           host_port, gateway_ports, hpn_disabled, hpn_buffer_size);
 
        /* Free the argument string. */
        xfree(hostname);
@@ -2766,7 +2787,8 @@ channel_send_window_changes(void)
  */
 int
 x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
-    int single_connection, u_int *display_numberp, int **chanids)
+    int single_connection, u_int *display_numberp, int **chanids, 
+    int hpn_disabled, int hpn_buffer_size)
 {
        Channel *nc = NULL;
        int display_number, sock;
@@ -2863,10 +2885,16 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
        *chanids = xmalloc(sizeof(**chanids) * (num_socks + 1));
        for (n = 0; n < num_socks; n++) {
                sock = socks[n];
-               nc = channel_new("x11 listener",
-                   SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
-                   CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
-                   0, "X11 inet listener", 1);
+               if (hpn_disabled) 
+                       nc = channel_new("x11 listener",
+                           SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+                           CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+                           0, "X11 inet listener", 1);
+               else 
+                       nc = channel_new("x11 listener",
+                           SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+                           hpn_buffer_size, CHAN_X11_PACKET_DEFAULT,
+                           0, "X11 inet listener", 1);
                nc->single_connection = single_connection;
                (*chanids)[n] = nc->self;
        }
index 3f4b7885f8ff8c72bee31522c5eebe50588788ef..f380531dcb7dce69fd1540c49dabdf05b894a2a3 100644 (file)
@@ -103,6 +103,7 @@ struct Channel {
        int     dynamic_window;
        int     extended_usage;
        int     single_connection;
+       u_int   tcpwinsz;       
 
        char   *ctype;          /* type */
 
@@ -124,12 +125,17 @@ struct Channel {
 #define CHAN_EXTENDED_WRITE            2
 
 /* default window/packet sizes for tcp/x11-fwd-channel */
-#define CHAN_SES_PACKET_DEFAULT        (32*1024)
-#define CHAN_SES_WINDOW_DEFAULT        (0xa00000/2)
-#define CHAN_TCP_PACKET_DEFAULT        (32*1024)
-#define CHAN_TCP_WINDOW_DEFAULT        (0xa00000/2)
-#define CHAN_X11_PACKET_DEFAULT        (16*1024)
-#define CHAN_X11_WINDOW_DEFAULT        (0xa00000/2)
+#define CHAN_SES_PACKET_DEFAULT                (32*1024)
+#define CHAN_SES_WINDOW_DEFAULT_HPN    (160*CHAN_TCP_PACKET_DEFAULT)
+#define CHAN_SES_WINDOW_DEFAULT                (4*CHAN_SES_PACKET_DEFAULT)
+
+#define CHAN_TCP_PACKET_DEFAULT                (32*1024)
+#define CHAN_TCP_WINDOW_DEFAULT_HPN    (160*CHAN_TCP_PACKET_DEFAULT)
+#define CHAN_TCP_WINDOW_DEFAULT                (4*CHAN_TCP_PACKET_DEFAULT)
+
+#define CHAN_X11_PACKET_DEFAULT                (16*1024)
+#define CHAN_X11_WINDOW_DEFAULT_HPN    (4*CHAN_X11_PACKET_DEFAULT)
+#define CHAN_X11_WINDOW_DEFAULT                (4*CHAN_X11_PACKET_DEFAULT)
 
 /* possible input states */
 #define CHAN_INPUT_OPEN                        0
@@ -209,21 +215,21 @@ void       channel_set_af(int af);
 void     channel_permit_all_opens(void);
 void    channel_add_permitted_opens(char *, int);
 void    channel_clear_permitted_opens(void);
-void     channel_input_port_forward_request(int, int);
+void     channel_input_port_forward_request(int, int, int, int);
 int     channel_connect_to(const char *, u_short);
 int     channel_connect_by_listen_address(u_short);
 void    channel_request_remote_forwarding(const char *, u_short,
             const char *, u_short);
 int     channel_setup_local_fwd_listener(const char *, u_short,
-            const char *, u_short, int);
+            const char *, u_short, int, int, int);
 void    channel_request_rforward_cancel(const char *host, u_short port);
-int     channel_setup_remote_fwd_listener(const char *, u_short, int);
+int     channel_setup_remote_fwd_listener(const char *, u_short, int, int, int);
 int     channel_cancel_rport_listener(const char *, u_short);
 
 /* x11 forwarding */
 
 int     x11_connect_display(void);
-int     x11_create_display_inet(int, int, int, u_int *, int **);
+int     x11_create_display_inet(int, int, int, u_int *, int **, int, int);
 void     x11_input_open(int, u_int32_t, void *);
 void    x11_request_forwarding_with_spoofing(int, const char *, const char *,
            const char *);
index cbcb1d1998a26dbebd2f28d3b61277ba12097a6b..3089bcf9cf784689537a23a5248b6c9d2b37030e 100644 (file)
@@ -59,7 +59,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.87 2001/11/09 18:59:23 markus Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.149 2005/12/30 15:56:37 reyk Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -77,10 +77,14 @@ RCSID("$OpenBSD: clientloop.c,v 1.87 2001/11/09 18:59:23 markus Exp $");
 #include "log.h"
 #include "readconf.h"
 #include "clientloop.h"
+#include "sshconnect.h"
 #include "authfd.h"
 #include "atomicio.h"
-#include "sshtty.h"
+#include "sshpty.h"
 #include "misc.h"
+#include "monitor_fdpass.h"
+#include "match.h"
+#include "msg.h"
 
 /* import options */
 extern Options options;
@@ -88,6 +92,12 @@ extern Options options;
 /* Flag indicating that stdin should be redirected from /dev/null. */
 extern int stdin_null_flag;
 
+/* Flag indicating that no shell has been requested */
+extern int no_shell_flag;
+
+/* Control socket */
+extern int control_fd;
+
 /*
  * Name of the host we are connecting to.  This is the name given on the
  * command line, or the HostName specified for the user-supplied name in a
@@ -101,10 +111,10 @@ extern char *host;
  * window size to be sent to the server a little later.  This is volatile
  * because this is updated in a signal handler.
  */
-static volatile int received_window_change_signal = 0;
-static volatile int received_signal = 0;
+static volatile sig_atomic_t received_window_change_signal = 0;
+static volatile sig_atomic_t received_signal = 0;
 
-/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
+/* Flag indicating whether the user's terminal is in non-blocking mode. */
 static int in_non_blocking_mode = 0;
 
 /* Common data for the client loop code. */
@@ -123,22 +133,35 @@ static int connection_in; /* Connection to server (input). */
 static int connection_out;     /* Connection to server (output). */
 static int need_rekeying;      /* Set to non-zero if rekeying is requested. */
 static int session_closed = 0; /* In SSH2: login session closed. */
+static int server_alive_timeouts = 0;
 
 static void client_init_dispatch(void);
 int    session_ident = -1;
 
+struct confirm_ctx {
+       int want_tty;
+       int want_subsys;
+       int want_x_fwd;
+       int want_agent_fwd;
+       Buffer cmd;
+       char *term;
+       struct termios tio;
+       char **env;
+};
+
 /*XXX*/
 extern Kex *xxx_kex;
 
+void ssh_process_session2_setup(int, int, int, Buffer *);
+
 /* Restores stdin to blocking mode. */
 
 static void
 leave_non_blocking(void)
 {
        if (in_non_blocking_mode) {
-               (void) fcntl(fileno(stdin), F_SETFL, 0);
+               unset_nonblock(fileno(stdin));
                in_non_blocking_mode = 0;
-               fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
        }
 }
 
@@ -148,8 +171,7 @@ static void
 enter_non_blocking(void)
 {
        in_non_blocking_mode = 1;
-       (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
-       fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
+       set_nonblock(fileno(stdin));
 }
 
 /*
@@ -189,6 +211,109 @@ get_current_time(void)
        return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
 }
 
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+void
+client_x11_get_proto(const char *display, const char *xauth_path,
+    u_int trusted, char **_proto, char **_data)
+{
+       char cmd[1024];
+       char line[512];
+       char xdisplay[512];
+       static char proto[512], data[512];
+       FILE *f;
+       int got_data = 0, generated = 0, do_unlink = 0, i;
+       char *xauthdir, *xauthfile;
+       struct stat st;
+
+       xauthdir = xauthfile = NULL;
+       *_proto = proto;
+       *_data = data;
+       proto[0] = data[0] = '\0';
+
+       if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+               debug("No xauth program.");
+       } else {
+               if (display == NULL) {
+                       debug("x11_get_proto: DISPLAY not set");
+                       return;
+               }
+               /*
+                * Handle FamilyLocal case where $DISPLAY does
+                * not match an authorization entry.  For this we
+                * just try "xauth list unix:displaynum.screennum".
+                * XXX: "localhost" match to determine FamilyLocal
+                *      is not perfect.
+                */
+               if (strncmp(display, "localhost:", 10) == 0) {
+                       snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+                           display + 10);
+                       display = xdisplay;
+               }
+               if (trusted == 0) {
+                       xauthdir = xmalloc(MAXPATHLEN);
+                       xauthfile = xmalloc(MAXPATHLEN);
+                       strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
+                       if (mkdtemp(xauthdir) != NULL) {
+                               do_unlink = 1;
+                               snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
+                                   xauthdir);
+                               snprintf(cmd, sizeof(cmd),
+                                   "%s -f %s generate %s " SSH_X11_PROTO
+                                   " untrusted timeout 1200 2>" _PATH_DEVNULL,
+                                   xauth_path, xauthfile, display);
+                               debug2("x11_get_proto: %s", cmd);
+                               if (system(cmd) == 0)
+                                       generated = 1;
+                       }
+               }
+               snprintf(cmd, sizeof(cmd),
+                   "%s %s%s list %s 2>" _PATH_DEVNULL,
+                   xauth_path,
+                   generated ? "-f " : "" ,
+                   generated ? xauthfile : "",
+                   display);
+               debug2("x11_get_proto: %s", cmd);
+               f = popen(cmd, "r");
+               if (f && fgets(line, sizeof(line), f) &&
+                   sscanf(line, "%*s %511s %511s", proto, data) == 2)
+                       got_data = 1;
+               if (f)
+                       pclose(f);
+       }
+
+       if (do_unlink) {
+               unlink(xauthfile);
+               rmdir(xauthdir);
+       }
+       if (xauthdir)
+               xfree(xauthdir);
+       if (xauthfile)
+               xfree(xauthfile);
+
+       /*
+        * If we didn't get authentication data, just make up some
+        * data.  The forwarding code will check the validity of the
+        * response anyway, and substitute this data.  The X11
+        * server, however, will ignore this fake data and use
+        * whatever authentication mechanisms it was using otherwise
+        * for the local connection.
+        */
+       if (!got_data) {
+               u_int32_t rnd = 0;
+
+               logit("Warning: No xauth data; "
+                   "using fake authentication data for X11 forwarding.");
+               strlcpy(proto, SSH_X11_PROTO, sizeof proto);
+               for (i = 0; i < 16; i++) {
+                       if (i % 4 == 0)
+                               rnd = arc4random();
+                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
+                           rnd & 0xff);
+                       rnd >>= 8;
+               }
+       }
+}
+
 /*
  * This is called when the interactive is entered.  This checks if there is
  * an EOF coming on stdin.  We must check this explicitly, as select() does
@@ -254,7 +379,7 @@ client_make_packets_from_stdin_data(void)
 
        /* Send buffered stdin data to the server. */
        while (buffer_len(&stdin_buffer) > 0 &&
-              packet_not_very_much_data_to_write()) {
+           packet_not_very_much_data_to_write()) {
                len = buffer_len(&stdin_buffer);
                /* Keep the packets at reasonable size. */
                if (len > packet_get_maxsize())
@@ -289,19 +414,13 @@ client_check_window_change(void)
        /** XXX race */
        received_window_change_signal = 0;
 
-       if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
-               return;
-
        debug2("client_check_window_change: changed");
 
        if (compat20) {
-               channel_request_start(session_ident, "window-change", 0);
-               packet_put_int(ws.ws_col);
-               packet_put_int(ws.ws_row);
-               packet_put_int(ws.ws_xpixel);
-               packet_put_int(ws.ws_ypixel);
-               packet_send();
+               channel_send_window_changes();
        } else {
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       return;
                packet_start(SSH_CMSG_WINDOW_SIZE);
                packet_put_int(ws.ws_row);
                packet_put_int(ws.ws_col);
@@ -311,15 +430,35 @@ client_check_window_change(void)
        }
 }
 
+static void
+client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+{
+       server_alive_timeouts = 0;
+       client_global_request_reply_fwd(type, seq, ctxt);
+}
+
+static void
+server_alive_check(void)
+{
+       if (++server_alive_timeouts > options.server_alive_count_max)
+               packet_disconnect("Timeout, server not responding.");
+       packet_start(SSH2_MSG_GLOBAL_REQUEST);
+       packet_put_cstring("keepalive@openssh.com");
+       packet_put_char(1);     /* boolean: want reply */
+       packet_send();
+}
+
 /*
  * Waits until the client can do something (some data becomes available on
  * one of the file descriptors).
  */
-
 static void
 client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
-    int *maxfdp, int *nallocp, int rekeying)
+    int *maxfdp, u_int *nallocp, int rekeying)
 {
+       struct timeval tv, *tvp;
+       int ret;
+
        /* Add any selections by the channel mechanism. */
        channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
 
@@ -358,16 +497,24 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
        if (packet_have_data_to_write())
                FD_SET(connection_out, *writesetp);
 
+       if (control_fd != -1)
+               FD_SET(control_fd, *readsetp);
+
        /*
         * Wait for something to happen.  This will suspend the process until
         * some selected descriptor can be read, written, or has some other
-        * event pending. Note: if you want to implement SSH_MSG_IGNORE
-        * messages to fool traffic analysis, this might be the place to do
-        * it: just have a random timeout for the select, and send a random
-        * SSH_MSG_IGNORE packet when the timeout expires.
+        * event pending.
         */
 
-       if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
+       if (options.server_alive_interval == 0 || !compat20)
+               tvp = NULL;
+       else {
+               tv.tv_sec = options.server_alive_interval;
+               tv.tv_usec = 0;
+               tvp = &tv;
+       }
+       ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+       if (ret < 0) {
                char buf[100];
 
                /*
@@ -384,19 +531,18 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
                snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
                buffer_append(&stderr_buffer, buf, strlen(buf));
                quit_pending = 1;
-       }
+       } else if (ret == 0)
+               server_alive_check();
 }
 
 static void
 client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
 {
-       struct winsize oldws, newws;
-
        /* Flush stdout and stderr buffers. */
        if (buffer_len(bout) > 0)
-               atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
+               atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
        if (buffer_len(berr) > 0)
-               atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
+               atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
 
        leave_raw_mode();
 
@@ -408,19 +554,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
        buffer_free(bout);
        buffer_free(berr);
 
-       /* Save old window size. */
-       ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
-
        /* Send the suspend signal to the program itself. */
        kill(getpid(), SIGTSTP);
 
-       /* Check if the window size has changed. */
-       if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
-           (oldws.ws_row != newws.ws_row ||
-            oldws.ws_col != newws.ws_col ||
-            oldws.ws_xpixel != newws.ws_xpixel ||
-            oldws.ws_ypixel != newws.ws_ypixel))
-               received_window_change_signal = 1;
+       /* Reset window sizes in case they have changed */
+       received_window_change_signal = 1;
 
        /* OK, we have been continued by the user. Reinitialize buffers. */
        buffer_init(bin);
@@ -470,6 +608,433 @@ client_process_net_input(fd_set * readset)
        }
 }
 
+static void
+client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
+{
+       int id;
+       Channel *c;
+
+       id = packet_get_int();
+       packet_check_eom();
+
+       if ((c = channel_lookup(id)) == NULL) {
+               error("%s: no channel for id %d", __func__, id);
+               return;
+       }
+
+       if (type == SSH2_MSG_CHANNEL_SUCCESS)
+               debug2("Request suceeded on channel %d", id);
+       else if (type == SSH2_MSG_CHANNEL_FAILURE) {
+               error("Request failed on channel %d", id);
+               channel_free(c);
+       }
+}
+
+static void
+client_extra_session2_setup(int id, void *arg)
+{
+       struct confirm_ctx *cctx = arg;
+       const char *display;
+       Channel *c;
+       int i;
+
+       if (cctx == NULL)
+               fatal("%s: cctx == NULL", __func__);
+       if ((c = channel_lookup(id)) == NULL)
+               fatal("%s: no channel for id %d", __func__, id);
+
+       display = getenv("DISPLAY");
+       if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
+               char *proto, *data;
+               /* Get reasonable local authentication information. */
+               client_x11_get_proto(display, options.xauth_location,
+                   options.forward_x11_trusted, &proto, &data);
+               /* Request forwarding with authentication spoofing. */
+               debug("Requesting X11 forwarding with authentication spoofing.");
+               x11_request_forwarding_with_spoofing(id, display, proto, data);
+               /* XXX wait for reply */
+       }
+
+       if (cctx->want_agent_fwd && options.forward_agent) {
+               debug("Requesting authentication agent forwarding.");
+               channel_request_start(id, "auth-agent-req@openssh.com", 0);
+               packet_send();
+       }
+
+       client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
+           cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
+           client_subsystem_reply);
+
+       c->confirm_ctx = NULL;
+       buffer_free(&cctx->cmd);
+       xfree(cctx->term);
+       if (cctx->env != NULL) {
+               for (i = 0; cctx->env[i] != NULL; i++)
+                       xfree(cctx->env[i]);
+               xfree(cctx->env);
+       }
+       xfree(cctx);
+}
+
+static void
+client_process_control(fd_set * readset)
+{
+       Buffer m;
+       Channel *c;
+       int client_fd, new_fd[3], ver, allowed;
+       socklen_t addrlen;
+       struct sockaddr_storage addr;
+       struct confirm_ctx *cctx;
+       char *cmd;
+       u_int i, len, env_len, command, flags;
+       uid_t euid;
+       gid_t egid;
+       int listen_port = 0;
+       int connect_port = 0;
+       char * listen_host = NULL;
+       char * connect_host = NULL;
+
+       /*
+        * Accept connection on control socket
+        */
+       if (control_fd == -1 || !FD_ISSET(control_fd, readset))
+               return;
+
+       memset(&addr, 0, sizeof(addr));
+       addrlen = sizeof(addr);
+       if ((client_fd = accept(control_fd,
+           (struct sockaddr*)&addr, &addrlen)) == -1) {
+               error("%s accept: %s", __func__, strerror(errno));
+               return;
+       }
+
+       if (getpeereid(client_fd, &euid, &egid) < 0) {
+               error("%s getpeereid failed: %s", __func__, strerror(errno));
+               close(client_fd);
+               return;
+       }
+       if ((euid != 0) && (getuid() != euid)) {
+               error("control mode uid mismatch: peer euid %u != uid %u",
+                   (u_int) euid, (u_int) getuid());
+               close(client_fd);
+               return;
+       }
+
+       unset_nonblock(client_fd);
+
+       /* Read command */
+       buffer_init(&m);
+       if (ssh_msg_recv(client_fd, &m) == -1) {
+               error("%s: client msg_recv failed", __func__);
+               close(client_fd);
+               buffer_free(&m);
+               return;
+       }
+       if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
+               error("%s: wrong client version %d", __func__, ver);
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       }
+
+       allowed = 1;
+       command = buffer_get_int(&m);
+       flags = buffer_get_int(&m);
+
+       if (SSHMUX_FLAG_PORTFORWARD & flags)
+       {
+               listen_host = buffer_get_string(&m,NULL);
+               listen_port = buffer_get_int(&m);
+               connect_host = buffer_get_string(&m,NULL);
+               connect_port = buffer_get_int(&m);
+       }
+       buffer_clear(&m);
+
+       switch (command) {
+       case SSHMUX_COMMAND_OPEN:
+               if (options.control_master == SSHCTL_MASTER_ASK ||
+                   options.control_master == SSHCTL_MASTER_AUTO_ASK)
+                       allowed = ask_permission("Allow shared connection "
+                           "to %s? ", host);
+               /* continue below */
+               break;
+       case SSHMUX_COMMAND_TERMINATE:
+               if (options.control_master == SSHCTL_MASTER_ASK ||
+                   options.control_master == SSHCTL_MASTER_AUTO_ASK)
+                       allowed = ask_permission("Terminate shared connection "
+                           "to %s? ", host);
+               if (allowed)
+                       quit_pending = 1;
+               /* FALLTHROUGH */
+       case SSHMUX_COMMAND_ALIVE_CHECK:
+               /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
+               buffer_clear(&m);
+               buffer_put_int(&m, allowed);
+               buffer_put_int(&m, getpid());
+               if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
+                       error("%s: client msg_send failed", __func__);
+                       close(client_fd);
+                       buffer_free(&m);
+                       return;
+               }
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       default:
+               error("Unsupported command %d", command);
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       }
+
+       if (allowed && (SSHMUX_FLAG_PORTFORWARD & flags) && listen_host && connect_host)
+       {
+               int ret;
+               Forward * fwd;
+
+               fwd = &options.local_forwards[options.num_local_forwards++];
+               fwd->listen_host = xstrdup(listen_host);
+               fwd->listen_port = listen_port;
+               fwd->connect_host = xstrdup(connect_host);
+               fwd->connect_port = connect_port;
+               ret = channel_setup_local_fwd_listener(
+                       options.local_forwards[options.num_local_forwards-1].listen_host,
+                       options.local_forwards[options.num_local_forwards-1].listen_port,
+                       options.local_forwards[options.num_local_forwards-1].connect_host,
+                       options.local_forwards[options.num_local_forwards-1].connect_port,
+                        options.gateway_ports, options.hpn_disabled, options.hpn_buffer_size);
+
+        }
+
+       
+       if (listen_host)
+               xfree(listen_host);
+       if (connect_host)
+               xfree(connect_host);
+
+       /* Reply for SSHMUX_COMMAND_OPEN */
+       buffer_clear(&m);
+       buffer_put_int(&m, allowed);
+       buffer_put_int(&m, getpid());
+       if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
+               error("%s: client msg_send failed", __func__);
+               close(client_fd);
+               buffer_free(&m);
+               return;
+       }
+
+       if (!allowed) {
+               error("Refused control connection");
+               close(client_fd);
+               buffer_free(&m);
+               return;
+       }
+
+       buffer_clear(&m);
+       if (ssh_msg_recv(client_fd, &m) == -1) {
+               error("%s: client msg_recv failed", __func__);
+               close(client_fd);
+               buffer_free(&m);
+               return;
+       }
+       if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
+               error("%s: wrong client version %d", __func__, ver);
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       }
+
+       cctx = xmalloc(sizeof(*cctx));
+       memset(cctx, 0, sizeof(*cctx));
+       cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
+       cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
+       cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
+       cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
+       cctx->term = buffer_get_string(&m, &len);
+
+       cmd = buffer_get_string(&m, &len);
+       buffer_init(&cctx->cmd);
+       buffer_append(&cctx->cmd, cmd, strlen(cmd));
+
+       env_len = buffer_get_int(&m);
+       env_len = MIN(env_len, 4096);
+       debug3("%s: receiving %d env vars", __func__, env_len);
+       if (env_len != 0) {
+               cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1));
+               for (i = 0; i < env_len; i++)
+                       cctx->env[i] = buffer_get_string(&m, &len);
+               cctx->env[i] = NULL;
+       }
+
+       debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
+           cctx->want_tty, cctx->want_subsys, cmd);
+
+       /* Gather fds from client */
+       new_fd[0] = mm_receive_fd(client_fd);
+       new_fd[1] = mm_receive_fd(client_fd);
+       new_fd[2] = mm_receive_fd(client_fd);
+
+       debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
+           new_fd[0], new_fd[1], new_fd[2]);
+
+       /* Try to pick up ttymodes from client before it goes raw */
+       if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
+               error("%s: tcgetattr: %s", __func__, strerror(errno));
+
+       /* This roundtrip is just for synchronisation of ttymodes */
+       buffer_clear(&m);
+       if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
+               error("%s: client msg_send failed", __func__);
+               close(client_fd);
+               close(new_fd[0]);
+               close(new_fd[1]);
+               close(new_fd[2]);
+               buffer_free(&m);
+               xfree(cctx->term);
+               if (env_len != 0) {
+                       for (i = 0; i < env_len; i++)
+                               xfree(cctx->env[i]);
+                       xfree(cctx->env);
+               }
+               return;
+       }
+       buffer_free(&m);
+
+       /* enable nonblocking unless tty */
+       if (!isatty(new_fd[0]))
+               set_nonblock(new_fd[0]);
+       if (!isatty(new_fd[1]))
+               set_nonblock(new_fd[1]);
+       if (!isatty(new_fd[2]))
+               set_nonblock(new_fd[2]);
+
+       set_nonblock(client_fd);
+
+       if (options.hpn_disabled) 
+               c = channel_new("session", SSH_CHANNEL_OPENING,
+                   new_fd[0], new_fd[1], new_fd[2],
+                   CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT,
+                   CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
+       else 
+               c = channel_new("session", SSH_CHANNEL_OPENING,
+                   new_fd[0], new_fd[1], new_fd[2],
+                   options.hpn_buffer_size, CHAN_SES_PACKET_DEFAULT,
+                   CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
+       /* XXX */
+       c->ctl_fd = client_fd;
+
+       debug3("%s: channel_new: %d", __func__, c->self);
+
+       channel_send_open(c->self);
+       channel_register_confirm(c->self, client_extra_session2_setup, cctx);
+}
+
+static void
+process_cmdline(void)
+{
+       void (*handler)(int);
+       char *s, *cmd, *cancel_host;
+       int delete = 0;
+       int local = 0;
+       u_short cancel_port;
+       Forward fwd;
+
+       leave_raw_mode();
+       handler = signal(SIGINT, SIG_IGN);
+       cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
+       if (s == NULL)
+               goto out;
+       while (*s && isspace(*s))
+               s++;
+       if (*s == '-')
+               s++;    /* Skip cmdline '-', if any */
+       if (*s == '\0')
+               goto out;
+
+       if (*s == 'h' || *s == 'H' || *s == '?') {
+               logit("Commands:");
+               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;
+       }
+
+       if (*s == 'K') {
+               delete = 1;
+               s++;
+       }
+       if (*s != 'L' && *s != 'R') {
+               logit("Invalid command.");
+               goto out;
+       }
+       if (*s == 'L')
+               local = 1;
+       if (local && delete) {
+               logit("Not supported.");
+               goto out;
+       }
+       if ((!local || delete) && !compat20) {
+               logit("Not supported for SSH protocol version 1.");
+               goto out;
+       }
+
+       s++;
+       while (*s && isspace(*s))
+               s++;
+
+       if (delete) {
+               cancel_port = 0;
+               cancel_host = hpdelim(&s);      /* may be NULL */
+               if (s != NULL) {
+                       cancel_port = a2port(s);
+                       cancel_host = cleanhostname(cancel_host);
+               } else {
+                       cancel_port = a2port(cancel_host);
+                       cancel_host = NULL;
+               }
+               if (cancel_port == 0) {
+                       logit("Bad forwarding close port");
+                       goto out;
+               }
+               channel_request_rforward_cancel(cancel_host, cancel_port);
+       } else {
+               if (!parse_forward(&fwd, s)) {
+                       logit("Bad forwarding specification.");
+                       goto out;
+               }
+               if (local) {
+                       if (channel_setup_local_fwd_listener(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port, options.gateway_ports, 
+                           options.hpn_disabled, options.hpn_buffer_size) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               } else {
+                       channel_request_remote_forwarding(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port);
+               }
+
+               logit("Forwarding port.");
+       }
+
+out:
+       signal(SIGINT, handler);
+       enter_raw_mode();
+       if (cmd)
+               xfree(cmd);
+}
+
 /* process the characters one by one */
 static int
 process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
@@ -481,7 +1046,10 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
        u_char ch;
        char *s;
 
-       for (i = 0; i < len; i++) {
+       if (len <= 0)
+               return (0);
+
+       for (i = 0; i < (u_int)len; i++) {
                /* Get one character at a time. */
                ch = buf[i];
 
@@ -512,10 +1080,23 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
                                /* We have been continued. */
                                continue;
 
+                       case 'B':
+                               if (compat20) {
+                                       snprintf(string, sizeof string,
+                                           "%cB\r\n", escape_char);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       channel_request_start(session_ident,
+                                           "break", 0);
+                                       packet_put_int(1000);
+                                       packet_send();
+                               }
+                               continue;
+
                        case 'R':
                                if (compat20) {
                                        if (datafellows & SSH_BUG_NOREKEY)
-                                               log("Server does not support re-keying");
+                                               logit("Server does not support re-keying");
                                        else
                                                need_rekeying = 1;
                                }
@@ -573,15 +1154,19 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
                                snprintf(string, sizeof string,
 "%c?\r\n\
 Supported escape sequences:\r\n\
-~.  - terminate connection\r\n\
-~R  - Request rekey (SSH protocol 2 only)\r\n\
-~^Z - suspend ssh\r\n\
-~#  - list forwarded connections\r\n\
-~&  - background ssh (when waiting for connections to terminate)\r\n\
-~?  - this message\r\n\
-~~  - send the escape character by typing it twice\r\n\
+%c.  - terminate connection\r\n\
+%cB  - send a BREAK to the remote system\r\n\
+%cC  - open a command line\r\n\
+%cR  - Request rekey (SSH protocol 2 only)\r\n\
+%c^Z - suspend ssh\r\n\
+%c#  - list forwarded connections\r\n\
+%c&  - background ssh (when waiting for connections to terminate)\r\n\
+%c?  - this message\r\n\
+%c%c  - send the escape character by typing it twice\r\n\
 (Note that escapes are only recognized immediately after newline.)\r\n",
-                                        escape_char);
+                                   escape_char, escape_char, escape_char, escape_char,
+                                   escape_char, escape_char, escape_char, escape_char,
+                                   escape_char, escape_char, escape_char);
                                buffer_append(berr, string, strlen(string));
                                continue;
 
@@ -593,6 +1178,10 @@ Supported escape sequences:\r\n\
                                xfree(s);
                                continue;
 
+                       case 'C':
+                               process_cmdline();
+                               continue;
+
                        default:
                                if (ch != escape_char) {
                                        buffer_put_char(bin, escape_char);
@@ -756,13 +1345,9 @@ simple_escape_filter(Channel *c, char *buf, int len)
 static void
 client_channel_closed(int id, void *arg)
 {
-       if (id != session_ident)
-               error("client_channel_closed: id %d != session_ident %d",
-                   id, session_ident);
        channel_cancel_cleanup(id);
        session_closed = 1;
-       if (in_raw_mode())
-               leave_raw_mode();
+       leave_raw_mode();
 }
 
 /*
@@ -777,7 +1362,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
 {
        fd_set *readset = NULL, *writeset = NULL;
        double start_time, total_time;
-       int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0;
+       int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+       u_int nalloc = 0;
        char buf[100];
 
        debug("Entering interactive session.");
@@ -793,6 +1379,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        connection_in = packet_get_connection_in();
        connection_out = packet_get_connection_out();
        max_fd = MAX(connection_in, connection_out);
+       if (control_fd != -1)
+               max_fd = MAX(max_fd, control_fd);
 
        if (!compat20) {
                /* enable nonblocking unless tty */
@@ -819,12 +1407,19 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
 
        client_init_dispatch();
 
-       /* Set signal handlers to restore non-blocking mode.  */
-       signal(SIGINT, signal_handler);
-       signal(SIGQUIT, signal_handler);
-       signal(SIGTERM, signal_handler);
-       if (have_pty)
-               signal(SIGWINCH, window_change_handler);
+       /*
+        * Set signal handlers, (e.g. to restore non-blocking mode)
+        * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
+        */
+       if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               signal(SIGHUP, signal_handler);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, signal_handler);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               signal(SIGQUIT, signal_handler);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               signal(SIGTERM, signal_handler);
+       signal(SIGWINCH, window_change_handler);
 
        if (have_pty)
                enter_raw_mode();
@@ -833,10 +1428,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                session_ident = ssh2_chan_id;
                if (escape_char != SSH_ESCAPECHAR_NONE)
                        channel_register_filter(session_ident,
-                           simple_escape_filter);
+                           simple_escape_filter, NULL);
                if (session_ident != -1)
                        channel_register_cleanup(session_ident,
-                           client_channel_closed);
+                           client_channel_closed, 0);
        } else {
                /* Check if we should immediately send eof on stdin. */
                client_check_initial_eof_on_stdin();
@@ -893,9 +1488,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                /* Do channel operations unless rekeying in progress. */
                if (!rekeying) {
                        channel_after_select(readset, writeset);
-
-                       if (need_rekeying) {
-                               debug("user requests rekeying");
+                       if (need_rekeying || packet_need_rekeying()) {
+                               debug("need rekeying");
                                xxx_kex->done = 0;
                                kex_send_kexinit(xxx_kex);
                                need_rekeying = 0;
@@ -905,6 +1499,9 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                /* Buffer input from the connection.  */
                client_process_net_input(readset);
 
+               /* Accept control connections.  */
+               client_process_control(readset);
+
                if (quit_pending)
                        break;
 
@@ -930,8 +1527,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        /* Terminate the session. */
 
        /* Stop watching for window change. */
-       if (have_pty)
-               signal(SIGWINCH, SIG_DFL);
+       signal(SIGWINCH, SIG_DFL);
 
        channel_free_all();
 
@@ -946,12 +1542,19 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        if (!isatty(fileno(stderr)))
                unset_nonblock(fileno(stderr));
 
-       if (received_signal) {
-               if (in_non_blocking_mode)       /* XXX */
-                       leave_non_blocking();
-               fatal("Killed by signal %d.", received_signal);
+       /*
+        * If there was no shell or command requested, there will be no remote
+        * exit status to be returned.  In that case, clear error code if the
+        * connection was deliberately terminated at this end.
+        */
+       if (no_shell_flag && received_signal == SIGTERM) {
+               received_signal = 0;
+               exit_status = 0;
        }
 
+       if (received_signal)
+               fatal("Killed by signal %d.", (int) received_signal);
+
        /*
         * In interactive mode (with pseudo tty) display a message indicating
         * that the connection has been closed.
@@ -994,11 +1597,11 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        /* Report bytes transferred, and transfer rates. */
        total_time = get_current_time() - start_time;
        debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
-             stdin_bytes, stdout_bytes, stderr_bytes, total_time);
+           stdin_bytes, stdout_bytes, stderr_bytes, total_time);
        if (total_time > 0)
                debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
-                     stdin_bytes / total_time, stdout_bytes / total_time,
-                     stderr_bytes / total_time);
+                   stdin_bytes / total_time, stdout_bytes / total_time,
+                   stderr_bytes / total_time);
 
        /* Return the exit status of the program. */
        debug("Exit status %d", exit_status);
@@ -1008,30 +1611,30 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
 /*********/
 
 static void
-client_input_stdout_data(int type, int plen, void *ctxt)
+client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
 {
        u_int data_len;
        char *data = packet_get_string(&data_len);
-       packet_integrity_check(plen, 4 + data_len, type);
+       packet_check_eom();
        buffer_append(&stdout_buffer, data, data_len);
        memset(data, 0, data_len);
        xfree(data);
 }
 static void
-client_input_stderr_data(int type, int plen, void *ctxt)
+client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
 {
        u_int data_len;
        char *data = packet_get_string(&data_len);
-       packet_integrity_check(plen, 4 + data_len, type);
+       packet_check_eom();
        buffer_append(&stderr_buffer, data, data_len);
        memset(data, 0, data_len);
        xfree(data);
 }
 static void
-client_input_exit_status(int type, int plen, void *ctxt)
+client_input_exit_status(int type, u_int32_t seq, void *ctxt)
 {
-       packet_integrity_check(plen, 4, type);
        exit_status = packet_get_int();
+       packet_check_eom();
        /* Acknowledge the exit. */
        packet_start(SSH_CMSG_EXIT_CONFIRMATION);
        packet_send();
@@ -1043,11 +1646,51 @@ client_input_exit_status(int type, int plen, void *ctxt)
        /* Flag that we want to exit. */
        quit_pending = 1;
 }
+static void
+client_input_agent_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int remote_id, sock;
+
+       /* Read the remote channel number from the message. */
+       remote_id = packet_get_int();
+       packet_check_eom();
+
+       /*
+        * Get a connection to the local authentication agent (this may again
+        * get forwarded).
+        */
+       sock = ssh_get_authentication_socket();
+
+       /*
+        * If we could not connect the agent, send an error message back to
+        * the server. This should never happen unless the agent dies,
+        * because authentication forwarding is only enabled if we have an
+        * agent.
+        */
+       if (sock >= 0) {
+               c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
+                   -1, 0, 0, 0, "authentication agent connection", 1);
+               c->remote_id = remote_id;
+               c->force_drain = 1;
+       }
+       if (c == NULL) {
+               packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(remote_id);
+       } else {
+               /* Send a confirmation to the remote host. */
+               debug("Forwarding authentication connection.");
+               packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+               packet_put_int(remote_id);
+               packet_put_int(c->self);
+       }
+       packet_send();
+}
 
 static Channel *
 client_request_forwarded_tcpip(const char *request_type, int rchan)
 {
-       Channelc = NULL;
+       Channel *c = NULL;
        char *listen_address, *originator_address;
        int listen_port, originator_port;
        int sock;
@@ -1057,7 +1700,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
        listen_port = packet_get_int();
        originator_address = packet_get_string(NULL);
        originator_port = packet_get_int();
-       packet_done();
+       packet_check_eom();
 
        debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
            listen_address, listen_port, originator_address, originator_port);
@@ -1068,20 +1711,22 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
                xfree(listen_address);
                return NULL;
        }
-       c = channel_new("forwarded-tcpip",
-           SSH_CHANNEL_CONNECTING, sock, sock, -1,
-           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
-           xstrdup(originator_address), 1);
-       if (c == NULL) {
-               error("client_request_forwarded_tcpip: channel_new failed");
-               close(sock);
-       }
+       if (options.hpn_disabled) 
+               c = channel_new("forwarded-tcpip",
+                   SSH_CHANNEL_CONNECTING, sock, sock, -1,
+                   CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
+                   originator_address, 1);
+       else
+               c = channel_new("forwarded-tcpip",
+                   SSH_CHANNEL_CONNECTING, sock, sock, -1,
+                   options.hpn_buffer_size, options.hpn_buffer_size, 0,
+                   originator_address, 1);
        xfree(originator_address);
        xfree(listen_address);
        return c;
 }
 
-static Channel*
+static Channel *
 client_request_x11(const char *request_type, int rchan)
 {
        Channel *c = NULL;
@@ -1091,7 +1736,7 @@ client_request_x11(const char *request_type, int rchan)
 
        if (!options.forward_x11) {
                error("Warning: ssh server tried X11 forwarding.");
-               error("Warning: this is probably a break in attempt by a malicious server.");
+               error("Warning: this is probably a break-in attempt by a malicious server.");
                return NULL;
        }
        originator = packet_get_string(NULL);
@@ -1101,7 +1746,7 @@ client_request_x11(const char *request_type, int rchan)
        } else {
                originator_port = packet_get_int();
        }
-       packet_done();
+       packet_check_eom();
        /* XXX check permission */
        debug("client_request_x11: request from %s %d", originator,
            originator_port);
@@ -1109,19 +1754,19 @@ client_request_x11(const char *request_type, int rchan)
        sock = x11_connect_display();
        if (sock < 0)
                return NULL;
-       c = channel_new("x11",
-           SSH_CHANNEL_X11_OPEN, sock, sock, -1,
-           CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,
-           xstrdup("x11"), 1);
-       if (c == NULL) {
-               error("client_request_x11: channel_new failed");
-               close(sock);
-       }
+       if (options.hpn_disabled) 
+               c = channel_new("x11",
+                   SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+                   CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+       else 
+               c = channel_new("x11",
+                   SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+                   options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
        c->force_drain = 1;
        return c;
 }
 
-static Channel*
+static Channel *
 client_request_agent(const char *request_type, int rchan)
 {
        Channel *c = NULL;
@@ -1129,34 +1774,34 @@ client_request_agent(const char *request_type, int rchan)
 
        if (!options.forward_agent) {
                error("Warning: ssh server tried agent forwarding.");
-               error("Warning: this is probably a break in attempt by a malicious server.");
+               error("Warning: this is probably a break-in attempt by a malicious server.");
                return NULL;
        }
        sock =  ssh_get_authentication_socket();
        if (sock < 0)
                return NULL;
-       c = channel_new("authentication agent connection",
-           SSH_CHANNEL_OPEN, sock, sock, -1,
-           CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
-           xstrdup("authentication agent connection"), 1);
-       if (c == NULL) {
-               error("client_request_agent: channel_new failed");
-               close(sock);
-       }
+       if (options.hpn_disabled) 
+               c = channel_new("authentication agent connection",
+                   SSH_CHANNEL_OPEN, sock, sock, -1,
+                   CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
+                   "authentication agent connection", 1);
+       else
+               c = channel_new("authentication agent connection",
+                   SSH_CHANNEL_OPEN, sock, sock, -1,
+                   options.hpn_buffer_size, options.hpn_buffer_size, 0,
+                   "authentication agent connection", 1);
        c->force_drain = 1;
        return c;
 }
 
 /* XXXX move to generic input handler */
 static void
-client_input_channel_open(int type, int plen, void *ctxt)
+client_input_channel_open(int type, u_int32_t seq, void *ctxt)
 {
        Channel *c = NULL;
        char *ctype;
-       u_int len;
        int rchan;
-       int rmaxpack;
-       int rwindow;
+       u_int rmaxpack, rwindow, len;
 
        ctype = packet_get_string(&len);
        rchan = packet_get_int();
@@ -1201,10 +1846,10 @@ client_input_channel_open(int type, int plen, void *ctxt)
        xfree(ctype);
 }
 static void
-client_input_channel_req(int type, int plen, void *ctxt)
+client_input_channel_req(int type, u_int32_t seq, void *ctxt)
 {
        Channel *c = NULL;
-       int id, reply, success = 0;
+       int exitval, id, reply, success = 0;
        char *rtype;
 
        id = packet_get_int();
@@ -1214,33 +1859,153 @@ client_input_channel_req(int type, int plen, void *ctxt)
        debug("client_input_channel_req: channel %d rtype %s reply %d",
            id, rtype, reply);
 
-       if (session_ident == -1) {
-               error("client_input_channel_req: no channel %d", session_ident);
-       } else if (id != session_ident) {
-               error("client_input_channel_req: channel %d: wrong channel: %d",
-                   session_ident, id);
-       }
-       c = channel_lookup(id);
-       if (c == NULL) {
+       if (id == -1) {
+               error("client_input_channel_req: request for channel -1");
+       } else if ((c = channel_lookup(id)) == NULL) {
                error("client_input_channel_req: channel %d: unknown channel", id);
        } else if (strcmp(rtype, "exit-status") == 0) {
-               success = 1;
-               exit_status = packet_get_int();
-               packet_done();
+               exitval = packet_get_int();
+               if (id == session_ident) {
+                       success = 1;
+                       exit_status = exitval;
+               } else if (c->ctl_fd == -1) {
+                       error("client_input_channel_req: unexpected channel %d",
+                           session_ident);
+               } else {
+                       atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval));
+                       success = 1;
+               }
+               packet_check_eom();
        }
        if (reply) {
                packet_start(success ?
                    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
-               packet_put_int(c->remote_id);
+               packet_put_int(id);
                packet_send();
        }
        xfree(rtype);
 }
+static void
+client_input_global_request(int type, u_int32_t seq, void *ctxt)
+{
+       char *rtype;
+       int want_reply;
+       int success = 0;
+
+       rtype = packet_get_string(NULL);
+       want_reply = packet_get_char();
+       debug("client_input_global_request: rtype %s want_reply %d",
+           rtype, want_reply);
+       if (want_reply) {
+               packet_start(success ?
+                   SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               packet_send();
+               packet_write_wait();
+       }
+       xfree(rtype);
+}
+
+void
+client_session2_setup(int id, int want_tty, int want_subsystem,
+    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
+    dispatch_fn *subsys_repl)
+{
+       int len;
+       Channel *c = NULL;
+
+       debug2("%s: id %d", __func__, id);
+
+       if ((c = channel_lookup(id)) == NULL)
+               fatal("client_session2_setup: channel %d: unknown channel", id);
+
+       if (want_tty) {
+               struct winsize ws;
+               struct termios tio;
+
+               /* Store window size in the packet. */
+               if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+
+               channel_request_start(id, "pty-req", 0);
+               packet_put_cstring(term != NULL ? term : "");
+               packet_put_int(ws.ws_col);
+               packet_put_int(ws.ws_row);
+               packet_put_int(ws.ws_xpixel);
+               packet_put_int(ws.ws_ypixel);
+               tio = get_saved_tio();
+               tty_make_modes(-1, tiop != NULL ? tiop : &tio);
+               packet_send();
+               /* XXX wait for reply */
+               c->client_tty = 1;
+       }
+
+       /* Transfer any environment variables from client to server */
+       if (options.num_send_env != 0 && env != NULL) {
+               int i, j, matched;
+               char *name, *val;
+
+               debug("Sending environment.");
+               for (i = 0; env[i] != NULL; i++) {
+                       /* Split */
+                       name = xstrdup(env[i]);
+                       if ((val = strchr(name, '=')) == NULL) {
+                               xfree(name);
+                               continue;
+                       }
+                       *val++ = '\0';
+
+                       matched = 0;
+                       for (j = 0; j < options.num_send_env; j++) {
+                               if (match_pattern(name, options.send_env[j])) {
+                                       matched = 1;
+                                       break;
+                               }
+                       }
+                       if (!matched) {
+                               debug3("Ignored env %s", name);
+                               xfree(name);
+                               continue;
+                       }
+
+                       debug("Sending env %s = %s", name, val);
+                       channel_request_start(id, "env", 0);
+                       packet_put_cstring(name);
+                       packet_put_cstring(val);
+                       packet_send();
+                       xfree(name);
+               }
+       }
+
+       len = buffer_len(cmd);
+       if (len > 0) {
+               if (len > 900)
+                       len = 900;
+               if (want_subsystem) {
+                       debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "subsystem", subsys_repl != NULL);
+                       if (subsys_repl != NULL) {
+                               /* register callback for reply */
+                               /* XXX we assume that client_loop has already been called */
+                               dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
+                               dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
+                       }
+               } else {
+                       debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "exec", 0);
+               }
+               packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
+               packet_send();
+       } else {
+               channel_request_start(id, "shell", 0);
+               packet_send();
+       }
+}
 
 static void
 client_init_dispatch_20(void)
 {
        dispatch_init(&dispatch_protocol_error);
+
        dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
        dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
        dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
@@ -1250,9 +2015,14 @@ client_init_dispatch_20(void)
        dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
        dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
        dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+       dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
 
        /* rekeying */
        dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+
+       /* global request reply messages */
+       dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+       dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
 }
 static void
 client_init_dispatch_13(void)
@@ -1269,7 +2039,7 @@ client_init_dispatch_13(void)
        dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
 
        dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
-           &auth_input_open_request : &deny_input_open);
+           &client_input_agent_open : &deny_input_open);
        dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
            &x11_input_open : &deny_input_open);
 }
@@ -1290,3 +2060,14 @@ client_init_dispatch(void)
        else
                client_init_dispatch_15();
 }
+
+/* client specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       leave_raw_mode();
+       leave_non_blocking();
+       if (options.control_path != NULL && control_fd != -1)
+               unlink(options.control_path);
+       _exit(i);
+}
index 1bc9a95236ccaa1bab54ddef1e4bbc540295f1b7..1845663376f3a1415047ad46bf954d6482f7da78 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clientloop.h,v 1.6 2001/06/26 17:27:23 markus Exp $   */
+/*     $OpenBSD: clientloop.h,v 1.14 2005/07/04 00:58:43 djm Exp $     */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
 
 /* Client side main loop for the interactive session. */
 int     client_loop(int, int, int);
+void    client_x11_get_proto(const char *, const char *, u_int,
+           char **, char **);
+void    client_global_request_reply_fwd(int, u_int32_t, void *);
+void    client_session2_setup(int, int, int, const char *, struct termios *,
+           int, Buffer *, char **, dispatch_fn *);
+
+/* Multiplexing protocol version */
+#define SSHMUX_VER                     1
+
+/* Multiplexing control protocol flags */
+#define SSHMUX_COMMAND_OPEN            1       /* Open new connection */
+#define SSHMUX_COMMAND_ALIVE_CHECK     2       /* Check master is alive */
+#define SSHMUX_COMMAND_TERMINATE       3       /* Ask master to exit */
+#define SSHMUX_COMMAND_PORTFORWARD      4       /* Ask master to portforward */
+
+#define SSHMUX_FLAG_TTY                        (1)     /* Request tty on open */
+#define SSHMUX_FLAG_SUBSYS             (1<<1)  /* Subsystem request on open */
+#define SSHMUX_FLAG_X11_FWD            (1<<2)  /* Request X11 forwarding */
+#define SSHMUX_FLAG_AGENT_FWD          (1<<3)  /* Request agent forwarding */
+#define SSHMUX_FLAG_PORTFORWARD         (1<<4)  /* Request portforward */
index 969045994cea346c133dd20c94b346c2d5101482..129d98cd1bbe0141e1edd0f4c8c8ed1c27e65edf 100644 (file)
@@ -31,7 +31,9 @@
        "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
        "arcfour128,arcfour256,arcfour," \
        "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \
-       "aes128-ctr,aes192-ctr,aes256-ctr,none"
+       "aes128-ctr,aes192-ctr,aes256-ctr"
+#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \
+       ",none"
 #define        KEX_DEFAULT_MAC \
        "hmac-md5,hmac-sha1,hmac-ripemd160," \
        "hmac-ripemd160@openssh.com," \
index 2377bb15b5ebd8dbd206e3cc8d2dee22f665d1c6..c5b0b8eef706f19c798474af6ad745967decc17f 100644 (file)
@@ -114,6 +114,8 @@ typedef enum {
        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
        oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
+       oHPNBufferSize,
        oDeprecated, oUnsupported
 } OpCodes;
 
@@ -213,6 +215,12 @@ static struct {
        { "tunneldevice", oTunnelDevice },
        { "localcommand", oLocalCommand },
        { "permitlocalcommand", oPermitLocalCommand },
+        { "noneenabled", oNoneEnabled },
+        { "tcprcvbufpoll", oTcpRcvBufPoll },
+        { "tcprcvbuf", oTcpRcvBuf },
+        { "noneswitch", oNoneSwitch },
+       { "hpndisabled", oHPNDisabled },
+       { "hpnbuffersize", oHPNBufferSize },
        { NULL, oBadOption }
 };
 
@@ -442,10 +450,31 @@ parse_flag:
                intptr = &options->check_host_ip;
                goto parse_flag;
 
+       case oNoneEnabled:
+               intptr = &options->none_enabled;
+               goto parse_flag;
+
+       case oNoneSwitch:
+               intptr = &options->none_switch;
+               goto parse_flag;
+
+       case oHPNDisabled:
+               intptr = &options->hpn_disabled;
+               goto parse_flag;
+
+       case oHPNBufferSize:
+               intptr = &options->hpn_buffer_size;
+               goto parse_int;
+
+       case oTcpRcvBufPoll:
+               intptr = &options->tcp_rcv_buf_poll;
+               goto parse_flag;
+
        case oVerifyHostKeyDNS:
                intptr = &options->verify_host_key_dns;
                goto parse_yesnoask;
 
+
        case oStrictHostKeyChecking:
                intptr = &options->strict_host_key_checking;
 parse_yesnoask:
@@ -607,6 +636,10 @@ parse_int:
                intptr = &options->connection_attempts;
                goto parse_int;
 
+       case oTcpRcvBuf:
+               intptr = &options->tcp_rcv_buf;
+               goto parse_int;
+
        case oCipher:
                intptr = &options->cipher;
                arg = strdelim(&s);
@@ -1032,7 +1065,6 @@ initialize_options(Options * options)
        options->verify_host_key_dns = -1;
        options->server_alive_interval = -1;
        options->server_alive_count_max = -1;
-       options->none_switch = -1;
        options->num_send_env = 0;
        options->control_path = NULL;
        options->control_master = -1;
@@ -1042,6 +1074,12 @@ initialize_options(Options * options)
        options->tun_remote = -1;
        options->local_command = NULL;
        options->permit_local_command = -1;
+       options->none_switch = -1;
+       options->none_enabled = -1;
+       options->hpn_disabled = -1;
+       options->hpn_buffer_size = -1;
+       options->tcp_rcv_buf_poll = -1;
+       options->tcp_rcv_buf = -1;
 }
 
 /*
@@ -1168,6 +1206,22 @@ fill_default_options(Options * options)
                options->server_alive_count_max = 3;
        if (options->none_switch == -1)
                options->none_switch = 0;
+       if (options->hpn_disabled == -1)
+               options->hpn_disabled = 0;
+       if (options->hpn_buffer_size == -1)
+               options->hpn_buffer_size = 2*1024*1024;
+       else {
+               if (options->hpn_buffer_size == 0)
+                       options->hpn_buffer_size = 1;
+               /*limit the buffer to 7MB*/
+               if (options->hpn_buffer_size > 7168)
+                       options->hpn_buffer_size = 7168;
+               options->hpn_buffer_size *=1024;
+       }       
+       if (options->tcp_rcv_buf == 0)
+               options->tcp_rcv_buf = 1;
+       if (options->tcp_rcv_buf > -1) 
+               options->tcp_rcv_buf *=1024;
        if (options->control_master == -1)
                options->control_master = 0;
        if (options->hash_known_hosts == -1)
index 4a2d095729dc8d2c733a3f03bcc6b2d6ff7ba03e..02486195bef4c4c16e86f74453dd7546093247f9 100644 (file)
@@ -60,6 +60,10 @@ typedef struct {
                                         * (best). */
        int     tcp_keep_alive; /* Set SO_KEEPALIVE. */
         int     tcp_rcv_buf; /* user switch to set tcp recv buffer */
+       int     tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */
+       int     hpn_disabled;    /* Switch to disable HPN buffer management */
+       int     hpn_buffer_size; /* User definable size for HPN buffer window */
+
        LogLevel log_level;     /* Level for logging. */
 
        int     port;           /* Port to connect. */
@@ -107,7 +111,8 @@ typedef struct {
 
        int     enable_ssh_keysign;
        int     rekey_limit;
-       int     none_switch;
+       int     none_switch;    /* use none cipher */
+       int     none_enabled;   /* Allow none to be used */
        int     no_host_authentication_for_localhost;
        int     identities_only;
        int     server_alive_interval;
index 92cab27ca0dc7c5c02980311a929ed01a6348fed..6e81062ee3c8ad17d6c6f2181875407cc3dc5112 100644 (file)
@@ -278,7 +278,7 @@ main(int argc, char **argv)
        addargs(&args, "-oClearAllForwardings yes");
 
        fflag = tflag = 0;
-       while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246zS:o:F:R:")) != -1)
+       while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246zS:o:F:w:")) != -1)
                switch (ch) {
                /* User-visible flags. */
                case '1':
@@ -340,9 +340,9 @@ main(int argc, char **argv)
                        setmode(0, O_BINARY);
 #endif
                        break;
-               case 'R':
-                 addargs(&args, "-r%s", optarg);
-                 break;
+               case 'w':
+                       addargs(&args, "-w%s", optarg);
+                       break;
                default:
                        usage();
                }
@@ -617,10 +617,6 @@ syserr:                    run_err("%s: %s", name, strerror(errno));
                (void) atomicio(vwrite, remout, buf, strlen(buf));
                if (response() < 0)
                        goto next;
-               /* this change decreases the number of read/write syscalls*/
-               /* when scp acts as data source. this is the critical change*/
-               /* buf can actually remain at 2k but increasing both to 16k*/
-               /* seemed to make sense*/
                if ((bp = allocbuf(&buffer, fd, sizeof(buf))) == NULL) {
 next:                  if (fd != -1) {
                                (void) close(fd);
@@ -1093,7 +1089,7 @@ usage(void)
 {
        (void) fprintf(stderr,
            "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
-           "           [-l limit] [-o ssh_option] [-P port] [-R Receive buffer size (Kb)] [-S program]\n"
+           "           [-l limit] [-o ssh_option] [-P port] [-w buffer size] [-S program]\n"
            "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
        exit(1);
 }
index 60328389873e52417daabbc2fa3e3660d33dd43f..9442a565a513d95d3303f7200cebbefda7240821 100644 (file)
@@ -109,6 +109,10 @@ initialize_server_options(ServerOptions *options)
        options->authorized_keys_file2 = NULL;
        options->num_accept_env = 0;
        options->permit_tun = -1;
+        options->none_enabled = -1;
+        options->tcp_rcv_buf_poll = -1;
+       options->hpn_disabled = -1;
+       options->hpn_buffer_size = -1;
 
        /* Needs to be accessable in many places */
        use_privsep = -1;
@@ -117,6 +121,7 @@ initialize_server_options(ServerOptions *options)
 void
 fill_default_server_options(ServerOptions *options)
 {
+
        /* Portable-specific options */
        if (options->use_pam == -1)
                options->use_pam = 0;
@@ -244,10 +249,26 @@ fill_default_server_options(ServerOptions *options)
        if (options->permit_tun == -1)
                options->permit_tun = SSH_TUNMODE_NO;
 
+       if (options->hpn_disabled == -1) 
+               options->hpn_disabled = 0;
+
+       if (options->hpn_buffer_size == -1)
+               options->hpn_buffer_size = 2*1024*1024;
+       else {
+               if (options->hpn_buffer_size == 0)
+                       options->hpn_buffer_size = 1;
+               /* limit the maximum buffer to 7MB */
+               if (options->hpn_buffer_size > 7168)
+                       options->hpn_buffer_size = 7168;
+               options->hpn_buffer_size *=1024;
+       }
+
        /* Turn privilege separation on by default */
        if (use_privsep == -1)
                use_privsep = 1;
 
+
+
 #ifndef HAVE_MMAP
        if (use_privsep && options->compression == 1) {
                error("This platform does not support both privilege "
@@ -287,10 +308,11 @@ typedef enum {
        sBanner, sUseDNS, sHostbasedAuthentication,
        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
        sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-       sGssAuthentication, sGssKeyEx, sGssCleanupCreds, 
-       sAcceptEnv, sPermitTunnel,
+       sGssKeyEx, 
        sGsiAllowLimitedProxy,
-       sUsePrivilegeSeparation,
+       sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+       sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll, 
+       sHPNDisabled, sHPNBufferSize,
        sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -402,6 +424,10 @@ static struct {
        { "authorizedkeysfile2", sAuthorizedKeysFile2 },
        { "useprivilegeseparation", sUsePrivilegeSeparation},
        { "acceptenv", sAcceptEnv },
+       { "noneenabled", sNoneEnabled },
+       { "hpndisabled", sHPNDisabled },
+       { "hpnbuffersize", sHPNBufferSize },
+       { "tcprcvbufpoll", sTcpRcvBufPoll },
        { "permittunnel", sPermitTunnel },
        { NULL, sBadOption }
 };
@@ -417,9 +443,9 @@ parse_token(const char *cp, const char *filename,
        u_int i;
 
        for (i = 0; keywords[i].name; i++)
-               if (strcasecmp(cp, keywords[i].name) == 0)
-                       return keywords[i].opcode;
-
+               if (strcasecmp(cp, keywords[i].name) == 0){
+                       debug ("TOKEN IS %s", keywords[i].name);
+                       return keywords[i].opcode;}
        error("%s: line %d: Bad configuration option: %s",
            filename, linenum, cp);
        return sBadOption;
@@ -483,6 +509,7 @@ process_server_config_line(ServerOptions *options, char *line,
        intptr = NULL;
        charptr = NULL;
        opcode = parse_token(arg, filename, linenum);
+
        switch (opcode) {
        /* Portable-specific options */
        case sUsePAM:
@@ -655,6 +682,22 @@ parse_flag:
                        *intptr = value;
                break;
 
+       case sNoneEnabled:
+               intptr = &options->none_enabled;
+               goto parse_flag;
+
+       case sTcpRcvBufPoll:
+               intptr = &options->tcp_rcv_buf_poll;
+               goto parse_flag;
+
+       case sHPNDisabled:
+               intptr = &options->hpn_disabled;
+               goto parse_flag;
+
+       case sHPNBufferSize:
+               intptr = &options->hpn_buffer_size;
+               goto parse_int;
+
        case sIgnoreUserKnownHosts:
                intptr = &options->ignore_user_known_hosts;
                goto parse_flag;
index ac51bf4d2a966b6b7692930b34a7ada4983e4302..3cf98c50568b86c5cc30ec157ac827fddfaaf320 100644 (file)
@@ -142,6 +142,10 @@ typedef struct {
        char   *authorized_keys_file2;
 
        int     use_pam;                /* Enable auth via PAM */
+        int     none_enabled;           /* enable NONE cipher switch */
+        int     tcp_rcv_buf_poll;       /* poll tcp rcv window in autotuning kernels*/
+       int     hpn_disabled;           /* disable hpn functionality. false by default */
+       int     hpn_buffer_size;        /* set the hpn buffer size - default 3MB */
 
        int     permit_tun;
 }       ServerOptions;
index b60932f0d0f8fe6798da0db1519b1d8eb4e6828a..5eb5fd565cf57c474fd055d1589fc68350809892 100644 (file)
@@ -907,9 +907,14 @@ server_request_direct_tcpip(void)
        xfree(originator);
        if (sock < 0)
                return NULL;
-       c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
-           sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
-           CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
+       if (options.hpn_disabled)
+               c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
+                   sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
+                   CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
+       else
+               c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
+                   sock, sock, -1, options.hpn_buffer_size,
+                   CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
        return c;
 }
 
@@ -944,8 +949,12 @@ server_request_tun(void)
        sock = tun_open(tun, mode);
        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);
+       if (options.hpn_disabled)
+               c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+                   CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+       else
+               c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+                   options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
        c->datagram = 1;
 #if defined(SSH_TUN_FILTER)
        if (mode == SSH_TUNMODE_POINTOPOINT)
@@ -975,7 +984,7 @@ server_request_session(void)
        c = channel_new("session", SSH_CHANNEL_LARVAL,
            -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
            0, "server-session", 1);
-       if (!(datafellows & SSH_BUG_LARGEWINDOW))
+       if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled))
                c->dynamic_window = 1;
        if (session_open(the_authctxt, c->self) != 1) {
                debug("session open failed, free channel %d", c->self);
@@ -1073,7 +1082,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
                } else {
                        /* Start listening on the port */
                        success = channel_setup_remote_fwd_listener(
-                           listen_address, listen_port, options.gateway_ports);
+                           listen_address, listen_port, options.gateway_ports, 
+                           options.hpn_disabled, options.hpn_buffer_size);
                }
                xfree(listen_address);
        } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
index 8864e064109cc54f904e9b1286339521fcec5022..13f7385260fc77d0517878bd7440e73ebf66f7b3 100644 (file)
@@ -191,6 +191,7 @@ auth_input_request_forwarding(struct passwd * pw)
                packet_disconnect("listen: %.100s", strerror(errno));
 
        /* Allocate a channel for the authentication agent socket. */
+       /* this shouldn't matter if its hpn or not - cjr */
        nc = channel_new("auth socket",
            SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
            CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
@@ -342,7 +343,9 @@ do_authenticated1(Authctxt *authctxt)
                                break;
                        }
                        debug("Received TCP/IP port forwarding request.");
-                       channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports);
+                       channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports, 
+                                                           options.hpn_disabled, 
+                                                          options.hpn_buffer_size);
                        success = 1;
                        break;
 
@@ -2232,11 +2235,18 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
         */
        if (s->chanid == -1)
                fatal("no channel for session %d", s->self);
-       channel_set_fds(s->chanid,
-           fdout, fdin, fderr,
-           fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
-           1,
-           CHAN_SES_WINDOW_DEFAULT);
+       if(options.hpn_disabled) 
+               channel_set_fds(s->chanid,
+                   fdout, fdin, fderr,
+                   fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+                   1,
+                   CHAN_SES_WINDOW_DEFAULT);
+       else
+               channel_set_fds(s->chanid,
+                   fdout, fdin, fderr,
+                   fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+                   1,
+                   options.hpn_buffer_size);
 }
 
 /*
@@ -2580,7 +2590,8 @@ session_setup_x11fwd(Session *s)
        }
        if (x11_create_display_inet(options.x11_display_offset,
            options.x11_use_localhost, s->single_connection,
-           &s->display_number, &s->x11_chanids) == -1) {
+           &s->display_number, &s->x11_chanids, 
+           options.hpn_disabled, options.hpn_buffer_size) == -1) {
                debug("x11_create_display_inet failed.");
                return 0;
        }
index 56a69221427c1ba7151231a9ecffc929c7a1422f..a2e3f6aad65f36fcd3e7e2ed79c3e2dbd6596419 100644 (file)
@@ -1464,7 +1464,7 @@ main(int argc, char **argv)
        ll = SYSLOG_LEVEL_INFO;
        infile = stdin;
 
-       while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:z")) != -1) {
+       while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) {
                switch (ch) {
                case 'C':
                        addargs(&args, "-C");
@@ -1519,9 +1519,6 @@ main(int argc, char **argv)
                                    optarg);
                        break;
                case 'h':
-                case 'z':       
-                        addargs(&args, "-%c", ch);
-                        break;
                default:
                        usage();
                }
index b72a7d89845eacac004fb513634cfac70a7f1cbd..78174647cf85588ede0148eca05accd12641a289 100644 (file)
@@ -157,13 +157,12 @@ static void
 usage(void)
 {
        fprintf(stderr,
-"usage: ssh [-1246AaCfgkMNnqrsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
+"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
 "           [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
 "           [-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"
 "           [-w tunnel:tunnel] [user@]hostname [command]\n"
-"           [-r Receive Buffer Size in K]\n"
        );
        exit(255);
 }
@@ -242,12 +241,10 @@ main(int ac, char **av)
 
        /* Parse command-line arguments. */
        host = NULL;
-       /* need to set options.tcp_rcv_buf to 0 */
-       options.tcp_rcv_buf = 0;
 
 again:
        while ((opt = getopt(ac, av,
-           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XYz")) != -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;
@@ -500,9 +497,6 @@ again:
                case 'F':
                        config = optarg;
                        break;
-               case 'r':
-                       options.tcp_rcv_buf = atoi(optarg) * 1024;
-                       break;
                case 'z':
                        /* make sure we can't turn on the none_switch */
                        /* if they try to force a no tty flag on a tty session */
@@ -835,7 +829,8 @@ ssh_init_forwarding(void)
                    options.local_forwards[i].listen_port,
                    options.local_forwards[i].connect_host,
                    options.local_forwards[i].connect_port,
-                   options.gateway_ports);
+                   options.gateway_ports, options.hpn_disabled,
+                   options.hpn_buffer_size);
        }
        if (i > 0 && success == 0)
                error("Could not request local forwarding.");
@@ -1117,9 +1112,14 @@ ssh_session2_setup(int id, void *arg)
                debug("Requesting tun.");
                if ((fd = tun_open(options.tun_local,
                    options.tun_open)) >= 0) {
-                       c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
-                           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
-                           0, "tun", 1);
+                       if(options.hpn_disabled)
+                               c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+                                   CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+                                   0, "tun", 1);
+                       else
+                               c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+                                   options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+                                   0, "tun", 1);
                        c->datagram = 1;
 #if defined(SSH_TUN_FILTER)
                        if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
@@ -1169,7 +1169,10 @@ ssh_session2_open(void)
        if (!isatty(err))
                set_nonblock(err);
 
-       window = CHAN_SES_WINDOW_DEFAULT;
+       if(options.hpn_disabled)
+               window = CHAN_SES_WINDOW_DEFAULT;
+       else
+               window = options.hpn_buffer_size;
        packetmax = CHAN_SES_PACKET_DEFAULT;
        if (tty_flag) {
                window = 4*CHAN_SES_PACKET_DEFAULT;
@@ -1180,8 +1183,9 @@ ssh_session2_open(void)
            "session", SSH_CHANNEL_OPENING, in, out, err,
            window, packetmax, CHAN_EXTENDED_WRITE,
            "client-session", /*nonblock*/0);
-       if (!tty_flag && (!(datafellows & SSH_BUG_LARGEWINDOW))) {
+       if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) {
                c->dynamic_window = 1;
+               debug ("Enabled Dynamic Window Scaling\n");
        }
        debug3("ssh_session2_open: channel_new: %d", c->self);
 
@@ -1362,12 +1366,23 @@ control_client(const char *path)
                flags |= SSHMUX_FLAG_X11_FWD;
        if (options.forward_agent)
                flags |= SSHMUX_FLAG_AGENT_FWD;
-
+       if (options.num_local_forwards > 0)
+               flags |= SSHMUX_FLAG_PORTFORWARD;
        buffer_init(&m);
 
        /* Send our command to server */
        buffer_put_int(&m, mux_command);
        buffer_put_int(&m, flags);
+       if (options.num_local_forwards > 0)
+        {
+               if (options.local_forwards[0].listen_host == NULL)
+                       buffer_put_string(&m,"LOCALHOST",11);
+               else
+                       buffer_put_string(&m,options.local_forwards[0].listen_host,512);
+               buffer_put_int(&m,options.local_forwards[0].listen_port);
+               buffer_put_string(&m,options.local_forwards[0].connect_host,512);       
+               buffer_put_int(&m,options.local_forwards[0].connect_port);
+       }
        if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1)
                fatal("%s: msg_send", __func__);
        buffer_clear(&m);
index 711d693a684281df502a062bebd2ce1057f754e3..975674ccaf99d12568d5773c879ae31f03713a27 100644 (file)
@@ -143,6 +143,31 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
        return 0;
 }
 
+/*
+ * Set TCP receive buffer if requested.
+ * Note: tuning needs to happen after the socket is
+ * created but before the connection happens
+ * so winscale is negotiated properly -cjr
+ */
+static void
+ssh_set_socket_recvbuf(int sock)
+{
+       void *buf = (void *)&options.tcp_rcv_buf;
+       int sz = sizeof(options.tcp_rcv_buf);
+       int socksize;
+       int socksizelen = sizeof(int);
+
+       debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf);
+       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) {
+         getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen);
+         debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize);
+       }
+       else
+               error("Couldn't set socket receive buffer to %d: %.100s",
+                   options.tcp_rcv_buf, strerror(errno));
+}
+
+
 /*
  * Creates a (possibly privileged) socket for use as the ssh connection.
  */
@@ -167,55 +192,16 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
                else
                        debug("Allocated local port %d.", p);
 
-               
-               /* tuning needs to happen after the socket is */
-               /* created but before the connection happens */
-               /* so winscale is negotiated properly -cjr */
-               
-               /* Set tcp receive buffer if requested */
-               if (options.tcp_rcv_buf) 
-                 {
-                   if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
-                                  (void *)&options.tcp_rcv_buf, 
-                                  sizeof(options.tcp_rcv_buf)) >= 0)
-                     {             
-                       debug("setsockopt SO_RCVBUF: %.100s", strerror(errno));
-                     } 
-                   else 
-                     {
-                       /* coudln't set the socket size to use spec. */
-                       /* should default to system param and continue */
-                       /* warn the user though - cjr */
-                       error("Couldn't set socket receive buffer as requested. Continuing anyway.");
-                     }
-                 }
+               if (options.tcp_rcv_buf > 0)
+                       ssh_set_socket_recvbuf(sock);           
                return sock;
        }
        sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
        if (sock < 0)
                error("socket: %.100s", strerror(errno));
        
-       /* tuning needs to happen after the socket is */
-       /* created but before the connection happens */
-       /* so winscale is negotiated properly -cjr */
-       
-       /* Set tcp receive buffer if requested */
-       if (options.tcp_rcv_buf) 
-         {
-           if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
-                          (void *)&options.tcp_rcv_buf, 
-                          sizeof(options.tcp_rcv_buf)) >= 0)
-             {             
-               debug("setsockopt SO_RCVBUF: %.100s", strerror(errno));
-             }
-           else 
-             {
-               /* coudln't set the socket size to use spec. */
-               /* should default to system param and continue */
-               /* warn the user though - cjr */
-               error("Couldn't set socket receive buffer as requested. Continuing anyway.");
-             }
-         }
+               if (options.tcp_rcv_buf > 0)
+                       ssh_set_socket_recvbuf(sock);
        
                /* Bind the socket to an alternative local IP address */
        if (options.bind_address == NULL)
index 0485095ae901bf9d1844b962f83ea2e37779993d..c35587ff7aee791309235947e054d2f3b2ce13db 100644 (file)
@@ -127,7 +127,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
        if (options.ciphers != NULL) {
                myproposal[PROPOSAL_ENC_ALGS_CTOS] =
                myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
-       }
+       } 
+
        myproposal[PROPOSAL_ENC_ALGS_CTOS] =
            compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
        myproposal[PROPOSAL_ENC_ALGS_STOC] =
@@ -380,7 +381,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
 
        pubkey_cleanup(&authctxt);
        dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
-       if ((options.none_switch == 1) && !tty_flag) /* no null on tty sessions */
+       if ((options.none_switch == 1) && (options.none_enabled == 1) && !tty_flag) /* no null on tty sessions */
        {
                debug("Requesting none rekeying...");
                myproposal[PROPOSAL_ENC_ALGS_STOC] = "none";
index 8077c975ed495e0bae8c0425c550fac54dd3ab50..7f09723f169dd5bb7ded774bb3f1c7c1cfd828e3 100644 (file)
@@ -2075,6 +2075,10 @@ do_ssh2_kex(void)
        if (options.ciphers != NULL) {
                myproposal[PROPOSAL_ENC_ALGS_CTOS] =
                myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       } else if (options.none_enabled == 1) {
+               debug ("WARNING: None cipher enabled");
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE;
        }
        myproposal[PROPOSAL_ENC_ALGS_CTOS] =
            compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
index 314bb6df89a4f42f3a45d71fd66164fdf8ccc77c..d260303b9453b15b7ceee0f9db9528f8d1a9807b 100644 (file)
 #MaxStartups 10
 #PermitTunnel no
 
+# override default of no subsystems
+Subsystem      sftp    /usr/libexec/sftp-server
+
 # no default banner path
 #Banner /some/path
 
-# override default of no subsystems
-Subsystem      sftp    /usr/libexec/sftp-server
+# the following are HPN related configuration options
+# tcp receive buffer polling. enable in autotuning kernels
+#TcpRcvBufPoll no
+
+# allow the use of the none cipher
+#NoneEnabled no
+
+# disable hpn performance boosts. 
+#HPNDisabled no
+
+# buffer size for hpn to non-hn connections
+#HPNBufferSize 2048
+
index c2766ee2b920a6dfb736a6febc606fc743fd3ce4..a690a83251f3a43d4fab60cae37d0dd4c3e7216b 100644 (file)
@@ -21,7 +21,7 @@
 #define SSH_VERSION    "OpenSSH_4.3"
 
 #define SSH_PORTABLE   "p2"
-#define SSH_HPN                "-hpn"
+#define SSH_HPN                "-hpn12"
 #define SSH_RELEASE    SSH_VERSION SSH_PORTABLE SSH_HPN \
                        " NCSA_GSSAPI_20060510" \
                        GSI_VERSION KRB5_VERSION MGLUE_VERSION
This page took 0.159015 seconds and 5 git commands to generate.