1 | | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
2 | | +++ b/HPN-README 2016-03-01 04:32:19.000000000 +0100 |
3 | | @@ -0,0 +1,129 @@ |
4 | | +Notes: |
5 | | + |
6 | | +MULTI-THREADED CIPHER: |
7 | | +The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations |
8 | | +on hosts with multiple cores to use more than one processing core during encryption. |
9 | | +Tests have show significant throughput performance increases when using MTR-AES-CTR up |
10 | | +to and including a full gigabit per second on quad core systems. It should be possible to |
11 | | +achieve full line rate on dual core systems but OS and data management overhead makes this |
12 | | +more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single |
13 | | +thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal |
14 | | +performance requires the MTR-AES-CTR mode be enabled on both ends of the connection. |
15 | | +The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same |
16 | | +nomenclature. |
17 | | +Use examples: ssh -caes128-ctr you@host.com |
18 | | + scp -oCipher=aes256-ctr file you@host.com:~/file |
19 | | + |
20 | | +NONE CIPHER: |
21 | | +To use the NONE option you must have the NoneEnabled switch set on the server and |
22 | | +you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE |
23 | | +feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not |
24 | | +spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will |
25 | | +be disabled. |
26 | | + |
27 | | +The performance increase will only be as good as the network and TCP stack tuning |
28 | | +on the receiver side of the connection allows. As a rule of thumb a user will need |
29 | | +at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The |
30 | | +HPN-SSH home page describes this in greater detail. |
31 | | + |
32 | | +http://www.psc.edu/networking/projects/hpn-ssh |
33 | | + |
34 | | +BUFFER SIZES: |
35 | | + |
36 | | +If HPN is disabled the receive buffer size will be set to the |
37 | | +OpenSSH default of 64K. |
38 | | + |
39 | | +If an HPN system connects to a nonHPN system the receive buffer will |
40 | | +be set to the HPNBufferSize value. The default is 2MB but user adjustable. |
41 | | + |
42 | | +If an HPN to HPN connection is established a number of different things might |
43 | | +happen based on the user options and conditions. |
44 | | + |
45 | | +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set |
46 | | +HPN Buffer Size = up to 64MB |
47 | | +This is the default state. The HPN buffer size will grow to a maximum of 64MB |
48 | | +as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is |
49 | | +geared towards 10GigE transcontinental connections. |
50 | | + |
51 | | +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set |
52 | | +HPN Buffer Size = TCP receive buffer value. |
53 | | +Users on non-autotuning systesm should disable TCPRcvBufPoll in the |
54 | | +ssh_cofig and sshd_config |
55 | | + |
56 | | +Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set |
57 | | +HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. |
58 | | +This would be the system defined TCP receive buffer (RWIN). |
59 | | + |
60 | | +Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET |
61 | | +HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. |
62 | | +Generally there is no need to set both. |
63 | | + |
64 | | +Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set |
65 | | +HPN Buffer Size = grows to HPNBufferSize |
66 | | +The buffer will grow up to the maximum size specified here. |
67 | | + |
68 | | +Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET |
69 | | +HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. |
70 | | +Generally there is no need to set both of these, especially on autotuning |
71 | | +systems. However, if the users wishes to override the autotuning this would be |
72 | | +one way to do it. |
73 | | + |
74 | | +Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET |
75 | | +HPN Buffer Size = TCPRcvBuf. |
76 | | +This will override autotuning and set the TCP recieve buffer to the user defined |
77 | | +value. |
78 | | + |
79 | | + |
80 | | +HPN Specific Configuration options |
81 | | + |
82 | | +TcpRcvBuf=[int]KB client |
83 | | + set the TCP socket receive buffer to n Kilobytes. It can be set up to the |
84 | | +maximum socket size allowed by the system. This is useful in situations where |
85 | | +the tcp receive window is set low but the maximum buffer size is set |
86 | | +higher (as is typical). This works on a per TCP connection basis. You can also |
87 | | +use this to artifically limit the transfer rate of the connection. In these |
88 | | +cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. |
89 | | +Default is the current system wide tcp receive buffer size. |
90 | | + |
91 | | +TcpRcvBufPoll=[yes/no] client/server |
92 | | + enable of disable the polling of the tcp receive buffer through the life |
93 | | +of the connection. You would want to make sure that this option is enabled |
94 | | +for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) |
95 | | +default is yes. |
96 | | + |
97 | | +NoneEnabled=[yes/no] client/server |
98 | | + enable or disable the use of the None cipher. Care must always be used |
99 | | +when enabling this as it will allow users to send data in the clear. However, |
100 | | +it is important to note that authentication information remains encrypted |
101 | | +even if this option is enabled. Set to no by default. |
102 | | + |
103 | | +NoneSwitch=[yes/no] client |
104 | | + Switch the encryption cipher being used to the None cipher after |
105 | | +authentication takes place. NoneEnabled must be enabled on both the client |
106 | | +and server side of the connection. When the connection switches to the NONE |
107 | | +cipher a warning is sent to STDERR. The connection attempt will fail with an |
108 | | +error if a client requests a NoneSwitch from the server that does not explicitly |
109 | | +have NoneEnabled set to yes. Note: The NONE cipher cannot be used in |
110 | | +interactive (shell) sessions and it will fail silently. Set to no by default. |
111 | | + |
112 | | +HPNDisabled=[yes/no] client/server |
113 | | + In some situations, such as transfers on a local area network, the impact |
114 | | +of the HPN code produces a net decrease in performance. In these cases it is |
115 | | +helpful to disable the HPN functionality. By default HPNDisabled is set to no. |
116 | | + |
117 | | +HPNBufferSize=[int]KB client/server |
118 | | + This is the default buffer size the HPN functionality uses when interacting |
119 | | +with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf |
120 | | +option as applied to the internal SSH flow control. This value can range from |
121 | | +1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance |
122 | | +problems depending on the length of the network path. The default size of this buffer |
123 | | +is 2MB. |
124 | | + |
125 | | + |
126 | | +Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) |
127 | | + The majority of the actual coding for versions up to HPN12v1 was performed |
128 | | + by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was |
129 | | + implemented by Ben Bennet (ben@psc.edu) and improved by Mike Tasota |
130 | | + (tasota@gmail.com) an NSF REU grant recipient for 2013. |
131 | | + This work was financed, in part, by Cisco System, Inc., the National |
132 | | + Library of Medicine, and the National Science Foundation. |
133 | | --- a/channels.c 2016-03-01 04:32:11.000000000 +0100 |
134 | | +++ b/channels.c 2016-03-01 04:32:19.000000000 +0100 |
135 | | @@ -186,6 +186,12 @@ static void port_open_helper(Channel *c, |
136 | | static int connect_next(struct channel_connect *); |
137 | | static void channel_connect_ctx_free(struct channel_connect *); |
138 | | |
139 | | + |
140 | | +#ifdef HPN_ENABLED |
141 | | +static int hpn_disabled = 0; |
142 | | +static int hpn_buffer_size = 2 * 1024 * 1024; |
143 | | +#endif |
144 | | + |
145 | | /* -- channel core */ |
146 | | |
147 | | Channel * |
148 | | @@ -336,6 +342,9 @@ channel_new(char *ctype, int type, int r |
149 | | c->local_window_max = window; |
150 | | c->local_consumed = 0; |
151 | | c->local_maxpacket = maxpack; |
152 | | +#ifdef HPN_ENABLED |
153 | | + c->dynamic_window = 0; |
154 | | +#endif |
155 | | c->remote_id = -1; |
156 | | c->remote_name = xstrdup(remote_name); |
157 | | c->remote_window = 0; |
158 | | @@ -840,11 +849,41 @@ channel_pre_open_13(Channel *c, fd_set * |
159 | | FD_SET(c->sock, writeset); |
160 | | } |
161 | | |
162 | | +#ifdef HPN_ENABLED |
163 | | +static u_int |
164 | | +channel_tcpwinsz(void) |
165 | | +{ |
166 | | + u_int32_t tcpwinsz = 0; |
167 | | + socklen_t optsz = sizeof(tcpwinsz); |
168 | | + int ret = -1; |
169 | | + |
170 | | + /* if we aren't on a socket return 128KB */ |
171 | | + if (!packet_connection_is_on_socket()) |
172 | | + return (128*1024); |
173 | | + ret = getsockopt(packet_get_connection_in(), |
174 | | + SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); |
175 | | + /* return no more than SSHBUF_SIZE_MAX */ |
176 | | + if (ret == 0 && tcpwinsz > SSHBUF_SIZE_MAX) |
177 | | + tcpwinsz = SSHBUF_SIZE_MAX; |
178 | | + debug2("tcpwinsz: %d for connection: %d", tcpwinsz, |
179 | | + packet_get_connection_in()); |
180 | | + return (tcpwinsz); |
181 | | +} |
182 | | +#endif |
183 | | + |
184 | | static void |
185 | | channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) |
186 | | { |
187 | | u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); |
188 | | |
189 | | +#ifdef HPN_ENABLED |
190 | | + /* check buffer limits */ |
191 | | + if (!c->tcpwinsz || c->dynamic_window > 0) |
192 | | + c->tcpwinsz = channel_tcpwinsz(); |
193 | | + |
194 | | + limit = MIN(limit, 2 * c->tcpwinsz); |
195 | | +#endif |
196 | | + |
197 | | if (c->istate == CHAN_INPUT_OPEN && |
198 | | limit > 0 && |
199 | | buffer_len(&c->input) < limit && |
200 | | @@ -1862,6 +1901,20 @@ channel_check_window(Channel *c) |
201 | | c->local_maxpacket*3) || |
202 | | c->local_window < c->local_window_max/2) && |
203 | | c->local_consumed > 0) { |
204 | | +#ifdef HPN_ENABLED |
205 | | + /* adjust max window size if we are in a dynamic environment */ |
206 | | + if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { |
207 | | + u_int addition = 0; |
208 | | + |
209 | | + /* |
210 | | + * grow the window somewhat aggressively to maintain |
211 | | + * pressure |
212 | | + */ |
213 | | + addition = 1.5*(c->tcpwinsz - c->local_window_max); |
214 | | + c->local_window_max += addition; |
215 | | + c->local_consumed += addition; |
216 | | + } |
217 | | +#endif |
218 | | packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); |
219 | | packet_put_int(c->remote_id); |
220 | | packet_put_int(c->local_consumed); |
221 | | @@ -2813,6 +2866,17 @@ channel_fwd_bind_addr(const char *listen |
222 | | return addr; |
223 | | } |
224 | | |
225 | | +#ifdef HPN_ENABLED |
226 | | +void |
227 | | +channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size) |
228 | | +{ |
229 | | + hpn_disabled = external_hpn_disabled; |
230 | | + hpn_buffer_size = external_hpn_buffer_size; |
231 | | + debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, |
232 | | + hpn_buffer_size); |
233 | | +} |
234 | | +#endif |
235 | | + |
236 | | static int |
237 | | channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, |
238 | | int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
239 | | @@ -2941,6 +3005,17 @@ channel_setup_fwd_listener_tcpip(int typ |
240 | | } |
241 | | |
242 | | /* Allocate a channel number for the socket. */ |
243 | | +#ifdef HPN_ENABLED |
244 | | + /* |
245 | | + * explicitly test for hpn disabled option. if true use smaller |
246 | | + * window size. |
247 | | + */ |
248 | | + if (!hpn_disabled) |
249 | | + c = channel_new("port listener", type, sock, sock, -1, |
250 | | + hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, |
251 | | + 0, "port listener", 1); |
252 | | + else |
253 | | +#endif |
254 | | c = channel_new("port listener", type, sock, sock, -1, |
255 | | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
256 | | 0, "port listener", 1); |
257 | | @@ -3975,6 +4050,14 @@ x11_create_display_inet(int x11_display_ |
258 | | *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); |
259 | | for (n = 0; n < num_socks; n++) { |
260 | | sock = socks[n]; |
261 | | +#ifdef HPN_ENABLED |
262 | | + if (!hpn_disabled) |
263 | | + nc = channel_new("x11 listener", |
264 | | + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, |
265 | | + hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, |
266 | | + 0, "X11 inet listener", 1); |
267 | | + else |
268 | | +#endif |
269 | | nc = channel_new("x11 listener", |
270 | | SSH_CHANNEL_X11_LISTENER, sock, sock, -1, |
271 | | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
272 | | --- a/channels.h 2016-02-26 04:40:04.000000000 +0100 |
273 | | +++ b/channels.h 2016-03-01 04:32:19.000000000 +0100 |
274 | | @@ -136,6 +136,10 @@ struct Channel { |
275 | | u_int local_maxpacket; |
276 | | int extended_usage; |
277 | | int single_connection; |
278 | | +#ifdef HPN_ENABLED |
279 | | + int dynamic_window; |
280 | | + u_int tcpwinsz; |
281 | | +#endif |
282 | | |
283 | | char *ctype; /* type */ |
284 | | |
285 | | @@ -312,4 +316,9 @@ void chan_rcvd_ieof(Channel *); |
286 | | void chan_write_failed(Channel *); |
287 | | void chan_obuf_empty(Channel *); |
288 | | |
289 | | +#ifdef HPN_ENABLED |
290 | | +/* hpn handler */ |
291 | | +void channel_set_hpn(int, int); |
292 | | +#endif |
293 | | + |
294 | | #endif |
295 | | --- a/cipher.c 2016-02-26 04:40:04.000000000 +0100 |
296 | | +++ b/cipher.c 2016-03-01 04:32:19.000000000 +0100 |
297 | | @@ -244,7 +244,13 @@ ciphers_valid(const char *names) |
298 | | for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; |
299 | | (p = strsep(&cp, CIPHER_SEP))) { |
300 | | c = cipher_by_name(p); |
301 | | - if (c == NULL || c->number != SSH_CIPHER_SSH2) { |
302 | | + if (c == NULL || (c->number != SSH_CIPHER_SSH2 && |
303 | | +#ifdef NONE_CIPHER_ENABLED |
304 | | + c->number != SSH_CIPHER_NONE |
305 | | +#else |
306 | | + 1 |
307 | | +#endif |
308 | | + )) { |
309 | | free(cipher_list); |
310 | | return 0; |
311 | | } |
312 | | @@ -544,6 +550,9 @@ cipher_get_keyiv(struct sshcipher_ctx *c |
313 | | |
314 | | switch (c->number) { |
315 | | #ifdef WITH_OPENSSL |
316 | | +#ifdef NONE_CIPHER_ENABLED |
317 | | + case SSH_CIPHER_NONE: |
318 | | +#endif |
319 | | case SSH_CIPHER_SSH2: |
320 | | case SSH_CIPHER_DES: |
321 | | case SSH_CIPHER_BLOWFISH: |
322 | | @@ -592,6 +601,9 @@ cipher_set_keyiv(struct sshcipher_ctx *c |
323 | | |
324 | | switch (c->number) { |
325 | | #ifdef WITH_OPENSSL |
326 | | +#ifdef NONE_CIPHER_ENABLED |
327 | | + case SSH_CIPHER_NONE: |
328 | | +#endif |
329 | | case SSH_CIPHER_SSH2: |
330 | | case SSH_CIPHER_DES: |
331 | | case SSH_CIPHER_BLOWFISH: |
332 | | --- a/clientloop.c 2016-03-01 04:32:11.000000000 +0100 |
333 | | +++ b/clientloop.c 2016-03-01 04:32:19.000000000 +0100 |
334 | | @@ -1995,6 +1995,15 @@ client_request_x11(const char *request_t |
335 | | sock = x11_connect_display(); |
336 | | if (sock < 0) |
337 | | return NULL; |
338 | | +#ifdef HPN_ENABLED |
339 | | + /* again is this really necessary for X11? */ |
340 | | + if (!options.hpn_disabled) |
341 | | + c = channel_new("x11", |
342 | | + SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
343 | | + options.hpn_buffer_size, |
344 | | + CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
345 | | + else |
346 | | +#endif |
347 | | c = channel_new("x11", |
348 | | SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
349 | | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
350 | | @@ -2020,6 +2029,14 @@ client_request_agent(const char *request |
351 | | __func__, ssh_err(r)); |
352 | | return NULL; |
353 | | } |
354 | | +#ifdef HPN_ENABLED |
355 | | + if (!options.hpn_disabled) |
356 | | + c = channel_new("authentication agent connection", |
357 | | + SSH_CHANNEL_OPEN, sock, sock, -1, |
358 | | + options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, |
359 | | + "authentication agent connection", 1); |
360 | | + else |
361 | | +#endif |
362 | | c = channel_new("authentication agent connection", |
363 | | SSH_CHANNEL_OPEN, sock, sock, -1, |
364 | | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, |
365 | | @@ -2050,6 +2067,12 @@ client_request_tun_fwd(int tun_mode, int |
366 | | return -1; |
367 | | } |
368 | | |
369 | | +#ifdef HPN_ENABLED |
370 | | + if (!options.hpn_disabled) |
371 | | + c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
372 | | + options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
373 | | + else |
374 | | +#endif |
375 | | c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
376 | | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
377 | | c->datagram = 1; |
378 | | --- a/compat.c 2016-02-26 04:40:04.000000000 +0100 |
379 | | +++ b/compat.c 2016-03-01 04:32:19.000000000 +0100 |
380 | | @@ -210,6 +210,14 @@ compat_datafellows(const char *version) |
381 | | debug("match: %s pat %s compat 0x%08x", |
382 | | version, check[i].pat, check[i].bugs); |
383 | | datafellows = check[i].bugs; /* XXX for now */ |
384 | | +#ifdef HPN_ENABLED |
385 | | + /* Check to see if the remote side is OpenSSH and not HPN */ |
386 | | + if (strstr(version,"OpenSSH") != NULL && |
387 | | + strstr(version,"hpn") == NULL) { |
388 | | + datafellows |= SSH_BUG_LARGEWINDOW; |
389 | | + debug("Remote is NON-HPN aware"); |
390 | | + } |
391 | | +#endif |
392 | | return check[i].bugs; |
393 | | } |
394 | | } |
395 | | --- a/compat.h 2016-02-26 04:40:04.000000000 +0100 |
396 | | +++ b/compat.h 2016-03-01 04:32:19.000000000 +0100 |
397 | | @@ -62,6 +62,9 @@ |
398 | | #define SSH_BUG_CURVE25519PAD 0x10000000 |
399 | | #define SSH_BUG_HOSTKEYS 0x20000000 |
400 | | #define SSH_BUG_DHGEX_LARGE 0x40000000 |
401 | | +#ifdef HPN_ENABLED |
402 | | +#define SSH_BUG_LARGEWINDOW 0x80000000 |
403 | | +#endif |
404 | | |
405 | | void enable_compat13(void); |
406 | | void enable_compat20(void); |
407 | | --- a/configure.ac 2016-02-26 04:40:04.000000000 +0100 |
408 | | +++ b/configure.ac 2016-03-01 04:32:19.000000000 +0100 |
409 | | @@ -4321,6 +4321,25 @@ AC_ARG_WITH([maildir], |
410 | | ] |
411 | | ) # maildir |
412 | | |
413 | | +#check whether user wants HPN support |
414 | | +HPN_MSG="no" |
415 | | +AC_ARG_WITH(hpn, |
416 | | + [ --with-hpn Enable HPN support], |
417 | | + [ if test "x$withval" != "xno" ; then |
418 | | + AC_DEFINE(HPN_ENABLED,1,[Define if you want HPN support.]) |
419 | | + HPN_MSG="yes" |
420 | | + fi ] |
421 | | +) |
422 | | +#check whether user wants NONECIPHER support |
423 | | +NONECIPHER_MSG="no" |
424 | | +AC_ARG_WITH(nonecipher, |
425 | | + [ --with-nonecipher Enable NONECIPHER support], |
426 | | + [ if test "x$withval" != "xno" ; then |
427 | | + AC_DEFINE(NONE_CIPHER_ENABLED,1,[Define if you want NONECIPHER support.]) |
428 | | + NONECIPHER_MSG="yes" |
429 | | + fi ] |
430 | | +) |
431 | | + |
432 | | if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then |
433 | | AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test]) |
434 | | disable_ptmx_check=yes |
435 | | @@ -4989,6 +5008,8 @@ echo " Translate v4 in v6 hack |
436 | | echo " BSD Auth support: $BSD_AUTH_MSG" |
437 | | echo " Random number source: $RAND_MSG" |
438 | | echo " Privsep sandbox style: $SANDBOX_STYLE" |
439 | | +echo " HPN support: $HPN_MSG" |
440 | | +echo " NONECIPHER support: $NONECIPHER_MSG" |
441 | | |
442 | | echo "" |
443 | | |
444 | | --- a/kex.c 2016-02-26 04:40:04.000000000 +0100 |
445 | | +++ b/kex.c 2016-03-01 04:32:19.000000000 +0100 |
446 | | @@ -822,6 +822,20 @@ kex_choose_conf(struct ssh *ssh) |
447 | | peer[ncomp] = NULL; |
448 | | goto out; |
449 | | } |
450 | | +#ifdef NONE_CIPHER_ENABLED |
451 | | + debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); |
452 | | + if (strcmp(newkeys->enc.name, "none") == 0) { |
453 | | + int auth_flag; |
454 | | + |
455 | | + auth_flag = ssh_packet_authentication_state(ssh); |
456 | | + debug("Requesting NONE. Authflag is %d", auth_flag); |
457 | | + if (auth_flag == 1) { |
458 | | + debug("None requested post authentication."); |
459 | | + } else { |
460 | | + fatal("Pre-authentication none cipher requests are not allowed."); |
461 | | + } |
462 | | + } |
463 | | +#endif |
464 | | debug("kex: %s cipher: %s MAC: %s compression: %s", |
465 | | ctos ? "client->server" : "server->client", |
466 | | newkeys->enc.name, |
467 | | --- a/packet.c 2016-02-26 04:40:04.000000000 +0100 |
468 | | +++ b/packet.c 2016-03-01 04:32:19.000000000 +0100 |
469 | | @@ -1037,6 +1037,24 @@ ssh_set_newkeys(struct ssh *ssh, int mod |
470 | | return 0; |
471 | | } |
472 | | |
473 | | +#ifdef NONE_CIPHER_ENABLED |
474 | | +/* this supports the forced rekeying required for the NONE cipher */ |
475 | | +int rekey_requested = 0; |
476 | | +void |
477 | | +packet_request_rekeying(void) |
478 | | +{ |
479 | | + rekey_requested = 1; |
480 | | +} |
481 | | + |
482 | | +int |
483 | | +ssh_packet_authentication_state(struct ssh *ssh) |
484 | | +{ |
485 | | + struct session_state *state = ssh->state; |
486 | | + |
487 | | + return(state->after_authentication); |
488 | | +} |
489 | | +#endif |
490 | | + |
491 | | #define MAX_PACKETS (1U<<31) |
492 | | static int |
493 | | ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) |
494 | | @@ -1055,6 +1073,12 @@ ssh_packet_need_rekeying(struct ssh *ssh |
495 | | /* Peer can't rekey */ |
496 | | if (ssh->compat & SSH_BUG_NOREKEY) |
497 | | return 0; |
498 | | +#ifdef NONE_CIPHER_ENABLED |
499 | | + if (rekey_requested == 1) { |
500 | | + rekey_requested = 0; |
501 | | + return 1; |
502 | | + } |
503 | | +#endif |
504 | | |
505 | | /* |
506 | | * Permit one packet in or out per rekey - this allows us to |
507 | | --- a/packet.h 2016-02-26 04:40:04.000000000 +0100 |
508 | | +++ b/packet.h 2016-03-01 04:32:19.000000000 +0100 |
509 | | @@ -185,6 +185,11 @@ int sshpkt_get_bignum2(struct ssh *ssh, |
510 | | int sshpkt_get_end(struct ssh *ssh); |
511 | | const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); |
512 | | |
513 | | +#ifdef NONE_CIPHER_ENABLED |
514 | | +void packet_request_rekeying(void); |
515 | | +int ssh_packet_authentication_state(struct ssh *ssh); |
516 | | +#endif |
517 | | + |
518 | | /* OLD API */ |
519 | | extern struct ssh *active_state; |
520 | | #include "opacket.h" |
521 | | --- a/readconf.c 2016-02-26 04:40:04.000000000 +0100 |
522 | | +++ b/readconf.c 2016-03-01 04:32:19.000000000 +0100 |
523 | | @@ -154,6 +154,12 @@ typedef enum { |
524 | | oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, |
525 | | oVisualHostKey, |
526 | | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
527 | | +#ifdef HPN_ENABLED |
528 | | + oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf, |
529 | | +#endif |
530 | | +#ifdef NONE_CIPHER_ENABLED |
531 | | + oNoneSwitch, oNoneEnabled, |
532 | | +#endif |
533 | | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
534 | | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
535 | | oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, |
536 | | @@ -280,6 +286,16 @@ static struct { |
537 | | { "updatehostkeys", oUpdateHostkeys }, |
538 | | { "hostbasedkeytypes", oHostbasedKeyTypes }, |
539 | | { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, |
540 | | +#ifdef NONE_CIPHER_ENABLED |
541 | | + { "noneenabled", oNoneEnabled }, |
542 | | + { "noneswitch", oNoneSwitch }, |
543 | | +#endif |
544 | | +#ifdef HPN_ENABLED |
545 | | + { "tcprcvbufpoll", oTcpRcvBufPoll }, |
546 | | + { "tcprcvbuf", oTcpRcvBuf }, |
547 | | + { "hpndisabled", oHPNDisabled }, |
548 | | + { "hpnbuffersize", oHPNBufferSize }, |
549 | | +#endif |
550 | | { "ignoreunknown", oIgnoreUnknown }, |
551 | | |
552 | | { NULL, oBadOption } |
553 | | @@ -938,6 +954,44 @@ parse_time: |
554 | | intptr = &options->check_host_ip; |
555 | | goto parse_flag; |
556 | | |
557 | | +#ifdef HPN_ENABLED |
558 | | + case oHPNDisabled: |
559 | | + intptr = &options->hpn_disabled; |
560 | | + goto parse_flag; |
561 | | + |
562 | | + case oHPNBufferSize: |
563 | | + intptr = &options->hpn_buffer_size; |
564 | | + goto parse_int; |
565 | | + |
566 | | + case oTcpRcvBufPoll: |
567 | | + intptr = &options->tcp_rcv_buf_poll; |
568 | | + goto parse_flag; |
569 | | + |
570 | | + case oTcpRcvBuf: |
571 | | + intptr = &options->tcp_rcv_buf; |
572 | | + goto parse_int; |
573 | | +#endif |
574 | | + |
575 | | +#ifdef NONE_CIPHER_ENABLED |
576 | | + case oNoneEnabled: |
577 | | + intptr = &options->none_enabled; |
578 | | + goto parse_flag; |
579 | | + |
580 | | + /* we check to see if the command comes from the */ |
581 | | + /* command line or not. If it does then enable it */ |
582 | | + /* otherwise fail. NONE should never be a default configuration */ |
583 | | + case oNoneSwitch: |
584 | | + if(strcmp(filename,"command-line") == 0) { |
585 | | + intptr = &options->none_switch; |
586 | | + goto parse_flag; |
587 | | + } else { |
588 | | + error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); |
589 | | + error("Continuing..."); |
590 | | + debug("NoneSwitch directive found in %.200s.", filename); |
591 | | + return 0; |
592 | | + } |
593 | | +#endif |
594 | | + |
595 | | case oVerifyHostKeyDNS: |
596 | | intptr = &options->verify_host_key_dns; |
597 | | multistate_ptr = multistate_yesnoask; |
598 | | @@ -1713,6 +1767,16 @@ initialize_options(Options * options) |
599 | | options->ip_qos_interactive = -1; |
600 | | options->ip_qos_bulk = -1; |
601 | | options->request_tty = -1; |
602 | | +#ifdef NONE_CIPHER_ENABLED |
603 | | + options->none_switch = -1; |
604 | | + options->none_enabled = -1; |
605 | | +#endif |
606 | | +#ifdef HPN_ENABLED |
607 | | + options->hpn_disabled = -1; |
608 | | + options->hpn_buffer_size = -1; |
609 | | + options->tcp_rcv_buf_poll = -1; |
610 | | + options->tcp_rcv_buf = -1; |
611 | | +#endif |
612 | | options->proxy_use_fdpass = -1; |
613 | | options->ignored_unknown = NULL; |
614 | | options->num_canonical_domains = 0; |
615 | | @@ -1867,6 +1931,35 @@ fill_default_options(Options * options) |
616 | | options->server_alive_interval = 0; |
617 | | if (options->server_alive_count_max == -1) |
618 | | options->server_alive_count_max = 3; |
619 | | +#ifdef NONE_CIPHER_ENABLED |
620 | | + if (options->none_switch == -1) |
621 | | + options->none_switch = 0; |
622 | | + if (options->none_enabled == -1) |
623 | | + options->none_enabled = 0; |
624 | | +#endif |
625 | | +#ifdef HPN_ENABLED |
626 | | + if (options->hpn_disabled == -1) |
627 | | + options->hpn_disabled = 0; |
628 | | + if (options->hpn_buffer_size > -1) { |
629 | | + /* if a user tries to set the size to 0 set it to 1KB */ |
630 | | + if (options->hpn_buffer_size == 0) |
631 | | + options->hpn_buffer_size = 1; |
632 | | + /* limit the buffer to 64MB */ |
633 | | + if (options->hpn_buffer_size > 64*1024) { |
634 | | + options->hpn_buffer_size = 64*1024*1024; |
635 | | + debug("User requested buffer larger than 64MB. Request" |
636 | | + " reverted to 64MB"); |
637 | | + } else |
638 | | + options->hpn_buffer_size *= 1024; |
639 | | + debug("hpn_buffer_size set to %d", options->hpn_buffer_size); |
640 | | + } |
641 | | + if (options->tcp_rcv_buf == 0) |
642 | | + options->tcp_rcv_buf = 1; |
643 | | + if (options->tcp_rcv_buf > -1) |
644 | | + options->tcp_rcv_buf *=1024; |
645 | | + if (options->tcp_rcv_buf_poll == -1) |
646 | | + options->tcp_rcv_buf_poll = 1; |
647 | | +#endif |
648 | | if (options->control_master == -1) |
649 | | options->control_master = 0; |
650 | | if (options->control_persist == -1) { |
651 | | --- a/readconf.h 2016-02-26 04:40:04.000000000 +0100 |
652 | | +++ b/readconf.h 2016-03-01 04:32:19.000000000 +0100 |
653 | | @@ -112,6 +112,16 @@ typedef struct { |
654 | | int clear_forwardings; |
655 | | |
656 | | int enable_ssh_keysign; |
657 | | +#ifdef NONE_CIPHER_ENABLED |
658 | | + int none_switch; /* Use none cipher */ |
659 | | + int none_enabled; /* Allow none to be used */ |
660 | | +#endif |
661 | | +#ifdef HPN_ENABLED |
662 | | + int tcp_rcv_buf; /* user switch to set tcp recv buffer */ |
663 | | + int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ |
664 | | + int hpn_disabled; /* Switch to disable HPN buffer management */ |
665 | | + int hpn_buffer_size; /* User definable size for HPN buffer window */ |
666 | | +#endif |
667 | | int64_t rekey_limit; |
668 | | int rekey_interval; |
669 | | int no_host_authentication_for_localhost; |
670 | | --- a/scp.c 2016-02-26 04:40:04.000000000 +0100 |
671 | | +++ b/scp.c 2016-03-01 04:32:19.000000000 +0100 |
672 | | @@ -760,7 +760,7 @@ source(int argc, char **argv) |
673 | | off_t i, statbytes; |
674 | | size_t amt, nr; |
675 | | int fd = -1, haderr, indx; |
676 | | - char *last, *name, buf[2048], encname[PATH_MAX]; |
677 | | + char *last, *name, buf[16384], encname[PATH_MAX]; |
678 | | int len; |
679 | | |
680 | | for (indx = 0; indx < argc; ++indx) { |
681 | | @@ -929,7 +929,7 @@ sink(int argc, char **argv) |
682 | | off_t size, statbytes; |
683 | | unsigned long long ull; |
684 | | int setimes, targisdir, wrerrno = 0; |
685 | | - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
686 | | + char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; |
687 | | struct timeval tv[2]; |
688 | | |
689 | | #define atime tv[0] |
690 | | --- a/servconf.c 2016-03-01 04:32:13.000000000 +0100 |
691 | | +++ b/servconf.c 2016-03-01 04:32:19.000000000 +0100 |
692 | | @@ -165,6 +165,14 @@ initialize_server_options(ServerOptions |
693 | | options->authorized_principals_file = NULL; |
694 | | options->authorized_principals_command = NULL; |
695 | | options->authorized_principals_command_user = NULL; |
696 | | +#ifdef NONE_CIPHER_ENABLED |
697 | | + options->none_enabled = -1; |
698 | | +#endif |
699 | | +#ifdef HPN_ENABLED |
700 | | + options->tcp_rcv_buf_poll = -1; |
701 | | + options->hpn_disabled = -1; |
702 | | + options->hpn_buffer_size = -1; |
703 | | +#endif |
704 | | options->ip_qos_interactive = -1; |
705 | | options->ip_qos_bulk = -1; |
706 | | options->version_addendum = NULL; |
707 | | @@ -341,6 +349,57 @@ fill_default_server_options(ServerOption |
708 | | } |
709 | | if (options->permit_tun == -1) |
710 | | options->permit_tun = SSH_TUNMODE_NO; |
711 | | +#ifdef NONE_CIPHER_ENABLED |
712 | | + if (options->none_enabled == -1) |
713 | | + options->none_enabled = 0; |
714 | | +#endif |
715 | | +#ifdef HPN_ENABLED |
716 | | + if (options->hpn_disabled == -1) |
717 | | + options->hpn_disabled = 0; |
718 | | + |
719 | | + if (options->hpn_buffer_size == -1) { |
720 | | + /* |
721 | | + * option not explicitly set. Now we have to figure out |
722 | | + * what value to use. |
723 | | + */ |
724 | | + if (options->hpn_disabled == 1) { |
725 | | + options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; |
726 | | + } else { |
727 | | + int sock, socksize; |
728 | | + socklen_t socksizelen = sizeof(socksize); |
729 | | + |
730 | | + /* |
731 | | + * get the current RCV size and set it to that |
732 | | + * create a socket but don't connect it |
733 | | + * we use that the get the rcv socket size |
734 | | + */ |
735 | | + sock = socket(AF_INET, SOCK_STREAM, 0); |
736 | | + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, |
737 | | + &socksize, &socksizelen); |
738 | | + close(sock); |
739 | | + options->hpn_buffer_size = socksize; |
740 | | + debug ("HPN Buffer Size: %d", options->hpn_buffer_size); |
741 | | + } |
742 | | + } else { |
743 | | + /* |
744 | | + * we have to do this incase the user sets both values in a |
745 | | + * contradictory manner. hpn_disabled overrrides |
746 | | + * hpn_buffer_size |
747 | | + */ |
748 | | + if (options->hpn_disabled <= 0) { |
749 | | + if (options->hpn_buffer_size == 0) |
750 | | + options->hpn_buffer_size = 1; |
751 | | + /* limit the maximum buffer to 64MB */ |
752 | | + if (options->hpn_buffer_size > 64*1024) { |
753 | | + options->hpn_buffer_size = 64*1024*1024; |
754 | | + } else { |
755 | | + options->hpn_buffer_size *= 1024; |
756 | | + } |
757 | | + } else |
758 | | + options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; |
759 | | + } |
760 | | +#endif |
761 | | + |
762 | | if (options->ip_qos_interactive == -1) |
763 | | options->ip_qos_interactive = IPTOS_LOWDELAY; |
764 | | if (options->ip_qos_bulk == -1) |
765 | | @@ -425,6 +484,12 @@ typedef enum { |
766 | | sHostCertificate, |
767 | | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
768 | | sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
769 | | +#ifdef NONE_CIPHER_ENABLED |
770 | | + sNoneEnabled, |
771 | | +#endif |
772 | | +#ifdef HPN_ENABLED |
773 | | + sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, |
774 | | +#endif |
775 | | sKexAlgorithms, sIPQoS, sVersionAddendum, |
776 | | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
777 | | sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, |
778 | | @@ -560,6 +625,14 @@ static struct { |
779 | | { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, |
780 | | { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
781 | | { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
782 | | +#ifdef NONE_CIPHER_ENABLED |
783 | | + { "noneenabled", sNoneEnabled, SSHCFG_ALL }, |
784 | | +#endif |
785 | | +#ifdef HPN_ENABLED |
786 | | + { "hpndisabled", sHPNDisabled, SSHCFG_ALL }, |
787 | | + { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL }, |
788 | | + { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL }, |
789 | | +#endif |
790 | | { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
791 | | { "ipqos", sIPQoS, SSHCFG_ALL }, |
792 | | { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
793 | | @@ -1180,6 +1253,25 @@ process_server_config_line(ServerOptions |
794 | | intptr = &options->ignore_user_known_hosts; |
795 | | goto parse_flag; |
796 | | |
797 | | +#ifdef NONE_CIPHER_ENABLED |
798 | | + case sNoneEnabled: |
799 | | + intptr = &options->none_enabled; |
800 | | + goto parse_flag; |
801 | | +#endif |
802 | | +#ifdef HPN_ENABLED |
803 | | + case sTcpRcvBufPoll: |
804 | | + intptr = &options->tcp_rcv_buf_poll; |
805 | | + goto parse_flag; |
806 | | + |
807 | | + case sHPNDisabled: |
808 | | + intptr = &options->hpn_disabled; |
809 | | + goto parse_flag; |
810 | | + |
811 | | + case sHPNBufferSize: |
812 | | + intptr = &options->hpn_buffer_size; |
813 | | + goto parse_int; |
814 | | +#endif |
815 | | + |
816 | | case sRhostsRSAAuthentication: |
817 | | intptr = &options->rhosts_rsa_authentication; |
818 | | goto parse_flag; |
819 | | --- a/servconf.h 2016-02-26 04:40:04.000000000 +0100 |
820 | | +++ b/servconf.h 2016-03-01 04:32:19.000000000 +0100 |
821 | | @@ -173,6 +173,15 @@ typedef struct { |
822 | | |
823 | | int use_pam; /* Enable auth via PAM */ |
824 | | |
825 | | +#ifdef NONE_CIPHER_ENABLED |
826 | | + int none_enabled; /* enable NONE cipher switch */ |
827 | | +#endif |
828 | | +#ifdef HPN_ENABLED |
829 | | + int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ |
830 | | + int hpn_disabled; /* disable hpn functionality. false by default */ |
831 | | + int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ |
832 | | +#endif |
833 | | + |
834 | | int permit_tun; |
835 | | |
836 | | int num_permitted_opens; |
837 | | --- a/serverloop.c 2016-02-26 04:40:04.000000000 +0100 |
838 | | +++ b/serverloop.c 2016-03-01 04:32:19.000000000 +0100 |
839 | | @@ -1041,6 +1041,12 @@ server_request_tun(void) |
840 | | sock = tun_open(tun, mode); |
841 | | if (sock < 0) |
842 | | goto done; |
843 | | +#ifdef HPN_ENABLED |
844 | | + if (!options.hpn_disabled) |
845 | | + c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, |
846 | | + options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
847 | | + else |
848 | | +#endif |
849 | | c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, |
850 | | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
851 | | c->datagram = 1; |
852 | | @@ -1078,6 +1084,10 @@ server_request_session(void) |
853 | | c = channel_new("session", SSH_CHANNEL_LARVAL, |
854 | | -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, |
855 | | 0, "server-session", 1); |
856 | | +#ifdef HPN_ENABLED |
857 | | + if (options.tcp_rcv_buf_poll && !options.hpn_disabled) |
858 | | + c->dynamic_window = 1; |
859 | | +#endif |
860 | | if (session_open(the_authctxt, c->self) != 1) { |
861 | | debug("session open failed, free channel %d", c->self); |
862 | | channel_free(c); |
863 | | --- a/session.c 2016-02-26 04:40:04.000000000 +0100 |
864 | | +++ b/session.c 2016-03-01 04:32:19.000000000 +0100 |
865 | | @@ -2326,6 +2326,14 @@ session_set_fds(Session *s, int fdin, in |
866 | | */ |
867 | | if (s->chanid == -1) |
868 | | fatal("no channel for session %d", s->self); |
869 | | +#ifdef HPN_ENABLED |
870 | | + if (!options.hpn_disabled) |
871 | | + channel_set_fds(s->chanid, |
872 | | + fdout, fdin, fderr, |
873 | | + ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, |
874 | | + 1, is_tty, options.hpn_buffer_size); |
875 | | + else |
876 | | +#endif |
877 | | channel_set_fds(s->chanid, |
878 | | fdout, fdin, fderr, |
879 | | ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, |
880 | | --- a/sftp.1 2016-02-26 04:40:04.000000000 +0100 |
881 | | +++ b/sftp.1 2016-03-01 04:32:19.000000000 +0100 |
882 | | @@ -264,7 +264,8 @@ diagnostic messages from |
883 | | Specify how many requests may be outstanding at any one time. |
884 | | Increasing this may slightly improve file transfer speed |
885 | | but will increase memory usage. |
886 | | -The default is 64 outstanding requests. |
887 | | +The default is 256 outstanding requests providing for 8MB |
888 | | +of outstanding data with a 32KB buffer. |
889 | | .It Fl r |
890 | | Recursively copy entire directories when uploading and downloading. |
891 | | Note that |
892 | | --- a/sftp.c 2016-02-26 04:40:04.000000000 +0100 |
893 | | +++ b/sftp.c 2016-03-01 04:32:19.000000000 +0100 |
894 | | @@ -71,7 +71,11 @@ typedef void EditLine; |
895 | | #include "sftp-client.h" |
896 | | |
897 | | #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ |
898 | | +#ifdef HPN_ENABLED |
899 | | +#define DEFAULT_NUM_REQUESTS 256 /* # concurrent outstanding requests */ |
900 | | +#else |
901 | | #define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ |
902 | | +#endif |
903 | | |
904 | | /* File to read commands from */ |
905 | | FILE* infile; |
906 | | --- a/ssh.c 2016-02-26 04:40:04.000000000 +0100 |
907 | | +++ b/ssh.c 2016-03-01 04:32:19.000000000 +0100 |
908 | | @@ -898,6 +898,14 @@ main(int ac, char **av) |
909 | | break; |
910 | | case 'T': |
911 | | options.request_tty = REQUEST_TTY_NO; |
912 | | +#ifdef NONE_CIPHER_ENABLED |
913 | | + /* |
914 | | + * ensure that the user doesn't try to backdoor a |
915 | | + * null cipher switch on an interactive session |
916 | | + * so explicitly disable it no matter what. |
917 | | + */ |
918 | | + options.none_switch = 0; |
919 | | +#endif |
920 | | break; |
921 | | case 'o': |
922 | | line = xstrdup(optarg); |
923 | | @@ -1851,9 +1859,85 @@ ssh_session2_open(void) |
924 | | if (!isatty(err)) |
925 | | set_nonblock(err); |
926 | | |
927 | | +#ifdef HPN_ENABLED |
928 | | + /* |
929 | | + * we need to check to see if what they want to do about buffer |
930 | | + * sizes here. In a hpn to nonhpn connection we want to limit |
931 | | + * the window size to something reasonable in case the far side |
932 | | + * has the large window bug. In hpn to hpn connection we want to |
933 | | + * use the max window size but allow the user to override it |
934 | | + * lastly if they disabled hpn then use the ssh std window size |
935 | | + |
936 | | + * so why don't we just do a getsockopt() here and set the |
937 | | + * ssh window to that? In the case of a autotuning receive |
938 | | + * window the window would get stuck at the initial buffer |
939 | | + * size generally less than 96k. Therefore we need to set the |
940 | | + * maximum ssh window size to the maximum hpn buffer size |
941 | | + * unless the user has specifically set the tcprcvbufpoll |
942 | | + * to no. In which case we *can* just set the window to the |
943 | | + * minimum of the hpn buffer size and tcp receive buffer size |
944 | | + */ |
945 | | + |
946 | | + if (tty_flag) |
947 | | + options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; |
948 | | + else |
949 | | + options.hpn_buffer_size = 2*1024*1024; |
950 | | + |
951 | | + if (datafellows & SSH_BUG_LARGEWINDOW) { |
952 | | + debug("HPN to Non-HPN Connection"); |
953 | | + } else { |
954 | | + int sock, socksize; |
955 | | + socklen_t socksizelen = sizeof(socksize); |
956 | | + |
957 | | + if (options.tcp_rcv_buf_poll <= 0) { |
958 | | + sock = socket(AF_INET, SOCK_STREAM, 0); |
959 | | + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, |
960 | | + &socksize, &socksizelen); |
961 | | + close(sock); |
962 | | + debug("socksize %d", socksize); |
963 | | + options.hpn_buffer_size = socksize; |
964 | | + debug ("HPNBufferSize set to TCP RWIN: %d", |
965 | | + options.hpn_buffer_size); |
966 | | + } else { |
967 | | + if (options.tcp_rcv_buf > 0) { |
968 | | + /* |
969 | | + * create a socket but don't connect it. |
970 | | + * we use that the get the rcv socket size |
971 | | + */ |
972 | | + sock = socket(AF_INET, SOCK_STREAM, 0); |
973 | | + /* |
974 | | + * if they are using the tcp_rcv_buf option |
975 | | + * attempt to set the buffer size to that |
976 | | + */ |
977 | | + if (options.tcp_rcv_buf) |
978 | | + setsockopt(sock, SOL_SOCKET, SO_RCVBUF, |
979 | | + (void *)&options.tcp_rcv_buf, |
980 | | + sizeof(options.tcp_rcv_buf)); |
981 | | + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, |
982 | | + &socksize, &socksizelen); |
983 | | + close(sock); |
984 | | + debug("socksize %d", socksize); |
985 | | + options.hpn_buffer_size = socksize; |
986 | | + debug ("HPNBufferSize set to user TCPRcvBuf: " |
987 | | + "%d", options.hpn_buffer_size); |
988 | | + } |
989 | | + } |
990 | | + } |
991 | | + |
992 | | + debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); |
993 | | + |
994 | | + window = options.hpn_buffer_size; |
995 | | + |
996 | | + channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); |
997 | | +#else |
998 | | window = CHAN_SES_WINDOW_DEFAULT; |
999 | | +#endif |
1000 | | + |
1001 | | packetmax = CHAN_SES_PACKET_DEFAULT; |
1002 | | if (tty_flag) { |
1003 | | +#ifdef HPN_ENABLED |
1004 | | + window = CHAN_SES_WINDOW_DEFAULT; |
1005 | | +#endif |
1006 | | window >>= 1; |
1007 | | packetmax >>= 1; |
1008 | | } |
1009 | | @@ -1862,6 +1946,12 @@ ssh_session2_open(void) |
1010 | | window, packetmax, CHAN_EXTENDED_WRITE, |
1011 | | "client-session", /*nonblock*/0); |
1012 | | |
1013 | | +#ifdef HPN_ENABLED |
1014 | | + if (options.tcp_rcv_buf_poll > 0 && !options.hpn_disabled) { |
1015 | | + c->dynamic_window = 1; |
1016 | | + debug ("Enabled Dynamic Window Scaling"); |
1017 | | + } |
1018 | | +#endif |
1019 | | debug3("ssh_session2_open: channel_new: %d", c->self); |
1020 | | |
1021 | | channel_send_open(c->self); |
1022 | | --- a/sshconnect.c 2016-02-26 04:40:04.000000000 +0100 |
1023 | | +++ b/sshconnect.c 2016-03-01 04:32:19.000000000 +0100 |
1024 | | @@ -267,6 +267,31 @@ ssh_kill_proxy_command(void) |
1025 | | kill(proxy_command_pid, SIGHUP); |
1026 | | } |
1027 | | |
1028 | | +#ifdef HPN_ENABLED |
1029 | | +/* |
1030 | | + * Set TCP receive buffer if requested. |
1031 | | + * Note: tuning needs to happen after the socket is |
1032 | | + * created but before the connection happens |
1033 | | + * so winscale is negotiated properly -cjr |
1034 | | + */ |
1035 | | +static void |
1036 | | +ssh_set_socket_recvbuf(int sock) |
1037 | | +{ |
1038 | | + void *buf = (void *)&options.tcp_rcv_buf; |
1039 | | + int sz = sizeof(options.tcp_rcv_buf); |
1040 | | + int socksize; |
1041 | | + socklen_t socksizelen = sizeof(socksize); |
1042 | | + |
1043 | | + debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); |
1044 | | + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { |
1045 | | + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); |
1046 | | + debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); |
1047 | | + } else |
1048 | | + error("Couldn't set socket receive buffer to %d: %.100s", |
1049 | | + options.tcp_rcv_buf, strerror(errno)); |
1050 | | +} |
1051 | | +#endif |
1052 | | + |
1053 | | /* |
1054 | | * Creates a (possibly privileged) socket for use as the ssh connection. |
1055 | | */ |
1056 | | @@ -283,6 +308,11 @@ ssh_create_socket(int privileged, struct |
1057 | | } |
1058 | | fcntl(sock, F_SETFD, FD_CLOEXEC); |
1059 | | |
1060 | | +#ifdef HPN_ENABLED |
1061 | | + if (options.tcp_rcv_buf > 0) |
1062 | | + ssh_set_socket_recvbuf(sock); |
1063 | | +#endif |
1064 | | + |
1065 | | /* Bind the socket to an alternative local IP address */ |
1066 | | if (options.bind_address == NULL && !privileged) |
1067 | | return sock; |
1068 | | @@ -526,11 +556,23 @@ send_client_banner(int connection_out, i |
1069 | | { |
1070 | | /* Send our own protocol version identification. */ |
1071 | | if (compat20) { |
1072 | | - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", |
1073 | | - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); |
1074 | | + xasprintf(&client_version_string, "SSH-%d.%d-%.100s%s\r\n", |
1075 | | + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, |
1076 | | +#ifdef HPN_ENABLED |
1077 | | + options.hpn_disabled ? "" : SSH_HPN |
1078 | | +#else |
1079 | | + "" |
1080 | | +#endif |
1081 | | + ); |
1082 | | } else { |
1083 | | - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n", |
1084 | | - PROTOCOL_MAJOR_1, minor1, SSH_VERSION); |
1085 | | + xasprintf(&client_version_string, "SSH-%d.%d-%.100s%s\n", |
1086 | | + PROTOCOL_MAJOR_1, minor1, SSH_VERSION, |
1087 | | +#ifdef HPN_ENABLED |
1088 | | + options.hpn_disabled ? "" : SSH_HPN |
1089 | | +#else |
1090 | | + "" |
1091 | | +#endif |
1092 | | + ); |
1093 | | } |
1094 | | if (atomicio(vwrite, connection_out, client_version_string, |
1095 | | strlen(client_version_string)) != strlen(client_version_string)) |
1096 | | --- a/sshconnect2.c 2016-02-26 04:40:04.000000000 +0100 |
1097 | | +++ b/sshconnect2.c 2016-03-01 04:32:19.000000000 +0100 |
1098 | | @@ -80,6 +80,14 @@ |
1099 | | extern char *client_version_string; |
1100 | | extern char *server_version_string; |
1101 | | extern Options options; |
1102 | | +#ifdef NONE_CIPHER_ENABLED |
1103 | | +struct kex *xxx_kex; |
1104 | | + |
1105 | | +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ |
1106 | | +/* if it is set then prevent the switch to the null cipher */ |
1107 | | + |
1108 | | +extern int tty_flag; |
1109 | | +#endif |
1110 | | |
1111 | | /* |
1112 | | * SSH2 key exchange |
1113 | | @@ -153,14 +161,17 @@ order_hostkeyalgs(char *host, struct soc |
1114 | | return ret; |
1115 | | } |
1116 | | |
1117 | | +static char *myproposal[PROPOSAL_MAX]; |
1118 | | +static const char *myproposal_default[PROPOSAL_MAX] = { KEX_CLIENT }; |
1119 | | void |
1120 | | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
1121 | | { |
1122 | | - char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; |
1123 | | char *s; |
1124 | | struct kex *kex; |
1125 | | int r; |
1126 | | |
1127 | | + memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); |
1128 | | + |
1129 | | xxx_host = host; |
1130 | | xxx_hostaddr = hostaddr; |
1131 | | |
1132 | | @@ -235,6 +246,9 @@ ssh_kex2(char *host, struct sockaddr *ho |
1133 | | packet_send(); |
1134 | | packet_write_wait(); |
1135 | | #endif |
1136 | | +#ifdef NONE_CIPHER_ENABLED |
1137 | | + xxx_kex = kex; |
1138 | | +#endif |
1139 | | } |
1140 | | |
1141 | | /* |
1142 | | @@ -404,6 +418,29 @@ ssh_userauth2(const char *local_user, co |
1143 | | pubkey_cleanup(&authctxt); |
1144 | | ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); |
1145 | | |
1146 | | +#ifdef NONE_CIPHER_ENABLED |
1147 | | + /* |
1148 | | + * if the user wants to use the none cipher do it |
1149 | | + * post authentication and only if the right conditions are met |
1150 | | + * both of the NONE commands must be true and there must be no |
1151 | | + * tty allocated. |
1152 | | + */ |
1153 | | + if ((options.none_switch == 1) && (options.none_enabled == 1)) { |
1154 | | + if (!tty_flag) { /* no null on tty sessions */ |
1155 | | + debug("Requesting none rekeying..."); |
1156 | | + myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; |
1157 | | + myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; |
1158 | | + kex_prop2buf(xxx_kex->my, myproposal); |
1159 | | + packet_request_rekeying(); |
1160 | | + fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n"); |
1161 | | + } else { |
1162 | | + /* requested NONE cipher when in a tty */ |
1163 | | + debug("Cannot switch to NONE cipher with tty allocated"); |
1164 | | + fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); |
1165 | | + } |
1166 | | + } |
1167 | | +#endif |
1168 | | + |
1169 | | debug("Authentication succeeded (%s).", authctxt.method->name); |
1170 | | } |
1171 | | |
1172 | | --- a/sshd.c 2016-03-01 04:32:17.000000000 +0100 |
1173 | | +++ b/sshd.c 2016-03-01 04:32:19.000000000 +0100 |
1174 | | @@ -430,8 +430,13 @@ sshd_exchange_identification(int sock_in |
1175 | | minor = PROTOCOL_MINOR_1; |
1176 | | } |
1177 | | |
1178 | | - xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", |
1179 | | + xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s%s", |
1180 | | major, minor, SSH_VERSION, |
1181 | | +#ifdef HPN_ENABLED |
1182 | | + options.hpn_disabled ? "" : SSH_HPN, |
1183 | | +#else |
1184 | | + "", |
1185 | | +#endif |
1186 | | *options.version_addendum == '\0' ? "" : " ", |
1187 | | options.version_addendum, newline); |
1188 | | |
1189 | | @@ -1167,6 +1172,10 @@ server_listen(void) |
1190 | | int ret, listen_sock, on = 1; |
1191 | | struct addrinfo *ai; |
1192 | | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
1193 | | +#ifdef HPN_ENABLED |
1194 | | + int socksize; |
1195 | | + socklen_t socksizelen = sizeof(socksize); |
1196 | | +#endif |
1197 | | |
1198 | | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { |
1199 | | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) |
1200 | | @@ -1207,6 +1216,13 @@ server_listen(void) |
1201 | | |
1202 | | debug("Bind to port %s on %s.", strport, ntop); |
1203 | | |
1204 | | +#ifdef HPN_ENABLED |
1205 | | + getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, |
1206 | | + &socksize, &socksizelen); |
1207 | | + debug("Server TCP RWIN socket size: %d", socksize); |
1208 | | + debug("HPN Buffer Size: %d", options.hpn_buffer_size); |
1209 | | +#endif |
1210 | | + |
1211 | | /* Bind the socket to the desired port. */ |
1212 | | if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
1213 | | error("Bind to port %s on %s failed: %.200s.", |
1214 | | @@ -1706,6 +1722,15 @@ main(int ac, char **av) |
1215 | | /* Fill in default values for those options not explicitly set. */ |
1216 | | fill_default_server_options(&options); |
1217 | | |
1218 | | +#ifdef NONE_CIPHER_ENABLED |
1219 | | + if (options.none_enabled == 1) { |
1220 | | + char *old_ciphers = options.ciphers; |
1221 | | + |
1222 | | + xasprintf(&options.ciphers, "%s,none", old_ciphers); |
1223 | | + free(old_ciphers); |
1224 | | + } |
1225 | | +#endif |
1226 | | + |
1227 | | /* challenge-response is implemented via keyboard interactive */ |
1228 | | if (options.challenge_response_authentication) |
1229 | | options.kbd_interactive_authentication = 1; |
1230 | | @@ -2136,6 +2161,11 @@ main(int ac, char **av) |
1231 | | cleanup_exit(255); |
1232 | | } |
1233 | | |
1234 | | +#ifdef HPN_ENABLED |
1235 | | + /* set the HPN options for the child */ |
1236 | | + channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); |
1237 | | +#endif |
1238 | | + |
1239 | | /* |
1240 | | * We use get_canonical_hostname with usedns = 0 instead of |
1241 | | * get_remote_ipaddr here so IP options will be checked. |
1242 | | @@ -2554,6 +2584,12 @@ do_ssh2_kex(void) |
1243 | | struct kex *kex; |
1244 | | int r; |
1245 | | |
1246 | | +#ifdef NONE_CIPHER_ENABLED |
1247 | | + if (options.none_enabled == 1) { |
1248 | | + debug ("WARNING: None cipher enabled"); |
1249 | | + } |
1250 | | +#endif |
1251 | | + |
1252 | | myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( |
1253 | | options.kex_algorithms); |
1254 | | myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( |
1255 | | --- a/sshd_config 2016-02-26 04:40:04.000000000 +0100 |
1256 | | +++ b/sshd_config 2016-03-01 04:32:19.000000000 +0100 |
1257 | | @@ -125,6 +125,20 @@ AuthorizedKeysFile .ssh/authorized_keys |
1258 | | # override default of no subsystems |
1259 | | Subsystem sftp /usr/libexec/sftp-server |
1260 | | |
1261 | | +# the following are HPN related configuration options |
1262 | | +# tcp receive buffer polling. disable in non autotuning kernels |
1263 | | +#TcpRcvBufPoll yes |
1264 | | + |
1265 | | +# disable hpn performance boosts |
1266 | | +#HPNDisabled no |
1267 | | + |
1268 | | +# buffer size for hpn to non-hpn connections |
1269 | | +#HPNBufferSize 2048 |
1270 | | + |
1271 | | + |
1272 | | +# allow the use of the none cipher |
1273 | | +#NoneEnabled no |
1274 | | + |
1275 | | # Example of overriding settings on a per-user basis |
1276 | | #Match User anoncvs |
1277 | | # X11Forwarding no |
1278 | | --- a/version.h 2016-02-26 04:40:04.000000000 +0100 |
1279 | | +++ b/version.h 2016-03-01 04:32:20.000000000 +0100 |
1280 | | @@ -4,3 +4,4 @@ |
1281 | | |
1282 | | #define SSH_PORTABLE "p1" |
1283 | | #define SSH_RELEASE SSH_VERSION SSH_PORTABLE |
1284 | | +#define SSH_HPN "-hpn14v5" |