Mercurial > dropbear
comparison common-kex.c @ 33:f789045062e6
Progressing client support
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 27 Jul 2004 16:30:46 +0000 |
parents | 0969767bca0d |
children | e2a1eaa19f22 |
comparison
equal
deleted
inserted
replaced
32:8fd0cdbb5b1b | 33:f789045062e6 |
---|---|
3 * SSH client implementation | 3 * SSH client implementation |
4 * | 4 * |
5 * This code is copied from the larger file "kex.c" | 5 * This code is copied from the larger file "kex.c" |
6 * some functions are verbatim, others are generalized --mihnea | 6 * some functions are verbatim, others are generalized --mihnea |
7 * | 7 * |
8 * Copyright (c) 2002,2003 Matt Johnston | 8 * Copyright (c) 2002-2004 Matt Johnston |
9 * Portions Copyright (c) 2004 by Mihnea Stoenescu | 9 * Portions Copyright (c) 2004 by Mihnea Stoenescu |
10 * All rights reserved. | 10 * All rights reserved. |
11 * | 11 * |
12 * Permission is hereby granted, free of charge, to any person obtaining a copy | 12 * Permission is hereby granted, free of charge, to any person obtaining a copy |
13 * of this software and associated documentation files (the "Software"), to deal | 13 * of this software and associated documentation files (the "Software"), to deal |
52 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, | 52 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, |
53 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | 53 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
54 | 54 |
55 const int DH_G_VAL = 2; | 55 const int DH_G_VAL = 2; |
56 | 56 |
57 static void kexinitialise(); | |
57 static void gen_new_keys(); | 58 static void gen_new_keys(); |
58 #ifndef DISABLE_ZLIB | 59 #ifndef DISABLE_ZLIB |
59 static void gen_new_zstreams(); | 60 static void gen_new_zstreams(); |
60 #endif | 61 #endif |
62 static void read_kex_algos(); | |
61 /* helper function for gen_new_keys */ | 63 /* helper function for gen_new_keys */ |
62 static void hashkeys(unsigned char *out, int outlen, | 64 static void hashkeys(unsigned char *out, int outlen, |
63 const hash_state * hs, unsigned const char X); | 65 const hash_state * hs, unsigned const char X); |
64 | 66 |
65 | 67 |
143 TRACE(("while RECVNEWKEYS=1")); | 145 TRACE(("while RECVNEWKEYS=1")); |
144 gen_new_keys(); | 146 gen_new_keys(); |
145 kexinitialise(); /* we've finished with this kex */ | 147 kexinitialise(); /* we've finished with this kex */ |
146 TRACE((" -> DATAALLOWED=1")); | 148 TRACE((" -> DATAALLOWED=1")); |
147 ses.dataallowed = 1; /* we can send other packets again now */ | 149 ses.dataallowed = 1; /* we can send other packets again now */ |
150 ses.kexstate.donefirstkex = 1; | |
148 } else { | 151 } else { |
149 ses.kexstate.sentnewkeys = 1; | 152 ses.kexstate.sentnewkeys = 1; |
150 TRACE(("SENTNEWKEYS=1")); | 153 TRACE(("SENTNEWKEYS=1")); |
151 } | 154 } |
152 | 155 |
166 TRACE(("while SENTNEWKEYS=1")); | 169 TRACE(("while SENTNEWKEYS=1")); |
167 gen_new_keys(); | 170 gen_new_keys(); |
168 kexinitialise(); /* we've finished with this kex */ | 171 kexinitialise(); /* we've finished with this kex */ |
169 TRACE((" -> DATAALLOWED=1")); | 172 TRACE((" -> DATAALLOWED=1")); |
170 ses.dataallowed = 1; /* we can send other packets again now */ | 173 ses.dataallowed = 1; /* we can send other packets again now */ |
174 ses.kexstate.donefirstkex = 1; | |
171 } else { | 175 } else { |
172 TRACE(("RECVNEWKEYS=1")); | 176 TRACE(("RECVNEWKEYS=1")); |
173 ses.kexstate.recvnewkeys = 1; | 177 ses.kexstate.recvnewkeys = 1; |
174 } | 178 } |
175 | 179 |
176 TRACE(("leave recv_msg_newkeys")); | 180 TRACE(("leave recv_msg_newkeys")); |
177 } | 181 } |
178 | 182 |
179 | 183 |
180 /* Duplicated verbatim from kex.c --mihnea */ | 184 /* Set up the kex for the first time */ |
181 void kexinitialise() { | 185 void kexfirstinitialise() { |
186 | |
187 ses.kexstate.donefirstkex = 0; | |
188 kexinitialise(); | |
189 } | |
190 | |
191 /* Reset the kex state, ready for a new negotiation */ | |
192 static void kexinitialise() { | |
182 | 193 |
183 struct timeval tv; | 194 struct timeval tv; |
184 | 195 |
185 TRACE(("kexinitialise()")); | 196 TRACE(("kexinitialise()")); |
186 | 197 |
402 | 413 |
403 if (IS_DROPBEAR_CLIENT) { | 414 if (IS_DROPBEAR_CLIENT) { |
404 #ifdef DROPBEAR_CLIENT | 415 #ifdef DROPBEAR_CLIENT |
405 | 416 |
406 /* read the peer's choice of algos */ | 417 /* read the peer's choice of algos */ |
407 read_kex_algos(cli_buf_match_algo); | 418 read_kex_algos(); |
408 | 419 |
409 /* V_C, the client's version string (CR and NL excluded) */ | 420 /* V_C, the client's version string (CR and NL excluded) */ |
410 buf_putstring(ses.kexhashbuf, | 421 buf_putstring(ses.kexhashbuf, |
411 (unsigned char*)LOCAL_IDENT, strlen(LOCAL_IDENT)); | 422 (unsigned char*)LOCAL_IDENT, strlen(LOCAL_IDENT)); |
412 /* V_S, the server's version string (CR and NL excluded) */ | 423 /* V_S, the server's version string (CR and NL excluded) */ |
421 buf_setpos(ses.payload, 0); | 432 buf_setpos(ses.payload, 0); |
422 buf_putstring(ses.kexhashbuf, | 433 buf_putstring(ses.kexhashbuf, |
423 buf_getptr(ses.payload, ses.payload->len), | 434 buf_getptr(ses.payload, ses.payload->len), |
424 ses.payload->len); | 435 ses.payload->len); |
425 | 436 |
426 cli_ses.state = KEXINIT_RCVD; | |
427 #endif | 437 #endif |
428 } else { | 438 } else { |
429 /* SERVER */ | 439 /* SERVER */ |
430 #ifdef DROPBEAR_SERVER | 440 #ifdef DROPBEAR_SERVER |
431 | 441 |
432 /* read the peer's choice of algos */ | 442 /* read the peer's choice of algos */ |
433 read_kex_algos(svr_buf_match_algo); | 443 read_kex_algos(); |
434 /* V_C, the client's version string (CR and NL excluded) */ | 444 /* V_C, the client's version string (CR and NL excluded) */ |
435 buf_putstring(ses.kexhashbuf, | 445 buf_putstring(ses.kexhashbuf, |
436 ses.remoteident, strlen((char*)ses.remoteident)); | 446 ses.remoteident, strlen((char*)ses.remoteident)); |
437 /* V_S, the server's version string (CR and NL excluded) */ | 447 /* V_S, the server's version string (CR and NL excluded) */ |
438 buf_putstring(ses.kexhashbuf, | 448 buf_putstring(ses.kexhashbuf, |
581 } | 591 } |
582 } | 592 } |
583 | 593 |
584 /* read the other side's algo list. buf_match_algo is a callback to match | 594 /* read the other side's algo list. buf_match_algo is a callback to match |
585 * algos for the client or server. */ | 595 * algos for the client or server. */ |
586 void read_kex_algos( | 596 static void read_kex_algos() { |
587 algo_type*(buf_match_algo)(buffer*buf, algo_type localalgos[], | |
588 int *goodguess)) { | |
589 | 597 |
590 algo_type * algo; | 598 algo_type * algo; |
591 char * erralgo = NULL; | 599 char * erralgo = NULL; |
592 | 600 |
593 int goodguess = 0; | 601 int goodguess = 0; |
597 buf_incrpos(ses.payload, 16); /* start after the cookie */ | 605 buf_incrpos(ses.payload, 16); /* start after the cookie */ |
598 | 606 |
599 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); | 607 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); |
600 | 608 |
601 /* kex_algorithms */ | 609 /* kex_algorithms */ |
602 algo = buf_match_algo(ses.payload, sshkex, &goodguess); | 610 algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess); |
603 allgood &= goodguess; | 611 allgood &= goodguess; |
604 if (algo == NULL) { | 612 if (algo == NULL) { |
605 erralgo = "kex"; | 613 erralgo = "kex"; |
606 goto error; | 614 goto error; |
607 } | 615 } |
608 ses.newkeys->algo_kex = algo->val; | 616 ses.newkeys->algo_kex = algo->val; |
609 | 617 |
610 /* server_host_key_algorithms */ | 618 /* server_host_key_algorithms */ |
611 algo = buf_match_algo(ses.payload, sshhostkey, &goodguess); | 619 algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess); |
612 allgood &= goodguess; | 620 allgood &= goodguess; |
613 if (algo == NULL) { | 621 if (algo == NULL) { |
614 erralgo = "hostkey"; | 622 erralgo = "hostkey"; |
615 goto error; | 623 goto error; |
616 } | 624 } |
617 ses.newkeys->algo_hostkey = algo->val; | 625 ses.newkeys->algo_hostkey = algo->val; |
618 | 626 |
619 /* encryption_algorithms_client_to_server */ | 627 /* encryption_algorithms_client_to_server */ |
620 algo = buf_match_algo(ses.payload, sshciphers, &goodguess); | 628 algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); |
621 if (algo == NULL) { | 629 if (algo == NULL) { |
622 erralgo = "enc c->s"; | 630 erralgo = "enc c->s"; |
623 goto error; | 631 goto error; |
624 } | 632 } |
625 ses.newkeys->recv_algo_crypt = (struct dropbear_cipher*)algo->data; | 633 ses.newkeys->recv_algo_crypt = (struct dropbear_cipher*)algo->data; |
626 | 634 |
627 /* encryption_algorithms_server_to_client */ | 635 /* encryption_algorithms_server_to_client */ |
628 algo = buf_match_algo(ses.payload, sshciphers, &goodguess); | 636 algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); |
629 if (algo == NULL) { | 637 if (algo == NULL) { |
630 erralgo = "enc s->c"; | 638 erralgo = "enc s->c"; |
631 goto error; | 639 goto error; |
632 } | 640 } |
633 ses.newkeys->trans_algo_crypt = (struct dropbear_cipher*)algo->data; | 641 ses.newkeys->trans_algo_crypt = (struct dropbear_cipher*)algo->data; |
634 | 642 |
635 /* mac_algorithms_client_to_server */ | 643 /* mac_algorithms_client_to_server */ |
636 algo = buf_match_algo(ses.payload, sshhashes, &goodguess); | 644 algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); |
637 if (algo == NULL) { | 645 if (algo == NULL) { |
638 erralgo = "mac c->s"; | 646 erralgo = "mac c->s"; |
639 goto error; | 647 goto error; |
640 } | 648 } |
641 ses.newkeys->recv_algo_mac = (struct dropbear_hash*)algo->data; | 649 ses.newkeys->recv_algo_mac = (struct dropbear_hash*)algo->data; |
642 | 650 |
643 /* mac_algorithms_server_to_client */ | 651 /* mac_algorithms_server_to_client */ |
644 algo = buf_match_algo(ses.payload, sshhashes, &goodguess); | 652 algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); |
645 if (algo == NULL) { | 653 if (algo == NULL) { |
646 erralgo = "mac s->c"; | 654 erralgo = "mac s->c"; |
647 goto error; | 655 goto error; |
648 } | 656 } |
649 ses.newkeys->trans_algo_mac = (struct dropbear_hash*)algo->data; | 657 ses.newkeys->trans_algo_mac = (struct dropbear_hash*)algo->data; |
650 | 658 |
651 /* compression_algorithms_client_to_server */ | 659 /* compression_algorithms_client_to_server */ |
652 algo = buf_match_algo(ses.payload, sshcompress, &goodguess); | 660 algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess); |
653 if (algo == NULL) { | 661 if (algo == NULL) { |
654 erralgo = "comp c->s"; | 662 erralgo = "comp c->s"; |
655 goto error; | 663 goto error; |
656 } | 664 } |
657 ses.newkeys->recv_algo_comp = algo->val; | 665 ses.newkeys->recv_algo_comp = algo->val; |
658 | 666 |
659 /* compression_algorithms_server_to_client */ | 667 /* compression_algorithms_server_to_client */ |
660 algo = buf_match_algo(ses.payload, sshcompress, &goodguess); | 668 algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess); |
661 if (algo == NULL) { | 669 if (algo == NULL) { |
662 erralgo = "comp s->c"; | 670 erralgo = "comp s->c"; |
663 goto error; | 671 goto error; |
664 } | 672 } |
665 ses.newkeys->trans_algo_comp = algo->val; | 673 ses.newkeys->trans_algo_comp = algo->val; |