summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--authfile.c8
-rw-r--r--channels.c10
-rw-r--r--cipher.c24
-rw-r--r--cipher.h8
-rw-r--r--clientloop.c210
-rw-r--r--compat.c6
-rw-r--r--contrib/redhat/openssh.spec4
-rw-r--r--kex.h11
-rw-r--r--myproposal.h20
-rw-r--r--packet.c32
-rw-r--r--packet.h4
-rw-r--r--ssh.c162
-rw-r--r--sshconnect.c350
-rw-r--r--sshd.c4
15 files changed, 737 insertions, 130 deletions
diff --git a/ChangeLog b/ChangeLog
index 33e522843..05d37dc4a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
120000406
2 - OpenBSD CVS update:
3 - [channels.c]
4 close efd on eof
5 - [clientloop.c compat.c ssh.c sshconnect.c myproposal.h]
6 ssh2 client implementation, interops w/ ssh.com and lsh servers.
7 - [sshconnect.c]
8 missing free.
9 - [authfile.c cipher.c cipher.h packet.c sshconnect.c sshd.c]
10 remove unused argument, split cipher_mask()
11 - [clientloop.c]
12 re-order: group ssh1 vs. ssh2
13 - Make Redhat spec require openssl >= 0.9.5a
14
120000404 1520000404
2 - Add tests for RAND_add function when searching for OpenSSL 16 - Add tests for RAND_add function when searching for OpenSSL
3 - OpenBSD CVS update: 17 - OpenBSD CVS update:
diff --git a/authfile.c b/authfile.c
index a6dab7575..6ce0ac61f 100644
--- a/authfile.c
+++ b/authfile.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: authfile.c,v 1.7 2000/03/02 12:57:18 damien Exp $"); 18RCSID("$Id: authfile.c,v 1.8 2000/04/06 02:32:38 damien Exp $");
19 19
20#ifdef HAVE_OPENSSL 20#ifdef HAVE_OPENSSL
21#include <openssl/bn.h> 21#include <openssl/bn.h>
@@ -107,7 +107,7 @@ save_private_key(const char *filename, const char *passphrase,
107 /* Allocate space for the private part of the key in the buffer. */ 107 /* Allocate space for the private part of the key in the buffer. */
108 buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); 108 buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
109 109
110 cipher_set_key_string(&cipher, cipher_type, passphrase, 1); 110 cipher_set_key_string(&cipher, cipher_type, passphrase);
111 cipher_encrypt(&cipher, (unsigned char *) cp, 111 cipher_encrypt(&cipher, (unsigned char *) cp,
112 (unsigned char *) buffer_ptr(&buffer), 112 (unsigned char *) buffer_ptr(&buffer),
113 buffer_len(&buffer)); 113 buffer_len(&buffer));
@@ -286,7 +286,7 @@ load_private_key(const char *filename, const char *passphrase,
286 xfree(buffer_get_string(&buffer, NULL)); 286 xfree(buffer_get_string(&buffer, NULL));
287 287
288 /* Check that it is a supported cipher. */ 288 /* Check that it is a supported cipher. */
289 if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & 289 if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
290 (1 << cipher_type)) == 0) { 290 (1 << cipher_type)) == 0) {
291 debug("Unsupported cipher %.100s used in key file %.200s.", 291 debug("Unsupported cipher %.100s used in key file %.200s.",
292 cipher_name(cipher_type), filename); 292 cipher_name(cipher_type), filename);
@@ -298,7 +298,7 @@ load_private_key(const char *filename, const char *passphrase,
298 buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); 298 buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
299 299
300 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 300 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
301 cipher_set_key_string(&cipher, cipher_type, passphrase, 0); 301 cipher_set_key_string(&cipher, cipher_type, passphrase);
302 cipher_decrypt(&cipher, (unsigned char *) cp, 302 cipher_decrypt(&cipher, (unsigned char *) cp,
303 (unsigned char *) buffer_ptr(&buffer), 303 (unsigned char *) buffer_ptr(&buffer),
304 buffer_len(&buffer)); 304 buffer_len(&buffer));
diff --git a/channels.c b/channels.c
index 18f667f6b..f03cf92b4 100644
--- a/channels.c
+++ b/channels.c
@@ -17,7 +17,7 @@
17 */ 17 */
18 18
19#include "includes.h" 19#include "includes.h"
20RCSID("$Id: channels.c,v 1.21 2000/04/04 04:39:00 damien Exp $"); 20RCSID("$Id: channels.c,v 1.22 2000/04/06 02:32:38 damien Exp $");
21 21
22#include "ssh.h" 22#include "ssh.h"
23#include "packet.h" 23#include "packet.h"
@@ -642,6 +642,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
642 char buf[16*1024]; 642 char buf[16*1024];
643 int len; 643 int len;
644 644
645/** XXX handle drain efd, too */
645 if (c->efd != -1) { 646 if (c->efd != -1) {
646 if (c->extended_usage == CHAN_EXTENDED_WRITE && 647 if (c->extended_usage == CHAN_EXTENDED_WRITE &&
647 FD_ISSET(c->efd, writeset) && 648 FD_ISSET(c->efd, writeset) &&
@@ -659,7 +660,12 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
659 len = read(c->efd, buf, sizeof(buf)); 660 len = read(c->efd, buf, sizeof(buf));
660 debug("channel %d: read %d from efd %d", 661 debug("channel %d: read %d from efd %d",
661 c->self, len, c->efd); 662 c->self, len, c->efd);
662 if (len > 0) 663 if (len == 0) {
664 debug("channel %d: closing efd %d",
665 c->self, c->efd);
666 close(c->efd);
667 c->efd = -1;
668 } else if (len > 0)
663 buffer_append(&c->extended, buf, len); 669 buffer_append(&c->extended, buf, len);
664 } 670 }
665 } 671 }
diff --git a/cipher.c b/cipher.c
index f7b7b4726..8911ffef6 100644
--- a/cipher.c
+++ b/cipher.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: cipher.c,v 1.15 2000/04/01 01:09:23 damien Exp $"); 15RCSID("$Id: cipher.c,v 1.16 2000/04/06 02:32:39 damien Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "cipher.h" 18#include "cipher.h"
@@ -137,17 +137,28 @@ static char *cipher_names[] =
137 */ 137 */
138 138
139unsigned int 139unsigned int
140cipher_mask() 140cipher_mask1()
141{ 141{
142 unsigned int mask = 0; 142 unsigned int mask = 0;
143 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ 143 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
144 mask |= 1 << SSH_CIPHER_BLOWFISH; 144 mask |= 1 << SSH_CIPHER_BLOWFISH;
145 return mask;
146}
147unsigned int
148cipher_mask2()
149{
150 unsigned int mask = 0;
145 mask |= 1 << SSH_CIPHER_BLOWFISH_CBC; 151 mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
146 mask |= 1 << SSH_CIPHER_3DES_CBC; 152 mask |= 1 << SSH_CIPHER_3DES_CBC;
147 mask |= 1 << SSH_CIPHER_ARCFOUR; 153 mask |= 1 << SSH_CIPHER_ARCFOUR;
148 mask |= 1 << SSH_CIPHER_CAST128_CBC; 154 mask |= 1 << SSH_CIPHER_CAST128_CBC;
149 return mask; 155 return mask;
150} 156}
157unsigned int
158cipher_mask()
159{
160 return cipher_mask1() | cipher_mask2();
161}
151 162
152/* Returns the name of the cipher. */ 163/* Returns the name of the cipher. */
153 164
@@ -182,8 +193,7 @@ cipher_number(const char *name)
182 */ 193 */
183 194
184void 195void
185cipher_set_key_string(CipherContext *context, int cipher, 196cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase)
186 const char *passphrase, int for_encryption)
187{ 197{
188 MD5_CTX md; 198 MD5_CTX md;
189 unsigned char digest[16]; 199 unsigned char digest[16];
@@ -192,7 +202,7 @@ cipher_set_key_string(CipherContext *context, int cipher,
192 MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase)); 202 MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
193 MD5_Final(digest, &md); 203 MD5_Final(digest, &md);
194 204
195 cipher_set_key(context, cipher, digest, 16, for_encryption); 205 cipher_set_key(context, cipher, digest, 16);
196 206
197 memset(digest, 0, sizeof(digest)); 207 memset(digest, 0, sizeof(digest));
198 memset(&md, 0, sizeof(md)); 208 memset(&md, 0, sizeof(md));
@@ -201,8 +211,8 @@ cipher_set_key_string(CipherContext *context, int cipher,
201/* Selects the cipher to use and sets the key. */ 211/* Selects the cipher to use and sets the key. */
202 212
203void 213void
204cipher_set_key(CipherContext *context, int cipher, 214cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
205 const unsigned char *key, int keylen, int for_encryption) 215 int keylen)
206{ 216{
207 unsigned char padded[32]; 217 unsigned char padded[32];
208 218
diff --git a/cipher.h b/cipher.h
index 6cfeb6399..94c0ceee5 100644
--- a/cipher.h
+++ b/cipher.h
@@ -11,7 +11,7 @@
11 * 11 *
12 */ 12 */
13 13
14/* RCSID("$Id: cipher.h,v 1.7 2000/04/01 01:09:23 damien Exp $"); */ 14/* RCSID("$Id: cipher.h,v 1.8 2000/04/06 02:32:39 damien Exp $"); */
15 15
16#ifndef CIPHER_H 16#ifndef CIPHER_H
17#define CIPHER_H 17#define CIPHER_H
@@ -76,6 +76,8 @@ typedef struct {
76 * supported cipher. 76 * supported cipher.
77 */ 77 */
78unsigned int cipher_mask(); 78unsigned int cipher_mask();
79unsigned int cipher_mask1();
80unsigned int cipher_mask2();
79 81
80/* Returns the name of the cipher. */ 82/* Returns the name of the cipher. */
81const char *cipher_name(int cipher); 83const char *cipher_name(int cipher);
@@ -92,7 +94,7 @@ int cipher_number(const char *name);
92 */ 94 */
93void 95void
94cipher_set_key(CipherContext * context, int cipher, 96cipher_set_key(CipherContext * context, int cipher,
95 const unsigned char *key, int keylen, int for_encryption); 97 const unsigned char *key, int keylen);
96void 98void
97cipher_set_key_iv(CipherContext * context, int cipher, 99cipher_set_key_iv(CipherContext * context, int cipher,
98 const unsigned char *key, int keylen, 100 const unsigned char *key, int keylen,
@@ -104,7 +106,7 @@ cipher_set_key_iv(CipherContext * context, int cipher,
104 */ 106 */
105void 107void
106cipher_set_key_string(CipherContext * context, int cipher, 108cipher_set_key_string(CipherContext * context, int cipher,
107 const char *passphrase, int for_encryption); 109 const char *passphrase);
108 110
109/* Encrypts data using the cipher. */ 111/* Encrypts data using the cipher. */
110void 112void
diff --git a/clientloop.c b/clientloop.c
index 1bc6d7e67..4f2e5037d 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -12,10 +12,11 @@
12 * 12 *
13 * The main loop for the interactive session (client side). 13 * The main loop for the interactive session (client side).
14 * 14 *
15 * SSH2 support added by Markus Friedl.
15 */ 16 */
16 17
17#include "includes.h" 18#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $"); 19RCSID("$Id: clientloop.c,v 1.9 2000/04/06 02:32:39 damien Exp $");
19 20
20#include "xmalloc.h" 21#include "xmalloc.h"
21#include "ssh.h" 22#include "ssh.h"
@@ -24,6 +25,7 @@ RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $");
24#include "authfd.h" 25#include "authfd.h"
25#include "readconf.h" 26#include "readconf.h"
26 27
28#include "ssh2.h"
27#include "compat.h" 29#include "compat.h"
28#include "channels.h" 30#include "channels.h"
29#include "dispatch.h" 31#include "dispatch.h"
@@ -75,6 +77,10 @@ static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
75static int quit_pending; /* Set to non-zero to quit the client loop. */ 77static int quit_pending; /* Set to non-zero to quit the client loop. */
76static int escape_char; /* Escape character. */ 78static int escape_char; /* Escape character. */
77 79
80
81void client_init_dispatch(void);
82int session_ident = -1;
83
78/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ 84/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */
79 85
80void 86void
@@ -273,23 +279,32 @@ client_make_packets_from_stdin_data()
273void 279void
274client_check_window_change() 280client_check_window_change()
275{ 281{
276 /* Send possible window change message to the server. */ 282 struct winsize ws;
277 if (received_window_change_signal) { 283
278 struct winsize ws; 284 if (! received_window_change_signal)
279 285 return;
280 /* Clear the window change indicator. */ 286 /** XXX race */
281 received_window_change_signal = 0; 287 received_window_change_signal = 0;
282 288
283 /* Read new window size. */ 289 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
284 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) { 290 return;
285 /* Successful, send the packet now. */ 291
286 packet_start(SSH_CMSG_WINDOW_SIZE); 292 debug("client_check_window_change: changed");
287 packet_put_int(ws.ws_row); 293
288 packet_put_int(ws.ws_col); 294 if (compat20) {
289 packet_put_int(ws.ws_xpixel); 295 channel_request_start(session_ident, "window-change", 0);
290 packet_put_int(ws.ws_ypixel); 296 packet_put_int(ws.ws_col);
291 packet_send(); 297 packet_put_int(ws.ws_row);
292 } 298 packet_put_int(ws.ws_xpixel);
299 packet_put_int(ws.ws_ypixel);
300 packet_send();
301 } else {
302 packet_start(SSH_CMSG_WINDOW_SIZE);
303 packet_put_int(ws.ws_row);
304 packet_put_int(ws.ws_col);
305 packet_put_int(ws.ws_xpixel);
306 packet_put_int(ws.ws_ypixel);
307 packet_send();
293 } 308 }
294} 309}
295 310
@@ -301,23 +316,33 @@ client_check_window_change()
301void 316void
302client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) 317client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
303{ 318{
319 /*debug("client_wait_until_can_do_something"); */
320
304 /* Initialize select masks. */ 321 /* Initialize select masks. */
305 FD_ZERO(readset); 322 FD_ZERO(readset);
323 FD_ZERO(writeset);
306 324
307 /* Read from the connection, unless our buffers are full. */ 325 if (!compat20) {
308 if (buffer_len(&stdout_buffer) < buffer_high && 326 /* Read from the connection, unless our buffers are full. */
309 buffer_len(&stderr_buffer) < buffer_high && 327 if (buffer_len(&stdout_buffer) < buffer_high &&
310 channel_not_very_much_buffered_data()) 328 buffer_len(&stderr_buffer) < buffer_high &&
329 channel_not_very_much_buffered_data())
330 FD_SET(connection_in, readset);
331 /*
332 * Read from stdin, unless we have seen EOF or have very much
333 * buffered data to send to the server.
334 */
335 if (!stdin_eof && packet_not_very_much_data_to_write())
336 FD_SET(fileno(stdin), readset);
337
338 /* Select stdout/stderr if have data in buffer. */
339 if (buffer_len(&stdout_buffer) > 0)
340 FD_SET(fileno(stdout), writeset);
341 if (buffer_len(&stderr_buffer) > 0)
342 FD_SET(fileno(stderr), writeset);
343 } else {
311 FD_SET(connection_in, readset); 344 FD_SET(connection_in, readset);
312 345 }
313 /*
314 * Read from stdin, unless we have seen EOF or have very much
315 * buffered data to send to the server.
316 */
317 if (!stdin_eof && packet_not_very_much_data_to_write())
318 FD_SET(fileno(stdin), readset);
319
320 FD_ZERO(writeset);
321 346
322 /* Add any selections by the channel mechanism. */ 347 /* Add any selections by the channel mechanism. */
323 channel_prepare_select(readset, writeset); 348 channel_prepare_select(readset, writeset);
@@ -326,14 +351,7 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
326 if (packet_have_data_to_write()) 351 if (packet_have_data_to_write())
327 FD_SET(connection_out, writeset); 352 FD_SET(connection_out, writeset);
328 353
329 /* Select stdout if have data in buffer. */ 354/* move UP XXX */
330 if (buffer_len(&stdout_buffer) > 0)
331 FD_SET(fileno(stdout), writeset);
332
333 /* Select stderr if have data in buffer. */
334 if (buffer_len(&stderr_buffer) > 0)
335 FD_SET(fileno(stderr), writeset);
336
337 /* Update maximum file descriptor number, if appropriate. */ 355 /* Update maximum file descriptor number, if appropriate. */
338 if (channel_max_fd() > max_fd) 356 if (channel_max_fd() > max_fd)
339 max_fd = channel_max_fd(); 357 max_fd = channel_max_fd();
@@ -408,10 +426,10 @@ client_suspend_self()
408} 426}
409 427
410void 428void
411client_process_input(fd_set * readset) 429client_process_net_input(fd_set * readset)
412{ 430{
413 int len, pid; 431 int len;
414 char buf[8192], *s; 432 char buf[8192];
415 433
416 /* 434 /*
417 * Read input from the server, and add any such data to the buffer of 435 * Read input from the server, and add any such data to the buffer of
@@ -420,6 +438,7 @@ client_process_input(fd_set * readset)
420 if (FD_ISSET(connection_in, readset)) { 438 if (FD_ISSET(connection_in, readset)) {
421 /* Read as much as possible. */ 439 /* Read as much as possible. */
422 len = read(connection_in, buf, sizeof(buf)); 440 len = read(connection_in, buf, sizeof(buf));
441/*debug("read connection_in len %d", len); XXX */
423 if (len == 0) { 442 if (len == 0) {
424 /* Received EOF. The remote host has closed the connection. */ 443 /* Received EOF. The remote host has closed the connection. */
425 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 444 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
@@ -447,6 +466,14 @@ client_process_input(fd_set * readset)
447 } 466 }
448 packet_process_incoming(buf, len); 467 packet_process_incoming(buf, len);
449 } 468 }
469}
470
471void
472client_process_input(fd_set * readset)
473{
474 int len, pid;
475 char buf[8192], *s;
476
450 /* Read input from stdin. */ 477 /* Read input from stdin. */
451 if (FD_ISSET(fileno(stdin), readset)) { 478 if (FD_ISSET(fileno(stdin), readset)) {
452 /* Read as much as possible. */ 479 /* Read as much as possible. */
@@ -703,8 +730,6 @@ client_process_buffered_input_packets()
703 * character for terminating or suspending the session. 730 * character for terminating or suspending the session.
704 */ 731 */
705 732
706void client_init_dispatch(void);
707
708int 733int
709client_loop(int have_pty, int escape_char_arg) 734client_loop(int have_pty, int escape_char_arg)
710{ 735{
@@ -753,7 +778,8 @@ client_loop(int have_pty, int escape_char_arg)
753 enter_raw_mode(); 778 enter_raw_mode();
754 779
755 /* Check if we should immediately send of on stdin. */ 780 /* Check if we should immediately send of on stdin. */
756 client_check_initial_eof_on_stdin(); 781 if (!compat20)
782 client_check_initial_eof_on_stdin();
757 783
758 /* Main loop of the client for the interactive session mode. */ 784 /* Main loop of the client for the interactive session mode. */
759 while (!quit_pending) { 785 while (!quit_pending) {
@@ -762,11 +788,17 @@ client_loop(int have_pty, int escape_char_arg)
762 /* Process buffered packets sent by the server. */ 788 /* Process buffered packets sent by the server. */
763 client_process_buffered_input_packets(); 789 client_process_buffered_input_packets();
764 790
791 if (compat20 && !channel_still_open()) {
792 debug("!channel_still_open.");
793 break;
794 }
795
765 /* 796 /*
766 * Make packets of buffered stdin data, and buffer them for 797 * Make packets of buffered stdin data, and buffer them for
767 * sending to the server. 798 * sending to the server.
768 */ 799 */
769 client_make_packets_from_stdin_data(); 800 if (!compat20)
801 client_make_packets_from_stdin_data();
770 802
771 /* 803 /*
772 * Make packets from buffered channel data, and buffer them 804 * Make packets from buffered channel data, and buffer them
@@ -796,17 +828,21 @@ client_loop(int have_pty, int escape_char_arg)
796 /* Do channel operations. */ 828 /* Do channel operations. */
797 channel_after_select(&readset, &writeset); 829 channel_after_select(&readset, &writeset);
798 830
799 /* 831 /* Buffer input from the connection. */
800 * Process input from the connection and from stdin. Buffer 832 client_process_net_input(&readset);
801 * any data that is available.
802 */
803 client_process_input(&readset);
804 833
805 /* 834 if (quit_pending)
806 * Process output to stdout and stderr. Output to the 835 break;
807 * connection is processed elsewhere (above). 836
808 */ 837 if (!compat20) {
809 client_process_output(&writeset); 838 /* Buffer data from stdin */
839 client_process_input(&readset);
840 /*
841 * Process output to stdout and stderr. Output to
842 * the connection is processed elsewhere (above).
843 */
844 client_process_output(&writeset);
845 }
810 846
811 /* Send as much buffered packet data as possible to the sender. */ 847 /* Send as much buffered packet data as possible to the sender. */
812 if (FD_ISSET(connection_out, &writeset)) 848 if (FD_ISSET(connection_out, &writeset))
@@ -918,6 +954,19 @@ client_input_exit_status(int type, int plen)
918} 954}
919 955
920void 956void
957client_init_dispatch_20()
958{
959 dispatch_init(&dispatch_protocol_error);
960 dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
961 dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
962 dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
963 dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
964 dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
965 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
966 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
967 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
968}
969void
921client_init_dispatch_13() 970client_init_dispatch_13()
922{ 971{
923 dispatch_init(NULL); 972 dispatch_init(NULL);
@@ -944,8 +993,55 @@ client_init_dispatch_15()
944void 993void
945client_init_dispatch() 994client_init_dispatch()
946{ 995{
947 if (compat13) 996 if (compat20)
997 client_init_dispatch_20();
998 else if (compat13)
948 client_init_dispatch_13(); 999 client_init_dispatch_13();
949 else 1000 else
950 client_init_dispatch_15(); 1001 client_init_dispatch_15();
951} 1002}
1003
1004void
1005client_input_channel_req(int id, void *arg)
1006{
1007 Channel *c = NULL;
1008 unsigned int len;
1009 int success = 0;
1010 int reply;
1011 char *rtype;
1012
1013 rtype = packet_get_string(&len);
1014 reply = packet_get_char();
1015
1016 log("session_input_channel_req: rtype %s reply %d", rtype, reply);
1017
1018 c = channel_lookup(id);
1019 if (c == NULL)
1020 fatal("session_input_channel_req: channel %d: bad channel", id);
1021
1022 if (session_ident == -1) {
1023 error("client_input_channel_req: no channel %d", id);
1024 } else if (id != session_ident) {
1025 error("client_input_channel_req: bad channel %d != %d",
1026 id, session_ident);
1027 } else if (strcmp(rtype, "exit-status") == 0) {
1028 success = 1;
1029 exit_status = packet_get_int();
1030 }
1031 if (reply) {
1032 packet_start(success ?
1033 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1034 packet_put_int(c->remote_id);
1035 packet_send();
1036 }
1037 xfree(rtype);
1038}
1039
1040void
1041client_set_session_ident(int id)
1042{
1043 debug("client_set_session_ident: id %d", id);
1044 session_ident = id;
1045 channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
1046 client_input_channel_req, (void *)0);
1047}
diff --git a/compat.c b/compat.c
index 3ecf7101e..d09f38ca6 100644
--- a/compat.c
+++ b/compat.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: compat.c,v 1.4 2000/04/04 04:39:01 damien Exp $"); 31RCSID("$Id: compat.c,v 1.5 2000/04/06 02:32:39 damien Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "packet.h" 34#include "packet.h"
@@ -40,7 +40,9 @@ int datafellows = 0;
40void 40void
41enable_compat20(void) 41enable_compat20(void)
42{ 42{
43 fatal("protocol 2.0 not implemented"); 43 verbose("Enabling compatibility mode for protocol 2.0");
44 compat20 = 1;
45 packet_set_ssh2_format();
44} 46}
45void 47void
46enable_compat13(void) 48enable_compat13(void)
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index 24f0e4280..35affbaa2 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -15,8 +15,8 @@ Copyright: BSD
15Group: Applications/Internet 15Group: Applications/Internet
16BuildRoot: /tmp/openssh-%{version}-buildroot 16BuildRoot: /tmp/openssh-%{version}-buildroot
17Obsoletes: ssh 17Obsoletes: ssh
18PreReq: openssl 18PreReq: openssl >= 0.9.5a
19Requires: openssl 19Requires: openssl >= 0.9.5a
20BuildPreReq: perl 20BuildPreReq: perl
21BuildPreReq: openssl-devel 21BuildPreReq: openssl-devel
22BuildPreReq: tcp_wrappers 22BuildPreReq: tcp_wrappers
diff --git a/kex.h b/kex.h
index f9e799948..81c41342a 100644
--- a/kex.h
+++ b/kex.h
@@ -29,6 +29,17 @@
29#ifndef KEX_H 29#ifndef KEX_H
30#define KEX_H 30#define KEX_H
31 31
32#include "config.h"
33
34#ifdef HAVE_OPENSSL
35# include <openssl/bn.h>
36# include <openssl/evp.h>
37#endif
38#ifdef HAVE_SSL
39# include <ssl/bn.h>
40# include <ssl/evp.h>
41#endif
42
32#define KEX_DH1 "diffie-hellman-group1-sha1" 43#define KEX_DH1 "diffie-hellman-group1-sha1"
33#define KEX_DSS "ssh-dss" 44#define KEX_DSS "ssh-dss"
34 45
diff --git a/myproposal.h b/myproposal.h
new file mode 100644
index 000000000..7e4baff9d
--- /dev/null
+++ b/myproposal.h
@@ -0,0 +1,20 @@
1#define KEX_DEFAULT_KEX "diffie-hellman-group1-sha1"
2#define KEX_DEFAULT_PK_ALG "ssh-dss"
3#define KEX_DEFAULT_ENCRYPT "blowfish-cbc,3des-cbc,arcfour,cast128-cbc"
4#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com"
5#define KEX_DEFAULT_COMP "zlib,none"
6#define KEX_DEFAULT_LANG ""
7
8
9static const char *myproposal[PROPOSAL_MAX] = {
10 KEX_DEFAULT_KEX,
11 KEX_DEFAULT_PK_ALG,
12 KEX_DEFAULT_ENCRYPT,
13 KEX_DEFAULT_ENCRYPT,
14 KEX_DEFAULT_MAC,
15 KEX_DEFAULT_MAC,
16 KEX_DEFAULT_COMP,
17 KEX_DEFAULT_COMP,
18 KEX_DEFAULT_LANG,
19 KEX_DEFAULT_LANG
20};
diff --git a/packet.c b/packet.c
index 39629a5ef..b11519e74 100644
--- a/packet.c
+++ b/packet.c
@@ -17,7 +17,18 @@
17 */ 17 */
18 18
19#include "includes.h" 19#include "includes.h"
20RCSID("$Id: packet.c,v 1.15 2000/04/04 04:57:08 damien Exp $"); 20RCSID("$Id: packet.c,v 1.16 2000/04/06 02:32:40 damien Exp $");
21
22#ifdef HAVE_OPENSSL
23# include <openssl/bn.h>
24# include <openssl/dh.h>
25# include <openssl/hmac.h>
26#endif /* HAVE_OPENSSL */
27#ifdef HAVE_SSL
28# include <ssl/bn.h>
29# include <ssl/dh.h>
30# include <ssl/hmac.h>
31#endif /* HAVE_SSL */
21 32
22#include "xmalloc.h" 33#include "xmalloc.h"
23#include "buffer.h" 34#include "buffer.h"
@@ -35,17 +46,6 @@ RCSID("$Id: packet.c,v 1.15 2000/04/04 04:57:08 damien Exp $");
35#include "compat.h" 46#include "compat.h"
36#include "ssh2.h" 47#include "ssh2.h"
37 48
38#ifdef HAVE_OPENSSL
39# include <openssl/bn.h>
40# include <openssl/dh.h>
41# include <openssl/hmac.h>
42#endif /* HAVE_OPENSSL */
43#ifdef HAVE_SSL
44# include <ssl/bn.h>
45# include <ssl/dh.h>
46# include <ssl/hmac.h>
47#endif /* HAVE_SSL */
48
49#include "buffer.h" 49#include "buffer.h"
50#include "kex.h" 50#include "kex.h"
51#include "hmac.h" 51#include "hmac.h"
@@ -152,8 +152,8 @@ packet_set_connection(int fd_in, int fd_out)
152 connection_in = fd_in; 152 connection_in = fd_in;
153 connection_out = fd_out; 153 connection_out = fd_out;
154 cipher_type = SSH_CIPHER_NONE; 154 cipher_type = SSH_CIPHER_NONE;
155 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 1); 155 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
156 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 0); 156 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
157 if (!initialized) { 157 if (!initialized) {
158 initialized = 1; 158 initialized = 1;
159 buffer_init(&input); 159 buffer_init(&input);
@@ -352,8 +352,8 @@ packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
352 fatal("keylen too small: %d", keylen); 352 fatal("keylen too small: %d", keylen);
353 353
354 /* All other ciphers use the same key in both directions for now. */ 354 /* All other ciphers use the same key in both directions for now. */
355 cipher_set_key(&receive_context, cipher, key, keylen, 0); 355 cipher_set_key(&receive_context, cipher, key, keylen);
356 cipher_set_key(&send_context, cipher, key, keylen, 1); 356 cipher_set_key(&send_context, cipher, key, keylen);
357} 357}
358 358
359/* Starts constructing a packet to send. */ 359/* Starts constructing a packet to send. */
diff --git a/packet.h b/packet.h
index 39c0edea2..61c12be94 100644
--- a/packet.h
+++ b/packet.h
@@ -13,13 +13,11 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: packet.h,v 1.11 2000/04/04 04:39:03 damien Exp $"); */ 16/* RCSID("$Id: packet.h,v 1.12 2000/04/06 02:32:40 damien Exp $"); */
17 17
18#ifndef PACKET_H 18#ifndef PACKET_H
19#define PACKET_H 19#define PACKET_H
20 20
21#include "config.h"
22
23#ifdef HAVE_OPENSSL 21#ifdef HAVE_OPENSSL
24#include <openssl/bn.h> 22#include <openssl/bn.h>
25#endif 23#endif
diff --git a/ssh.c b/ssh.c
index 70f9d6a68..cce0e6b7f 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $"); 14RCSID("$Id: ssh.c,v 1.24 2000/04/06 02:32:40 damien Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "ssh.h" 17#include "ssh.h"
@@ -20,6 +20,9 @@ RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $");
20#include "authfd.h" 20#include "authfd.h"
21#include "readconf.h" 21#include "readconf.h"
22#include "uidswap.h" 22#include "uidswap.h"
23
24#include "ssh2.h"
25#include "compat.h"
23#include "channels.h" 26#include "channels.h"
24 27
25#ifdef HAVE___PROGNAME 28#ifdef HAVE___PROGNAME
@@ -41,6 +44,10 @@ int debug_flag = 0;
41 44
42int tty_flag = 0; 45int tty_flag = 0;
43 46
47/* don't exec a shell */
48int no_shell_flag = 0;
49int no_tty_flag = 0;
50
44/* 51/*
45 * Flag indicating that nothing should be read from stdin. This can be set 52 * Flag indicating that nothing should be read from stdin. This can be set
46 * on the command line. 53 * on the command line.
@@ -90,6 +97,9 @@ RSA *host_private_key = NULL;
90/* Original real UID. */ 97/* Original real UID. */
91uid_t original_real_uid; 98uid_t original_real_uid;
92 99
100/* command to be executed */
101Buffer command;
102
93/* Prints a help message to the user. This function never returns. */ 103/* Prints a help message to the user. This function never returns. */
94 104
95void 105void
@@ -104,9 +114,9 @@ usage()
104 fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); 114 fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n");
105#endif /* AFS */ 115#endif /* AFS */
106 fprintf(stderr, " -x Disable X11 connection forwarding.\n"); 116 fprintf(stderr, " -x Disable X11 connection forwarding.\n");
107 fprintf(stderr, " -X Enable X11 connection forwarding.\n");
108 fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n"); 117 fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
109 fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n"); 118 fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
119 fprintf(stderr, " -T Do not allocate a tty.\n");
110 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); 120 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
111 fprintf(stderr, " -V Display version number only.\n"); 121 fprintf(stderr, " -V Display version number only.\n");
112 fprintf(stderr, " -P Don't allocate a privileged port.\n"); 122 fprintf(stderr, " -P Don't allocate a privileged port.\n");
@@ -123,6 +133,7 @@ usage()
123 fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0); 133 fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
124 fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); 134 fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
125 fprintf(stderr, " -C Enable compression.\n"); 135 fprintf(stderr, " -C Enable compression.\n");
136 fprintf(stderr, " -N Do not execute a shell or command.\n");
126 fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); 137 fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
127 fprintf(stderr, " -4 Use IPv4 only.\n"); 138 fprintf(stderr, " -4 Use IPv4 only.\n");
128 fprintf(stderr, " -6 Use IPv6 only.\n"); 139 fprintf(stderr, " -6 Use IPv6 only.\n");
@@ -168,23 +179,22 @@ rsh_connect(char *host, char *user, Buffer * command)
168 exit(1); 179 exit(1);
169} 180}
170 181
182int ssh_session(void);
183int ssh_session2(void);
184
171/* 185/*
172 * Main program for the ssh client. 186 * Main program for the ssh client.
173 */ 187 */
174int 188int
175main(int ac, char **av) 189main(int ac, char **av)
176{ 190{
177 int i, opt, optind, type, exit_status, ok, authfd; 191 int i, opt, optind, exit_status, ok;
178 u_short fwd_port, fwd_host_port; 192 u_short fwd_port, fwd_host_port;
179 char *optarg, *cp, buf[256]; 193 char *optarg, *cp, buf[256];
180 Buffer command;
181 struct winsize ws;
182 struct stat st; 194 struct stat st;
183 struct passwd *pw, pwcopy; 195 struct passwd *pw, pwcopy;
184 int interactive = 0, dummy; 196 int dummy;
185 int have_pty = 0;
186 uid_t original_effective_uid; 197 uid_t original_effective_uid;
187 int plen;
188 198
189 /* 199 /*
190 * Save the original real uid. It will be needed later (uid-swapping 200 * Save the original real uid. It will be needed later (uid-swapping
@@ -328,7 +338,7 @@ main(int ac, char **av)
328 case 'V': 338 case 'V':
329 fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n", 339 fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
330 SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR); 340 SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
331 fprintf(stderr, "Compiled with SSL.\n"); 341 fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
332 if (opt == 'V') 342 if (opt == 'V')
333 exit(0); 343 exit(0);
334 debug_flag = 1; 344 debug_flag = 1;
@@ -397,6 +407,15 @@ main(int ac, char **av)
397 options.compression = 1; 407 options.compression = 1;
398 break; 408 break;
399 409
410 case 'N':
411 no_shell_flag = 1;
412 no_tty_flag = 1;
413 break;
414
415 case 'T':
416 no_tty_flag = 1;
417 break;
418
400 case 'o': 419 case 'o':
401 dummy = 1; 420 dummy = 1;
402 if (process_config_line(&options, host ? host : "", optarg, 421 if (process_config_line(&options, host ? host : "", optarg,
@@ -455,6 +474,10 @@ main(int ac, char **av)
455 fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n"); 474 fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
456 tty_flag = 0; 475 tty_flag = 0;
457 } 476 }
477 /* force */
478 if (no_tty_flag)
479 tty_flag = 0;
480
458 /* Get user data. */ 481 /* Get user data. */
459 pw = getpwuid(original_real_uid); 482 pw = getpwuid(original_real_uid);
460 if (!pw) { 483 if (!pw) {
@@ -620,6 +643,23 @@ main(int ac, char **av)
620 if (host_private_key_loaded) 643 if (host_private_key_loaded)
621 RSA_free(host_private_key); /* Destroys contents safely */ 644 RSA_free(host_private_key); /* Destroys contents safely */
622 645
646 exit_status = compat20 ? ssh_session2() : ssh_session();
647 packet_close();
648 return exit_status;
649}
650
651int
652ssh_session(void)
653{
654 int type;
655 int i;
656 int plen;
657 int interactive = 0;
658 int have_tty = 0;
659 struct winsize ws;
660 int authfd;
661 char *cp;
662
623 /* Enable compression if requested. */ 663 /* Enable compression if requested. */
624 if (options.compression) { 664 if (options.compression) {
625 debug("Requesting compression at level %d.", options.compression_level); 665 debug("Requesting compression at level %d.", options.compression_level);
@@ -673,7 +713,7 @@ main(int ac, char **av)
673 type = packet_read(&plen); 713 type = packet_read(&plen);
674 if (type == SSH_SMSG_SUCCESS) { 714 if (type == SSH_SMSG_SUCCESS) {
675 interactive = 1; 715 interactive = 1;
676 have_pty = 1; 716 have_tty = 1;
677 } else if (type == SSH_SMSG_FAILURE) 717 } else if (type == SSH_SMSG_FAILURE)
678 log("Warning: Remote host failed or refused to allocate a pseudo tty."); 718 log("Warning: Remote host failed or refused to allocate a pseudo tty.");
679 else 719 else
@@ -802,11 +842,103 @@ main(int ac, char **av)
802 } 842 }
803 843
804 /* Enter the interactive session. */ 844 /* Enter the interactive session. */
805 exit_status = client_loop(have_pty, tty_flag ? options.escape_char : -1); 845 return client_loop(have_tty, tty_flag ? options.escape_char : -1);
846}
806 847
807 /* Close the connection to the remote host. */ 848void
808 packet_close(); 849init_local_fwd(void)
850{
851 int i;
852 /* Initiate local TCP/IP port forwardings. */
853 for (i = 0; i < options.num_local_forwards; i++) {
854 debug("Connections to local port %d forwarded to remote address %.200s:%d",
855 options.local_forwards[i].port,
856 options.local_forwards[i].host,
857 options.local_forwards[i].host_port);
858 channel_request_local_forwarding(options.local_forwards[i].port,
859 options.local_forwards[i].host,
860 options.local_forwards[i].host_port,
861 options.gateway_ports);
862 }
863}
864
865extern void client_set_session_ident(int id);
866
867void
868client_init(int id, void *arg)
869{
870 int len;
871 debug("client_init id %d arg %d", id, (int)arg);
872
873 if (no_shell_flag)
874 goto done;
875
876 if (tty_flag) {
877 struct winsize ws;
878 char *cp;
879 cp = getenv("TERM");
880 if (!cp)
881 cp = "";
882 /* Store window size in the packet. */
883 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
884 memset(&ws, 0, sizeof(ws));
885
886 channel_request_start(id, "pty-req", 0);
887 packet_put_cstring(cp);
888 packet_put_int(ws.ws_col);
889 packet_put_int(ws.ws_row);
890 packet_put_int(ws.ws_xpixel);
891 packet_put_int(ws.ws_ypixel);
892 packet_put_cstring(""); /* XXX: encode terminal modes */
893 packet_send();
894 /* XXX wait for reply */
895 }
896 len = buffer_len(&command);
897 if (len > 0) {
898 if (len > 900)
899 len = 900;
900 debug("Sending command: %.*s", len, buffer_ptr(&command));
901 channel_request_start(id, "exec", 0);
902 packet_put_string(buffer_ptr(&command), len);
903 packet_send();
904 } else {
905 channel_request(id, "shell", 0);
906 }
907 /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
908done:
909 /* register different callback, etc. XXX */
910 client_set_session_ident(id);
911}
912
913int
914ssh_session2(void)
915{
916 int window, packetmax, id;
917 int in = dup(STDIN_FILENO);
918 int out = dup(STDOUT_FILENO);
919 int err = dup(STDERR_FILENO);
920
921 if (in < 0 || out < 0 || err < 0)
922 fatal("dump in/out/err failed");
923
924 /* should be pre-session */
925 init_local_fwd();
926
927 window = 32*1024;
928 if (tty_flag) {
929 packetmax = window/8;
930 } else {
931 window *= 2;
932 packetmax = window/2;
933 }
934
935 id = channel_new(
936 "session", SSH_CHANNEL_OPENING, in, out, err,
937 window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
938
939
940 channel_open(id);
941 channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
809 942
810 /* Exit with the status returned by the program on the remote side. */ 943 return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
811 exit(exit_status);
812} 944}
diff --git a/sshconnect.c b/sshconnect.c
index d64c0e2c0..2f9496090 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -5,27 +5,30 @@
5 * Created: Sat Mar 18 22:15:47 1995 ylo 5 * Created: Sat Mar 18 22:15:47 1995 ylo
6 * Code to connect to a remote host, and to perform the client side of the 6 * Code to connect to a remote host, and to perform the client side of the
7 * login (authentication) dialog. 7 * login (authentication) dialog.
8 *
9 * SSH2 support added by Markus Friedl.
8 */ 10 */
9 11
10#include "includes.h" 12#include "includes.h"
11RCSID("$OpenBSD: sshconnect.c,v 1.58 2000/03/23 22:15:33 markus Exp $"); 13RCSID("$OpenBSD: sshconnect.c,v 1.61 2000/04/04 21:37:27 markus Exp $");
12 14
13#ifdef HAVE_OPENSSL 15#ifdef HAVE_OPENSSL
16#include <openssl/bn.h>
14#include <openssl/rsa.h> 17#include <openssl/rsa.h>
15#include <openssl/dsa.h> 18#include <openssl/dsa.h>
16#include <openssl/md5.h> 19#include <openssl/md5.h>
17#include <openssl/bn.h>
18#endif 20#endif
19#ifdef HAVE_SSL 21#ifdef HAVE_SSL
22#include <ssl/bn.h>
20#include <ssl/rsa.h> 23#include <ssl/rsa.h>
21#include <ssl/dsa.h> 24#include <ssl/dsa.h>
22#include <ssl/md5.h> 25#include <ssl/md5.h>
23#include <ssl/bn.h>
24#endif 26#endif
25 27
26#include "xmalloc.h" 28#include "xmalloc.h"
27#include "rsa.h" 29#include "rsa.h"
28#include "ssh.h" 30#include "ssh.h"
31#include "buffer.h"
29#include "packet.h" 32#include "packet.h"
30#include "authfd.h" 33#include "authfd.h"
31#include "cipher.h" 34#include "cipher.h"
@@ -33,7 +36,14 @@ RCSID("$OpenBSD: sshconnect.c,v 1.58 2000/03/23 22:15:33 markus Exp $");
33#include "uidswap.h" 36#include "uidswap.h"
34#include "compat.h" 37#include "compat.h"
35#include "readconf.h" 38#include "readconf.h"
39
40#include "bufaux.h"
41
42#include "ssh2.h"
43#include "kex.h"
44#include "myproposal.h"
36#include "key.h" 45#include "key.h"
46#include "dsa.h"
37#include "hostfile.h" 47#include "hostfile.h"
38 48
39/* Session id for the current session. */ 49/* Session id for the current session. */
@@ -42,6 +52,9 @@ unsigned char session_id[16];
42/* authentications supported by server */ 52/* authentications supported by server */
43unsigned int supported_authentications; 53unsigned int supported_authentications;
44 54
55static char *client_version_string = NULL;
56static char *server_version_string = NULL;
57
45extern Options options; 58extern Options options;
46extern char *__progname; 59extern char *__progname;
47 60
@@ -957,6 +970,21 @@ try_password_authentication(char *prompt)
957 return 0; 970 return 0;
958} 971}
959 972
973char *
974chop(char *s)
975{
976 char *t = s;
977 while (*t) {
978 if(*t == '\n' || *t == '\r') {
979 *t = '\0';
980 return s;
981 }
982 t++;
983 }
984 return s;
985
986}
987
960/* 988/*
961 * Waits for the server identification string, and sends our own 989 * Waits for the server identification string, and sends our own
962 * identification string. 990 * identification string.
@@ -979,7 +1007,7 @@ ssh_exchange_identification()
979 if (buf[i] == '\r') { 1007 if (buf[i] == '\r') {
980 buf[i] = '\n'; 1008 buf[i] = '\n';
981 buf[i + 1] = 0; 1009 buf[i + 1] = 0;
982 break; 1010 continue; /**XXX wait for \n */
983 } 1011 }
984 if (buf[i] == '\n') { 1012 if (buf[i] == '\n') {
985 buf[i + 1] = 0; 1013 buf[i + 1] = 0;
@@ -987,17 +1015,21 @@ ssh_exchange_identification()
987 } 1015 }
988 } 1016 }
989 buf[sizeof(buf) - 1] = 0; 1017 buf[sizeof(buf) - 1] = 0;
1018 server_version_string = xstrdup(buf);
990 1019
991 /* 1020 /*
992 * Check that the versions match. In future this might accept 1021 * Check that the versions match. In future this might accept
993 * several versions and set appropriate flags to handle them. 1022 * several versions and set appropriate flags to handle them.
994 */ 1023 */
995 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, 1024 if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
996 remote_version) != 3) 1025 &remote_major, &remote_minor, remote_version) != 3)
997 fatal("Bad remote protocol version identification: '%.100s'", buf); 1026 fatal("Bad remote protocol version identification: '%.100s'", buf);
998 debug("Remote protocol version %d.%d, remote software version %.100s", 1027 debug("Remote protocol version %d.%d, remote software version %.100s",
999 remote_major, remote_minor, remote_version); 1028 remote_major, remote_minor, remote_version);
1000 1029
1030/*** XXX option for disabling 2.0 or 1.5 */
1031 compat_datafellows(remote_version);
1032
1001 /* Check if the remote protocol version is too old. */ 1033 /* Check if the remote protocol version is too old. */
1002 if (remote_major == 1 && remote_minor < 3) 1034 if (remote_major == 1 && remote_minor < 3)
1003 fatal("Remote machine has too old SSH software version."); 1035 fatal("Remote machine has too old SSH software version.");
@@ -1010,6 +1042,10 @@ ssh_exchange_identification()
1010 options.forward_agent = 0; 1042 options.forward_agent = 0;
1011 } 1043 }
1012 } 1044 }
1045 if ((remote_major == 2 && remote_minor == 0) ||
1046 (remote_major == 1 && remote_minor == 99)) {
1047 enable_compat20();
1048 }
1013#if 0 1049#if 0
1014 /* 1050 /*
1015 * Removed for now, to permit compatibility with latter versions. The 1051 * Removed for now, to permit compatibility with latter versions. The
@@ -1020,16 +1056,19 @@ ssh_exchange_identification()
1020 fatal("Protocol major versions differ: %d vs. %d", 1056 fatal("Protocol major versions differ: %d vs. %d",
1021 PROTOCOL_MAJOR, remote_major); 1057 PROTOCOL_MAJOR, remote_major);
1022#endif 1058#endif
1023
1024 /* Send our own protocol version identification. */ 1059 /* Send our own protocol version identification. */
1025 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 1060 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
1026 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); 1061 compat20 ? 2 : PROTOCOL_MAJOR,
1062 compat20 ? 0 : PROTOCOL_MINOR,
1063 SSH_VERSION);
1027 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) 1064 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
1028 fatal("write: %.100s", strerror(errno)); 1065 fatal("write: %.100s", strerror(errno));
1066 client_version_string = xstrdup(buf);
1067 chop(client_version_string);
1068 chop(server_version_string);
1069 debug("Local version string %.100s", client_version_string);
1029} 1070}
1030 1071
1031int ssh_cipher_default = SSH_CIPHER_3DES;
1032
1033int 1072int
1034read_yes_or_no(const char *prompt, int defval) 1073read_yes_or_no(const char *prompt, int defval)
1035{ 1074{
@@ -1283,6 +1322,278 @@ check_rsa_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key)
1283} 1322}
1284 1323
1285/* 1324/*
1325 * SSH2 key exchange
1326 */
1327void
1328ssh_kex2(char *host, struct sockaddr *hostaddr)
1329{
1330 Kex *kex;
1331 char *cprop[PROPOSAL_MAX];
1332 char *sprop[PROPOSAL_MAX];
1333 Buffer *client_kexinit;
1334 Buffer *server_kexinit;
1335 int payload_len, dlen;
1336 unsigned int klen, kout;
1337 char *ptr;
1338 char *signature = NULL;
1339 unsigned int slen;
1340 char *server_host_key_blob = NULL;
1341 Key *server_host_key;
1342 unsigned int sbloblen;
1343 DH *dh;
1344 BIGNUM *dh_server_pub = 0;
1345 BIGNUM *shared_secret = 0;
1346 int i;
1347 unsigned char *kbuf;
1348 unsigned char *hash;
1349
1350/* KEXINIT */
1351
1352 debug("Sending KEX init.");
1353 if (options.cipher == SSH_CIPHER_ARCFOUR ||
1354 options.cipher == SSH_CIPHER_3DES_CBC ||
1355 options.cipher == SSH_CIPHER_CAST128_CBC ||
1356 options.cipher == SSH_CIPHER_BLOWFISH_CBC) {
1357 myproposal[PROPOSAL_ENC_ALGS_CTOS] = cipher_name(options.cipher);
1358 myproposal[PROPOSAL_ENC_ALGS_STOC] = cipher_name(options.cipher);
1359 }
1360 if (options.compression) {
1361 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
1362 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
1363 } else {
1364 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
1365 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
1366 }
1367 for (i = 0; i < PROPOSAL_MAX; i++)
1368 cprop[i] = xstrdup(myproposal[i]);
1369
1370 client_kexinit = kex_init(cprop);
1371 packet_start(SSH2_MSG_KEXINIT);
1372 packet_put_raw(buffer_ptr(client_kexinit), buffer_len(client_kexinit));
1373 packet_send();
1374 packet_write_wait();
1375
1376 debug("done");
1377
1378 packet_read_expect(&payload_len, SSH2_MSG_KEXINIT);
1379
1380 /* save payload for session_id */
1381 server_kexinit = xmalloc(sizeof(*server_kexinit));
1382 buffer_init(server_kexinit);
1383 ptr = packet_get_raw(&payload_len);
1384 buffer_append(server_kexinit, ptr, payload_len);
1385
1386 /* skip cookie */
1387 for (i = 0; i < 16; i++)
1388 (void) packet_get_char();
1389 /* kex init proposal strings */
1390 for (i = 0; i < PROPOSAL_MAX; i++) {
1391 sprop[i] = packet_get_string(NULL);
1392 debug("got kexinit string: %s", sprop[i]);
1393 }
1394 i = (int) packet_get_char();
1395 debug("first kex follow == %d", i);
1396 i = packet_get_int();
1397 debug("reserved == %d", i);
1398
1399 debug("done read kexinit");
1400 kex = kex_choose_conf(cprop, sprop, 0);
1401
1402/* KEXDH */
1403
1404 debug("Sending SSH2_MSG_KEXDH_INIT.");
1405
1406 /* generate and send 'e', client DH public key */
1407 dh = new_dh_group1();
1408 packet_start(SSH2_MSG_KEXDH_INIT);
1409 packet_put_bignum2(dh->pub_key);
1410 packet_send();
1411 packet_write_wait();
1412
1413#ifdef DEBUG_KEXDH
1414 fprintf(stderr, "\np= ");
1415 bignum_print(dh->p);
1416 fprintf(stderr, "\ng= ");
1417 bignum_print(dh->g);
1418 fprintf(stderr, "\npub= ");
1419 bignum_print(dh->pub_key);
1420 fprintf(stderr, "\n");
1421 DHparams_print_fp(stderr, dh);
1422#endif
1423
1424 debug("Wait SSH2_MSG_KEXDH_REPLY.");
1425
1426 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_REPLY);
1427
1428 debug("Got SSH2_MSG_KEXDH_REPLY.");
1429
1430 /* key, cert */
1431 server_host_key_blob = packet_get_string(&sbloblen);
1432 server_host_key = dsa_serverkey_from_blob(server_host_key_blob, sbloblen);
1433 if (server_host_key == NULL)
1434 fatal("cannot decode server_host_key_blob");
1435
1436 check_host_key(host, hostaddr, server_host_key);
1437
1438 /* DH paramter f, server public DH key */
1439 dh_server_pub = BN_new();
1440 if (dh_server_pub == NULL)
1441 fatal("dh_server_pub == NULL");
1442 packet_get_bignum2(dh_server_pub, &dlen);
1443
1444#ifdef DEBUG_KEXDH
1445 fprintf(stderr, "\ndh_server_pub= ");
1446 bignum_print(dh_server_pub);
1447 fprintf(stderr, "\n");
1448 debug("bits %d", BN_num_bits(dh_server_pub));
1449#endif
1450
1451 /* signed H */
1452 signature = packet_get_string(&slen);
1453
1454 klen = DH_size(dh);
1455 kbuf = xmalloc(klen);
1456 kout = DH_compute_key(kbuf, dh_server_pub, dh);
1457#ifdef DEBUG_KEXDH
1458 debug("shared secret: len %d/%d", klen, kout);
1459 fprintf(stderr, "shared secret == ");
1460 for (i = 0; i< kout; i++)
1461 fprintf(stderr, "%02x", (kbuf[i])&0xff);
1462 fprintf(stderr, "\n");
1463#endif
1464 shared_secret = BN_new();
1465
1466 BN_bin2bn(kbuf, kout, shared_secret);
1467 memset(kbuf, 0, klen);
1468 xfree(kbuf);
1469
1470 /* calc and verify H */
1471 hash = kex_hash(
1472 client_version_string,
1473 server_version_string,
1474 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
1475 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
1476 server_host_key_blob, sbloblen,
1477 dh->pub_key,
1478 dh_server_pub,
1479 shared_secret
1480 );
1481 buffer_free(client_kexinit);
1482 buffer_free(server_kexinit);
1483 xfree(client_kexinit);
1484 xfree(server_kexinit);
1485#ifdef DEBUG_KEXDH
1486 fprintf(stderr, "hash == ");
1487 for (i = 0; i< 20; i++)
1488 fprintf(stderr, "%02x", (hash[i])&0xff);
1489 fprintf(stderr, "\n");
1490#endif
1491 dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20);
1492 key_free(server_host_key);
1493
1494 kex_derive_keys(kex, hash, shared_secret);
1495 packet_set_kex(kex);
1496
1497 /* have keys, free DH */
1498 DH_free(dh);
1499
1500 debug("Wait SSH2_MSG_NEWKEYS.");
1501 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
1502 debug("GOT SSH2_MSG_NEWKEYS.");
1503
1504 debug("send SSH2_MSG_NEWKEYS.");
1505 packet_start(SSH2_MSG_NEWKEYS);
1506 packet_send();
1507 packet_write_wait();
1508 debug("done: send SSH2_MSG_NEWKEYS.");
1509
1510 /* send 1st encrypted/maced/compressed message */
1511 packet_start(SSH2_MSG_IGNORE);
1512 packet_put_cstring("markus");
1513 packet_send();
1514 packet_write_wait();
1515
1516 debug("done: KEX2.");
1517}
1518/*
1519 * Authenticate user
1520 */
1521void
1522ssh_userauth2(int host_key_valid, RSA *own_host_key,
1523 uid_t original_real_uid, char *host)
1524{
1525 int type;
1526 int plen;
1527 unsigned int dlen;
1528 int partial;
1529 struct passwd *pw;
1530 char *server_user, *local_user;
1531 char *auths;
1532 char *password;
1533 char *service = "ssh-connection"; // service name
1534
1535 debug("send SSH2_MSG_SERVICE_REQUEST");
1536 packet_start(SSH2_MSG_SERVICE_REQUEST);
1537 packet_put_cstring("ssh-userauth");
1538 packet_send();
1539 packet_write_wait();
1540
1541 type = packet_read(&plen);
1542 if (type != SSH2_MSG_SERVICE_ACCEPT) {
1543 fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
1544 }
1545 /* payload empty for ssh-2.0.13 ?? */
1546 /* reply = packet_get_string(&payload_len); */
1547 debug("got SSH2_MSG_SERVICE_ACCEPT");
1548
1549 /*XX COMMONCODE: */
1550 /* Get local user name. Use it as server user if no user name was given. */
1551 pw = getpwuid(original_real_uid);
1552 if (!pw)
1553 fatal("User id %d not found from user database.", original_real_uid);
1554 local_user = xstrdup(pw->pw_name);
1555 server_user = options.user ? options.user : local_user;
1556
1557 /* INITIAL request for auth */
1558 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1559 packet_put_cstring(server_user);
1560 packet_put_cstring(service);
1561 packet_put_cstring("none");
1562 packet_send();
1563 packet_write_wait();
1564
1565 for (;;) {
1566 type = packet_read(&plen);
1567 if (type == SSH2_MSG_USERAUTH_SUCCESS)
1568 break;
1569 if (type != SSH2_MSG_USERAUTH_FAILURE)
1570 fatal("access denied: %d", type);
1571 /* SSH2_MSG_USERAUTH_FAILURE means: try again */
1572 auths = packet_get_string(&dlen);
1573 debug("authentications that can continue: %s", auths);
1574 partial = packet_get_char();
1575 if (partial)
1576 debug("partial success");
1577 if (strstr(auths, "password") == NULL)
1578 fatal("passwd auth not supported: %s", auths);
1579 xfree(auths);
1580 /* try passwd */
1581 password = read_passphrase("password: ", 0);
1582 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1583 packet_put_cstring(server_user);
1584 packet_put_cstring(service);
1585 packet_put_cstring("password");
1586 packet_put_char(0);
1587 packet_put_cstring(password);
1588 memset(password, 0, strlen(password));
1589 xfree(password);
1590 packet_send();
1591 packet_write_wait();
1592 }
1593 debug("ssh-userauth2 successfull");
1594}
1595
1596/*
1286 * SSH1 key exchange 1597 * SSH1 key exchange
1287 */ 1598 */
1288void 1599void
@@ -1293,6 +1604,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
1293 RSA *host_key; 1604 RSA *host_key;
1294 RSA *public_key; 1605 RSA *public_key;
1295 int bits, rbits; 1606 int bits, rbits;
1607 int ssh_cipher_default = SSH_CIPHER_3DES;
1296 unsigned char session_key[SSH_SESSION_KEY_LENGTH]; 1608 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
1297 unsigned char cookie[8]; 1609 unsigned char cookie[8];
1298 unsigned int supported_ciphers; 1610 unsigned int supported_ciphers;
@@ -1427,7 +1739,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
1427 RSA_free(host_key); 1739 RSA_free(host_key);
1428 1740
1429 if (options.cipher == SSH_CIPHER_NOT_SET) { 1741 if (options.cipher == SSH_CIPHER_NOT_SET) {
1430 if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default)) 1742 if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default))
1431 options.cipher = ssh_cipher_default; 1743 options.cipher = ssh_cipher_default;
1432 else { 1744 else {
1433 debug("Cipher %s not supported, using %.100s instead.", 1745 debug("Cipher %s not supported, using %.100s instead.",
@@ -1640,12 +1952,16 @@ ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
1640 /* Put the connection into non-blocking mode. */ 1952 /* Put the connection into non-blocking mode. */
1641 packet_set_nonblocking(); 1953 packet_set_nonblocking();
1642 1954
1643 supported_authentications = 0;
1644 /* key exchange */ 1955 /* key exchange */
1645 ssh_kex(host, hostaddr);
1646 if (supported_authentications == 0)
1647 fatal("supported_authentications == 0.");
1648
1649 /* authenticate user */ 1956 /* authenticate user */
1650 ssh_userauth(host_key_valid, own_host_key, original_real_uid, host); 1957 if (compat20) {
1958 ssh_kex2(host, hostaddr);
1959 ssh_userauth2(host_key_valid, own_host_key, original_real_uid, host);
1960 } else {
1961 supported_authentications = 0;
1962 ssh_kex(host, hostaddr);
1963 if (supported_authentications == 0)
1964 fatal("supported_authentications == 0.");
1965 ssh_userauth(host_key_valid, own_host_key, original_real_uid, host);
1966 }
1651} 1967}
diff --git a/sshd.c b/sshd.c
index 6ec413d6f..bb5685dc4 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$OpenBSD: sshd.c,v 1.96 2000/03/28 21:15:45 markus Exp $"); 14RCSID("$OpenBSD: sshd.c,v 1.97 2000/04/04 21:37:27 markus Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "rsa.h" 17#include "rsa.h"
@@ -911,7 +911,7 @@ do_ssh1_kex()
911 packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); 911 packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
912 912
913 /* Declare which ciphers we support. */ 913 /* Declare which ciphers we support. */
914 packet_put_int(cipher_mask()); 914 packet_put_int(cipher_mask1());
915 915
916 /* Declare supported authentication types. */ 916 /* Declare supported authentication types. */
917 auth_mask = 0; 917 auth_mask = 0;