diff -NupwB ../4.7/openssh-4.7p1/atomicio.c openssh-4.7p1/atomicio.c --- ../4.7/openssh-4.7p1/atomicio.c 2007-06-25 08:15:12.000000000 -0400 +++ openssh-4.7p1/atomicio.c 2008-02-06 13:28:54.000000000 -0500 @@ -57,13 +57,13 @@ atomicio(ssize_t (*f) (int, void *, size res = (f) (fd, s + pos, n - pos); switch (res) { case -1: -#ifdef EWOULDBLOCK - if (errno == EINTR || errno == EWOULDBLOCK) -#else if (errno == EINTR) -#endif continue; +#ifdef EWOULDBLOCK + if (errno == EAGAIN || errno == EWOULDBLOCK) { +#else if (errno == EAGAIN) { +#endif (void)poll(&pfd, 1, -1); continue; } @@ -103,13 +103,13 @@ atomiciov(ssize_t (*f) (int, const struc res = (f) (fd, iov, iovcnt); switch (res) { case -1: -#ifdef EWOULDBLOCK - if (errno == EINTR || errno == EWOULDBLOCK) -#else if (errno == EINTR) -#endif continue; +#ifdef EWOULDBLOCK + if (errno == EAGAIN || errno == EWOULDBLOCK) { +#else if (errno == EAGAIN) { +#endif (void)poll(&pfd, 1, -1); continue; } diff -NupwB ../4.7/openssh-4.7p1/auth2.c openssh-4.7p1/auth2.c --- ../4.7/openssh-4.7p1/auth2.c 2007-05-20 00:58:41.000000000 -0400 +++ openssh-4.7p1/auth2.c 2008-02-06 13:29:19.000000000 -0500 @@ -44,6 +44,7 @@ #include "dispatch.h" #include "pathnames.h" #include "buffer.h" +#include "canohost.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -67,6 +68,9 @@ extern Authmethod method_hostbased; extern Authmethod method_gssapi; #endif +static int log_flag = 0; + + Authmethod *authmethods[] = { &method_none, &method_pubkey, @@ -151,6 +155,11 @@ input_userauth_request(int type, u_int32 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) diff -NupwB ../4.7/openssh-4.7p1/buffer.c openssh-4.7p1/buffer.c --- ../4.7/openssh-4.7p1/buffer.c 2006-08-04 22:39:39.000000000 -0400 +++ openssh-4.7p1/buffer.c 2008-02-06 17:02:07.000000000 -0500 @@ -127,7 +127,9 @@ restart: /* Increase the size of the buffer and retry. */ newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); - if (newlen > BUFFER_MAX_LEN) + /* need it to be slightly larger than the MAX LEN for this */ + /* still investigating *why* but this works for now -cjr */ + if (newlen > (BUFFER_MAX_LEN_HPN + BUFFER_MAX_LEN)) fatal("buffer_append_space: alloc %u not supported", newlen); buffer->buf = xrealloc(buffer->buf, 1, newlen); diff -NupwB ../4.7/openssh-4.7p1/buffer.h openssh-4.7p1/buffer.h --- ../4.7/openssh-4.7p1/buffer.h 2006-08-04 22:39:39.000000000 -0400 +++ openssh-4.7p1/buffer.h 2008-02-06 13:28:23.000000000 -0500 @@ -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. */ diff -NupwB ../4.7/openssh-4.7p1/channels.c openssh-4.7p1/channels.c --- ../4.7/openssh-4.7p1/channels.c 2007-06-25 05:04:47.000000000 -0400 +++ openssh-4.7p1/channels.c 2008-02-06 13:29:19.000000000 -0500 @@ -311,6 +311,7 @@ channel_new(char *ctype, int type, int r 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; @@ -765,11 +766,35 @@ channel_pre_open_13(Channel *c, fd_set * 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 && @@ -1661,14 +1686,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; @@ -1871,11 +1903,12 @@ channel_after_select(fd_set *readset, fd /* 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]; @@ -1915,7 +1948,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); } @@ -1945,7 +1978,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; } @@ -1980,12 +2013,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); } @@ -2342,7 +2376,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; @@ -2455,9 +2490,15 @@ channel_setup_fwd_listener(int type, con 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; @@ -2494,20 +2535,22 @@ channel_cancel_rport_listener(const char /* 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); } /* @@ -2622,7 +2665,8 @@ channel_request_rforward_cancel(const ch * message if there was an error). */ int -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; int success = 0; @@ -2648,7 +2692,7 @@ channel_input_port_forward_request(int i /* Initiate forwarding */ success = 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); @@ -2852,7 +2896,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; @@ -2949,10 +2994,17 @@ x11_create_display_inet(int x11_display_ *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; } diff -NupwB ../4.7/openssh-4.7p1/channels.h openssh-4.7p1/channels.h --- ../4.7/openssh-4.7p1/channels.h 2007-06-12 09:38:54.000000000 -0400 +++ openssh-4.7p1/channels.h 2008-02-06 13:29:19.000000000 -0500 @@ -98,8 +98,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 */ @@ -122,9 +124,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) @@ -193,7 +197,7 @@ void channel_input_window_adjust(int, u 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); @@ -208,21 +212,21 @@ void channel_add_permitted_opens(char * int channel_add_adm_permitted_opens(char *, int); void channel_clear_permitted_opens(void); void channel_clear_adm_permitted_opens(void); -int channel_input_port_forward_request(int, int); +int 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); int 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 *); diff -NupwB ../4.7/openssh-4.7p1/cipher.c openssh-4.7p1/cipher.c --- ../4.7/openssh-4.7p1/cipher.c 2006-08-04 22:39:39.000000000 -0400 +++ openssh-4.7p1/cipher.c 2008-02-06 13:28:54.000000000 -0500 @@ -55,6 +55,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(voi 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_ch 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_ch int evplen = 0; switch (c->number) { + case SSH_CIPHER_NONE: case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: diff -NupwB ../4.7/openssh-4.7p1/cipher-ctr-mt.c openssh-4.7p1/cipher-ctr-mt.c --- ../4.7/openssh-4.7p1/cipher-ctr-mt.c 1969-12-31 19:00:00.000000000 -0500 +++ openssh-4.7p1/cipher-ctr-mt.c 2008-02-06 13:28:54.000000000 -0500 @@ -0,0 +1,473 @@ +/* + * OpenSSH Multi-threaded AES-CTR Cipher + * + * Author: Benjamin Bennett + * 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 + * + * 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 + +#include +#include + +#include + +#include "xmalloc.h" +#include "log.h" + +/* compatibility with old or broken OpenSSL versions */ +#include "openbsd-compat/openssl-compat.h" + +#ifndef USE_BUILTIN_RIJNDAEL +#include +#endif + +#include + +/*-------------------- 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; +}; + +/* + * 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); +} + +/* */ +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); +} diff -NupwB ../4.7/openssh-4.7p1/clientloop.c openssh-4.7p1/clientloop.c --- ../4.7/openssh-4.7p1/clientloop.c 2007-08-15 05:13:42.000000000 -0400 +++ openssh-4.7p1/clientloop.c 2008-02-06 13:28:23.000000000 -0500 @@ -910,13 +910,16 @@ client_process_control(fd_set *readset) set_nonblock(client_fd); + if (options.hpn_disabled) window = CHAN_SES_WINDOW_DEFAULT; + else + window = options.hpn_buffer_size; + packetmax = CHAN_SES_PACKET_DEFAULT; if (cctx->want_tty) { window >>= 1; packetmax >>= 1; } - c = channel_new("session", SSH_CHANNEL_OPENING, new_fd[0], new_fd[1], new_fd[2], window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); @@ -1018,7 +1021,8 @@ process_cmdline(void) if (local) { if (channel_setup_local_fwd_listener(fwd.listen_host, fwd.listen_port, fwd.connect_host, - fwd.connect_port, options.gateway_ports) < 0) { + fwd.connect_port, options.gateway_ports, + options.hpn_disabled, options.hpn_buffer_size) < 0) { logit("Port forwarding failed."); goto out; } @@ -1717,10 +1721,16 @@ client_request_forwarded_tcpip(const cha xfree(listen_address); return NULL; } + 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; @@ -1754,9 +1764,15 @@ client_request_x11(const char *request_t 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; } @@ -1775,10 +1791,17 @@ client_request_agent(const char *request sock = ssh_get_authentication_socket(); if (sock < 0) return NULL; + /* not sure this is really needed here either */ + 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; } @@ -1805,10 +1828,18 @@ client_request_tun_fwd(int tun_mode, int 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); + 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) channel_register_filter(c->self, sys_tun_infilter, diff -NupwB ../4.7/openssh-4.7p1/compat.c openssh-4.7p1/compat.c --- ../4.7/openssh-4.7p1/compat.c 2007-01-05 00:26:46.000000000 -0500 +++ openssh-4.7p1/compat.c 2008-02-06 13:28:23.000000000 -0500 @@ -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; } } diff -NupwB ../4.7/openssh-4.7p1/compat.h openssh-4.7p1/compat.h --- ../4.7/openssh-4.7p1/compat.h 2007-01-05 00:26:46.000000000 -0500 +++ openssh-4.7p1/compat.h 2008-02-06 13:28:23.000000000 -0500 @@ -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); Common subdirectories: ../4.7/openssh-4.7p1/contrib and openssh-4.7p1/contrib diff -NupwB ../4.7/openssh-4.7p1/HPN12-README openssh-4.7p1/HPN12-README --- ../4.7/openssh-4.7p1/HPN12-README 1969-12-31 19:00:00.000000000 -0500 +++ openssh-4.7p1/HPN12-README 2008-02-06 13:28:23.000000000 -0500 @@ -0,0 +1,111 @@ +Notes: + +To use the NONE option you must have the NoneEnabled switch set on the server and +you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE +feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not +spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will +be disabled. + +The performance increase will only be as good as the network and TCP stack tuning +on the reciever side of the connection allows. As a rule of thumb a user will need +at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The +HPN-SSH home page describes this in greater detail. + +http://www.psc.edu/networking/projects/hpn-ssh + +Buffer Sizes: + +If HPN is disabled the receive buffer size will be set to the +OpenSSH default of 64K. + +If an HPN system connects to a nonHPN system the receive buffer will +be set to the HPNBufferSize value. The default is 2MB but user adjustable. + +If an HPN to HPN connection is established a number of different things might +happen based on the user options and conditions. + +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set +HPN Buffer Size = up to 64MB +This is the default state. The HPN buffer size will grow to a maximum of 64MB +as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is +geared towards 10GigE transcontinental connections. + +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set +HPN Buffer Size = TCP receive buffer value. +Users on non-autotuning systesm should disable TCPRcvBufPoll in the +ssh_cofig and sshd_config + +Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set +HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. +This would be the system defined TCP receive buffer (RWIN). + +Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET +HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. +Generally there is no need to set both. + +Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set +HPN Buffer Size = grows to HPNBufferSize +The buffer will grow up to the maximum size specified here. + +Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET +HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. +Generally there is no need to set both of these, especially on autotuning +systems. However, if the users wishes to override the autotuning this would be +one way to do it. + +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET +HPN Buffer Size = TCPRcvBuf. +This will override autotuning and set the TCP recieve buffer to the user defined +value. + + +HPN Specific Configuration 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 yes. + +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 64MB (1-65536). Use of oversized or undersized buffers can cause performance +problems depending on the length of the network path. The default size of this buffer +is 2MB. + + +Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) + The majority of the actual coding for versions up to HPN12v1 was performed + by Michael Stevens (mstevens@andrew.cmu.edu). This work was financed, in part, + by Cisco System, Inc., and the National Science Foundation. diff -NupwB ../4.7/openssh-4.7p1/kex.c openssh-4.7p1/kex.c --- ../4.7/openssh-4.7p1/kex.c 2007-06-05 04:30:18.000000000 -0400 +++ openssh-4.7p1/kex.c 2008-02-06 13:29:19.000000000 -0500 @@ -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], diff -NupwB ../4.7/openssh-4.7p1/kex.h openssh-4.7p1/kex.h --- ../4.7/openssh-4.7p1/kex.h 2007-06-11 00:01:42.000000000 -0400 +++ openssh-4.7p1/kex.h 2008-02-06 13:28:23.000000000 -0500 @@ -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 *); diff -NupwB ../4.7/openssh-4.7p1/Makefile.in openssh-4.7p1/Makefile.in --- ../4.7/openssh-4.7p1/Makefile.in 2007-06-11 00:01:42.000000000 -0400 +++ openssh-4.7p1/Makefile.in 2008-02-06 13:28:54.000000000 -0500 @@ -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-a 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 \ diff -NupwB ../4.7/openssh-4.7p1/myproposal.h openssh-4.7p1/myproposal.h --- ../4.7/openssh-4.7p1/myproposal.h 2007-06-11 00:01:42.000000000 -0400 +++ openssh-4.7p1/myproposal.h 2008-02-06 13:28:23.000000000 -0500 @@ -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," \ Common subdirectories: ../4.7/openssh-4.7p1/openbsd-compat and openssh-4.7p1/openbsd-compat diff -NupwB ../4.7/openssh-4.7p1/packet.c openssh-4.7p1/packet.c --- ../4.7/openssh-4.7p1/packet.c 2007-06-11 00:01:42.000000000 -0400 +++ openssh-4.7p1/packet.c 2008-02-06 13:29:19.000000000 -0500 @@ -710,7 +710,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; @@ -822,11 +822,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; @@ -844,7 +846,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)); } } @@ -852,7 +854,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) { @@ -865,19 +867,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); } /* @@ -1415,21 +1420,23 @@ 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 <= 0) { if (errno == EAGAIN) - return; + return (0); else fatal("Write failed: %.100s", strerror(errno)); } buffer_consume(&output, len); } + return(len); } /* @@ -1437,14 +1444,15 @@ packet_write_poll(void) * written. */ -void +int packet_write_wait(void) { fd_set *setp; + 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)); @@ -1452,9 +1460,10 @@ packet_write_wait(void) while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && (errno == EAGAIN || errno == EINTR)) ; - packet_write_poll(); + bytes_sent += packet_write_poll(); } xfree(setp); + return (bytes_sent); } /* Returns true if there is buffered data to write to the connection. */ @@ -1576,12 +1585,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) || @@ -1606,3 +1627,9 @@ packet_set_authenticated(void) { after_authentication = 1; } + +int +packet_authentication_state(void) +{ + return(after_authentication); +} diff -NupwB ../4.7/openssh-4.7p1/packet.h openssh-4.7p1/packet.h --- ../4.7/openssh-4.7p1/packet.h 2006-03-25 22:30:02.000000000 -0500 +++ openssh-4.7p1/packet.h 2008-02-06 13:29:19.000000000 -0500 @@ -20,6 +20,9 @@ #include +void +packet_request_rekeying(void); + void packet_set_connection(int, int); void packet_set_nonblocking(void); int packet_get_connection_in(void); @@ -34,6 +37,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); @@ -43,7 +47,7 @@ void packet_put_bignum2(BIGNUM * val 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); @@ -71,8 +75,8 @@ void packet_set_state(int, u_int32_t, u 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); diff -NupwB ../4.7/openssh-4.7p1/readconf.c openssh-4.7p1/readconf.c --- ../4.7/openssh-4.7p1/readconf.c 2007-03-21 05:46:03.000000000 -0400 +++ openssh-4.7p1/readconf.c 2008-02-06 13:28:23.000000000 -0500 @@ -130,6 +130,8 @@ typedef enum { oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, + oHPNBufferSize, oDeprecated, oUnsupported } OpCodes; @@ -226,6 +228,12 @@ static struct { { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, + { "noneenabled", oNoneEnabled }, + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "noneswitch", oNoneSwitch }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, { NULL, oBadOption } }; @@ -453,6 +461,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; @@ -632,6 +671,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); @@ -1065,6 +1108,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; } /* @@ -1187,6 +1236,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) diff -NupwB ../4.7/openssh-4.7p1/readconf.h openssh-4.7p1/readconf.h --- ../4.7/openssh-4.7p1/readconf.h 2006-08-04 22:39:40.000000000 -0400 +++ openssh-4.7p1/readconf.h 2008-02-06 13:28:23.000000000 -0500 @@ -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; int 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; Common subdirectories: ../4.7/openssh-4.7p1/regress and openssh-4.7p1/regress Common subdirectories: ../4.7/openssh-4.7p1/scard and openssh-4.7p1/scard diff -NupwB ../4.7/openssh-4.7p1/scp.c openssh-4.7p1/scp.c --- ../4.7/openssh-4.7p1/scp.c 2007-08-08 00:29:58.000000000 -0400 +++ openssh-4.7p1/scp.c 2008-02-06 13:28:23.000000000 -0500 @@ -585,7 +585,7 @@ source(int argc, char **argv) off_t i, amt, statbytes; size_t result; 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) { @@ -645,7 +645,7 @@ syserr: run_err("%s: %s", name, strerr (void) atomicio(vwrite, remout, buf, strlen(buf)); if (response() < 0) goto next; - if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { + if ((bp = allocbuf(&buffer, fd, sizeof(buf))) == NULL) { next: if (fd != -1) { (void) close(fd); fd = -1; @@ -813,7 +813,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] @@ -974,7 +974,7 @@ bad: run_err("%s: %s", np, strerror(er continue; } (void) atomicio(vwrite, remout, "", 1); - if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { + if ((bp = allocbuf(&buffer, ofd, sizeof(buf))) == NULL) { (void) close(ofd); continue; } @@ -984,8 +984,8 @@ bad: run_err("%s: %s", np, strerror(er statbytes = 0; if (showprogress) start_progress_meter(curfile, size, &statbytes); - for (count = i = 0; i < size; i += 4096) { - amt = 4096; + for (count = i = 0; i < size; i += sizeof(buf)) { + amt = sizeof(buf); if (i + amt > size) amt = size - i; count += amt; @@ -1002,7 +1002,7 @@ bad: run_err("%s: %s", np, strerror(er } while (amt > 0); if (limit_rate) - bwlimit(4096); + bwlimit(sizeof(buf)); if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ diff -NupwB ../4.7/openssh-4.7p1/servconf.c openssh-4.7p1/servconf.c --- ../4.7/openssh-4.7p1/servconf.c 2007-05-20 01:03:16.000000000 -0400 +++ openssh-4.7p1/servconf.c 2008-02-06 13:28:23.000000000 -0500 @@ -122,11 +122,19 @@ initialize_server_options(ServerOptions options->permit_tun = -1; options->num_permitted_opens = -1; options->adm_forced_command = 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) { + int sock; + int socksize; + int socksizelen = sizeof(int); + /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; @@ -250,6 +258,42 @@ fill_default_server_options(ServerOption 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; @@ -292,7 +336,8 @@ typedef enum { sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, - sUsePrivilegeSeparation, + sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll, + sHPNDisabled, sHPNBufferSize, sDeprecated, sUnsupported } ServerOpCodes; @@ -403,6 +448,10 @@ static struct { { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL }, + { "noneenabled", sNoneEnabled }, + { "hpndisabled", sHPNDisabled }, + { "hpnbuffersize", sHPNBufferSize }, + { "tcprcvbufpoll", sTcpRcvBufPoll }, { NULL, sBadOption, 0 } }; @@ -418,6 +467,7 @@ parse_token(const char *cp, const char * 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; } @@ -827,6 +877,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; diff -NupwB ../4.7/openssh-4.7p1/servconf.h openssh-4.7p1/servconf.h --- ../4.7/openssh-4.7p1/servconf.h 2007-02-19 06:25:38.000000000 -0500 +++ openssh-4.7p1/servconf.h 2008-02-06 13:28:23.000000000 -0500 @@ -137,6 +137,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; diff -NupwB ../4.7/openssh-4.7p1/serverloop.c openssh-4.7p1/serverloop.c --- ../4.7/openssh-4.7p1/serverloop.c 2007-01-28 18:16:28.000000000 -0500 +++ openssh-4.7p1/serverloop.c 2008-02-06 13:29:19.000000000 -0500 @@ -92,10 +92,10 @@ static int fdin; /* Descriptor for stdi 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_si 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 */ @@ -408,6 +422,7 @@ process_input(fd_set *readset) } else { /* Buffer any received data. */ packet_process_incoming(buf, len); + fdout_bytes += len; } } if (compat20) @@ -430,6 +445,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. */ @@ -496,7 +512,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(); } /* @@ -813,8 +829,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; @@ -876,6 +894,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 @@ -957,9 +980,14 @@ server_request_direct_tcpip(void) xfree(originator); if (sock < 0) return NULL; + 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; } @@ -994,8 +1022,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) @@ -1025,6 +1057,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 > 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); channel_free(c); @@ -1121,7 +1155,8 @@ server_input_global_request(int type, u_ } 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) { diff -NupwB ../4.7/openssh-4.7p1/session.c openssh-4.7p1/session.c --- ../4.7/openssh-4.7p1/session.c 2007-08-16 09:28:04.000000000 -0400 +++ openssh-4.7p1/session.c 2008-02-06 13:28:23.000000000 -0500 @@ -211,6 +211,7 @@ auth_input_request_forwarding(struct pas 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, @@ -348,7 +349,8 @@ do_authenticated1(Authctxt *authctxt) } debug("Received TCP/IP port forwarding request."); if (channel_input_port_forward_request(s->pw->pw_uid == 0, - options.gateway_ports) < 0) { + options.gateway_ports, options.hpn_disabled, + options.hpn_buffer_size) < 0) { debug("Port forwarding failed."); break; } @@ -2058,11 +2060,18 @@ session_set_fds(Session *s, int fdin, in */ 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, 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); } /* @@ -2407,7 +2416,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; } diff -NupwB ../4.7/openssh-4.7p1/ssh.c openssh-4.7p1/ssh.c --- ../4.7/openssh-4.7p1/ssh.c 2007-08-08 00:32:41.000000000 -0400 +++ openssh-4.7p1/ssh.c 2008-02-06 13:28:23.000000000 -0500 @@ -502,9 +502,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); @@ -513,6 +510,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; @@ -829,7 +833,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 != i && options.exit_on_forward_failure) fatal("Could not request local forwarding."); @@ -1142,6 +1147,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); @@ -1162,9 +1170,70 @@ 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(options.hpn_disabled) + { + options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; + } + else if (datafellows & SSH_BUG_LARGEWINDOW) + { + debug("HPN to Non-HPN Connection"); + if (options.hpn_buffer_size < 0) + options.hpn_buffer_size = 2*1024*1024; + } + else + { + if (options.hpn_buffer_size < 0) + options.hpn_buffer_size = BUFFER_MAX_LEN_HPN; + + /*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); + if (options.tcp_rcv_buf_poll <= 0) + { + options.hpn_buffer_size = MIN(socksize,options.hpn_buffer_size); + debug ("MIN of TCP RWIN and HPNBufferSize: %d", options.hpn_buffer_size); + } + else + { + if (options.tcp_rcv_buf > 0) + options.hpn_buffer_size = MIN(options.tcp_rcv_buf, options.hpn_buffer_size); + debug ("MIN of TCPRcvBuf and HPNBufferSize: %d", options.hpn_buffer_size); + } + + } + + debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); + + window = options.hpn_buffer_size; + packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { + window = 4*CHAN_SES_PACKET_DEFAULT; window >>= 1; packetmax >>= 1; } @@ -1172,7 +1241,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); diff -NupwB ../4.7/openssh-4.7p1/sshconnect2.c openssh-4.7p1/sshconnect2.c --- ../4.7/openssh-4.7p1/sshconnect2.c 2007-05-20 01:11:33.000000000 -0400 +++ openssh-4.7p1/sshconnect2.c 2008-02-06 13:28:23.000000000 -0500 @@ -73,6 +73,12 @@ 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 @@ -326,6 +332,28 @@ ssh_userauth2(const char *local_user, co 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); } diff -NupwB ../4.7/openssh-4.7p1/sshconnect.c openssh-4.7p1/sshconnect.c --- ../4.7/openssh-4.7p1/sshconnect.c 2006-10-23 13:02:24.000000000 -0400 +++ openssh-4.7p1/sshconnect.c 2008-02-06 13:28:23.000000000 -0500 @@ -164,6 +164,31 @@ ssh_proxy_connect(const char *host, u_sh } /* + * 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. */ static int @@ -186,12 +211,18 @@ ssh_create_socket(int privileged, struct 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; @@ -487,7 +518,7 @@ ssh_exchange_identification(void) snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, compat20 ? PROTOCOL_MINOR_2 : minor1, - SSH_VERSION); + SSH_RELEASE); if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) fatal("write: %.100s", strerror(errno)); client_version_string = xstrdup(buf); diff -NupwB ../4.7/openssh-4.7p1/sshd.c openssh-4.7p1/sshd.c --- ../4.7/openssh-4.7p1/sshd.c 2007-06-05 04:22:32.000000000 -0400 +++ openssh-4.7p1/sshd.c 2008-02-06 13:29:19.000000000 -0500 @@ -134,6 +134,9 @@ int deny_severity = LOG_WARNING; #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. */ @@ -419,7 +422,7 @@ sshd_exchange_identification(int sock_in major = PROTOCOL_MAJOR_1; minor = PROTOCOL_MINOR_1; } - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_RELEASE); server_version_string = xstrdup(buf); /* Send our protocol version identification. */ @@ -470,6 +473,9 @@ sshd_exchange_identification(int sock_in } 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); @@ -942,6 +948,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) @@ -979,6 +987,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.", @@ -2094,9 +2107,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]); diff -NupwB ../4.7/openssh-4.7p1/sshd_config openssh-4.7p1/sshd_config --- ../4.7/openssh-4.7p1/sshd_config 2007-03-21 05:42:25.000000000 -0400 +++ openssh-4.7p1/sshd_config 2008-02-06 13:28:23.000000000 -0500 @@ -109,6 +109,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 diff -NupwB ../4.7/openssh-4.7p1/version.h openssh-4.7p1/version.h --- ../4.7/openssh-4.7p1/version.h 2007-08-15 05:14:52.000000000 -0400 +++ openssh-4.7p1/version.h 2008-02-06 15:31:47.000000000 -0500 @@ -3,4 +3,5 @@ #define SSH_VERSION "OpenSSH_4.7" #define SSH_PORTABLE "p1" -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE +#define SSH_HPN "-hpn13v1" +#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN