mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Get rid of client/server specific buf_match_algo, use single
function with a couple of if statements instead --HG-- branch : kexguess
This commit is contained in:
parent
99d9cf500b
commit
9c7485331a
@ -28,12 +28,12 @@ COMMONOBJS=dbutil.o buffer.o \
|
|||||||
queue.o \
|
queue.o \
|
||||||
atomicio.o compat.o fake-rfc2553.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-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-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
|
||||||
svr-tcpfwd.o svr-authpam.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-session.o cli-service.o cli-runopts.o cli-chansession.o \
|
||||||
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
|
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
|
||||||
cli-agentfwd.o list.o
|
cli-agentfwd.o list.o
|
||||||
|
4
algo.h
4
algo.h
@ -93,9 +93,7 @@ enum kexguess2_used {
|
|||||||
#define KEXGUESS2_ALGO_ID 99
|
#define KEXGUESS2_ALGO_ID 99
|
||||||
|
|
||||||
|
|
||||||
algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
|
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||||
enum kexguess2_used *kexguess2, int *goodguess);
|
|
||||||
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
|
|
||||||
enum kexguess2_used *kexguess2, int *goodguess);
|
enum kexguess2_used *kexguess2, int *goodguess);
|
||||||
|
|
||||||
#ifdef ENABLE_USER_ALGO_LIST
|
#ifdef ENABLE_USER_ALGO_LIST
|
||||||
|
121
cli-algo.c
121
cli-algo.c
@ -1,121 +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[],
|
|
||||||
enum kexguess2_used *kexguess2, int *goodguess) {
|
|
||||||
|
|
||||||
unsigned char * algolist = NULL;
|
|
||||||
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
|
|
||||||
unsigned int len;
|
|
||||||
unsigned int count, i, j;
|
|
||||||
algo_type * ret = NULL;
|
|
||||||
|
|
||||||
if (goodguess) {
|
|
||||||
*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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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++) {
|
|
||||||
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 (goodguess && kexguess2) {
|
|
||||||
if (*kexguess2 == KEXGUESS2_YES) {
|
|
||||||
if (j == 0) {
|
|
||||||
*goodguess = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (i == 0 && j == 0) {
|
|
||||||
*goodguess = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = &localalgos[j];
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
m_free(algolist);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
@ -148,7 +148,6 @@ static void cli_session_init() {
|
|||||||
|
|
||||||
/* For printing "remote host closed" for the user */
|
/* For printing "remote host closed" for the user */
|
||||||
ses.remoteclosed = cli_remoteclosed;
|
ses.remoteclosed = cli_remoteclosed;
|
||||||
ses.buf_match_algo = cli_buf_match_algo;
|
|
||||||
|
|
||||||
/* packet handlers */
|
/* packet handlers */
|
||||||
ses.packettypes = cli_packettypes;
|
ses.packettypes = cli_packettypes;
|
||||||
|
117
common-algo.c
117
common-algo.c
@ -24,6 +24,7 @@
|
|||||||
* SOFTWARE. */
|
* SOFTWARE. */
|
||||||
|
|
||||||
#include "algo.h"
|
#include "algo.h"
|
||||||
|
#include "session.h"
|
||||||
#include "dbutil.h"
|
#include "dbutil.h"
|
||||||
|
|
||||||
/* This file (algo.c) organises the ciphers which can be used, and is used to
|
/* This file (algo.c) organises the ciphers which can be used, and is used to
|
||||||
@ -308,6 +309,122 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
|
|||||||
buf_free(algolist);
|
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
|
#ifdef DROPBEAR_NONE_CIPHER
|
||||||
|
|
||||||
void
|
void
|
||||||
|
16
common-kex.c
16
common-kex.c
@ -695,7 +695,7 @@ static void read_kex_algos() {
|
|||||||
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
|
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
|
||||||
|
|
||||||
/* kex_algorithms */
|
/* kex_algorithms */
|
||||||
algo = ses.buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
|
algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
|
||||||
allgood &= goodguess;
|
allgood &= goodguess;
|
||||||
if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
|
if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
|
||||||
erralgo = "kex";
|
erralgo = "kex";
|
||||||
@ -706,7 +706,7 @@ static void read_kex_algos() {
|
|||||||
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, &kexguess2, &goodguess);
|
algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
|
||||||
allgood &= goodguess;
|
allgood &= goodguess;
|
||||||
if (algo == NULL) {
|
if (algo == NULL) {
|
||||||
erralgo = "hostkey";
|
erralgo = "hostkey";
|
||||||
@ -716,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, NULL, NULL);
|
c2s_cipher_algo = 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;
|
||||||
@ -724,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, NULL, NULL);
|
s2c_cipher_algo = 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;
|
||||||
@ -732,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, NULL, NULL);
|
c2s_hash_algo = 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;
|
||||||
@ -740,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, NULL, NULL);
|
s2c_hash_algo = 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;
|
||||||
@ -748,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, NULL, NULL);
|
c2s_comp_algo = 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;
|
||||||
@ -756,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, NULL, NULL);
|
s2c_comp_algo = 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;
|
||||||
|
@ -169,13 +169,6 @@ struct sshsession {
|
|||||||
concluded (ie, while dataallowed was unset)*/
|
concluded (ie, while dataallowed was unset)*/
|
||||||
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[],
|
|
||||||
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,
|
|
||||||
hence the function-pointer callback.*/
|
|
||||||
|
|
||||||
void(*remoteclosed)(); /* A callback to handle closure of the
|
void(*remoteclosed)(); /* A callback to handle closure of the
|
||||||
remote connection */
|
remote connection */
|
||||||
|
|
||||||
|
124
svr-algo.c
124
svr-algo.c
@ -1,124 +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[],
|
|
||||||
enum kexguess2_used *kexguess2, int *goodguess)
|
|
||||||
{
|
|
||||||
|
|
||||||
unsigned char * algolist = NULL;
|
|
||||||
unsigned char * remotealgos[MAX_PROPOSED_ALGO];
|
|
||||||
unsigned int len;
|
|
||||||
unsigned int count, i, j;
|
|
||||||
algo_type * ret = NULL;
|
|
||||||
|
|
||||||
if (goodguess) {
|
|
||||||
*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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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++) {
|
|
||||||
|
|
||||||
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 (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];
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
m_free(algolist);
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -106,7 +106,6 @@ void svr_session(int sock, int childpipe) {
|
|||||||
|
|
||||||
/* packet handlers */
|
/* packet handlers */
|
||||||
ses.packettypes = svr_packettypes;
|
ses.packettypes = svr_packettypes;
|
||||||
ses.buf_match_algo = svr_buf_match_algo;
|
|
||||||
|
|
||||||
ses.isserver = 1;
|
ses.isserver = 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user