diff --git a/algo.h b/algo.h index ad57037f0edcf4de2f386a0792f2438ef29d9ec3..755cfcdf15ea1f7d528527d5114843a80cec398a 100644 --- a/algo.h +++ b/algo.h @@ -83,10 +83,20 @@ void crypto_init(); int have_algo(char* algo, size_t algolen, algo_type algos[]); void buf_put_algolist(buffer * buf, algo_type localalgos[]); +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 * svr_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess); + enum kexguess2_used *kexguess2, int *goodguess); algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess); + enum kexguess2_used *kexguess2, int *goodguess); #ifdef ENABLE_USER_ALGO_LIST int check_user_algos(const char* user_algo_list, algo_type * algos, diff --git a/cli-algo.c b/cli-algo.c index 09da41a3d27b95f47ae09a0103a477c1b8d3d1f7..ec8c541f2997578dea5880dddb1709ef64c2b815 100644 --- a/cli-algo.c +++ b/cli-algo.c @@ -34,7 +34,7 @@ * that is also on the server's list. */ algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], - int *goodguess) { + enum kexguess2_used *kexguess2, int *goodguess) { unsigned char * algolist = NULL; unsigned char * remotealgos[MAX_PROPOSED_ALGO]; @@ -42,7 +42,9 @@ algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], unsigned int count, i, j; algo_type * ret = NULL; - *goodguess = 0; + if (goodguess) { + *goodguess = 0; + } /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ algolist = buf_getstring(buf, &len); @@ -72,6 +74,19 @@ algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], } } + if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) { + for (i = 0; i < count; i++) + { + if (strcmp(remotealgos[i], KEXGUESS2_ALGO_NAME) == 0) { + *kexguess2 = KEXGUESS2_YES; + break; + } + } + if (*kexguess2 == KEXGUESS2_LOOK) { + *kexguess2 = KEXGUESS2_NO; + } + } + /* iterate and find the first match */ for (j = 0; localalgos[j].name != NULL; j++) { @@ -81,9 +96,16 @@ algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], if (len == strlen(remotealgos[i]) && strncmp(localalgos[j].name, remotealgos[i], len) == 0) { - if (i == 0 && j == 0) { - /* was a good guess */ - *goodguess = 1; + if (goodguess && kexguess2) { + if (*kexguess2 == KEXGUESS2_YES) { + if (j == 0) { + *goodguess = 1; + } + } else { + if (i == 0 && j == 0) { + *goodguess = 1; + } + } } ret = &localalgos[j]; goto out; diff --git a/common-algo.c b/common-algo.c index 4a14651e79e5f017ed7bb480470e70d4469158cd..46dbe74f43ef5f18f02b85e4b42645064b05cf58 100644 --- a/common-algo.c +++ b/common-algo.c @@ -215,6 +215,7 @@ algo_type sshhostkey[] = { 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} }; diff --git a/common-kex.c b/common-kex.c index e4b4c0230c3284c1bf491125f1b268131f4b7aaf..0640b9f8dfdc440133018dbb8e59a4ef7bd68885 100644 --- a/common-kex.c +++ b/common-kex.c @@ -692,18 +692,21 @@ static void read_kex_algos() { 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 = ses.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 = ses.buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess); allgood &= goodguess; if (algo == NULL) { erralgo = "hostkey"; @@ -713,7 +716,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, sshciphers, NULL, NULL); if (c2s_cipher_algo == NULL) { erralgo = "enc c->s"; goto error; @@ -721,7 +724,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, sshciphers, NULL, NULL); if (s2c_cipher_algo == NULL) { erralgo = "enc s->c"; goto error; @@ -729,7 +732,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, sshhashes, NULL, NULL); if (c2s_hash_algo == NULL) { erralgo = "mac c->s"; goto error; @@ -737,7 +740,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, sshhashes, NULL, NULL); if (s2c_hash_algo == NULL) { erralgo = "mac s->c"; goto error; @@ -745,7 +748,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); if (c2s_comp_algo == NULL) { erralgo = "comp c->s"; goto error; @@ -753,7 +756,7 @@ static void read_kex_algos() { 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 = ses.buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); if (s2c_comp_algo == NULL) { erralgo = "comp s->c"; goto error; diff --git a/debug.h b/debug.h index b20e68504882a87ce219fdefa463705ae040f263..02c100f99d815cf762cbf0fdd9a37e8a54155de6 100644 --- a/debug.h +++ b/debug.h @@ -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 --git a/kex.h b/kex.h index dc5f46bcc390d724d0b6c77c1bc8c17b171a341e..72430e9681ac6ccf422a38bd693cb450e1d7fff8 100644 --- a/kex.h +++ b/kex.h @@ -66,6 +66,7 @@ struct KEXState { }; + #define MAX_KEXHASHBUF 2000 #endif /* _KEX_H_ */ diff --git a/options.h b/options.h index c52d6c240d2d526e4a0423da5708f1a08ae24c2f..71d39ccd728ed831bc2d5714e05f228575f94e73 100644 --- a/options.h +++ b/options.h @@ -174,9 +174,9 @@ much traffic. */ * 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 --git a/session.h b/session.h index 6b106f5c1cc9680ecddb4ee2b866deb4c06cdcdf..3b9e957e2110b1b681004de3f0cfc01654c56ca1 100644 --- a/session.h +++ b/session.h @@ -170,6 +170,7 @@ struct sshsession { struct packetlist *reply_queue_head, *reply_queue_tail; algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[], + enum kexguess2_used *kexguess2, 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, diff --git a/svr-algo.c b/svr-algo.c index f8f9055979f6013c2adf809199a1f424a7cf77a1..620cfeb96d648dfa42e1480417d163b7e65fc0af 100644 --- a/svr-algo.c +++ b/svr-algo.c @@ -33,7 +33,7 @@ * 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) + enum kexguess2_used *kexguess2, int *goodguess) { unsigned char * algolist = NULL; @@ -42,7 +42,9 @@ algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], unsigned int count, i, j; algo_type * ret = NULL; - *goodguess = 0; + if (goodguess) { + *goodguess = 0; + } /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ algolist = buf_getstring(buf, &len); @@ -73,6 +75,19 @@ algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], } } + if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) { + for (i = 0; i < count; i++) + { + if (strcmp(remotealgos[i], KEXGUESS2_ALGO_NAME) == 0) { + *kexguess2 = KEXGUESS2_YES; + break; + } + } + if (*kexguess2 == KEXGUESS2_LOOK) { + *kexguess2 = KEXGUESS2_NO; + } + } + /* iterate and find the first match */ for (i = 0; i < count; i++) { @@ -83,8 +98,17 @@ algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], 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; + 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 */ ret = &localalgos[j];