# HG changeset patch # User Matt Johnston # Date 1364661675 -28800 # Node ID cd201dc2da9a1c835dab0be0df79314c6619c6ce # Parent eafdf8b363f541b8b94854902cea18d977012783# Parent 78eda530c0005dbd656eeeaaeb21560c15e3b568 merge diff -r 78eda530c000 -r cd201dc2da9a Makefile.in --- a/Makefile.in Sun Mar 31 00:40:00 2013 +0800 +++ b/Makefile.in Sun Mar 31 00:41:15 2013 +0800 @@ -28,12 +28,12 @@ queue.o \ atomicio.o compat.o fake-rfc2553.o -SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \ +SVROBJS=svr-kex.o svr-auth.o sshpty.o \ svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \ svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\ svr-tcpfwd.o svr-authpam.o -CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ +CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ cli-session.o cli-service.o cli-runopts.o cli-chansession.o \ cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \ cli-agentfwd.o list.o diff -r 78eda530c000 -r cd201dc2da9a algo.h --- a/algo.h Sun Mar 31 00:40:00 2013 +0800 +++ b/algo.h Sun Mar 31 00:41:15 2013 +0800 @@ -83,10 +83,18 @@ int have_algo(char* algo, size_t algolen, algo_type algos[]); void buf_put_algolist(buffer * buf, algo_type localalgos[]); -algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess); -algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess); +enum kexguess2_used { + KEXGUESS2_LOOK, + KEXGUESS2_NO, + KEXGUESS2_YES, +}; + +#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au" +#define KEXGUESS2_ALGO_ID 99 + + +algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], + enum kexguess2_used *kexguess2, int *goodguess); #ifdef ENABLE_USER_ALGO_LIST int check_user_algos(const char* user_algo_list, algo_type * algos, diff -r 78eda530c000 -r cd201dc2da9a cli-algo.c --- a/cli-algo.c Sun Mar 31 00:40:00 2013 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Dropbear - a SSH2 server - * SSH client implementation - * - * Copyright (c) 2002,2003 Matt Johnston - * Copyright (c) 2004 by Mihnea Stoenescu - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ - -#include "algo.h" -#include "dbutil.h" - - -/* - * The chosen [encryption | MAC | compression] algorithm to each - * direction MUST be the first algorithm on the client's list - * that is also on the server's list. - */ -algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess) { - - unsigned char * algolist = NULL; - unsigned char * remotealgos[MAX_PROPOSED_ALGO]; - unsigned int len; - unsigned int count, i, j; - algo_type * ret = NULL; - - *goodguess = 0; - - /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ - algolist = buf_getstring(buf, &len); - TRACE(("cli_buf_match_algo: %s", algolist)) - if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { - goto out; /* just a sanity check, no other use */ - } - - /* remotealgos will contain a list of the strings parsed out */ - /* We will have at least one string (even if it's just "") */ - remotealgos[0] = algolist; - count = 1; - /* Iterate through, replacing ','s with NULs, to split it into - * words. */ - for (i = 0; i < len; i++) { - if (algolist[i] == '\0') { - /* someone is trying something strange */ - goto out; - } - if (algolist[i] == ',') { - algolist[i] = '\0'; - remotealgos[count] = &algolist[i+1]; - count++; - } - if (count >= MAX_PROPOSED_ALGO) { - break; - } - } - - /* iterate and find the first match */ - - for (j = 0; localalgos[j].name != NULL; j++) { - if (localalgos[j].usable) { - len = strlen(localalgos[j].name); - for (i = 0; i < count; i++) { - if (len == strlen(remotealgos[i]) - && strncmp(localalgos[j].name, - remotealgos[i], len) == 0) { - if (i == 0 && j == 0) { - /* was a good guess */ - *goodguess = 1; - } - ret = &localalgos[j]; - goto out; - } - } - } - } - -out: - m_free(algolist); - return ret; -} - diff -r 78eda530c000 -r cd201dc2da9a cli-kex.c --- a/cli-kex.c Sun Mar 31 00:40:00 2013 +0800 +++ b/cli-kex.c Sun Mar 31 00:41:15 2013 +0800 @@ -42,7 +42,7 @@ #define MAX_KNOWNHOSTS_LINE 4500 void send_msg_kexdh_init() { - + TRACE(("send_msg_kexdh_init()")) cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int)); cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int)); m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); @@ -53,7 +53,8 @@ buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); buf_putmpint(ses.writepayload, cli_ses.dh_e); encrypt_packet(); - ses.requirenext = SSH_MSG_KEXDH_REPLY; + // XXX fixme + //ses.requirenext = SSH_MSG_KEXDH_REPLY; } /* Handle a diffie-hellman key exchange reply. */ diff -r 78eda530c000 -r cd201dc2da9a cli-session.c --- a/cli-session.c Sun Mar 31 00:40:00 2013 +0800 +++ b/cli-session.c Sun Mar 31 00:41:15 2013 +0800 @@ -109,6 +109,12 @@ } +static void cli_send_kex_first_guess() { + send_msg_kexdh_init(); + dropbear_log(LOG_INFO, "kexdh_init guess sent"); + //cli_ses.kex_state = KEXDH_INIT_SENT; +} + static void cli_session_init() { cli_ses.state = STATE_NOTHING; @@ -142,12 +148,14 @@ /* For printing "remote host closed" for the user */ ses.remoteclosed = cli_remoteclosed; - ses.buf_match_algo = cli_buf_match_algo; /* packet handlers */ ses.packettypes = cli_packettypes; ses.isserver = 0; + + ses.send_kex_first_guess = cli_send_kex_first_guess; + } /* This function drives the progress of the session - it initiates KEX, @@ -157,15 +165,13 @@ TRACE(("enter cli_sessionloop")) if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) { - cli_ses.kex_state = KEXINIT_RCVD; - } - - if (cli_ses.kex_state == KEXINIT_RCVD) { - /* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT * negotiation would have failed. */ - send_msg_kexdh_init(); - cli_ses.kex_state = KEXDH_INIT_SENT; + if (!ses.kexstate.our_first_follows_matches) { + dropbear_log(LOG_INFO, "kexdh_init after remote's kexinit"); + send_msg_kexdh_init(); + } + cli_ses.kex_state = KEXDH_INIT_SENT; TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD")) return; } diff -r 78eda530c000 -r cd201dc2da9a common-algo.c --- a/common-algo.c Sun Mar 31 00:40:00 2013 +0800 +++ b/common-algo.c Sun Mar 31 00:41:15 2013 +0800 @@ -24,6 +24,7 @@ * SOFTWARE. */ #include "algo.h" +#include "session.h" #include "dbutil.h" /* This file (algo.c) organises the ciphers which can be used, and is used to @@ -215,6 +216,7 @@ algo_type sshkex[] = { {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, {"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL}, + {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL}, {NULL, 0, NULL, 0, NULL} }; @@ -307,6 +309,122 @@ buf_free(algolist); } +/* match the first algorithm in the comma-separated list in buf which is + * also in localalgos[], or return NULL on failure. + * (*goodguess) is set to 1 if the preferred client/server algos match, + * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are + * guessed correctly */ +algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], + enum kexguess2_used *kexguess2, int *goodguess) +{ + + unsigned char * algolist = NULL; + const unsigned char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO]; + unsigned int len; + unsigned int remotecount, localcount, clicount, servcount, i, j; + algo_type * ret = NULL; + const unsigned char **clinames, **servnames; + + if (goodguess) { + *goodguess = 0; + } + + /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ + algolist = buf_getstring(buf, &len); + TRACE(("buf_match_algo: %s", algolist)) + if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { + goto out; + } + + /* remotenames will contain a list of the strings parsed out */ + /* We will have at least one string (even if it's just "") */ + remotenames[0] = algolist; + remotecount = 1; + for (i = 0; i < len; i++) { + if (algolist[i] == '\0') { + /* someone is trying something strange */ + goto out; + } + if (algolist[i] == ',') { + algolist[i] = '\0'; + remotenames[remotecount] = &algolist[i+1]; + remotecount++; + } + if (remotecount >= MAX_PROPOSED_ALGO) { + break; + } + } + if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) { + for (i = 0; i < remotecount; i++) + { + if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) { + *kexguess2 = KEXGUESS2_YES; + break; + } + } + if (*kexguess2 == KEXGUESS2_LOOK) { + *kexguess2 = KEXGUESS2_NO; + } + } + + for (i = 0; localalgos[i].name != NULL; i++) { + if (localalgos[i].usable) { + localnames[i] = localalgos[i].name; + } else { + localnames[i] = NULL; + } + } + localcount = i; + + if (IS_DROPBEAR_SERVER) { + clinames = remotenames; + clicount = remotecount; + servnames = localnames; + servcount = localcount; + } else { + clinames = localnames; + clicount = localcount; + servnames = remotenames; + servcount = remotecount; + } + + /* iterate and find the first match */ + for (i = 0; i < clicount; i++) { + for (j = 0; j < servcount; j++) { + if (!(servnames[j] && clinames[i])) { + // unusable algos are NULL + continue; + } + if (strcmp(servnames[j], clinames[i]) == 0) { + /* set if it was a good guess */ + if (goodguess && kexguess2) { + if (*kexguess2 == KEXGUESS2_YES) { + if (i == 0) { + *goodguess = 1; + } + + } else { + if (i == 0 && j == 0) { + *goodguess = 1; + } + } + } + /* set the algo to return */ + if (IS_DROPBEAR_SERVER) { + ret = &localalgos[j]; + } else { + ret = &localalgos[i]; + } + goto out; + } + } + } + +out: + m_free(algolist); + return ret; +} + #ifdef DROPBEAR_NONE_CIPHER void diff -r 78eda530c000 -r cd201dc2da9a common-kex.c --- a/common-kex.c Sun Mar 31 00:40:00 2013 +0800 +++ b/common-kex.c Sun Mar 31 00:41:15 2013 +0800 @@ -131,8 +131,8 @@ /* languages_server_to_client */ buf_putstring(ses.writepayload, "", 0); - /* first_kex_packet_follows - unimplemented for now */ - buf_putbyte(ses.writepayload, 0x00); + /* first_kex_packet_follows */ + buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL)); /* reserved unit32 */ buf_putint(ses.writepayload, 0); @@ -144,9 +144,19 @@ encrypt_packet(); ses.dataallowed = 0; /* don't send other packets during kex */ + ses.kexstate.sentkexinit = 1; + + ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); + + if (ses.send_kex_first_guess) { + ses.newkeys->algo_kex = sshkex[0].val; + ses.newkeys->algo_hostkey = sshhostkey[0].val; + ses.send_kex_first_guess(); + } + TRACE(("DATAALLOWED=0")) TRACE(("-> KEXINIT")) - ses.kexstate.sentkexinit = 1; + } /* *** NOTE regarding (send|recv)_msg_newkeys *** @@ -236,11 +246,13 @@ ses.kexstate.sentnewkeys = 0; /* first_packet_follows */ - ses.kexstate.firstfollows = 0; + ses.kexstate.them_firstfollows = 0; ses.kexstate.datatrans = 0; ses.kexstate.datarecv = 0; + ses.kexstate.our_first_follows_matches = 0; + ses.kexstate.lastkextime = time(NULL); } @@ -555,7 +567,7 @@ DEF_MP_INT(dh_q); DEF_MP_INT(dh_g); - TRACE(("enter send_msg_kexdh_reply")) + TRACE(("enter gen_kexdh_vals")) m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); @@ -678,20 +690,23 @@ buf_incrpos(ses.payload, 16); /* start after the cookie */ - ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); + memset(ses.newkeys, 0x0, sizeof(*ses.newkeys)); + + enum kexguess2_used kexguess2 = KEXGUESS2_LOOK; /* kex_algorithms */ - algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess); + algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess); allgood &= goodguess; - if (algo == NULL) { + if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) { erralgo = "kex"; goto error; } + TRACE(("kexguess2 %d", kexguess2)) TRACE(("kex algo %s", algo->name)) ses.newkeys->algo_kex = algo->val; /* server_host_key_algorithms */ - algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess); + algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess); allgood &= goodguess; if (algo == NULL) { erralgo = "hostkey"; @@ -701,7 +716,7 @@ ses.newkeys->algo_hostkey = algo->val; /* encryption_algorithms_client_to_server */ - c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); + c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL); if (c2s_cipher_algo == NULL) { erralgo = "enc c->s"; goto error; @@ -709,7 +724,7 @@ TRACE(("enc c2s is %s", c2s_cipher_algo->name)) /* encryption_algorithms_server_to_client */ - s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); + s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL); if (s2c_cipher_algo == NULL) { erralgo = "enc s->c"; goto error; @@ -717,7 +732,7 @@ TRACE(("enc s2c is %s", s2c_cipher_algo->name)) /* mac_algorithms_client_to_server */ - c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); + c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); if (c2s_hash_algo == NULL) { erralgo = "mac c->s"; goto error; @@ -725,7 +740,7 @@ TRACE(("hash c2s is %s", c2s_hash_algo->name)) /* mac_algorithms_server_to_client */ - s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); + s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); if (s2c_hash_algo == NULL) { erralgo = "mac s->c"; goto error; @@ -733,7 +748,7 @@ TRACE(("hash s2c is %s", s2c_hash_algo->name)) /* compression_algorithms_client_to_server */ - c2s_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); + c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); if (c2s_comp_algo == NULL) { erralgo = "comp c->s"; goto error; @@ -741,7 +756,7 @@ TRACE(("hash c2s is %s", c2s_comp_algo->name)) /* compression_algorithms_server_to_client */ - s2c_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); + s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); if (s2c_comp_algo == NULL) { erralgo = "comp s->c"; goto error; @@ -754,9 +769,10 @@ /* languages_server_to_client */ buf_eatstring(ses.payload); - /* first_kex_packet_follows */ + /* their first_kex_packet_follows */ if (buf_getbool(ses.payload)) { - ses.kexstate.firstfollows = 1; + TRACE(("them kex firstfollows. allgood %d", allgood)) + ses.kexstate.them_firstfollows = 1; /* if the guess wasn't good, we ignore the packet sent */ if (!allgood) { ses.ignorenext = 1; @@ -799,6 +815,11 @@ /* reserved for future extensions */ buf_getint(ses.payload); + + if (ses.send_kex_first_guess && allgood) { + TRACE(("our_first_follows_matches 1")) + ses.kexstate.our_first_follows_matches = 1; + } return; error: diff -r 78eda530c000 -r cd201dc2da9a debug.h --- a/debug.h Sun Mar 31 00:40:00 2013 +0800 +++ b/debug.h Sun Mar 31 00:41:15 2013 +0800 @@ -39,7 +39,7 @@ * Caution: Don't use this in an unfriendly environment (ie unfirewalled), * since the printing may not sanitise strings etc. This will add a reasonable * amount to your executable size. */ -/*#define DEBUG_TRACE */ +#define DEBUG_TRACE /* All functions writing to the cleartext payload buffer call * CHECKCLEARTOWRITE() before writing. This is only really useful if you're @@ -69,7 +69,7 @@ /* To debug with GDB it is easier to run with no forking of child processes. You will need to pass "-F" as well. */ -/* #define DEBUG_NOFORK */ +#define DEBUG_NOFORK /* For testing as non-root on shadowed systems, include the crypt of a password diff -r 78eda530c000 -r cd201dc2da9a kex.h --- a/kex.h Sun Mar 31 00:40:00 2013 +0800 +++ b/kex.h Sun Mar 31 00:41:15 2013 +0800 @@ -51,19 +51,22 @@ unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */ unsigned recvkexinit : 1; - unsigned firstfollows : 1; /* true when first_kex_packet_follows is set */ + unsigned them_firstfollows : 1; /* true when first_kex_packet_follows is set */ unsigned sentnewkeys : 1; /* set once we've send MSG_NEWKEYS (will be cleared once we have also received */ unsigned recvnewkeys : 1; /* set once we've received MSG_NEWKEYS (cleared once we have also sent */ unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed, ie the transport layer has been set up */ + unsigned our_first_follows_matches : 1; + time_t lastkextime; /* time of the last kex */ unsigned int datatrans; /* data transmitted since last kex */ unsigned int datarecv; /* data received since last kex */ }; + #define MAX_KEXHASHBUF 2000 #endif /* _KEX_H_ */ diff -r 78eda530c000 -r cd201dc2da9a options.h --- a/options.h Sun Mar 31 00:40:00 2013 +0800 +++ b/options.h Sun Mar 31 00:41:15 2013 +0800 @@ -174,9 +174,9 @@ * PAM challenge/response. * You can't enable both PASSWORD and PAM. */ -#define ENABLE_SVR_PASSWORD_AUTH +//#define ENABLE_SVR_PASSWORD_AUTH /* PAM requires ./configure --enable-pam */ -/*#define ENABLE_SVR_PAM_AUTH*/ +#define ENABLE_SVR_PAM_AUTH #define ENABLE_SVR_PUBKEY_AUTH /* Whether to take public key options in diff -r 78eda530c000 -r cd201dc2da9a session.h --- a/session.h Sun Mar 31 00:40:00 2013 +0800 +++ b/session.h Sun Mar 31 00:41:15 2013 +0800 @@ -172,15 +172,11 @@ concluded (ie, while dataallowed was unset)*/ struct packetlist *reply_queue_head, *reply_queue_tail; - algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[], - int *goodguess); /* The function to use to choose which algorithm - to use from the ones presented by the remote - side. Is specific to the client/server mode, - hence the function-pointer callback.*/ - void(*remoteclosed)(); /* A callback to handle closure of the remote connection */ + void(*send_kex_first_guess)(); + struct AuthState authstate; /* Common amongst client and server, since most struct elements are common */ diff -r 78eda530c000 -r cd201dc2da9a svr-algo.c --- a/svr-algo.c Sun Mar 31 00:40:00 2013 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Dropbear - a SSH2 server - * SSH client implementation - * - * Copyright (c) 2002,2003 Matt Johnston - * Copyright (c) 2004 by Mihnea Stoenescu - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ - -#include "algo.h" -#include "dbutil.h" - -/* match the first algorithm in the comma-separated list in buf which is - * also in localalgos[], or return NULL on failure. - * (*goodguess) is set to 1 if the preferred client/server algos match, - * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are - * guessed correctly */ -algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess) -{ - - unsigned char * algolist = NULL; - unsigned char * remotealgos[MAX_PROPOSED_ALGO]; - unsigned int len; - unsigned int count, i, j; - algo_type * ret = NULL; - - *goodguess = 0; - - /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ - algolist = buf_getstring(buf, &len); - /* Debug this */ - TRACE(("buf_match_algo: %s", algolist)) - if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { - goto out; /* just a sanity check, no other use */ - } - - /* remotealgos will contain a list of the strings parsed out */ - /* We will have at least one string (even if it's just "") */ - remotealgos[0] = algolist; - count = 1; - /* Iterate through, replacing ','s with NULs, to split it into - * words. */ - for (i = 0; i < len; i++) { - if (algolist[i] == '\0') { - /* someone is trying something strange */ - goto out; - } - if (algolist[i] == ',') { - algolist[i] = '\0'; - remotealgos[count] = &algolist[i+1]; - count++; - } - if (count >= MAX_PROPOSED_ALGO) { - break; - } - } - - /* iterate and find the first match */ - for (i = 0; i < count; i++) { - - len = strlen(remotealgos[i]); - - for (j = 0; localalgos[j].name != NULL; j++) { - if (localalgos[j].usable) { - if (len == strlen(localalgos[j].name) && - strncmp(localalgos[j].name, remotealgos[i], len) == 0) { - /* set if it was a good guess */ - if (i == 0 && j == 0) { - *goodguess = 1; - } - /* set the algo to return */ - ret = &localalgos[j]; - goto out; - } - } - } - } - -out: - m_free(algolist); - return ret; -} diff -r 78eda530c000 -r cd201dc2da9a svr-session.c --- a/svr-session.c Sun Mar 31 00:40:00 2013 +0800 +++ b/svr-session.c Sun Mar 31 00:41:15 2013 +0800 @@ -106,7 +106,6 @@ /* packet handlers */ ses.packettypes = svr_packettypes; - ses.buf_match_algo = svr_buf_match_algo; ses.isserver = 1;