summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/kex.c b/kex.c
index bdbf3882c..2c1cacfec 100644
--- a/kex.c
+++ b/kex.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); 26RCSID("$OpenBSD: kex.c,v 1.54 2003/02/16 17:09:57 markus Exp $");
27 27
28#include <openssl/crypto.h> 28#include <openssl/crypto.h>
29 29
@@ -44,11 +44,6 @@ RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $");
44 44
45#define KEX_COOKIE_LEN 16 45#define KEX_COOKIE_LEN 16
46 46
47/* Use privilege separation for sshd */
48int use_privsep;
49struct monitor *pmonitor;
50
51
52/* prototype */ 47/* prototype */
53static void kex_kexinit_finish(Kex *); 48static void kex_kexinit_finish(Kex *);
54static void kex_choose_conf(Kex *); 49static void kex_choose_conf(Kex *);
@@ -74,7 +69,7 @@ kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
74 69
75/* parse buffer and return algorithm proposal */ 70/* parse buffer and return algorithm proposal */
76static char ** 71static char **
77kex_buf2prop(Buffer *raw) 72kex_buf2prop(Buffer *raw, int *first_kex_follows)
78{ 73{
79 Buffer b; 74 Buffer b;
80 int i; 75 int i;
@@ -94,6 +89,8 @@ kex_buf2prop(Buffer *raw)
94 } 89 }
95 /* first kex follows / reserved */ 90 /* first kex follows / reserved */
96 i = buffer_get_char(&b); 91 i = buffer_get_char(&b);
92 if (first_kex_follows != NULL)
93 *first_kex_follows = i;
97 debug2("kex_parse_kexinit: first_kex_follows %d ", i); 94 debug2("kex_parse_kexinit: first_kex_follows %d ", i);
98 i = buffer_get_int(&b); 95 i = buffer_get_int(&b);
99 debug2("kex_parse_kexinit: reserved %d ", i); 96 debug2("kex_parse_kexinit: reserved %d ", i);
@@ -135,7 +132,7 @@ kex_finish(Kex *kex)
135 /* packet_write_wait(); */ 132 /* packet_write_wait(); */
136 debug("SSH2_MSG_NEWKEYS sent"); 133 debug("SSH2_MSG_NEWKEYS sent");
137 134
138 debug("waiting for SSH2_MSG_NEWKEYS"); 135 debug("expecting SSH2_MSG_NEWKEYS");
139 packet_read_expect(SSH2_MSG_NEWKEYS); 136 packet_read_expect(SSH2_MSG_NEWKEYS);
140 packet_check_eom(); 137 packet_check_eom();
141 debug("SSH2_MSG_NEWKEYS received"); 138 debug("SSH2_MSG_NEWKEYS received");
@@ -235,14 +232,10 @@ kex_kexinit_finish(Kex *kex)
235 232
236 kex_choose_conf(kex); 233 kex_choose_conf(kex);
237 234
238 switch (kex->kex_type) { 235 if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
239 case DH_GRP1_SHA1: 236 kex->kex[kex->kex_type] != NULL) {
240 kexdh(kex); 237 (kex->kex[kex->kex_type])(kex);
241 break; 238 } else {
242 case DH_GEX_SHA1:
243 kexgex(kex);
244 break;
245 default:
246 fatal("Unsupported key exchange %d", kex->kex_type); 239 fatal("Unsupported key exchange %d", kex->kex_type);
247 } 240 }
248} 241}
@@ -299,9 +292,9 @@ choose_kex(Kex *k, char *client, char *server)
299 if (k->name == NULL) 292 if (k->name == NULL)
300 fatal("no kex alg"); 293 fatal("no kex alg");
301 if (strcmp(k->name, KEX_DH1) == 0) { 294 if (strcmp(k->name, KEX_DH1) == 0) {
302 k->kex_type = DH_GRP1_SHA1; 295 k->kex_type = KEX_DH_GRP1_SHA1;
303 } else if (strcmp(k->name, KEX_DHGEX) == 0) { 296 } else if (strcmp(k->name, KEX_DHGEX) == 0) {
304 k->kex_type = DH_GEX_SHA1; 297 k->kex_type = KEX_DH_GEX_SHA1;
305 } else 298 } else
306 fatal("bad kex alg %s", k->name); 299 fatal("bad kex alg %s", k->name);
307} 300}
@@ -317,6 +310,30 @@ choose_hostkeyalg(Kex *k, char *client, char *server)
317 xfree(hostkeyalg); 310 xfree(hostkeyalg);
318} 311}
319 312
313static int
314proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
315{
316 static int check[] = {
317 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
318 };
319 int *idx;
320 char *p;
321
322 for (idx = &check[0]; *idx != -1; idx++) {
323 if ((p = strchr(my[*idx], ',')) != NULL)
324 *p = '\0';
325 if ((p = strchr(peer[*idx], ',')) != NULL)
326 *p = '\0';
327 if (strcmp(my[*idx], peer[*idx]) != 0) {
328 debug2("proposal mismatch: my %s peer %s",
329 my[*idx], peer[*idx]);
330 return (0);
331 }
332 }
333 debug2("proposals match");
334 return (1);
335}
336
320static void 337static void
321kex_choose_conf(Kex *kex) 338kex_choose_conf(Kex *kex)
322{ 339{
@@ -327,9 +344,10 @@ kex_choose_conf(Kex *kex)
327 int mode; 344 int mode;
328 int ctos; /* direction: if true client-to-server */ 345 int ctos; /* direction: if true client-to-server */
329 int need; 346 int need;
347 int first_kex_follows, type;
330 348
331 my = kex_buf2prop(&kex->my); 349 my = kex_buf2prop(&kex->my, NULL);
332 peer = kex_buf2prop(&kex->peer); 350 peer = kex_buf2prop(&kex->peer, &first_kex_follows);
333 351
334 if (kex->server) { 352 if (kex->server) {
335 cprop=peer; 353 cprop=peer;
@@ -373,6 +391,12 @@ kex_choose_conf(Kex *kex)
373 /* XXX need runden? */ 391 /* XXX need runden? */
374 kex->we_need = need; 392 kex->we_need = need;
375 393
394 /* ignore the next message if the proposals do not match */
395 if (first_kex_follows && !proposals_match(my, peer)) {
396 type = packet_read();
397 debug2("skipping next packet (type %u)", type);
398 }
399
376 kex_prop_free(my); 400 kex_prop_free(my);
377 kex_prop_free(peer); 401 kex_prop_free(peer);
378} 402}
@@ -433,7 +457,7 @@ kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret)
433 for (i = 0; i < NKEYS; i++) 457 for (i = 0; i < NKEYS; i++)
434 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); 458 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret);
435 459
436 debug("kex_derive_keys"); 460 debug2("kex_derive_keys");
437 for (mode = 0; mode < MODE_MAX; mode++) { 461 for (mode = 0; mode < MODE_MAX; mode++) {
438 current_keys[mode] = kex->newkeys[mode]; 462 current_keys[mode] = kex->newkeys[mode];
439 kex->newkeys[mode] = NULL; 463 kex->newkeys[mode] = NULL;