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;