Add kexguess2 behaviour

--HG--
branch : kexguess
This commit is contained in:
Matt Johnston 2013-03-29 23:29:48 +08:00
parent 4f62da0f0d
commit 99d9cf500b
9 changed files with 86 additions and 24 deletions

14
algo.h
View File

@ -83,10 +83,20 @@ void crypto_init();
int have_algo(char* algo, size_t algolen, algo_type algos[]); int have_algo(char* algo, size_t algolen, algo_type algos[]);
void buf_put_algolist(buffer * buf, algo_type localalgos[]); 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[], 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[], algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess); enum kexguess2_used *kexguess2, int *goodguess);
#ifdef ENABLE_USER_ALGO_LIST #ifdef ENABLE_USER_ALGO_LIST
int check_user_algos(const char* user_algo_list, algo_type * algos, int check_user_algos(const char* user_algo_list, algo_type * algos,

View File

@ -34,7 +34,7 @@
* that is also on the server's list. * that is also on the server's list.
*/ */
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[], 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 * algolist = NULL;
unsigned char * remotealgos[MAX_PROPOSED_ALGO]; 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; unsigned int count, i, j;
algo_type * ret = NULL; algo_type * ret = NULL;
*goodguess = 0; if (goodguess) {
*goodguess = 0;
}
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len); 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 */ /* iterate and find the first match */
for (j = 0; localalgos[j].name != NULL; j++) { 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]) if (len == strlen(remotealgos[i])
&& strncmp(localalgos[j].name, && strncmp(localalgos[j].name,
remotealgos[i], len) == 0) { remotealgos[i], len) == 0) {
if (i == 0 && j == 0) { if (goodguess && kexguess2) {
/* was a good guess */ if (*kexguess2 == KEXGUESS2_YES) {
*goodguess = 1; if (j == 0) {
*goodguess = 1;
}
} else {
if (i == 0 && j == 0) {
*goodguess = 1;
}
}
} }
ret = &localalgos[j]; ret = &localalgos[j];
goto out; goto out;

View File

@ -215,6 +215,7 @@ algo_type sshhostkey[] = {
algo_type sshkex[] = { algo_type sshkex[] = {
{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL}, {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, 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} {NULL, 0, NULL, 0, NULL}
}; };

View File

@ -692,18 +692,21 @@ static void read_kex_algos() {
memset(ses.newkeys, 0x0, sizeof(*ses.newkeys)); memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
/* kex_algorithms */ /* kex_algorithms */
algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess); algo = ses.buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
allgood &= goodguess; allgood &= goodguess;
if (algo == NULL) { if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
erralgo = "kex"; erralgo = "kex";
goto error; goto error;
} }
TRACE(("kexguess2 %d", kexguess2))
TRACE(("kex algo %s", algo->name)) TRACE(("kex algo %s", algo->name))
ses.newkeys->algo_kex = algo->val; ses.newkeys->algo_kex = algo->val;
/* server_host_key_algorithms */ /* 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; allgood &= goodguess;
if (algo == NULL) { if (algo == NULL) {
erralgo = "hostkey"; erralgo = "hostkey";
@ -713,7 +716,7 @@ static void read_kex_algos() {
ses.newkeys->algo_hostkey = algo->val; ses.newkeys->algo_hostkey = algo->val;
/* encryption_algorithms_client_to_server */ /* 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) { if (c2s_cipher_algo == NULL) {
erralgo = "enc c->s"; erralgo = "enc c->s";
goto error; goto error;
@ -721,7 +724,7 @@ static void read_kex_algos() {
TRACE(("enc c2s is %s", c2s_cipher_algo->name)) TRACE(("enc c2s is %s", c2s_cipher_algo->name))
/* encryption_algorithms_server_to_client */ /* 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) { if (s2c_cipher_algo == NULL) {
erralgo = "enc s->c"; erralgo = "enc s->c";
goto error; goto error;
@ -729,7 +732,7 @@ static void read_kex_algos() {
TRACE(("enc s2c is %s", s2c_cipher_algo->name)) TRACE(("enc s2c is %s", s2c_cipher_algo->name))
/* mac_algorithms_client_to_server */ /* 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) { if (c2s_hash_algo == NULL) {
erralgo = "mac c->s"; erralgo = "mac c->s";
goto error; goto error;
@ -737,7 +740,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_hash_algo->name)) TRACE(("hash c2s is %s", c2s_hash_algo->name))
/* mac_algorithms_server_to_client */ /* 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) { if (s2c_hash_algo == NULL) {
erralgo = "mac s->c"; erralgo = "mac s->c";
goto error; goto error;
@ -745,7 +748,7 @@ static void read_kex_algos() {
TRACE(("hash s2c is %s", s2c_hash_algo->name)) TRACE(("hash s2c is %s", s2c_hash_algo->name))
/* compression_algorithms_client_to_server */ /* 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) { if (c2s_comp_algo == NULL) {
erralgo = "comp c->s"; erralgo = "comp c->s";
goto error; goto error;
@ -753,7 +756,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_comp_algo->name)) TRACE(("hash c2s is %s", c2s_comp_algo->name))
/* compression_algorithms_server_to_client */ /* 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) { if (s2c_comp_algo == NULL) {
erralgo = "comp s->c"; erralgo = "comp s->c";
goto error; goto error;

View File

@ -39,7 +39,7 @@
* Caution: Don't use this in an unfriendly environment (ie unfirewalled), * Caution: Don't use this in an unfriendly environment (ie unfirewalled),
* since the printing may not sanitise strings etc. This will add a reasonable * since the printing may not sanitise strings etc. This will add a reasonable
* amount to your executable size. */ * amount to your executable size. */
/*#define DEBUG_TRACE */ #define DEBUG_TRACE
/* All functions writing to the cleartext payload buffer call /* All functions writing to the cleartext payload buffer call
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're * 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. /* To debug with GDB it is easier to run with no forking of child processes.
You will need to pass "-F" as well. */ 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 /* For testing as non-root on shadowed systems, include the crypt of a password

1
kex.h
View File

@ -66,6 +66,7 @@ struct KEXState {
}; };
#define MAX_KEXHASHBUF 2000 #define MAX_KEXHASHBUF 2000
#endif /* _KEX_H_ */ #endif /* _KEX_H_ */

View File

@ -174,9 +174,9 @@ much traffic. */
* PAM challenge/response. * PAM challenge/response.
* You can't enable both PASSWORD and PAM. */ * You can't enable both PASSWORD and PAM. */
#define ENABLE_SVR_PASSWORD_AUTH //#define ENABLE_SVR_PASSWORD_AUTH
/* PAM requires ./configure --enable-pam */ /* PAM requires ./configure --enable-pam */
/*#define ENABLE_SVR_PAM_AUTH*/ #define ENABLE_SVR_PAM_AUTH
#define ENABLE_SVR_PUBKEY_AUTH #define ENABLE_SVR_PUBKEY_AUTH
/* Whether to take public key options in /* Whether to take public key options in

View File

@ -170,6 +170,7 @@ struct sshsession {
struct packetlist *reply_queue_head, *reply_queue_tail; struct packetlist *reply_queue_head, *reply_queue_tail;
algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[], algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[],
enum kexguess2_used *kexguess2,
int *goodguess); /* The function to use to choose which algorithm int *goodguess); /* The function to use to choose which algorithm
to use from the ones presented by the remote to use from the ones presented by the remote
side. Is specific to the client/server mode, side. Is specific to the client/server mode,

View File

@ -33,7 +33,7 @@
* 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
* guessed correctly */ * guessed correctly */
algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[], algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess) enum kexguess2_used *kexguess2, int *goodguess)
{ {
unsigned char * algolist = NULL; unsigned char * algolist = NULL;
@ -42,7 +42,9 @@ algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
unsigned int count, i, j; unsigned int count, i, j;
algo_type * ret = NULL; algo_type * ret = NULL;
*goodguess = 0; if (goodguess) {
*goodguess = 0;
}
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len); 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 */ /* iterate and find the first match */
for (i = 0; i < count; i++) { 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) && if (len == strlen(localalgos[j].name) &&
strncmp(localalgos[j].name, remotealgos[i], len) == 0) { strncmp(localalgos[j].name, remotealgos[i], len) == 0) {
/* set if it was a good guess */ /* set if it was a good guess */
if (i == 0 && j == 0) { if (goodguess && kexguess2) {
*goodguess = 1; if (*kexguess2 == KEXGUESS2_YES) {
if (i == 0) {
*goodguess = 1;
}
} else {
if (i == 0 && j == 0) {
*goodguess = 1;
}
}
} }
/* set the algo to return */ /* set the algo to return */
ret = &localalgos[j]; ret = &localalgos[j];