]> andersk Git - gssapi-openssh.git/commitdiff
http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.1p1-hpn13v5.diff.gz committe... OPENSSH_5_1P1_HPN13v5
authorbasney <basney>
Wed, 30 Jul 2008 19:51:11 +0000 (19:51 +0000)
committerbasney <basney>
Wed, 30 Jul 2008 19:51:11 +0000 (19:51 +0000)
32 files changed:
openssh/Makefile.in
openssh/auth2.c
openssh/buffer.c
openssh/buffer.h
openssh/channels.c
openssh/channels.h
openssh/cipher-ctr-mt.c [new file with mode: 0644]
openssh/cipher.c
openssh/clientloop.c
openssh/compat.c
openssh/compat.h
openssh/kex.c
openssh/kex.h
openssh/myproposal.h
openssh/packet.c
openssh/packet.h
openssh/progressmeter.c
openssh/readconf.c
openssh/readconf.h
openssh/scp.c
openssh/servconf.c
openssh/servconf.h
openssh/serverloop.c
openssh/session.c
openssh/sftp.1
openssh/sftp.c
openssh/ssh.c
openssh/sshconnect.c
openssh/sshconnect2.c
openssh/sshd.c
openssh/sshd_config
openssh/version.h

index 22172e25f11ddc93f0741d9b3695ebe6b71d0591..0506c4e8f8d9cfc0593eb42b26408c0c1eb4b2f2 100644 (file)
@@ -43,7 +43,7 @@ CC=@CC@
 LD=@LD@
 CFLAGS=@CFLAGS@
 CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
-LIBS=@LIBS@
+LIBS=@LIBS@ -lpthread
 SSHDLIBS=@SSHDLIBS@
 LIBEDIT=@LIBEDIT@
 AR=@AR@
@@ -64,7 +64,7 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keys
 
 LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
        canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
-       cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
+       cipher-bf1.o cipher-ctr.o cipher-ctr-mt.o cipher-3des1.o cleanup.o \
        compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
        log.o match.o md-sha256.o moduli.o nchan.o packet.o \
        readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
index a835abfc6c3366241e9b94fa29ada5abd22e34b5..b30e91f276ff3289b9a494acb7eb50474e138686 100644 (file)
@@ -49,6 +49,7 @@
 #include "dispatch.h"
 #include "pathnames.h"
 #include "buffer.h"
+#include "canohost.h"
 
 #ifdef GSSAPI
 #include "ssh-gss.h"
@@ -72,6 +73,9 @@ extern Authmethod method_hostbased;
 extern Authmethod method_gssapi;
 #endif
 
+static int log_flag = 0;
+
+
 Authmethod *authmethods[] = {
        &method_none,
        &method_pubkey,
@@ -219,6 +223,11 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        service = packet_get_string(NULL);
        method = packet_get_string(NULL);
        debug("userauth-request for user %s service %s method %s", user, service, method);
+       if (!log_flag) {
+               logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", 
+                     get_remote_ipaddr(), get_remote_port(), user);
+               log_flag = 1;
+       }
        debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
        if ((style = strchr(user, ':')) != NULL)
index e02e1e35c9947dce9937655cff72db2d00efa9a6..cb0b620703ccadf23ce5eb480c6fdeb6542c018d 100644 (file)
@@ -127,7 +127,7 @@ restart:
 
        /* Increase the size of the buffer and retry. */
        newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
-       if (newlen > BUFFER_MAX_LEN)
+       if (newlen > BUFFER_MAX_LEN_HPN)
                fatal("buffer_append_space: alloc %u not supported",
                    newlen);
        buffer->buf = xrealloc(buffer->buf, 1, newlen);
index d0f354ee7bf7e685a51f6edf44b60aef603e5837..1467791c2e524f87da1aad1ba174190a88eed405 100644 (file)
@@ -16,6 +16,9 @@
 #ifndef BUFFER_H
 #define BUFFER_H
 
+/* move the following to a more appropriate place and name */
+#define BUFFER_MAX_LEN_HPN          0x4000000  /* 64MB */
+
 typedef struct {
        u_char  *buf;           /* Buffer for data. */
        u_int    alloc;         /* Number of bytes allocated for data. */
index 69c99c9b2f773d05f5c29c1ff754879598899c67..9dd954a606706c425d150bdc0c226dc7e5901490 100644 (file)
@@ -169,8 +169,14 @@ static void port_open_helper(Channel *c, char *rtype);
 static int connect_next(struct channel_connect *);
 static void channel_connect_ctx_free(struct channel_connect *);
 
+
+static int hpn_disabled = 0;
+static int hpn_buffer_size = 2 * 1024 * 1024;
+
 /* -- channel core */
 
+
+
 Channel *
 channel_by_id(int id)
 {
@@ -307,6 +313,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
        c->local_window_max = window;
        c->local_consumed = 0;
        c->local_maxpacket = maxpack;
+       c->dynamic_window = 0;
        c->remote_id = -1;
        c->remote_name = xstrdup(remote_name);
        c->remote_window = 0;
@@ -793,11 +800,35 @@ 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 we aren't on a socket return 128KB*/
+       if(!packet_connection_is_on_socket()) 
+           return(128*1024);
+       ret = getsockopt(packet_get_connection_in(),
+                        SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+       /* return no more than 64MB */
+       if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN)
+           tcpwinsz = BUFFER_MAX_LEN_HPN;
+       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 */
+       if ((!c->tcpwinsz) || (c->dynamic_window > 0))
+           c->tcpwinsz = channel_tcpwinsz();
+       
+       limit = MIN(limit, 2 * c->tcpwinsz);
+       
        if (c->istate == CHAN_INPUT_OPEN &&
            limit > 0 &&
            buffer_len(&c->input) < limit &&
@@ -1708,14 +1739,21 @@ channel_check_window(Channel *c)
            c->local_maxpacket*3) ||
            c->local_window < c->local_window_max/2) &&
            c->local_consumed > 0) {
+               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)) {
+                       /* grow the window somewhat aggressively to maintain pressure */
+                       addition = 1.5*(c->tcpwinsz - c->local_window_max);
+                       c->local_window_max += addition;
+               }
                packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
                packet_put_int(c->remote_id);
-               packet_put_int(c->local_consumed);
+               packet_put_int(c->local_consumed + addition);
                packet_send();
                debug2("channel %d: window %d sent adjust %d",
                    c->self, c->local_window,
                    c->local_consumed);
-               c->local_window += c->local_consumed;
+               c->local_window += c->local_consumed + addition;
                c->local_consumed = 0;
        }
        return 1;
@@ -1918,11 +1956,12 @@ channel_after_select(fd_set *readset, fd_set *writeset)
 
 
 /* If there is data to send to the connection, enqueue some of it now. */
-void
+int
 channel_output_poll(void)
 {
        Channel *c;
        u_int i, len;
+       int packet_length = 0;
 
        for (i = 0; i < channels_alloc; i++) {
                c = channels[i];
@@ -1962,7 +2001,7 @@ channel_output_poll(void)
                                        packet_start(SSH2_MSG_CHANNEL_DATA);
                                        packet_put_int(c->remote_id);
                                        packet_put_string(data, dlen);
-                                       packet_send();
+                                       packet_length = packet_send();
                                        c->remote_window -= dlen + 4;
                                        xfree(data);
                                }
@@ -1992,7 +2031,7 @@ channel_output_poll(void)
                                    SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
                                packet_put_int(c->remote_id);
                                packet_put_string(buffer_ptr(&c->input), len);
-                               packet_send();
+                               packet_length = packet_send();
                                buffer_consume(&c->input, len);
                                c->remote_window -= len;
                        }
@@ -2027,12 +2066,13 @@ channel_output_poll(void)
                        packet_put_int(c->remote_id);
                        packet_put_int(SSH2_EXTENDED_DATA_STDERR);
                        packet_put_string(buffer_ptr(&c->extended), len);
-                       packet_send();
+                       packet_length = packet_send();
                        buffer_consume(&c->extended, len);
                        c->remote_window -= len;
                        debug2("channel %d: sent ext data %d", c->self, len);
                }
        }
+       return (packet_length);
 }
 
 
@@ -2408,6 +2448,15 @@ channel_set_af(int af)
        IPv4or6 = af;
 }
 
+
+void 
+channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size)
+{
+       hpn_disabled = external_hpn_disabled;
+       hpn_buffer_size = external_hpn_buffer_size;
+       debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size);
+}
+
 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)
@@ -2524,9 +2573,15 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                        continue;
                }
                /* Allocate a channel number for the socket. */
+               /* 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;
@@ -3059,10 +3114,17 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
        *chanids = xcalloc(num_socks + 1, sizeof(**chanids));
        for (n = 0; n < num_socks; n++) {
                sock = socks[n];
+               /* Is this really necassary? */
+               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 108b360681d678557e56660bd5902b6ff683b34e..419c009501053e9643ffca0f4d5189e255ac23d4 100644 (file)
@@ -117,8 +117,10 @@ struct Channel {
        u_int   local_window_max;
        u_int   local_consumed;
        u_int   local_maxpacket;
+       int     dynamic_window;
        int     extended_usage;
        int     single_connection;
+       u_int   tcpwinsz;       
 
        char   *ctype;          /* type */
 
@@ -148,9 +150,11 @@ struct Channel {
 
 /* default window/packet sizes for tcp/x11-fwd-channel */
 #define CHAN_SES_PACKET_DEFAULT        (32*1024)
-#define CHAN_SES_WINDOW_DEFAULT        (64*CHAN_SES_PACKET_DEFAULT)
+#define CHAN_SES_WINDOW_DEFAULT        (4*CHAN_SES_PACKET_DEFAULT)
+
 #define CHAN_TCP_PACKET_DEFAULT        (32*1024)
-#define CHAN_TCP_WINDOW_DEFAULT        (64*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        (4*CHAN_X11_PACKET_DEFAULT)
 
@@ -223,7 +227,7 @@ void         channel_input_status_confirm(int, u_int32_t, void *);
 
 void    channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int);
 void     channel_after_select(fd_set *, fd_set *);
-void     channel_output_poll(void);
+int      channel_output_poll(void);
 
 int      channel_not_very_much_buffered_data(void);
 void     channel_close_all(void);
@@ -279,4 +283,7 @@ void         chan_rcvd_ieof(Channel *);
 void    chan_write_failed(Channel *);
 void    chan_obuf_empty(Channel *);
 
+/* hpn handler */
+void     channel_set_hpn(int, int);
+
 #endif
diff --git a/openssh/cipher-ctr-mt.c b/openssh/cipher-ctr-mt.c
new file mode 100644 (file)
index 0000000..93fb444
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * OpenSSH Multi-threaded AES-CTR Cipher
+ *
+ * Author: Benjamin Bennett <ben@psc.edu>
+ * Copyright (c) 2008 Pittsburgh Supercomputing Center. All rights reserved.
+ *
+ * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged,
+ * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include "xmalloc.h"
+#include "log.h"
+
+/* compatibility with old or broken OpenSSL versions */
+#include "openbsd-compat/openssl-compat.h"
+
+#ifndef USE_BUILTIN_RIJNDAEL
+#include <openssl/aes.h>
+#endif
+
+#include <pthread.h>
+
+/*-------------------- TUNABLES --------------------*/
+/* Number of pregen threads to use */
+#define CIPHER_THREADS 2
+
+/* Number of keystream queues */
+#define NUMKQ          (CIPHER_THREADS + 2)
+
+/* Length of a keystream queue */
+#define KQLEN          4096
+
+/* Processor cacheline length */
+#define CACHELINE_LEN  64
+
+/* Collect thread stats and print at cancellation when in debug mode */
+/* #define CIPHER_THREAD_STATS */
+
+/* Use single-byte XOR instead of 8-byte XOR */
+/* #define CIPHER_BYTE_XOR */
+/*-------------------- END TUNABLES --------------------*/
+
+
+const EVP_CIPHER *evp_aes_ctr_mt(void);
+
+#ifdef CIPHER_THREAD_STATS
+/*
+ * Struct to collect thread stats
+ */
+struct thread_stats {
+       u_int   fills;
+       u_int   skips;
+       u_int   waits;
+       u_int   drains;
+};
+
+/*
+ * Debug print the thread stats
+ * Use with pthread_cleanup_push for displaying at thread cancellation
+ */
+static void
+thread_loop_stats(void *x)
+{
+       struct thread_stats *s = x;
+
+       debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(),
+                       s->fills, s->skips, s->waits);
+}
+
+ #define STATS_STRUCT(s)       struct thread_stats s
+ #define STATS_INIT(s)         { memset(&s, 0, sizeof(s)); }
+ #define STATS_FILL(s)         { s.fills++; }
+ #define STATS_SKIP(s)         { s.skips++; }
+ #define STATS_WAIT(s)         { s.waits++; }
+ #define STATS_DRAIN(s)                { s.drains++; }
+#else
+ #define STATS_STRUCT(s)
+ #define STATS_INIT(s)
+ #define STATS_FILL(s)
+ #define STATS_SKIP(s)
+ #define STATS_WAIT(s)
+ #define STATS_DRAIN(s)
+#endif
+
+/* Keystream Queue state */
+enum {
+       KQINIT,
+       KQEMPTY,
+       KQFILLING,
+       KQFULL,
+       KQDRAINING
+};
+
+/* Keystream Queue struct */
+struct kq {
+       u_char          keys[KQLEN][AES_BLOCK_SIZE];
+       u_char          ctr[AES_BLOCK_SIZE];
+       u_char          pad0[CACHELINE_LEN];
+       volatile int    qstate;
+       pthread_mutex_t lock;
+       pthread_cond_t  cond;
+       u_char          pad1[CACHELINE_LEN];
+};
+
+/* Context struct */
+struct ssh_aes_ctr_ctx
+{
+       struct kq       q[NUMKQ];
+       AES_KEY         aes_ctx;
+       STATS_STRUCT(stats);
+       u_char          aes_counter[AES_BLOCK_SIZE];
+       pthread_t       tid[CIPHER_THREADS];
+       int             state;
+       int             qidx;
+       int             ridx;
+};
+
+/* <friedl>
+ * increment counter 'ctr',
+ * the counter is of size 'len' bytes and stored in network-byte-order.
+ * (LSB at ctr[len-1], MSB at ctr[0])
+ */
+static void
+ssh_ctr_inc(u_char *ctr, u_int len)
+{
+       int i;
+
+       for (i = len - 1; i >= 0; i--)
+               if (++ctr[i])   /* continue on overflow */
+                       return;
+}
+
+/*
+ * Add num to counter 'ctr'
+ */
+static void
+ssh_ctr_add(u_char *ctr, uint32_t num, u_int len)
+{
+       int i;
+       uint16_t n;
+
+       for (n = 0, i = len - 1; i >= 0 && (num || n); i--) {
+               n = ctr[i] + (num & 0xff) + n;
+               num >>= 8;
+               ctr[i] = n & 0xff;
+               n >>= 8;
+       }
+}
+
+/*
+ * Threads may be cancelled in a pthread_cond_wait, we must free the mutex
+ */
+static void
+thread_loop_cleanup(void *x)
+{
+       pthread_mutex_unlock((pthread_mutex_t *)x);
+}
+
+/*
+ * The life of a pregen thread:
+ *    Find empty keystream queues and fill them using their counter.
+ *    When done, update counter for the next fill.
+ */
+static void *
+thread_loop(void *x)
+{
+       AES_KEY key;
+       STATS_STRUCT(stats);
+       struct ssh_aes_ctr_ctx *c = x;
+       struct kq *q;
+       int i;
+       int qidx;
+
+       /* Threads stats on cancellation */
+       STATS_INIT(stats);
+#ifdef CIPHER_THREAD_STATS
+       pthread_cleanup_push(thread_loop_stats, &stats);
+#endif
+
+       /* Thread local copy of AES key */
+       memcpy(&key, &c->aes_ctx, sizeof(key));
+
+       /*
+        * Handle the special case of startup, one thread must fill
+        * the first KQ then mark it as draining. Lock held throughout.
+        */
+       if (pthread_equal(pthread_self(), c->tid[0])) {
+               q = &c->q[0];
+               pthread_mutex_lock(&q->lock);
+               if (q->qstate == KQINIT) {
+                       for (i = 0; i < KQLEN; i++) {
+                               AES_encrypt(q->ctr, q->keys[i], &key);
+                               ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE);
+                       }
+                       ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
+                       q->qstate = KQDRAINING;
+                       STATS_FILL(stats);
+                       pthread_cond_broadcast(&q->cond);
+               }
+               pthread_mutex_unlock(&q->lock);
+       }
+       else 
+               STATS_SKIP(stats);
+
+       /*
+        * Normal case is to find empty queues and fill them, skipping over
+        * queues already filled by other threads and stopping to wait for
+        * a draining queue to become empty.
+        *
+        * Multiple threads may be waiting on a draining queue and awoken
+        * when empty.  The first thread to wake will mark it as filling,
+        * others will move on to fill, skip, or wait on the next queue.
+        */
+       for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) {
+               /* Check if I was cancelled, also checked in cond_wait */
+               pthread_testcancel();
+
+               /* Lock queue and block if its draining */
+               q = &c->q[qidx];
+               pthread_mutex_lock(&q->lock);
+               pthread_cleanup_push(thread_loop_cleanup, &q->lock);
+               while (q->qstate == KQDRAINING || q->qstate == KQINIT) {
+                       STATS_WAIT(stats);
+                       pthread_cond_wait(&q->cond, &q->lock);
+               }
+               pthread_cleanup_pop(0);
+
+               /* If filling or full, somebody else got it, skip */
+               if (q->qstate != KQEMPTY) {
+                       pthread_mutex_unlock(&q->lock);
+                       STATS_SKIP(stats);
+                       continue;
+               }
+
+               /*
+                * Empty, let's fill it.
+                * Queue lock is relinquished while we do this so others
+                * can see that it's being filled.
+                */
+               q->qstate = KQFILLING;
+               pthread_mutex_unlock(&q->lock);
+               for (i = 0; i < KQLEN; i++) {
+                       AES_encrypt(q->ctr, q->keys[i], &key);
+                       ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE);
+               }
+
+               /* Re-lock, mark full and signal consumer */
+               pthread_mutex_lock(&q->lock);
+               ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
+               q->qstate = KQFULL;
+               STATS_FILL(stats);
+               pthread_cond_signal(&q->cond);
+               pthread_mutex_unlock(&q->lock);
+       }
+
+#ifdef CIPHER_THREAD_STATS
+       /* Stats */
+       pthread_cleanup_pop(1);
+#endif
+
+       return NULL;
+}
+
+static int
+ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
+    u_int len)
+{
+       struct ssh_aes_ctr_ctx *c;
+       struct kq *q, *oldq;
+       int ridx;
+       u_char *buf;
+
+       if (len == 0)
+               return (1);
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
+               return (0);
+
+       q = &c->q[c->qidx];
+       ridx = c->ridx;
+
+       /* src already padded to block multiple */
+       while (len > 0) {
+               buf = q->keys[ridx];
+
+#ifdef CIPHER_BYTE_XOR
+               dest[0] = src[0] ^ buf[0];
+               dest[1] = src[1] ^ buf[1];
+               dest[2] = src[2] ^ buf[2];
+               dest[3] = src[3] ^ buf[3];
+               dest[4] = src[4] ^ buf[4];
+               dest[5] = src[5] ^ buf[5];
+               dest[6] = src[6] ^ buf[6];
+               dest[7] = src[7] ^ buf[7];
+               dest[8] = src[8] ^ buf[8];
+               dest[9] = src[9] ^ buf[9];
+               dest[10] = src[10] ^ buf[10];
+               dest[11] = src[11] ^ buf[11];
+               dest[12] = src[12] ^ buf[12];
+               dest[13] = src[13] ^ buf[13];
+               dest[14] = src[14] ^ buf[14];
+               dest[15] = src[15] ^ buf[15];
+#else
+               *(uint64_t *)dest = *(uint64_t *)src ^ *(uint64_t *)buf;
+               *(uint64_t *)(dest + 8) = *(uint64_t *)(src + 8) ^
+                                               *(uint64_t *)(buf + 8);
+#endif
+
+               dest += 16;
+               src += 16;
+               len -= 16;
+               ssh_ctr_inc(ctx->iv, AES_BLOCK_SIZE);
+
+               /* Increment read index, switch queues on rollover */
+               if ((ridx = (ridx + 1) % KQLEN) == 0) {
+                       oldq = q;
+
+                       /* Mark next queue draining, may need to wait */
+                       c->qidx = (c->qidx + 1) % NUMKQ;
+                       q = &c->q[c->qidx];
+                       pthread_mutex_lock(&q->lock);
+                       while (q->qstate != KQFULL) {
+                               STATS_WAIT(c->stats);
+                               pthread_cond_wait(&q->cond, &q->lock);
+                       }
+                       q->qstate = KQDRAINING;
+                       pthread_mutex_unlock(&q->lock);
+
+                       /* Mark consumed queue empty and signal producers */
+                       pthread_mutex_lock(&oldq->lock);
+                       oldq->qstate = KQEMPTY;
+                       STATS_DRAIN(c->stats);
+                       pthread_cond_broadcast(&oldq->cond);
+                       pthread_mutex_unlock(&oldq->lock);
+               }
+       }
+       c->ridx = ridx;
+       return (1);
+}
+
+#define HAVE_NONE       0
+#define HAVE_KEY        1
+#define HAVE_IV         2
+static int
+ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+    int enc)
+{
+       struct ssh_aes_ctr_ctx *c;
+       int i;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               c = xmalloc(sizeof(*c));
+
+               c->state = HAVE_NONE;
+               for (i = 0; i < NUMKQ; i++) {
+                       pthread_mutex_init(&c->q[i].lock, NULL);
+                       pthread_cond_init(&c->q[i].cond, NULL);
+               }
+
+               STATS_INIT(c->stats);
+               
+               EVP_CIPHER_CTX_set_app_data(ctx, c);
+       }
+
+       if (c->state == (HAVE_KEY | HAVE_IV)) {
+               /* Cancel pregen threads */
+               for (i = 0; i < CIPHER_THREADS; i++)
+                       pthread_cancel(c->tid[i]);
+               for (i = 0; i < CIPHER_THREADS; i++)
+                       pthread_join(c->tid[i], NULL);
+               /* Start over getting key & iv */
+               c->state = HAVE_NONE;
+       }
+
+       if (key != NULL) {
+               AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+                   &c->aes_ctx);
+               c->state |= HAVE_KEY;
+       }
+
+       if (iv != NULL) {
+               memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
+               c->state |= HAVE_IV;
+       }
+
+       if (c->state == (HAVE_KEY | HAVE_IV)) {
+               /* Clear queues */
+               memcpy(c->q[0].ctr, ctx->iv, AES_BLOCK_SIZE);
+               c->q[0].qstate = KQINIT;
+               for (i = 1; i < NUMKQ; i++) {
+                       memcpy(c->q[i].ctr, ctx->iv, AES_BLOCK_SIZE);
+                       ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE);
+                       c->q[i].qstate = KQEMPTY;
+               }
+               c->qidx = 0;
+               c->ridx = 0;
+
+               /* Start threads */
+               for (i = 0; i < CIPHER_THREADS; i++) {
+                       pthread_create(&c->tid[i], NULL, thread_loop, c);
+               }
+               pthread_mutex_lock(&c->q[0].lock);
+               while (c->q[0].qstate != KQDRAINING)
+                       pthread_cond_wait(&c->q[0].cond, &c->q[0].lock);
+               pthread_mutex_unlock(&c->q[0].lock);
+               
+       }
+       return (1);
+}
+
+static int
+ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
+{
+       struct ssh_aes_ctr_ctx *c;
+       int i;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+#ifdef CIPHER_THREAD_STATS
+               debug("main thread: %u drains, %u waits", c->stats.drains,
+                               c->stats.waits);
+#endif
+               /* Cancel pregen threads */
+               for (i = 0; i < CIPHER_THREADS; i++)
+                       pthread_cancel(c->tid[i]);
+               for (i = 0; i < CIPHER_THREADS; i++)
+                       pthread_join(c->tid[i], NULL);
+
+               memset(c, 0, sizeof(*c));
+               xfree(c);
+               EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+       }
+       return (1);
+}
+
+/* <friedl> */
+const EVP_CIPHER *
+evp_aes_ctr_mt(void)
+{
+       static EVP_CIPHER aes_ctr;
+
+       memset(&aes_ctr, 0, sizeof(EVP_CIPHER));
+       aes_ctr.nid = NID_undef;
+       aes_ctr.block_size = AES_BLOCK_SIZE;
+       aes_ctr.iv_len = AES_BLOCK_SIZE;
+       aes_ctr.key_len = 16;
+       aes_ctr.init = ssh_aes_ctr_init;
+       aes_ctr.cleanup = ssh_aes_ctr_cleanup;
+       aes_ctr.do_cipher = ssh_aes_ctr;
+#ifndef SSH_OLD_EVP
+       aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
+           EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+#endif
+       return (&aes_ctr);
+}
index b264063c40314e696ecf990e103bd6f4ae64968c..8d0e58cb76c0e6dc7c51031b0d8b054bb855692d 100644 (file)
@@ -55,6 +55,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(void);
 extern const EVP_CIPHER *evp_ssh1_3des(void);
 extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
 extern const EVP_CIPHER *evp_aes_128_ctr(void);
+extern const EVP_CIPHER *evp_aes_ctr_mt(void);
 extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
 
 struct Cipher {
@@ -81,9 +82,9 @@ struct Cipher {
        { "aes256-cbc",         SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc },
        { "rijndael-cbc@lysator.liu.se",
                                SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc },
-       { "aes128-ctr",         SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr },
-       { "aes192-ctr",         SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_128_ctr },
-       { "aes256-ctr",         SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_128_ctr },
+       { "aes128-ctr",         SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_ctr_mt },
+       { "aes192-ctr",         SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_ctr_mt },
+       { "aes256-ctr",         SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_ctr_mt },
 #ifdef USE_CIPHER_ACSS
        { "acss@openssh.org",   SSH_CIPHER_SSH2, 16, 5, 0, EVP_acss },
 #endif
@@ -156,7 +157,8 @@ ciphers_valid(const char *names)
        for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
            (p = strsep(&cp, CIPHER_SEP))) {
                c = cipher_by_name(p);
-               if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+               if (c == NULL || (c->number != SSH_CIPHER_SSH2 && 
+c->number != SSH_CIPHER_NONE)) {
                        debug("bad cipher %s [%s]", p, names);
                        xfree(cipher_list);
                        return 0;
@@ -330,6 +332,7 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
        int evplen;
 
        switch (c->number) {
+       case SSH_CIPHER_NONE:
        case SSH_CIPHER_SSH2:
        case SSH_CIPHER_DES:
        case SSH_CIPHER_BLOWFISH:
@@ -364,6 +367,7 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
        int evplen = 0;
 
        switch (c->number) {
+       case SSH_CIPHER_NONE:
        case SSH_CIPHER_SSH2:
        case SSH_CIPHER_DES:
        case SSH_CIPHER_BLOWFISH:
index f10fab7698cf6b1f4e1dbe90b25d483892c2a578..d1f2f4604726d5b3d734ccb74a74f968fff030d4 100644 (file)
@@ -1682,9 +1682,15 @@ client_request_x11(const char *request_type, int rchan)
        sock = x11_connect_display();
        if (sock < 0)
                return NULL;
+       /* again is this really necessary for X11? */
+       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;
 }
@@ -1704,9 +1710,15 @@ client_request_agent(const char *request_type, int rchan)
        sock = ssh_get_authentication_socket();
        if (sock < 0)
                return NULL;
+       if (options.hpn_disabled) 
        c = channel_new("authentication agent connection",
            SSH_CHANNEL_OPEN, sock, sock, -1,
-           CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
+                   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;
@@ -1734,10 +1746,18 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
                return -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,
-           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 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)
                channel_register_filter(c->self, sys_tun_infilter,
index bc113158144bef3a0dda64a8664e5c87956d79f1..d1addc871ead6e68789f6cbb4d26d7cc04046d81 100644 (file)
@@ -169,6 +169,15 @@ compat_datafellows(const char *version)
                    strlen(check[i].pat), 0) == 1) {
                        debug("match: %s pat %s", version, check[i].pat);
                        datafellows = check[i].bugs;
+                       /* Check to see if the remote side is OpenSSH and not HPN */
+                       if(strstr(version,"OpenSSH") != NULL)
+                       {
+                               if (strstr(version,"hpn") == NULL)
+                               {
+                                       datafellows |= SSH_BUG_LARGEWINDOW;
+                                       debug("Remote is NON-HPN aware");
+                               }
+                       }
                        return;
                }
        }
index 4d8ebc908a425891fe3ed7a7c6c5c2797389afaf..ec00fd3efbfd22e1f4a35f2cdafae59c083c565f 100644 (file)
@@ -57,6 +57,7 @@
 #define SSH_BUG_FIRSTKEX       0x00800000
 #define SSH_OLD_FORWARD_ADDR   0x01000000
 #define SSH_BUG_RFWD_ADDR      0x02000000
+#define SSH_BUG_LARGEWINDOW     0x04000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
index 332fadf6e20b3ed5495926abbdad3220a8a40b03..e55727a14fa7d683223076c39cb4aced87c07a1a 100644 (file)
@@ -48,6 +48,7 @@
 #include "match.h"
 #include "dispatch.h"
 #include "monitor.h"
+#include "canohost.h"
 
 #define KEX_COOKIE_LEN 16
 
@@ -64,7 +65,8 @@ static void kex_kexinit_finish(Kex *);
 static void kex_choose_conf(Kex *);
 
 /* put algorithm proposal into buffer */
-static void
+/* used in sshconnect.c as well as kex.c */
+void
 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
        u_int i;
@@ -376,6 +378,13 @@ kex_choose_conf(Kex *kex)
        int nenc, nmac, ncomp;
        u_int mode, ctos, need;
        int first_kex_follows, type;
+       int log_flag = 0;
+
+       int auth_flag;
+
+       auth_flag = packet_authentication_state();
+
+       debug ("AUTH STATE IS %d", auth_flag);
 
        my   = kex_buf2prop(&kex->my, NULL);
        peer = kex_buf2prop(&kex->peer, &first_kex_follows);
@@ -400,11 +409,34 @@ kex_choose_conf(Kex *kex)
                choose_enc (&newkeys->enc,  cprop[nenc],  sprop[nenc]);
                choose_mac (&newkeys->mac,  cprop[nmac],  sprop[nmac]);
                choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
+               debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
+               if (strcmp(newkeys->enc.name, "none") == 0) {
+                               debug("Requesting NONE. Authflag is %d", auth_flag);                    
+                       if (auth_flag == 1) {
+                               debug("None requested post authentication.");
+                       } else {
+                               fatal("Pre-authentication none cipher requests are not allowed.");
+                       }
+               } 
                debug("kex: %s %s %s %s",
                    ctos ? "client->server" : "server->client",
                    newkeys->enc.name,
                    newkeys->mac.name,
                    newkeys->comp.name);
+               /* client starts withctos = 0 && log flag = 0 and no log*/
+               /* 2nd client pass ctos=1 and flag = 1 so no log*/
+               /* server starts with ctos =1 && log_flag = 0 so log */
+               /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/
+               /* -cjr*/
+               if (ctos && !log_flag) {
+                       logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s",
+                             get_remote_ipaddr(),
+                             get_remote_port(),
+                             newkeys->enc.name,
+                             newkeys->mac.name,
+                             newkeys->comp.name);
+               }
+               log_flag = 1;
        }
        choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
        choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
index 8e29c90e9025d168978c12504590801e6329d4d7..786038ed456cd93f5bff0e9a79c3dbd246924ccc 100644 (file)
@@ -127,6 +127,8 @@ struct Kex {
        void    (*kex[KEX_MAX])(Kex *);
 };
 
+void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]);
+
 Kex    *kex_setup(char *[PROPOSAL_MAX]);
 void    kex_finish(Kex *);
 
index 87a9e5820024841b7b6d4fc1263697158e7870dd..46bd6dfd2baa0311ad8170f68d3df2960acdba33 100644 (file)
@@ -46,6 +46,8 @@
        "arcfour128,arcfour256,arcfour," \
        "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \
        "aes128-ctr,aes192-ctr,aes256-ctr"
+#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \
+       ",none"
 #define        KEX_DEFAULT_MAC \
        "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \
        "hmac-ripemd160@openssh.com," \
index 8abd43eb461946a1208b435a2abcf5c576283a43..b3bb4f3b69c21c6ad20e90f28e6326b862bc3303 100644 (file)
@@ -739,7 +739,7 @@ packet_enable_delayed_compress(void)
 /*
  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
  */
-static void
+static int
 packet_send2_wrapped(void)
 {
        u_char type, *cp, *macbuf = NULL;
@@ -852,11 +852,13 @@ packet_send2_wrapped(void)
                set_newkeys(MODE_OUT);
        else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side)
                packet_enable_delayed_compress();
+       return(packet_length);
 }
 
-static void
+static int
 packet_send2(void)
 {
+        static int packet_length = 0;
        static int rekeying = 0;
        struct packet *p;
        u_char type, *cp;
@@ -874,7 +876,7 @@ packet_send2(void)
                        memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
                        buffer_init(&outgoing_packet);
                        TAILQ_INSERT_TAIL(&outgoing, p, next);
-                       return;
+                       return(sizeof(Buffer));
                }
        }
 
@@ -882,7 +884,7 @@ packet_send2(void)
        if (type == SSH2_MSG_KEXINIT)
                rekeying = 1;
 
-       packet_send2_wrapped();
+       packet_length = packet_send2_wrapped();
 
        /* after a NEWKEYS message we can send the complete queue */
        if (type == SSH2_MSG_NEWKEYS) {
@@ -895,19 +897,22 @@ packet_send2(void)
                            sizeof(Buffer));
                        TAILQ_REMOVE(&outgoing, p, next);
                        xfree(p);
-                       packet_send2_wrapped();
+                       packet_length += packet_send2_wrapped();
                }
        }
+       return(packet_length);
 }
 
-void
+int
 packet_send(void)
 {
+  int packet_len = 0;
        if (compat20)
-               packet_send2();
+               packet_len = packet_send2();
        else
                packet_send1();
        DBG(debug("packet_send done"));
+       return(packet_len);
 }
 
 /*
@@ -1483,23 +1488,25 @@ packet_disconnect(const char *fmt,...)
 
 /* Checks if there is any buffered output, and tries to write some of the output. */
 
-void
+int
 packet_write_poll(void)
 {
-       int len = buffer_len(&output);
+       int len = 0;
+       len = buffer_len(&output);
 
        if (len > 0) {
                len = write(connection_out, buffer_ptr(&output), len);
                if (len == -1) {
                        if (errno == EINTR || errno == EAGAIN ||
                            errno == EWOULDBLOCK)
-                               return;
+                               return (0);
                        fatal("Write failed: %.100s", strerror(errno));
                }
                if (len == 0)
                        fatal("Write connection closed");
                buffer_consume(&output, len);
        }
+       return(len);
 }
 
 
@@ -1508,16 +1515,17 @@ packet_write_poll(void)
  * written.
  */
 
-void
+int
 packet_write_wait(void)
 {
        fd_set *setp;
        int ret, ms_remain;
        struct timeval start, timeout, *timeoutp = NULL;
+       u_int bytes_sent = 0;
 
        setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
            sizeof(fd_mask));
-       packet_write_poll();
+       bytes_sent += packet_write_poll();
        while (packet_have_data_to_write()) {
                memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
                    sizeof(fd_mask));
@@ -1551,7 +1559,7 @@ packet_write_wait(void)
                            "waiting to write", get_remote_ipaddr());
                        cleanup_exit(255);
                }
-               packet_write_poll();
+               bytes_sent += packet_write_poll();
        }
        xfree(setp);
 }
@@ -1675,12 +1683,24 @@ packet_send_ignore(int nbytes)
        }
 }
 
+int rekey_requested = 0;
+void
+packet_request_rekeying(void)
+{
+       rekey_requested = 1;
+}
+
 #define MAX_PACKETS    (1U<<31)
 int
 packet_need_rekeying(void)
 {
        if (datafellows & SSH_BUG_NOREKEY)
                return 0;
+       if (rekey_requested == 1)
+       {
+               rekey_requested = 0;
+               return 1;
+       }
        return
            (p_send.packets > MAX_PACKETS) ||
            (p_read.packets > MAX_PACKETS) ||
@@ -1705,3 +1725,9 @@ packet_set_authenticated(void)
 {
        after_authentication = 1;
 }
+
+int
+packet_authentication_state(void)
+{
+       return(after_authentication);
+}
index 03bb87c9beed95408721ac770baa52f2f8ea971f..a52107883696ca11cdaa94176747cfb5e6f03175 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <openssl/bn.h>
 
+void
+packet_request_rekeying(void);
+
 void     packet_set_connection(int, int);
 void     packet_set_timeout(int, int);
 void     packet_set_nonblocking(void);
@@ -35,6 +38,7 @@ void     packet_set_interactive(int);
 int      packet_is_interactive(void);
 void     packet_set_server(void);
 void     packet_set_authenticated(void);
+int     packet_authentication_state(void);
 
 void     packet_start(u_char);
 void     packet_put_char(int ch);
@@ -44,7 +48,7 @@ void     packet_put_bignum2(BIGNUM * value);
 void     packet_put_string(const void *buf, u_int len);
 void     packet_put_cstring(const char *str);
 void     packet_put_raw(const void *buf, u_int len);
-void     packet_send(void);
+int      packet_send(void);
 
 int      packet_read(void);
 void     packet_read_expect(int type);
@@ -73,8 +77,8 @@ void   packet_set_state(int, u_int32_t, u_int64_t, u_int32_t, u_int64_t);
 int     packet_get_ssh1_cipher(void);
 void    packet_set_iv(int, u_char *);
 
-void     packet_write_poll(void);
-void     packet_write_wait(void);
+int      packet_write_poll(void);
+int      packet_write_wait(void);
 int      packet_have_data_to_write(void);
 int      packet_not_very_much_data_to_write(void);
 
index 0f95222d24874f760eb14227fdc772cbb7927b8a..79d13bac1727a9c5f520e54d5ba836b12cb987d4 100644 (file)
@@ -68,6 +68,8 @@ static time_t last_update;    /* last progress update */
 static char *file;             /* name of the file being transferred */
 static off_t end_pos;          /* ending position of transfer */
 static off_t cur_pos;          /* transfer position as of last refresh */
+static off_t last_pos;
+static off_t max_delta_pos = 0;
 static volatile off_t *counter;        /* progress counter */
 static long stalled;           /* how long we have been stalled */
 static int bytes_per_second;   /* current speed in bytes per second */
@@ -128,12 +130,17 @@ refresh_progress_meter(void)
        int hours, minutes, seconds;
        int i, len;
        int file_len;
+       off_t delta_pos;
 
        transferred = *counter - cur_pos;
        cur_pos = *counter;
        now = time(NULL);
        bytes_left = end_pos - cur_pos;
 
+       delta_pos = cur_pos - last_pos;
+       if (delta_pos > max_delta_pos) 
+               max_delta_pos = delta_pos;
+
        if (bytes_left > 0)
                elapsed = now - last_update;
        else {
@@ -158,7 +165,7 @@ refresh_progress_meter(void)
 
        /* filename */
        buf[0] = '\0';
-       file_len = win_size - 35;
+       file_len = win_size - 45;
        if (file_len > 0) {
                len = snprintf(buf, file_len + 1, "\r%s", file);
                if (len < 0)
@@ -175,7 +182,8 @@ refresh_progress_meter(void)
                percent = ((float)cur_pos / end_pos) * 100;
        else
                percent = 100;
-       snprintf(buf + strlen(buf), win_size - strlen(buf),
+
+       snprintf(buf + strlen(buf), win_size - strlen(buf-8),
            " %3d%% ", percent);
 
        /* amount transferred */
@@ -188,6 +196,15 @@ refresh_progress_meter(void)
            (off_t)bytes_per_second);
        strlcat(buf, "/s ", win_size);
 
+       /* instantaneous rate */
+       if (bytes_left > 0)
+               format_rate(buf + strlen(buf), win_size - strlen(buf),
+                           delta_pos);
+       else
+               format_rate(buf + strlen(buf), win_size - strlen(buf),
+                           max_delta_pos);
+       strlcat(buf, "/s ", win_size);
+
        /* ETA */
        if (!transferred)
                stalled += elapsed;
@@ -224,6 +241,7 @@ refresh_progress_meter(void)
 
        atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
        last_update = now;
+       last_pos = cur_pos;
 }
 
 /*ARGSUSED*/
index 73f6eb361e7fed7775f6a9a67fc3bd795f2ca390..66f16cc64a0e220368c5132349970081c703a8d5 100644 (file)
@@ -131,6 +131,8 @@ typedef enum {
        oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
        oVisualHostKey,
+       oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
+       oHPNBufferSize,
        oDeprecated, oUnsupported
 } OpCodes;
 
@@ -228,6 +230,12 @@ static struct {
        { "localcommand", oLocalCommand },
        { "permitlocalcommand", oPermitLocalCommand },
        { "visualhostkey", oVisualHostKey },
+       { "noneenabled", oNoneEnabled },
+       { "tcprcvbufpoll", oTcpRcvBufPoll },
+       { "tcprcvbuf", oTcpRcvBuf },
+       { "noneswitch", oNoneSwitch },
+       { "hpndisabled", oHPNDisabled },
+       { "hpnbuffersize", oHPNBufferSize },
        { NULL, oBadOption }
 };
 
@@ -456,6 +464,37 @@ parse_flag:
                intptr = &options->check_host_ip;
                goto parse_flag;
 
+       case oNoneEnabled:
+               intptr = &options->none_enabled;
+               goto parse_flag;
+       /* we check to see if the command comes from the */
+       /* command line or not. If it does then enable it */
+       /* otherwise fail. NONE should never be a default configuration */
+       case oNoneSwitch:
+               if(strcmp(filename,"command-line")==0)
+               {               
+                   intptr = &options->none_switch;
+                   goto parse_flag;
+               } else {
+                   error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
+                   error("Continuing...");
+                   debug("NoneSwitch directive found in %.200s.", filename);
+                   return 0;
+               }
+
+       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;
@@ -634,6 +673,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);
@@ -1072,6 +1115,12 @@ initialize_options(Options * options)
        options->local_command = NULL;
        options->permit_local_command = -1;
        options->visual_host_key = -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;
 }
 
 /*
@@ -1194,6 +1243,29 @@ fill_default_options(Options * options)
                options->server_alive_interval = 0;
        if (options->server_alive_count_max == -1)
                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)
+       {
+         /* if a user tries to set the size to 0 set it to 1KB */
+               if (options->hpn_buffer_size == 0)
+               options->hpn_buffer_size = 1024;
+               /*limit the buffer to 64MB*/
+               if (options->hpn_buffer_size > 65536)
+               {
+                       options->hpn_buffer_size = 65536*1024;
+                       debug("User requested buffer larger than 64MB. Request reverted to 64MB");
+               }
+               debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
+       }
+       if (options->tcp_rcv_buf == 0)
+               options->tcp_rcv_buf = 1;
+       if (options->tcp_rcv_buf > -1) 
+               options->tcp_rcv_buf *=1024;
+       if (options->tcp_rcv_buf_poll == -1)
+               options->tcp_rcv_buf_poll = 1;
        if (options->control_master == -1)
                options->control_master = 0;
        if (options->hash_known_hosts == -1)
index 47c7aef4e046dc63d900227312c484f4e3f15352..1664b7bfb2cdc46e10e49232b4255c1aa6915e8c 100644 (file)
@@ -56,6 +56,11 @@ typedef struct {
        int     compression_level;      /* Compression level 1 (fast) to 9
                                         * (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. */
@@ -101,6 +106,8 @@ typedef struct {
 
        int     enable_ssh_keysign;
        int64_t rekey_limit;
+       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 9f8b7a192ac6702dd9f4fe9e43a14e81a9a1370f..411dc8b99ef3e9fe8ec812f0abda1eea5aa9bc8c 100644 (file)
@@ -632,7 +632,7 @@ source(int argc, char **argv)
        off_t i, statbytes;
        size_t amt;
        int fd = -1, haderr, indx;
-       char *last, *name, buf[2048], encname[MAXPATHLEN];
+       char *last, *name, buf[16384], encname[MAXPATHLEN];
        int len;
 
        for (indx = 0; indx < argc; ++indx) {
@@ -868,7 +868,7 @@ sink(int argc, char **argv)
        mode_t mode, omode, mask;
        off_t size, statbytes;
        int setimes, targisdir, wrerrno = 0;
-       char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+       char ch, *cp, *np, *targ, *why, *vect[1], buf[16384];
        struct timeval tv[2];
 
 #define        atime   tv[0]
index 66e22979f926eec8c6ae490f408edeeac522deef..a571135fe550b6449bb636a8195ea878de040654 100644 (file)
@@ -127,11 +127,20 @@ initialize_server_options(ServerOptions *options)
        options->num_permitted_opens = -1;
        options->adm_forced_command = NULL;
        options->chroot_directory = NULL;
+       options->none_enabled = -1;
+       options->tcp_rcv_buf_poll = -1;
+       options->hpn_disabled = -1;
+       options->hpn_buffer_size = -1;
 }
 
 void
 fill_default_server_options(ServerOptions *options)
 {
+       /* needed for hpn socket tests */
+       int sock;
+       int socksize;
+       int socksizelen = sizeof(int);
+
        /* Portable-specific options */
        if (options->use_pam == -1)
                options->use_pam = 0;
@@ -259,6 +268,42 @@ 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) {
+               /* option not explicitly set. Now we have to figure out */
+               /* what value to use */
+               if (options->hpn_disabled == 1) {
+                       options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
+               } else {
+                       /* get the current RCV size and set it to that */
+                       /*create a socket but don't connect it */
+                       /* we use that the get the rcv socket size */
+                       sock = socket(AF_INET, SOCK_STREAM, 0);
+                       getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+                                  &socksize, &socksizelen);
+                       close(sock);
+                       options->hpn_buffer_size = socksize;
+                       debug ("HPN Buffer Size: %d", options->hpn_buffer_size);
+                       
+               } 
+       } else {
+               /* we have to do this incase the user sets both values in a contradictory */
+               /* manner. hpn_disabled overrrides hpn_buffer_size*/
+               if (options->hpn_disabled <= 0) {
+                       if (options->hpn_buffer_size == 0)
+                               options->hpn_buffer_size = 1;
+                       /* limit the maximum buffer to 64MB */
+                       if (options->hpn_buffer_size > 64*1024) {
+                               options->hpn_buffer_size = 64*1024*1024;
+                       } else {
+                               options->hpn_buffer_size *= 1024;
+                       }
+               } else
+                       options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT;
+       }
+
        /* Turn privilege separation on by default */
        if (use_privsep == -1)
                use_privsep = 1;
@@ -302,6 +347,7 @@ typedef enum {
        sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
+       sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
        sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -415,6 +461,10 @@ static struct {
        { "permitopen", sPermitOpen, SSHCFG_ALL },
        { "forcecommand", sForceCommand, SSHCFG_ALL },
        { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+       { "noneenabled", sNoneEnabled },
+       { "hpndisabled", sHPNDisabled },
+       { "hpnbuffersize", sHPNBufferSize },
+       { "tcprcvbufpoll", sTcpRcvBufPoll },
        { NULL, sBadOption, 0 }
 };
 
@@ -441,6 +491,7 @@ parse_token(const char *cp, const char *filename,
 
        for (i = 0; keywords[i].name; i++)
                if (strcasecmp(cp, keywords[i].name) == 0) {
+                       debug ("Config token is %s", keywords[i].name);
                        *flags = keywords[i].flags;
                        return keywords[i].opcode;
                }
@@ -838,6 +889,22 @@ process_server_config_line(ServerOptions *options, char *line,
                        *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 40ac64f135094b0afd95804b61eaf7b71082ded8..48bdb9c203450c7631a782161ba21b32b2e091d7 100644 (file)
@@ -143,6 +143,10 @@ typedef struct {
        char   *adm_forced_command;
 
        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;
 
index 77d9dee75ceb9c26de8b1b04f3d00d6b6b939b4b..2955e11844c1161023330d6cd3808eb286910cae 100644 (file)
@@ -93,10 +93,10 @@ static int fdin;            /* Descriptor for stdin (for writing) */
 static int fdout;              /* Descriptor for stdout (for reading);
                                   May be same number as fdin. */
 static int fderr;              /* Descriptor for stderr.  May be -1. */
-static long stdin_bytes = 0;   /* Number of bytes written to stdin. */
-static long stdout_bytes = 0;  /* Number of stdout bytes sent to client. */
-static long stderr_bytes = 0;  /* Number of stderr bytes sent to client. */
-static long fdout_bytes = 0;   /* Number of stdout bytes read from program. */
+static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */
+static u_long stdout_bytes = 0;        /* Number of stdout bytes sent to client. */
+static u_long stderr_bytes = 0;        /* Number of stderr bytes sent to client. */
+static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */
 static int stdin_eof = 0;      /* EOF message received from client. */
 static int fdout_eof = 0;      /* EOF encountered reading from fdout. */
 static int fderr_eof = 0;      /* EOF encountered readung from fderr. */
@@ -120,6 +120,20 @@ static volatile sig_atomic_t received_sigterm = 0;
 /* prototypes */
 static void server_init_dispatch(void);
 
+/*
+ * Returns current time in seconds from Jan 1, 1970 with the maximum
+ * available resolution.
+ */
+
+static double
+get_current_time(void)
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+}
+
+
 /*
  * we write to this pipe if a SIGCHLD is caught in order to avoid
  * the race between select() and child_terminated
@@ -410,6 +424,7 @@ process_input(fd_set *readset)
                } else {
                        /* Buffer any received data. */
                        packet_process_incoming(buf, len);
+                       fdout_bytes += len;
                }
        }
        if (compat20)
@@ -432,6 +447,7 @@ process_input(fd_set *readset)
                } else {
                        buffer_append(&stdout_buffer, buf, len);
                        fdout_bytes += len;
+                       debug ("FD out now: %ld", fdout_bytes);
                }
        }
        /* Read and buffer any available stderr data from the program. */
@@ -499,7 +515,7 @@ process_output(fd_set *writeset)
        }
        /* Send any buffered packet data to the client. */
        if (FD_ISSET(connection_out, writeset))
-               packet_write_poll();
+               stdin_bytes += packet_write_poll();
 }
 
 /*
@@ -816,8 +832,10 @@ server_loop2(Authctxt *authctxt)
 {
        fd_set *readset = NULL, *writeset = NULL;
        int rekeying = 0, max_fd, nalloc = 0;
+       double start_time, total_time;
 
        debug("Entering interactive session for SSH2.");
+       start_time = get_current_time();
 
        mysignal(SIGCHLD, sigchld_handler);
        child_terminated = 0;
@@ -879,6 +897,11 @@ server_loop2(Authctxt *authctxt)
 
        /* free remaining sessions, e.g. remove wtmp entries */
        session_destroy_all(NULL);
+       total_time = get_current_time() - start_time;
+       logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
+             get_remote_ipaddr(), get_remote_port(),
+             stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, 
+             fdout_bytes / total_time);
 }
 
 static void
@@ -994,8 +1017,12 @@ server_request_tun(void)
        sock = tun_open(tun, mode);
        if (sock < 0)
                goto done;
+       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)
@@ -1031,6 +1058,8 @@ 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 ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled))
+               c->dynamic_window = 1;
        if (session_open(the_authctxt, c->self) != 1) {
                debug("session open failed, free channel %d", c->self);
                channel_free(c);
index 93babf95701a723398e098d8965c1579ac269dac..3b40fa322a70f27987b6e7d3190804dc7665ccb8 100644 (file)
@@ -224,6 +224,7 @@ auth_input_request_forwarding(struct passwd * pw)
        }
 
        /* 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,
@@ -2295,10 +2296,16 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
         */
        if (s->chanid == -1)
                fatal("no channel for session %d", s->self);
+       if (options.hpn_disabled)
        channel_set_fds(s->chanid,
            fdout, fdin, fderr,
            fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
            1, is_tty, CHAN_SES_WINDOW_DEFAULT);
+       else 
+               channel_set_fds(s->chanid,
+                   fdout, fdin, fderr,
+                   fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+                   1, is_tty, options.hpn_buffer_size);
 }
 
 /*
index b4f9a6884554317038573c33ae6736529b962a8f..c57443038fd6f5cb48283e1c89e1d0a69ac613e3 100644 (file)
@@ -204,7 +204,8 @@ This option may be useful in debugging the client and server.
 Specify how many requests may be outstanding at any one time.
 Increasing this may slightly improve file transfer speed
 but will increase memory usage.
-The default is 64 outstanding requests.
+The default is 256 outstanding requests providing for 8MB 
+of outstanding data with a 32KB buffer.
 .It Fl S Ar program
 Name of the
 .Ar program
index e1aa49d0f0863eefdacf7b24b8685842c8159188..e7cb9cf3a01ca88980018ea655328fb2125f09e1 100644 (file)
@@ -75,7 +75,7 @@ int batchmode = 0;
 size_t copy_buffer_len = 32768;
 
 /* Number of concurrent outstanding requests */
-size_t num_requests = 64;
+size_t num_requests = 256;
 
 /* PID of ssh transport process */
 static pid_t sshpid = -1;
index e2dd67d688bdad9a74c94180a03bf5b50da3314f..fbe03d4423deae627e52e17edef8e93f6d7576bc 100644 (file)
@@ -504,9 +504,6 @@ main(int ac, char **av)
                        no_shell_flag = 1;
                        no_tty_flag = 1;
                        break;
-               case 'T':
-                       no_tty_flag = 1;
-                       break;
                case 'o':
                        dummy = 1;
                        line = xstrdup(optarg);
@@ -515,6 +512,13 @@ main(int ac, char **av)
                                exit(255);
                        xfree(line);
                        break;
+               case 'T':
+                       no_tty_flag = 1;
+                       /* ensure that the user doesn't try to backdoor a */
+                       /* null cipher switch on an interactive session */
+                       /* so explicitly disable it no matter what */
+                       options.none_switch=0;
+                       break;
                case 's':
                        subsystem_flag = 1;
                        break;
@@ -1147,6 +1151,9 @@ ssh_session2_open(void)
 {
        Channel *c;
        int window, packetmax, in, out, err;
+       int sock;
+       int socksize;
+       int socksizelen = sizeof(int);
 
        if (stdin_null_flag) {
                in = open(_PATH_DEVNULL, O_RDONLY);
@@ -1167,9 +1174,75 @@ ssh_session2_open(void)
        if (!isatty(err))
                set_nonblock(err);
 
-       window = CHAN_SES_WINDOW_DEFAULT;
+       /* we need to check to see if what they want to do about buffer */
+       /* sizes here. In a hpn to nonhpn connection we want to limit */
+       /* the window size to something reasonable in case the far side */
+       /* has the large window bug. In hpn to hpn connection we want to */
+       /* use the max window size but allow the user to override it */
+       /* lastly if they disabled hpn then use the ssh std window size */
+
+       /* so why don't we just do a getsockopt() here and set the */
+       /* ssh window to that? In the case of a autotuning receive */
+       /* window the window would get stuck at the initial buffer */
+       /* size generally less than 96k. Therefore we need to set the */
+       /* maximum ssh window size to the maximum hpn buffer size */
+       /* unless the user has specifically set the tcprcvbufpoll */
+       /* to no. In which case we *can* just set the window to the */
+       /* minimum of the hpn buffer size and tcp receive buffer size */
+       
+       if (tty_flag)
+               options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
+       else
+               options.hpn_buffer_size = 2*1024*1024;
+
+       if (datafellows & SSH_BUG_LARGEWINDOW) 
+       {
+               debug("HPN to Non-HPN Connection");
+       } 
+       else 
+       {
+               if (options.tcp_rcv_buf_poll <= 0) 
+               {
+                       sock = socket(AF_INET, SOCK_STREAM, 0);
+                       getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+                                  &socksize, &socksizelen);
+                       close(sock);
+                       debug("socksize %d", socksize);
+                       options.hpn_buffer_size = socksize;
+                       debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size);
+               } 
+               else
+               {
+                       if (options.tcp_rcv_buf > 0) 
+                       {
+                               /*create a socket but don't connect it */
+                               /* we use that the get the rcv socket size */
+                               sock = socket(AF_INET, SOCK_STREAM, 0);
+                               /* if they are using the tcp_rcv_buf option */
+                               /* attempt to set the buffer size to that */
+                               if (options.tcp_rcv_buf) 
+                                       setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, 
+                                                  sizeof(options.tcp_rcv_buf));
+                               getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+                                          &socksize, &socksizelen);
+                               close(sock);
+                               debug("socksize %d", socksize);
+                               options.hpn_buffer_size = socksize;
+                               debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size);
+                       }
+               }
+               
+       }
+
+       debug("Final hpn_buffer_size = %d", options.hpn_buffer_size);
+
+       window = options.hpn_buffer_size;
+
+       channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
+
        packetmax = CHAN_SES_PACKET_DEFAULT;
        if (tty_flag) {
+               window = 4*CHAN_SES_PACKET_DEFAULT;
                window >>= 1;
                packetmax >>= 1;
        }
@@ -1177,7 +1250,10 @@ ssh_session2_open(void)
            "session", SSH_CHANNEL_OPENING, in, out, err,
            window, packetmax, CHAN_EXTENDED_WRITE,
            "client-session", /*nonblock*/0);
-
+       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);
 
        channel_send_open(c->self);
index ec8ba33e01674ea93d7b1cc14a9beb0e81621f78..7972c0fa6e8b1bd5d31e0a58a8836f0a03795518 100644 (file)
@@ -168,6 +168,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.
  */
@@ -191,12 +216,18 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
                            strerror(errno));
                else
                        debug("Allocated local port %d.", p);
+
+               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));
 
+       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)
                return sock;
@@ -540,7 +571,7 @@ ssh_exchange_identification(int timeout_ms)
        snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
            compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
            compat20 ? PROTOCOL_MINOR_2 : minor1,
-           SSH_VERSION, compat20 ? "\r\n" : "\n");
+           SSH_RELEASE, compat20 ? "\r\n" : "\n");
        if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
                fatal("write: %.100s", strerror(errno));
        client_version_string = xstrdup(buf);
index 389bec9e43b47dcf9eb9e12f4ff3a692e3941fe1..ef404b1347a2560c408f4c2271b3b26c7e1d1ca2 100644 (file)
 extern char *client_version_string;
 extern char *server_version_string;
 extern Options options;
+extern Kex *xxx_kex;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
 
 /*
  * SSH2 key exchange
@@ -329,6 +335,28 @@ 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 the user wants to use the none cipher do it */
+       /* post authentication and only if the right conditions are met */
+       /* both of the NONE commands must be true and there must be no */
+       /* tty allocated */
+       if ((options.none_switch == 1) && (options.none_enabled == 1)) 
+       {
+               if (!tty_flag) /* no null on tty sessions */
+               {
+                       debug("Requesting none rekeying...");
+                       myproposal[PROPOSAL_ENC_ALGS_STOC] = "none";
+                       myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none";
+                       kex_prop2buf(&xxx_kex->my,myproposal);
+                       packet_request_rekeying();
+                       fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n");
+               }
+               else
+               {
+                       /* requested NONE cipher when in a tty */
+                       debug("Cannot switch to NONE cipher with tty allocated");
+                       fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n");
+               }
+       }
        debug("Authentication succeeded (%s).", authctxt.method->name);
 }
 
index 6e5bb5476a571cf318aeef0a5020ba1888a7253c..6ce4590d09fec20f0cc01a5a75ce68ce1acf8340 100644 (file)
@@ -137,6 +137,9 @@ int deny_severity;
 #define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
 #define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
 
+int myflag = 0;
+
+
 extern char *__progname;
 
 /* Server configuration options. */
@@ -416,7 +419,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
                minor = PROTOCOL_MINOR_1;
        }
        snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
-           SSH_VERSION, newline);
+           SSH_RELEASE, newline);
        server_version_string = xstrdup(buf);
 
        /* Send our protocol version identification. */
@@ -467,6 +470,9 @@ sshd_exchange_identification(int sock_in, int sock_out)
        }
        debug("Client protocol version %d.%d; client software version %.100s",
            remote_major, remote_minor, remote_version);
+       logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s",
+             get_remote_ipaddr(), get_remote_port(),
+           remote_major, remote_minor, remote_version);
 
        compat_datafellows(remote_version);
 
@@ -945,6 +951,8 @@ server_listen(void)
        int ret, listen_sock, on = 1;
        struct addrinfo *ai;
        char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+       int socksize;
+       int socksizelen = sizeof(int);
 
        for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
                if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@@ -991,6 +999,11 @@ server_listen(void)
 
                debug("Bind to port %s on %s.", strport, ntop);
 
+               getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, 
+                                  &socksize, &socksizelen);
+               debug("Server TCP RWIN socket size: %d", socksize);
+               debug("HPN Buffer Size: %d", options.hpn_buffer_size);
+
                /* Bind the socket to the desired port. */
                if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                        error("Bind to port %s on %s failed: %.200s.",
@@ -1818,6 +1831,9 @@ main(int ac, char **av)
        /* Log the connection. */
        verbose("Connection from %.500s port %d", remote_ip, remote_port);
 
+       /* set the HPN options for the child */
+       channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
+
        /*
         * We don't want to listen forever unless the other side
         * successfully authenticates itself.  So we set up an alarm which is
@@ -2172,9 +2188,15 @@ do_ssh2_kex(void)
 {
        Kex *kex;
 
+       myflag++;
+       debug ("MYFLAG IS %d", myflag);
        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 1b53a0efb91fcd232f2be78c8cd95823cc5c766d..932bcbe7efb9ed7d8c226fe7e25d27b0fc7dc64b 100644 (file)
@@ -112,6 +112,20 @@ Protocol 2
 # override default of no subsystems
 Subsystem      sftp    /usr/libexec/sftp-server
 
+# the following are HPN related configuration options
+# tcp receive buffer polling. disable in non autotuning kernels
+#TcpRcvBufPoll yes
+# allow the use of the none cipher
+#NoneEnabled no
+
+# disable hpn performance boosts. 
+#HPNDisabled no
+
+# buffer size for hpn to non-hpn connections
+#HPNBufferSize 2048
+
+
 # Example of overriding settings on a per-user basis
 #Match User anoncvs
 #      X11Forwarding no
index 41a081f12d61820e2000e3645751aac2540b4557..1e24f5013d9406332cf42f17acab973dc2b5c768 100644 (file)
@@ -3,4 +3,5 @@
 #define SSH_VERSION    "OpenSSH_5.1"
 
 #define SSH_PORTABLE   "p1"
-#define SSH_RELEASE    SSH_VERSION SSH_PORTABLE
+#define SSH_HPN         "-hpn13v5"
+#define SSH_RELEASE    SSH_VERSION SSH_PORTABLE SSH_HPN
This page took 0.206585 seconds and 5 git commands to generate.