summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-04-12 20:17:38 +1000
committerDamien Miller <djm@mindrot.org>2000-04-12 20:17:38 +1000
commit78928793fb23a3a4c80ae62eca6a7826b2987690 (patch)
treeadd8a953ac4cf06877b91624fe7f647b17e6cf6f
parentefb4afe0265333ce554f699c2a19ae249dd8d1b5 (diff)
- OpenBSD CVS updates:
- [channels.c] repair x11-fwd - [sshconnect.c] fix passwd prompt for ssh2, less debugging output. - [clientloop.c compat.c dsa.c kex.c sshd.c] less debugging output - [kex.c kex.h sshconnect.c sshd.c] check for reasonable public DH values - [README.openssh2 cipher.c cipher.h compat.c compat.h readconf.c] [readconf.h servconf.c servconf.h ssh.c ssh.h sshconnect.c sshd.c] add Cipher and Protocol options to ssh/sshd, e.g.: ssh -o 'Protocol 1,2' if you prefer proto 1, ssh -o 'Ciphers arcfour,3des-cbc' - [sshd.c] print 1.99 only if server supports both
-rw-r--r--ChangeLog18
-rw-r--r--README.openssh219
-rw-r--r--channels.c4
-rw-r--r--cipher.c37
-rw-r--r--cipher.h5
-rw-r--r--clientloop.c4
-rw-r--r--compat.c33
-rw-r--r--compat.h9
-rw-r--r--dsa.c24
-rw-r--r--kex.c56
-rw-r--r--kex.h3
-rw-r--r--readconf.c31
-rw-r--r--readconf.h4
-rw-r--r--servconf.c67
-rw-r--r--servconf.h4
-rw-r--r--ssh.c9
-rw-r--r--ssh.h14
-rw-r--r--sshconnect.c91
-rw-r--r--sshd.c76
19 files changed, 363 insertions, 145 deletions
diff --git a/ChangeLog b/ChangeLog
index 976c3834f..af54ab6d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
120000412
2 - OpenBSD CVS updates:
3 - [channels.c]
4 repair x11-fwd
5 - [sshconnect.c]
6 fix passwd prompt for ssh2, less debugging output.
7 - [clientloop.c compat.c dsa.c kex.c sshd.c]
8 less debugging output
9 - [kex.c kex.h sshconnect.c sshd.c]
10 check for reasonable public DH values
11 - [README.openssh2 cipher.c cipher.h compat.c compat.h readconf.c]
12 [readconf.h servconf.c servconf.h ssh.c ssh.h sshconnect.c sshd.c]
13 add Cipher and Protocol options to ssh/sshd, e.g.:
14 ssh -o 'Protocol 1,2' if you prefer proto 1, ssh -o 'Ciphers
15 arcfour,3des-cbc'
16 - [sshd.c]
17 print 1.99 only if server supports both
18
120000408 1920000408
2 - Avoid some compiler warnings in fake-get*.c 20 - Avoid some compiler warnings in fake-get*.c
3 - Add IPTOS macros for systems which lack them 21 - Add IPTOS macros for systems which lack them
diff --git a/README.openssh2 b/README.openssh2
index 59f8cf9f6..bdf78bf58 100644
--- a/README.openssh2
+++ b/README.openssh2
@@ -1,4 +1,13 @@
1$Id: README.openssh2,v 1.2 2000/04/06 21:28:22 markus Exp $ 1$Id: README.openssh2,v 1.3 2000/04/12 07:45:43 markus Exp $
2
3howto:
4 1) generate server key:
5 $ umask 077
6 $ openssl dsaparam 1024 -out dsa1024.pem
7 $ openssl gendsa -out /etc/ssh_dsa_key dsa1024.pem -rand /dev/arandom
8 2) enable ssh2:
9 server: add 'Protocol 2,1' to /etc/sshd_config
10 client: ssh -o 'Protocol 2,1', or add to .ssh/config
2 11
3works: 12works:
4 secsh-transport: works w/o rekey 13 secsh-transport: works w/o rekey
@@ -11,11 +20,7 @@ works:
11 tcp-forwarding: -L works 20 tcp-forwarding: -L works
12 dss: verification works, 21 dss: verification works,
13 key database in ~/.ssh/known_hosts with bits == 0 hack 22 key database in ~/.ssh/known_hosts with bits == 0 hack
14 dss: signature works, keygen w/ openssl: 23 dss: signature works, keygen w/ openssl
15 $ umask 077
16 $ openssl dsaparam 1024 -out dsa1024.pem
17 $ openssl gendsa -out /etc/ssh_dsa_key dsa1024.pem -rand /dev/arandom
18 start sshd with '-2' flag
19 client interops w/ sshd2, lshd 24 client interops w/ sshd2, lshd
20 server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT 25 server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT
21 server supports multiple concurrent sessions (e.g. with SSH.com Windows client) 26 server supports multiple concurrent sessions (e.g. with SSH.com Windows client)
@@ -33,4 +38,4 @@ todo:
33 sftp 38 sftp
34 39
35-markus 40-markus
36$Date: 2000/04/06 21:28:22 $ 41$Date: 2000/04/12 07:45:43 $
diff --git a/channels.c b/channels.c
index c140b77dc..957b4a428 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.23 2000/04/12 08:45:06 damien Exp $"); 20RCSID("$Id: channels.c,v 1.24 2000/04/12 10:17:38 damien Exp $");
21 21
22#include "ssh.h" 22#include "ssh.h"
23#include "packet.h" 23#include "packet.h"
@@ -437,6 +437,7 @@ channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
437 if (ret == 1) { 437 if (ret == 1) {
438 /* Start normal processing for the channel. */ 438 /* Start normal processing for the channel. */
439 c->type = SSH_CHANNEL_OPEN; 439 c->type = SSH_CHANNEL_OPEN;
440 channel_pre_open_13(c, readset, writeset);
440 } else if (ret == -1) { 441 } else if (ret == -1) {
441 /* 442 /*
442 * We have received an X11 connection that has bad 443 * We have received an X11 connection that has bad
@@ -460,6 +461,7 @@ channel_pre_x11_open_15(Channel *c, fd_set * readset, fd_set * writeset)
460 int ret = x11_open_helper(c); 461 int ret = x11_open_helper(c);
461 if (ret == 1) { 462 if (ret == 1) {
462 c->type = SSH_CHANNEL_OPEN; 463 c->type = SSH_CHANNEL_OPEN;
464 channel_pre_open_15(c, readset, writeset);
463 } else if (ret == -1) { 465 } else if (ret == -1) {
464 debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); 466 debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
465 chan_read_failed(c); 467 chan_read_failed(c);
diff --git a/cipher.c b/cipher.c
index 8911ffef6..27debf90f 100644
--- a/cipher.c
+++ b/cipher.c
@@ -12,11 +12,11 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: cipher.c,v 1.16 2000/04/06 02:32:39 damien Exp $"); 15RCSID("$Id: cipher.c,v 1.17 2000/04/12 10:17:39 damien Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "cipher.h" 18#include "cipher.h"
19#include "config.h" 19#include "xmalloc.h"
20 20
21#ifdef HAVE_OPENSSL 21#ifdef HAVE_OPENSSL
22#include <openssl/md5.h> 22#include <openssl/md5.h>
@@ -26,7 +26,9 @@ RCSID("$Id: cipher.c,v 1.16 2000/04/06 02:32:39 damien Exp $");
26#endif 26#endif
27 27
28/* 28/*
29 * What kind of tripple DES are these 2 routines? 29 * This is used by SSH1:
30 *
31 * What kind of triple DES are these 2 routines?
30 * 32 *
31 * Why is there a redundant initialization vector? 33 * Why is there a redundant initialization vector?
32 * 34 *
@@ -81,7 +83,7 @@ SSH_3CBC_DECRYPT(des_key_schedule ks1,
81} 83}
82 84
83/* 85/*
84 * SSH uses a variation on Blowfish, all bytes must be swapped before 86 * SSH1 uses a variation on Blowfish, all bytes must be swapped before
85 * and after encryption/decryption. Thus the swap_bytes stuff (yuk). 87 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
86 */ 88 */
87static void 89static void
@@ -167,10 +169,34 @@ cipher_name(int cipher)
167{ 169{
168 if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) || 170 if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
169 cipher_names[cipher] == NULL) 171 cipher_names[cipher] == NULL)
170 fatal("cipher_name: bad cipher number: %d", cipher); 172 fatal("cipher_name: bad cipher name: %d", cipher);
171 return cipher_names[cipher]; 173 return cipher_names[cipher];
172} 174}
173 175
176/* Returns 1 if the name of the ciphers are valid. */
177
178#define CIPHER_SEP ","
179int
180ciphers_valid(const char *names)
181{
182 char *ciphers;
183 char *p;
184 int i;
185
186 if (strcmp(names, "") == 0)
187 return 0;
188 ciphers = xstrdup(names);
189 for ((p = strtok(ciphers, CIPHER_SEP)); p; (p = strtok(NULL, CIPHER_SEP))) {
190 i = cipher_number(p);
191 if (i == -1 || !(cipher_mask2() & (1 << i))) {
192 xfree(ciphers);
193 return 0;
194 }
195 }
196 xfree(ciphers);
197 return 1;
198}
199
174/* 200/*
175 * Parses the name of the cipher. Returns the number of the corresponding 201 * Parses the name of the cipher. Returns the number of the corresponding
176 * cipher, or -1 on error. 202 * cipher, or -1 on error.
@@ -271,7 +297,6 @@ cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
271 memset(padded, 0, sizeof(padded)); 297 memset(padded, 0, sizeof(padded));
272} 298}
273 299
274
275void 300void
276cipher_set_key_iv(CipherContext * context, int cipher, 301cipher_set_key_iv(CipherContext * context, int cipher,
277 const unsigned char *key, int keylen, 302 const unsigned char *key, int keylen,
diff --git a/cipher.h b/cipher.h
index 94c0ceee5..ee0e312fb 100644
--- a/cipher.h
+++ b/cipher.h
@@ -11,7 +11,7 @@
11 * 11 *
12 */ 12 */
13 13
14/* RCSID("$Id: cipher.h,v 1.8 2000/04/06 02:32:39 damien Exp $"); */ 14/* RCSID("$Id: cipher.h,v 1.9 2000/04/12 10:17:39 damien Exp $"); */
15 15
16#ifndef CIPHER_H 16#ifndef CIPHER_H
17#define CIPHER_H 17#define CIPHER_H
@@ -88,6 +88,9 @@ const char *cipher_name(int cipher);
88 */ 88 */
89int cipher_number(const char *name); 89int cipher_number(const char *name);
90 90
91/* returns 1 if all ciphers are supported (ssh2 only) */
92int ciphers_valid(const char *names);
93
91/* 94/*
92 * Selects the cipher to use and sets the key. If for_encryption is true, 95 * Selects the cipher to use and sets the key. If for_encryption is true,
93 * the key is setup for encryption; otherwise it is setup for decryption. 96 * the key is setup for encryption; otherwise it is setup for decryption.
diff --git a/clientloop.c b/clientloop.c
index 4f2e5037d..91a200663 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$Id: clientloop.c,v 1.9 2000/04/06 02:32:39 damien Exp $"); 19RCSID("$Id: clientloop.c,v 1.10 2000/04/12 10:17:39 damien Exp $");
20 20
21#include "xmalloc.h" 21#include "xmalloc.h"
22#include "ssh.h" 22#include "ssh.h"
@@ -1013,7 +1013,7 @@ client_input_channel_req(int id, void *arg)
1013 rtype = packet_get_string(&len); 1013 rtype = packet_get_string(&len);
1014 reply = packet_get_char(); 1014 reply = packet_get_char();
1015 1015
1016 log("session_input_channel_req: rtype %s reply %d", rtype, reply); 1016 debug("session_input_channel_req: rtype %s reply %d", rtype, reply);
1017 1017
1018 c = channel_lookup(id); 1018 c = channel_lookup(id);
1019 if (c == NULL) 1019 if (c == NULL)
diff --git a/compat.c b/compat.c
index c183866c3..d56e3e81d 100644
--- a/compat.c
+++ b/compat.c
@@ -28,10 +28,12 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: compat.c,v 1.6 2000/04/12 08:45:06 damien Exp $"); 31RCSID("$Id: compat.c,v 1.7 2000/04/12 10:17:39 damien Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "packet.h" 34#include "packet.h"
35#include "xmalloc.h"
36#include "compat.h"
35 37
36int compat13 = 0; 38int compat13 = 0;
37int compat20 = 0; 39int compat20 = 0;
@@ -65,9 +67,36 @@ compat_datafellows(const char *version)
65 len = strlen(check[i]); 67 len = strlen(check[i]);
66 if (strlen(version) >= len && 68 if (strlen(version) >= len &&
67 (strncmp(version, check[i], len) == 0)) { 69 (strncmp(version, check[i], len) == 0)) {
68 log("datafellows: %.200s", version); 70 verbose("datafellows: %.200s", version);
69 datafellows = 1; 71 datafellows = 1;
70 return; 72 return;
71 } 73 }
72 } 74 }
73} 75}
76
77#define SEP ","
78int
79proto_spec(const char *spec)
80{
81 char *s = xstrdup(spec);
82 char *p;
83 int ret = SSH_PROTO_UNKNOWN;
84
85 for ((p = strtok(s, SEP)); p; (p = strtok(NULL, SEP))) {
86 switch(atoi(p)) {
87 case 1:
88 if (ret == SSH_PROTO_UNKNOWN)
89 ret |= SSH_PROTO_1_PREFERRED;
90 ret |= SSH_PROTO_1;
91 break;
92 case 2:
93 ret |= SSH_PROTO_2;
94 break;
95 default:
96 log("ignoring bad proto spec: '%s'.", p);
97 break;
98 }
99 }
100 xfree(s);
101 return ret;
102}
diff --git a/compat.h b/compat.h
index 4247f53b4..4943e5a29 100644
--- a/compat.h
+++ b/compat.h
@@ -26,13 +26,20 @@
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29/* RCSID("$Id: compat.h,v 1.4 2000/04/04 04:39:01 damien Exp $"); */ 29/* RCSID("$Id: compat.h,v 1.5 2000/04/12 10:17:39 damien Exp $"); */
30 30
31#ifndef COMPAT_H 31#ifndef COMPAT_H
32#define COMPAT_H 32#define COMPAT_H
33
34#define SSH_PROTO_UNKNOWN 0x00
35#define SSH_PROTO_1 0x01
36#define SSH_PROTO_1_PREFERRED 0x02
37#define SSH_PROTO_2 0x04
38
33void enable_compat13(void); 39void enable_compat13(void);
34void enable_compat20(void); 40void enable_compat20(void);
35void compat_datafellows(const char *s); 41void compat_datafellows(const char *s);
42int proto_spec(const char *spec);
36extern int compat13; 43extern int compat13;
37extern int compat20; 44extern int compat20;
38extern int datafellows; 45extern int datafellows;
diff --git a/dsa.c b/dsa.c
index eeb4ead10..a35d85bf5 100644
--- a/dsa.c
+++ b/dsa.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: dsa.c,v 1.1 2000/04/04 04:39:01 damien Exp $"); 31RCSID("$Id: dsa.c,v 1.2 2000/04/12 06:37:02 markus Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "xmalloc.h" 34#include "xmalloc.h"
@@ -80,7 +80,7 @@ dsa_serverkey_from_blob(
80 buffer_append(&b, serverhostkey, serverhostkeylen); 80 buffer_append(&b, serverhostkey, serverhostkeylen);
81 ktype = buffer_get_string(&b, NULL); 81 ktype = buffer_get_string(&b, NULL);
82 if (strcmp(KEX_DSS, ktype) != 0) { 82 if (strcmp(KEX_DSS, ktype) != 0) {
83 log("dsa_serverkey_from_blob: cannot handle type %s", ktype); 83 error("dsa_serverkey_from_blob: cannot handle type %s", ktype);
84 key_free(key); 84 key_free(key);
85 return NULL; 85 return NULL;
86 } 86 }
@@ -90,10 +90,10 @@ dsa_serverkey_from_blob(
90 buffer_get_bignum2(&b, dsa->pub_key); 90 buffer_get_bignum2(&b, dsa->pub_key);
91 rlen = buffer_len(&b); 91 rlen = buffer_len(&b);
92 if(rlen != 0) 92 if(rlen != 0)
93 log("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen); 93 error("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen);
94 buffer_free(&b); 94 buffer_free(&b);
95 95
96 log("keytype %s", ktype); 96 debug("keytype %s", ktype);
97#ifdef DEBUG_DSS 97#ifdef DEBUG_DSS
98 DSA_print_fp(stderr, dsa, 8); 98 DSA_print_fp(stderr, dsa, 8);
99#endif 99#endif
@@ -172,7 +172,7 @@ dsa_sign(
172 Buffer b; 172 Buffer b;
173 173
174 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 174 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
175 log("dsa_sign: no DSA key"); 175 error("dsa_sign: no DSA key");
176 return -1; 176 return -1;
177 } 177 }
178 digest = xmalloc(evp_md->md_size); 178 digest = xmalloc(evp_md->md_size);
@@ -185,11 +185,11 @@ dsa_sign(
185 rlen = BN_num_bytes(sig->r); 185 rlen = BN_num_bytes(sig->r);
186 slen = BN_num_bytes(sig->s); 186 slen = BN_num_bytes(sig->s);
187 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 187 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
188 log("bad sig size %d %d", rlen, slen); 188 error("bad sig size %d %d", rlen, slen);
189 DSA_SIG_free(sig); 189 DSA_SIG_free(sig);
190 return -1; 190 return -1;
191 } 191 }
192 log("sig size %d %d", rlen, slen); 192 debug("sig size %d %d", rlen, slen);
193 193
194 memset(sigblob, 0, SIGBLOB_LEN); 194 memset(sigblob, 0, SIGBLOB_LEN);
195 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 195 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
@@ -197,7 +197,7 @@ dsa_sign(
197 DSA_SIG_free(sig); 197 DSA_SIG_free(sig);
198 198
199 if (datafellows) { 199 if (datafellows) {
200 log("datafellows"); 200 debug("datafellows");
201 ret = xmalloc(SIGBLOB_LEN); 201 ret = xmalloc(SIGBLOB_LEN);
202 memcpy(ret, sigblob, SIGBLOB_LEN); 202 memcpy(ret, sigblob, SIGBLOB_LEN);
203 if (lenp != NULL) 203 if (lenp != NULL)
@@ -239,7 +239,7 @@ dsa_verify(
239 int ret; 239 int ret;
240 240
241 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 241 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
242 log("dsa_verify: no DSA key"); 242 error("dsa_verify: no DSA key");
243 return -1; 243 return -1;
244 } 244 }
245 245
@@ -248,7 +248,7 @@ dsa_verify(
248 datafellows = 0; 248 datafellows = 0;
249 } 249 }
250 250
251 log("len %d datafellows %d", signaturelen, datafellows); 251 debug("len %d datafellows %d", signaturelen, datafellows);
252 252
253 /* fetch signature */ 253 /* fetch signature */
254 if (datafellows) { 254 if (datafellows) {
@@ -262,7 +262,7 @@ dsa_verify(
262 sigblob = (unsigned char *)buffer_get_string(&b, &len); 262 sigblob = (unsigned char *)buffer_get_string(&b, &len);
263 rlen = buffer_len(&b); 263 rlen = buffer_len(&b);
264 if(rlen != 0) 264 if(rlen != 0)
265 log("remaining bytes in signature %d", rlen); 265 error("remaining bytes in signature %d", rlen);
266 buffer_free(&b); 266 buffer_free(&b);
267 } 267 }
268 268
@@ -305,6 +305,6 @@ dsa_verify(
305 txt = "error"; 305 txt = "error";
306 break; 306 break;
307 } 307 }
308 log("dsa_verify: signature %s", txt); 308 debug("dsa_verify: signature %s", txt);
309 return ret; 309 return ret;
310} 310}
diff --git a/kex.c b/kex.c
index d2047d6f1..9ec75ee0e 100644
--- a/kex.c
+++ b/kex.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: kex.c,v 1.2 2000/04/04 04:57:08 damien Exp $"); 31RCSID("$Id: kex.c,v 1.3 2000/04/12 10:17:39 damien Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "ssh2.h" 34#include "ssh2.h"
@@ -43,8 +43,6 @@ RCSID("$Id: kex.c,v 1.2 2000/04/04 04:57:08 damien Exp $");
43# include <openssl/dh.h> 43# include <openssl/dh.h>
44# include <openssl/crypto.h> 44# include <openssl/crypto.h>
45# include <openssl/bio.h> 45# include <openssl/bio.h>
46# include <openssl/bn.h>
47# include <openssl/dh.h>
48# include <openssl/pem.h> 46# include <openssl/pem.h>
49#endif /* HAVE_OPENSSL */ 47#endif /* HAVE_OPENSSL */
50#if HAVE_SSL 48#if HAVE_SSL
@@ -52,12 +50,9 @@ RCSID("$Id: kex.c,v 1.2 2000/04/04 04:57:08 damien Exp $");
52# include <ssl/dh.h> 50# include <ssl/dh.h>
53# include <ssl/crypto.h> 51# include <ssl/crypto.h>
54# include <ssl/bio.h> 52# include <ssl/bio.h>
55# include <ssl/bn.h>
56# include <ssl/dh.h>
57# include <ssl/pem.h> 53# include <ssl/pem.h>
58#endif /* HAVE_SSL */ 54#endif /* HAVE_SSL */
59 55
60#include "entropy.h"
61#include "kex.h" 56#include "kex.h"
62 57
63Buffer * 58Buffer *
@@ -85,8 +80,36 @@ kex_init(char *myproposal[PROPOSAL_MAX])
85 80
86/* diffie-hellman-group1-sha1 */ 81/* diffie-hellman-group1-sha1 */
87 82
83int
84dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
85{
86 int i;
87 int n = BN_num_bits(dh_pub);
88 int bits_set = 0;
89
90 /* we only accept g==2 */
91 if (!BN_is_word(dh->g, 2)) {
92 log("invalid DH base != 2");
93 return 0;
94 }
95 if (dh_pub->neg) {
96 log("invalid public DH value: negativ");
97 return 0;
98 }
99 for (i = 0; i <= n; i++)
100 if (BN_is_bit_set(dh_pub, i))
101 bits_set++;
102 debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
103
104 /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
105 if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
106 return 1;
107 log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
108 return 0;
109}
110
88DH * 111DH *
89new_dh_group1() 112dh_new_group1()
90{ 113{
91 static char *group1 = 114 static char *group1 =
92 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" 115 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
@@ -96,22 +119,23 @@ new_dh_group1()
96 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" 119 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
97 "FFFFFFFF" "FFFFFFFF"; 120 "FFFFFFFF" "FFFFFFFF";
98 DH *dh; 121 DH *dh;
99 int ret; 122 int ret, tries = 0;
100 dh = DH_new(); 123 dh = DH_new();
101 if(dh == NULL) 124 if(dh == NULL)
102 fatal("DH_new"); 125 fatal("DH_new");
103 ret = BN_hex2bn(&dh->p,group1); 126 ret = BN_hex2bn(&dh->p, group1);
104 if(ret<0) 127 if(ret<0)
105 fatal("BN_hex2bn"); 128 fatal("BN_hex2bn");
106 dh->g = BN_new(); 129 dh->g = BN_new();
107 if(dh->g == NULL) 130 if(dh->g == NULL)
108 fatal("DH_new g"); 131 fatal("DH_new g");
109 BN_set_word(dh->g,2); 132 BN_set_word(dh->g, 2);
110 133 do {
111 seed_rng(); 134 if (DH_generate_key(dh) == 0)
112 if (DH_generate_key(dh) == 0) 135 fatal("DH_generate_key");
113 fatal("DH_generate_key"); 136 if (tries++ > 10)
114 137 fatal("dh_new_group1: too many bad keys: giving up");
138 } while (!dh_pub_is_valid(dh, dh->pub_key));
115 return dh; 139 return dh;
116} 140}
117 141
@@ -356,7 +380,7 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
356 choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]); 380 choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]);
357 choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]); 381 choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]);
358 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]); 382 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
359 log("kex: %s %s %s %s", 383 debug("kex: %s %s %s %s",
360 ctos ? "client->server" : "server->client", 384 ctos ? "client->server" : "server->client",
361 k->enc[mode].name, 385 k->enc[mode].name,
362 k->mac[mode].name, 386 k->mac[mode].name,
diff --git a/kex.h b/kex.h
index 81c41342a..29e1e887f 100644
--- a/kex.h
+++ b/kex.h
@@ -102,7 +102,8 @@ struct Kex {
102}; 102};
103 103
104Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); 104Buffer *kex_init(char *myproposal[PROPOSAL_MAX]);
105DH *new_dh_group1(); 105int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
106DH *dh_new_group1();
106Kex *kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server); 107Kex *kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server);
107int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); 108int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret);
108void bignum_print(BIGNUM *b); 109void bignum_print(BIGNUM *b);
diff --git a/readconf.c b/readconf.c
index bb420ac05..1ba70c36a 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,13 +14,14 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: readconf.c,v 1.9 2000/04/01 01:09:25 damien Exp $"); 17RCSID("$Id: readconf.c,v 1.10 2000/04/12 10:17:40 damien Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "cipher.h" 20#include "cipher.h"
21#include "readconf.h" 21#include "readconf.h"
22#include "match.h" 22#include "match.h"
23#include "xmalloc.h" 23#include "xmalloc.h"
24#include "compat.h"
24 25
25/* Format of the configuration file: 26/* Format of the configuration file:
26 27
@@ -103,7 +104,7 @@ typedef enum {
103 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 104 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
104 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 105 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
105 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, 106 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
106 oUsePrivilegedPort, oLogLevel 107 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol
107} OpCodes; 108} OpCodes;
108 109
109/* Textual representations of the tokens. */ 110/* Textual representations of the tokens. */
@@ -134,6 +135,8 @@ static struct {
134 { "proxycommand", oProxyCommand }, 135 { "proxycommand", oProxyCommand },
135 { "port", oPort }, 136 { "port", oPort },
136 { "cipher", oCipher }, 137 { "cipher", oCipher },
138 { "ciphers", oCiphers },
139 { "protocol", oProtocol },
137 { "remoteforward", oRemoteForward }, 140 { "remoteforward", oRemoteForward },
138 { "localforward", oLocalForward }, 141 { "localforward", oLocalForward },
139 { "user", oUser }, 142 { "user", oUser },
@@ -444,6 +447,26 @@ parse_int:
444 *intptr = value; 447 *intptr = value;
445 break; 448 break;
446 449
450 case oCiphers:
451 cp = strtok(NULL, WHITESPACE);
452 if (!ciphers_valid(cp))
453 fatal("%.200s line %d: Bad cipher spec '%s'.",
454 filename, linenum, cp ? cp : "<NONE>");
455 if (*activep && options->ciphers == NULL)
456 options->ciphers = xstrdup(cp);
457 break;
458
459 case oProtocol:
460 intptr = &options->protocol;
461 cp = strtok(NULL, WHITESPACE);
462 value = proto_spec(cp);
463 if (value == SSH_PROTO_UNKNOWN)
464 fatal("%.200s line %d: Bad protocol spec '%s'.",
465 filename, linenum, cp ? cp : "<NONE>");
466 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
467 *intptr = value;
468 break;
469
447 case oLogLevel: 470 case oLogLevel:
448 intptr = (int *) &options->log_level; 471 intptr = (int *) &options->log_level;
449 cp = strtok(NULL, WHITESPACE); 472 cp = strtok(NULL, WHITESPACE);
@@ -616,6 +639,8 @@ initialize_options(Options * options)
616 options->connection_attempts = -1; 639 options->connection_attempts = -1;
617 options->number_of_password_prompts = -1; 640 options->number_of_password_prompts = -1;
618 options->cipher = -1; 641 options->cipher = -1;
642 options->ciphers = NULL;
643 options->protocol = SSH_PROTO_UNKNOWN;
619 options->num_identity_files = 0; 644 options->num_identity_files = 0;
620 options->hostname = NULL; 645 options->hostname = NULL;
621 options->proxy_command = NULL; 646 options->proxy_command = NULL;
@@ -689,6 +714,8 @@ fill_default_options(Options * options)
689 /* Selected in ssh_login(). */ 714 /* Selected in ssh_login(). */
690 if (options->cipher == -1) 715 if (options->cipher == -1)
691 options->cipher = SSH_CIPHER_NOT_SET; 716 options->cipher = SSH_CIPHER_NOT_SET;
717 if (options->protocol == SSH_PROTO_UNKNOWN)
718 options->protocol = SSH_PROTO_1;
692 if (options->num_identity_files == 0) { 719 if (options->num_identity_files == 0) {
693 options->identity_files[0] = 720 options->identity_files[0] =
694 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1); 721 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
diff --git a/readconf.h b/readconf.h
index 09f051401..86f342d37 100644
--- a/readconf.h
+++ b/readconf.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: readconf.h,v 1.6 1999/12/06 00:47:29 damien Exp $"); */ 16/* RCSID("$Id: readconf.h,v 1.7 2000/04/12 10:17:40 damien Exp $"); */
17 17
18#ifndef READCONF_H 18#ifndef READCONF_H
19#define READCONF_H 19#define READCONF_H
@@ -64,6 +64,8 @@ typedef struct {
64 int number_of_password_prompts; /* Max number of password 64 int number_of_password_prompts; /* Max number of password
65 * prompts. */ 65 * prompts. */
66 int cipher; /* Cipher to use. */ 66 int cipher; /* Cipher to use. */
67 char *ciphers; /* Ciphers in order of preference. */
68 int protocol; /* Protocol in order of preference. */
67 char *hostname; /* Real host to connect. */ 69 char *hostname; /* Real host to connect. */
68 char *proxy_command; /* Proxy command for connecting the host. */ 70 char *proxy_command; /* Proxy command for connecting the host. */
69 char *user; /* User to log in as. */ 71 char *user; /* User to log in as. */
diff --git a/servconf.c b/servconf.c
index 800c4d5f4..918fb8ed2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -12,11 +12,12 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: servconf.c,v 1.10 2000/04/12 08:45:06 damien Exp $"); 15RCSID("$Id: servconf.c,v 1.11 2000/04/12 10:17:40 damien Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "servconf.h" 18#include "servconf.h"
19#include "xmalloc.h" 19#include "xmalloc.h"
20#include "compat.h"
20 21
21/* add listen address */ 22/* add listen address */
22void add_listen_addr(ServerOptions *options, char *addr); 23void add_listen_addr(ServerOptions *options, char *addr);
@@ -68,6 +69,8 @@ initialize_server_options(ServerOptions *options)
68 options->num_deny_users = 0; 69 options->num_deny_users = 0;
69 options->num_allow_groups = 0; 70 options->num_allow_groups = 0;
70 options->num_deny_groups = 0; 71 options->num_deny_groups = 0;
72 options->ciphers = NULL;
73 options->protocol = SSH_PROTO_UNKNOWN;
71} 74}
72 75
73void 76void
@@ -139,6 +142,8 @@ fill_default_server_options(ServerOptions *options)
139 options->permit_empty_passwd = 0; 142 options->permit_empty_passwd = 0;
140 if (options->use_login == -1) 143 if (options->use_login == -1)
141 options->use_login = 0; 144 options->use_login = 0;
145 if (options->protocol == SSH_PROTO_UNKNOWN)
146 options->protocol = SSH_PROTO_1;
142} 147}
143 148
144#define WHITESPACE " \t\r\n" 149#define WHITESPACE " \t\r\n"
@@ -162,7 +167,7 @@ typedef enum {
162 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, 167 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
163 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, 168 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
164 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 169 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
165 sIgnoreUserKnownHosts, sDSAKeyFile 170 sIgnoreUserKnownHosts, sDSAKeyFile, sCiphers, sProtocol
166} ServerOpCodes; 171} ServerOpCodes;
167 172
168/* Textual representation of the tokens. */ 173/* Textual representation of the tokens. */
@@ -211,6 +216,8 @@ static struct {
211 { "denyusers", sDenyUsers }, 216 { "denyusers", sDenyUsers },
212 { "allowgroups", sAllowGroups }, 217 { "allowgroups", sAllowGroups },
213 { "denygroups", sDenyGroups }, 218 { "denygroups", sDenyGroups },
219 { "ciphers", sCiphers },
220 { "protocol", sProtocol },
214 { NULL, 0 } 221 { NULL, 0 }
215}; 222};
216 223
@@ -494,7 +501,7 @@ parse_flag:
494 value = log_facility_number(cp); 501 value = log_facility_number(cp);
495 if (value == (SyslogFacility) - 1) 502 if (value == (SyslogFacility) - 1)
496 fatal("%.200s line %d: unsupported log facility '%s'\n", 503 fatal("%.200s line %d: unsupported log facility '%s'\n",
497 filename, linenum, cp ? cp : "<NONE>"); 504 filename, linenum, cp ? cp : "<NONE>");
498 if (*intptr == -1) 505 if (*intptr == -1)
499 *intptr = (SyslogFacility) value; 506 *intptr = (SyslogFacility) value;
500 break; 507 break;
@@ -505,55 +512,67 @@ parse_flag:
505 value = log_level_number(cp); 512 value = log_level_number(cp);
506 if (value == (LogLevel) - 1) 513 if (value == (LogLevel) - 1)
507 fatal("%.200s line %d: unsupported log level '%s'\n", 514 fatal("%.200s line %d: unsupported log level '%s'\n",
508 filename, linenum, cp ? cp : "<NONE>"); 515 filename, linenum, cp ? cp : "<NONE>");
509 if (*intptr == -1) 516 if (*intptr == -1)
510 *intptr = (LogLevel) value; 517 *intptr = (LogLevel) value;
511 break; 518 break;
512 519
513 case sAllowUsers: 520 case sAllowUsers:
514 while ((cp = strtok(NULL, WHITESPACE))) { 521 while ((cp = strtok(NULL, WHITESPACE))) {
515 if (options->num_allow_users >= MAX_ALLOW_USERS) { 522 if (options->num_allow_users >= MAX_ALLOW_USERS)
516 fprintf(stderr, "%s line %d: too many allow users.\n", 523 fatal("%s line %d: too many allow users.\n",
517 filename, linenum); 524 filename, linenum);
518 exit(1);
519 }
520 options->allow_users[options->num_allow_users++] = xstrdup(cp); 525 options->allow_users[options->num_allow_users++] = xstrdup(cp);
521 } 526 }
522 break; 527 break;
523 528
524 case sDenyUsers: 529 case sDenyUsers:
525 while ((cp = strtok(NULL, WHITESPACE))) { 530 while ((cp = strtok(NULL, WHITESPACE))) {
526 if (options->num_deny_users >= MAX_DENY_USERS) { 531 if (options->num_deny_users >= MAX_DENY_USERS)
527 fprintf(stderr, "%s line %d: too many deny users.\n", 532 fatal( "%s line %d: too many deny users.\n",
528 filename, linenum); 533 filename, linenum);
529 exit(1);
530 }
531 options->deny_users[options->num_deny_users++] = xstrdup(cp); 534 options->deny_users[options->num_deny_users++] = xstrdup(cp);
532 } 535 }
533 break; 536 break;
534 537
535 case sAllowGroups: 538 case sAllowGroups:
536 while ((cp = strtok(NULL, WHITESPACE))) { 539 while ((cp = strtok(NULL, WHITESPACE))) {
537 if (options->num_allow_groups >= MAX_ALLOW_GROUPS) { 540 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
538 fprintf(stderr, "%s line %d: too many allow groups.\n", 541 fatal("%s line %d: too many allow groups.\n",
539 filename, linenum); 542 filename, linenum);
540 exit(1);
541 }
542 options->allow_groups[options->num_allow_groups++] = xstrdup(cp); 543 options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
543 } 544 }
544 break; 545 break;
545 546
546 case sDenyGroups: 547 case sDenyGroups:
547 while ((cp = strtok(NULL, WHITESPACE))) { 548 while ((cp = strtok(NULL, WHITESPACE))) {
548 if (options->num_deny_groups >= MAX_DENY_GROUPS) { 549 if (options->num_deny_groups >= MAX_DENY_GROUPS)
549 fprintf(stderr, "%s line %d: too many deny groups.\n", 550 fatal("%s line %d: too many deny groups.\n",
550 filename, linenum); 551 filename, linenum);
551 exit(1);
552 }
553 options->deny_groups[options->num_deny_groups++] = xstrdup(cp); 552 options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
554 } 553 }
555 break; 554 break;
556 555
556 case sCiphers:
557 cp = strtok(NULL, WHITESPACE);
558 if (!ciphers_valid(cp))
559 fatal("%s line %d: Bad cipher spec '%s'.",
560 filename, linenum, cp ? cp : "<NONE>");
561 if (options->ciphers == NULL)
562 options->ciphers = xstrdup(cp);
563 break;
564
565 case sProtocol:
566 intptr = &options->protocol;
567 cp = strtok(NULL, WHITESPACE);
568 value = proto_spec(cp);
569 if (value == SSH_PROTO_UNKNOWN)
570 fatal("%s line %d: Bad protocol spec '%s'.",
571 filename, linenum, cp ? cp : "<NONE>");
572 if (*intptr == SSH_PROTO_UNKNOWN)
573 *intptr = value;
574 break;
575
557 default: 576 default:
558 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n", 577 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
559 filename, linenum, cp, opcode); 578 filename, linenum, cp, opcode);
diff --git a/servconf.h b/servconf.h
index 5ce3f1594..2a3686245 100644
--- a/servconf.h
+++ b/servconf.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: servconf.h,v 1.7 2000/04/12 08:45:07 damien Exp $"); */ 16/* RCSID("$Id: servconf.h,v 1.8 2000/04/12 10:17:40 damien Exp $"); */
17 17
18#ifndef SERVCONF_H 18#ifndef SERVCONF_H
19#define SERVCONF_H 19#define SERVCONF_H
@@ -48,6 +48,8 @@ typedef struct {
48 * searching at */ 48 * searching at */
49 int strict_modes; /* If true, require string home dir modes. */ 49 int strict_modes; /* If true, require string home dir modes. */
50 int keepalives; /* If true, set SO_KEEPALIVE. */ 50 int keepalives; /* If true, set SO_KEEPALIVE. */
51 char *ciphers; /* Ciphers in order of preference. */
52 int protocol; /* Protocol in order of preference. */
51 SyslogFacility log_facility; /* Facility for system logging. */ 53 SyslogFacility log_facility; /* Facility for system logging. */
52 LogLevel log_level; /* Level for system logging. */ 54 LogLevel log_level; /* Level for system logging. */
53 int rhosts_authentication; /* If true, permit rhosts 55 int rhosts_authentication; /* If true, permit rhosts
diff --git a/ssh.c b/ssh.c
index cce0e6b7f..f23694247 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.24 2000/04/06 02:32:40 damien Exp $"); 14RCSID("$Id: ssh.c,v 1.25 2000/04/12 10:17:40 damien Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "ssh.h" 17#include "ssh.h"
@@ -42,6 +42,7 @@ int IPv4or6 = AF_UNSPEC;
42/* Flag indicating whether debug mode is on. This can be set on the command line. */ 42/* Flag indicating whether debug mode is on. This can be set on the command line. */
43int debug_flag = 0; 43int debug_flag = 0;
44 44
45/* Flag indicating whether a tty should be allocated */
45int tty_flag = 0; 46int tty_flag = 0;
46 47
47/* don't exec a shell */ 48/* don't exec a shell */
@@ -336,8 +337,10 @@ main(int ac, char **av)
336 337
337 case 'v': 338 case 'v':
338 case 'V': 339 case 'V':
339 fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n", 340 fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
340 SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR); 341 SSH_VERSION,
342 PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
343 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
341 fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay()); 344 fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
342 if (opt == 'V') 345 if (opt == 'V')
343 exit(0); 346 exit(0);
diff --git a/ssh.h b/ssh.h
index 7c5bf9c52..ea2dc032c 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: ssh.h,v 1.30 2000/04/12 08:45:07 damien Exp $"); */ 16/* RCSID("$Id: ssh.h,v 1.31 2000/04/12 10:17:41 damien Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -54,14 +54,16 @@
54/* 54/*
55 * Major protocol version. Different version indicates major incompatiblity 55 * Major protocol version. Different version indicates major incompatiblity
56 * that prevents communication. 56 * that prevents communication.
57 */ 57 *
58#define PROTOCOL_MAJOR 1
59
60/*
61 * Minor protocol version. Different version indicates minor incompatibility 58 * Minor protocol version. Different version indicates minor incompatibility
62 * that does not prevent interoperation. 59 * that does not prevent interoperation.
63 */ 60 */
64#define PROTOCOL_MINOR 5 61#define PROTOCOL_MAJOR_1 1
62#define PROTOCOL_MINOR_1 5
63
64/* We support both SSH1 and SSH2 */
65#define PROTOCOL_MAJOR_2 2
66#define PROTOCOL_MINOR_2 0
65 67
66/* 68/*
67 * Name for the service. The port named by this service overrides the 69 * Name for the service. The port named by this service overrides the
diff --git a/sshconnect.c b/sshconnect.c
index 2f9496090..167b8e63a 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: sshconnect.c,v 1.61 2000/04/04 21:37:27 markus Exp $"); 13RCSID("$OpenBSD: sshconnect.c,v 1.65 2000/04/12 07:56:16 markus Exp $");
14 14
15#ifdef HAVE_OPENSSL 15#ifdef HAVE_OPENSSL
16#include <openssl/bn.h> 16#include <openssl/bn.h>
@@ -993,7 +993,7 @@ void
993ssh_exchange_identification() 993ssh_exchange_identification()
994{ 994{
995 char buf[256], remote_version[256]; /* must be same size! */ 995 char buf[256], remote_version[256]; /* must be same size! */
996 int remote_major, remote_minor, i; 996 int remote_major, remote_minor, i, mismatch;
997 int connection_in = packet_get_connection_in(); 997 int connection_in = packet_get_connection_in();
998 int connection_out = packet_get_connection_out(); 998 int connection_out = packet_get_connection_out();
999 999
@@ -1027,39 +1027,51 @@ ssh_exchange_identification()
1027 debug("Remote protocol version %d.%d, remote software version %.100s", 1027 debug("Remote protocol version %d.%d, remote software version %.100s",
1028 remote_major, remote_minor, remote_version); 1028 remote_major, remote_minor, remote_version);
1029 1029
1030/*** XXX option for disabling 2.0 or 1.5 */
1031 compat_datafellows(remote_version); 1030 compat_datafellows(remote_version);
1032 1031 mismatch = 0;
1033 /* Check if the remote protocol version is too old. */ 1032
1034 if (remote_major == 1 && remote_minor < 3) 1033 switch(remote_major) {
1035 fatal("Remote machine has too old SSH software version."); 1034 case 1:
1036 1035 if (remote_minor == 99 &&
1037 /* We speak 1.3, too. */ 1036 (options.protocol & SSH_PROTO_2) &&
1038 if (remote_major == 1 && remote_minor == 3) { 1037 !(options.protocol & SSH_PROTO_1_PREFERRED)) {
1039 enable_compat13(); 1038 enable_compat20();
1040 if (options.forward_agent) { 1039 break;
1041 log("Agent forwarding disabled for protocol 1.3");
1042 options.forward_agent = 0;
1043 } 1040 }
1041 if (!(options.protocol & SSH_PROTO_1)) {
1042 mismatch = 1;
1043 break;
1044 }
1045 if (remote_minor < 3) {
1046 fatal("Remote machine has too old SSH software version.");
1047 } else if (remote_minor == 3) {
1048 /* We speak 1.3, too. */
1049 enable_compat13();
1050 if (options.forward_agent) {
1051 log("Agent forwarding disabled for protocol 1.3");
1052 options.forward_agent = 0;
1053 }
1054 }
1055 break;
1056 case 2:
1057 if (options.protocol & SSH_PROTO_2) {
1058 enable_compat20();
1059 break;
1060 }
1061 /* FALLTHROUGH */
1062 default:
1063 mismatch = 1;
1064 break;
1044 } 1065 }
1045 if ((remote_major == 2 && remote_minor == 0) || 1066 if (mismatch)
1046 (remote_major == 1 && remote_minor == 99)) {
1047 enable_compat20();
1048 }
1049#if 0
1050 /*
1051 * Removed for now, to permit compatibility with latter versions. The
1052 * server will reject our version and disconnect if it doesn't
1053 * support it.
1054 */
1055 if (remote_major != PROTOCOL_MAJOR)
1056 fatal("Protocol major versions differ: %d vs. %d", 1067 fatal("Protocol major versions differ: %d vs. %d",
1057 PROTOCOL_MAJOR, remote_major); 1068 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
1058#endif 1069 remote_major);
1070
1059 /* Send our own protocol version identification. */ 1071 /* Send our own protocol version identification. */
1060 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 1072 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
1061 compat20 ? 2 : PROTOCOL_MAJOR, 1073 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
1062 compat20 ? 0 : PROTOCOL_MINOR, 1074 compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
1063 SSH_VERSION); 1075 SSH_VERSION);
1064 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) 1076 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
1065 fatal("write: %.100s", strerror(errno)); 1077 fatal("write: %.100s", strerror(errno));
@@ -1350,11 +1362,15 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
1350/* KEXINIT */ 1362/* KEXINIT */
1351 1363
1352 debug("Sending KEX init."); 1364 debug("Sending KEX init.");
1353 if (options.cipher == SSH_CIPHER_ARCFOUR || 1365 if (options.ciphers != NULL) {
1366 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1367 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
1368 } else if (
1369 options.cipher == SSH_CIPHER_ARCFOUR ||
1354 options.cipher == SSH_CIPHER_3DES_CBC || 1370 options.cipher == SSH_CIPHER_3DES_CBC ||
1355 options.cipher == SSH_CIPHER_CAST128_CBC || 1371 options.cipher == SSH_CIPHER_CAST128_CBC ||
1356 options.cipher == SSH_CIPHER_BLOWFISH_CBC) { 1372 options.cipher == SSH_CIPHER_BLOWFISH_CBC) {
1357 myproposal[PROPOSAL_ENC_ALGS_CTOS] = cipher_name(options.cipher); 1373 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1358 myproposal[PROPOSAL_ENC_ALGS_STOC] = cipher_name(options.cipher); 1374 myproposal[PROPOSAL_ENC_ALGS_STOC] = cipher_name(options.cipher);
1359 } 1375 }
1360 if (options.compression) { 1376 if (options.compression) {
@@ -1404,7 +1420,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
1404 debug("Sending SSH2_MSG_KEXDH_INIT."); 1420 debug("Sending SSH2_MSG_KEXDH_INIT.");
1405 1421
1406 /* generate and send 'e', client DH public key */ 1422 /* generate and send 'e', client DH public key */
1407 dh = new_dh_group1(); 1423 dh = dh_new_group1();
1408 packet_start(SSH2_MSG_KEXDH_INIT); 1424 packet_start(SSH2_MSG_KEXDH_INIT);
1409 packet_put_bignum2(dh->pub_key); 1425 packet_put_bignum2(dh->pub_key);
1410 packet_send(); 1426 packet_send();
@@ -1451,6 +1467,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
1451 /* signed H */ 1467 /* signed H */
1452 signature = packet_get_string(&slen); 1468 signature = packet_get_string(&slen);
1453 1469
1470 if (!dh_pub_is_valid(dh, dh_server_pub))
1471 packet_disconnect("bad server public DH value");
1472
1454 klen = DH_size(dh); 1473 klen = DH_size(dh);
1455 kbuf = xmalloc(klen); 1474 kbuf = xmalloc(klen);
1456 kout = DH_compute_key(kbuf, dh_server_pub, dh); 1475 kout = DH_compute_key(kbuf, dh_server_pub, dh);
@@ -1507,12 +1526,13 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
1507 packet_write_wait(); 1526 packet_write_wait();
1508 debug("done: send SSH2_MSG_NEWKEYS."); 1527 debug("done: send SSH2_MSG_NEWKEYS.");
1509 1528
1529#ifdef DEBUG_KEXDH
1510 /* send 1st encrypted/maced/compressed message */ 1530 /* send 1st encrypted/maced/compressed message */
1511 packet_start(SSH2_MSG_IGNORE); 1531 packet_start(SSH2_MSG_IGNORE);
1512 packet_put_cstring("markus"); 1532 packet_put_cstring("markus");
1513 packet_send(); 1533 packet_send();
1514 packet_write_wait(); 1534 packet_write_wait();
1515 1535#endif
1516 debug("done: KEX2."); 1536 debug("done: KEX2.");
1517} 1537}
1518/* 1538/*
@@ -1527,6 +1547,7 @@ ssh_userauth2(int host_key_valid, RSA *own_host_key,
1527 unsigned int dlen; 1547 unsigned int dlen;
1528 int partial; 1548 int partial;
1529 struct passwd *pw; 1549 struct passwd *pw;
1550 char prompt[80];
1530 char *server_user, *local_user; 1551 char *server_user, *local_user;
1531 char *auths; 1552 char *auths;
1532 char *password; 1553 char *password;
@@ -1578,7 +1599,9 @@ ssh_userauth2(int host_key_valid, RSA *own_host_key,
1578 fatal("passwd auth not supported: %s", auths); 1599 fatal("passwd auth not supported: %s", auths);
1579 xfree(auths); 1600 xfree(auths);
1580 /* try passwd */ 1601 /* try passwd */
1581 password = read_passphrase("password: ", 0); 1602 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1603 server_user, host);
1604 password = read_passphrase(prompt, 0);
1582 packet_start(SSH2_MSG_USERAUTH_REQUEST); 1605 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1583 packet_put_cstring(server_user); 1606 packet_put_cstring(server_user);
1584 packet_put_cstring(service); 1607 packet_put_cstring(service);
diff --git a/sshd.c b/sshd.c
index 44782e397..266146bf0 100644
--- a/sshd.c
+++ b/sshd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: sshd.c,v 1.99 2000/04/07 09:17:39 markus Exp $"); 17RCSID("$OpenBSD: sshd.c,v 1.103 2000/04/12 08:11:36 markus Exp $");
18 18
19#include "xmalloc.h" 19#include "xmalloc.h"
20#include "rsa.h" 20#include "rsa.h"
@@ -77,9 +77,6 @@ int IPv4or6 = AF_INET;
77int IPv4or6 = AF_UNSPEC; 77int IPv4or6 = AF_UNSPEC;
78#endif 78#endif
79 79
80/* Flag indicating whether SSH2 is enabled */
81int allow_ssh2 = 0;
82
83/* 80/*
84 * Debug mode flag. This can be set on the command line. If debug 81 * Debug mode flag. This can be set on the command line. If debug
85 * mode is enabled, extra debugging output will be sent to the system 82 * mode is enabled, extra debugging output will be sent to the system
@@ -284,16 +281,25 @@ chop(char *s)
284void 281void
285sshd_exchange_identification(int sock_in, int sock_out) 282sshd_exchange_identification(int sock_in, int sock_out)
286{ 283{
287 int i; 284 int i, mismatch;
288 int remote_major, remote_minor; 285 int remote_major, remote_minor;
286 int major, minor;
289 char *s; 287 char *s;
290 char buf[256]; /* Must not be larger than remote_version. */ 288 char buf[256]; /* Must not be larger than remote_version. */
291 char remote_version[256]; /* Must be at least as big as buf. */ 289 char remote_version[256]; /* Must be at least as big as buf. */
292 290
293 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 291 if ((options.protocol & SSH_PROTO_1) &&
294 allow_ssh2 ? 1 : PROTOCOL_MAJOR, 292 (options.protocol & SSH_PROTO_2)) {
295 allow_ssh2 ? 99 : PROTOCOL_MINOR, 293 major = PROTOCOL_MAJOR_1;
296 SSH_VERSION); 294 minor = 99;
295 } else if (options.protocol & SSH_PROTO_2) {
296 major = PROTOCOL_MAJOR_2;
297 minor = PROTOCOL_MINOR_2;
298 } else {
299 major = PROTOCOL_MAJOR_1;
300 minor = PROTOCOL_MINOR_1;
301 }
302 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
297 server_version_string = xstrdup(buf); 303 server_version_string = xstrdup(buf);
298 304
299 if (client_version_string == NULL) { 305 if (client_version_string == NULL) {
@@ -314,7 +320,6 @@ sshd_exchange_identification(int sock_in, int sock_out)
314 buf[i] = '\n'; 320 buf[i] = '\n';
315 buf[i + 1] = 0; 321 buf[i + 1] = 0;
316 continue; 322 continue;
317 //break;
318 } 323 }
319 if (buf[i] == '\n') { 324 if (buf[i] == '\n') {
320 /* buf[i] == '\n' */ 325 /* buf[i] == '\n' */
@@ -345,8 +350,13 @@ sshd_exchange_identification(int sock_in, int sock_out)
345 350
346 compat_datafellows(remote_version); 351 compat_datafellows(remote_version);
347 352
353 mismatch = 0;
348 switch(remote_major) { 354 switch(remote_major) {
349 case 1: 355 case 1:
356 if (!(options.protocol & SSH_PROTO_1)) {
357 mismatch = 1;
358 break;
359 }
350 if (remote_minor < 3) { 360 if (remote_minor < 3) {
351 packet_disconnect("Your ssh version is too old and" 361 packet_disconnect("Your ssh version is too old and"
352 "is no longer supported. Please install a newer version."); 362 "is no longer supported. Please install a newer version.");
@@ -354,27 +364,37 @@ sshd_exchange_identification(int sock_in, int sock_out)
354 /* note that this disables agent-forwarding */ 364 /* note that this disables agent-forwarding */
355 enable_compat13(); 365 enable_compat13();
356 } 366 }
357 if (remote_minor != 99) 367 if (remote_minor == 99) {
358 break; 368 if (options.protocol & SSH_PROTO_2)
359 /* FALLTHROUGH */ 369 enable_compat20();
370 else
371 mismatch = 1;
372 }
373 break;
360 case 2: 374 case 2:
361 if (allow_ssh2) { 375 if (options.protocol & SSH_PROTO_2) {
362 enable_compat20(); 376 enable_compat20();
363 break; 377 break;
364 } 378 }
365 /* FALLTHROUGH */ 379 /* FALLTHROUGH */
366 default: 380 default:
381 mismatch = 1;
382 break;
383 }
384 chop(server_version_string);
385 chop(client_version_string);
386 debug("Local version string %.200s", server_version_string);
387
388 if (mismatch) {
367 s = "Protocol major versions differ.\n"; 389 s = "Protocol major versions differ.\n";
368 (void) atomicio(write, sock_out, s, strlen(s)); 390 (void) atomicio(write, sock_out, s, strlen(s));
369 close(sock_in); 391 close(sock_in);
370 close(sock_out); 392 close(sock_out);
371 log("Protocol major versions differ for %s: %d vs. %d", 393 log("Protocol major versions differ for %s: %.200s vs. %.200s",
372 get_remote_ipaddr(), PROTOCOL_MAJOR, remote_major); 394 get_remote_ipaddr(),
395 server_version_string, client_version_string);
373 fatal_cleanup(); 396 fatal_cleanup();
374 break;
375 } 397 }
376 chop(server_version_string);
377 chop(client_version_string);
378} 398}
379 399
380/* 400/*
@@ -410,11 +430,8 @@ main(int ac, char **av)
410 initialize_server_options(&options); 430 initialize_server_options(&options);
411 431
412 /* Parse command-line arguments. */ 432 /* Parse command-line arguments. */
413 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ246")) != EOF) { 433 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) {
414 switch (opt) { 434 switch (opt) {
415 case '2':
416 allow_ssh2 = 1;
417 break;
418 case '4': 435 case '4':
419 IPv4or6 = AF_INET; 436 IPv4or6 = AF_INET;
420 break; 437 break;
@@ -593,6 +610,7 @@ main(int ac, char **av)
593 public_key = RSA_new(); 610 public_key = RSA_new();
594 sensitive_data.private_key = RSA_new(); 611 sensitive_data.private_key = RSA_new();
595 612
613 /* XXX check options.protocol */
596 log("Generating %d bit RSA key.", options.server_key_bits); 614 log("Generating %d bit RSA key.", options.server_key_bits);
597 rsa_generate_key(sensitive_data.private_key, public_key, 615 rsa_generate_key(sensitive_data.private_key, public_key,
598 options.server_key_bits); 616 options.server_key_bits);
@@ -1126,6 +1144,11 @@ do_ssh2_kex()
1126 1144
1127/* KEXINIT */ 1145/* KEXINIT */
1128 1146
1147 if (options.ciphers != NULL) {
1148 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1149 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
1150 }
1151
1129 debug("Sending KEX init."); 1152 debug("Sending KEX init.");
1130 1153
1131 for (i = 0; i < PROPOSAL_MAX; i++) 1154 for (i = 0; i < PROPOSAL_MAX; i++)
@@ -1185,7 +1208,7 @@ do_ssh2_kex()
1185#endif 1208#endif
1186 1209
1187 /* generate DH key */ 1210 /* generate DH key */
1188 dh = new_dh_group1(); /* XXX depends on 'kex' */ 1211 dh = dh_new_group1(); /* XXX depends on 'kex' */
1189 1212
1190#ifdef DEBUG_KEXDH 1213#ifdef DEBUG_KEXDH
1191 fprintf(stderr, "\np= "); 1214 fprintf(stderr, "\np= ");
@@ -1196,6 +1219,8 @@ do_ssh2_kex()
1196 bignum_print(dh->pub_key); 1219 bignum_print(dh->pub_key);
1197 fprintf(stderr, "\n"); 1220 fprintf(stderr, "\n");
1198#endif 1221#endif
1222 if (!dh_pub_is_valid(dh, dh_client_pub))
1223 packet_disconnect("bad client public DH value");
1199 1224
1200 klen = DH_size(dh); 1225 klen = DH_size(dh);
1201 kbuf = xmalloc(klen); 1226 kbuf = xmalloc(klen);
@@ -1267,11 +1292,12 @@ do_ssh2_kex()
1267 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); 1292 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
1268 debug("GOT SSH2_MSG_NEWKEYS."); 1293 debug("GOT SSH2_MSG_NEWKEYS.");
1269 1294
1295#ifdef DEBUG_KEXDH
1270 /* send 1st encrypted/maced/compressed message */ 1296 /* send 1st encrypted/maced/compressed message */
1271 packet_start(SSH2_MSG_IGNORE); 1297 packet_start(SSH2_MSG_IGNORE);
1272 packet_put_cstring("markus"); 1298 packet_put_cstring("markus");
1273 packet_send(); 1299 packet_send();
1274 packet_write_wait(); 1300 packet_write_wait();
1275 1301#endif
1276 debug("done: KEX2."); 1302 debug("done: KEX2.");
1277} 1303}