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[]);
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,

View File

@ -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;

View File

@ -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}
};

View File

@ -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;

View File

@ -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

1
kex.h
View File

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

View File

@ -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

View File

@ -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,

View File

@ -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];