mirror of
https://github.com/clearml/dropbear
synced 2025-05-02 19:22:29 +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 \
|
||||
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
|
||||
|
4
algo.h
4
algo.h
@ -93,9 +93,7 @@ enum kexguess2_used {
|
||||
#define KEXGUESS2_ALGO_ID 99
|
||||
|
||||
|
||||
algo_type * svr_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[],
|
||||
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
|
||||
enum kexguess2_used *kexguess2, int *goodguess);
|
||||
|
||||
#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 */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
ses.buf_match_algo = cli_buf_match_algo;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = cli_packettypes;
|
||||
|
117
common-algo.c
117
common-algo.c
@ -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
|
||||
@ -308,6 +309,122 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
|
||||
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
|
||||
|
16
common-kex.c
16
common-kex.c
@ -695,7 +695,7 @@ static void read_kex_algos() {
|
||||
enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
|
||||
|
||||
/* kex_algorithms */
|
||||
algo = ses.buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
|
||||
algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
|
||||
allgood &= goodguess;
|
||||
if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
|
||||
erralgo = "kex";
|
||||
@ -706,7 +706,7 @@ static void read_kex_algos() {
|
||||
ses.newkeys->algo_kex = algo->val;
|
||||
|
||||
/* 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;
|
||||
if (algo == NULL) {
|
||||
erralgo = "hostkey";
|
||||
@ -716,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, NULL, NULL);
|
||||
c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
|
||||
if (c2s_cipher_algo == NULL) {
|
||||
erralgo = "enc c->s";
|
||||
goto error;
|
||||
@ -724,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, NULL, NULL);
|
||||
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
|
||||
if (s2c_cipher_algo == NULL) {
|
||||
erralgo = "enc s->c";
|
||||
goto error;
|
||||
@ -732,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, NULL, NULL);
|
||||
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
|
||||
if (c2s_hash_algo == NULL) {
|
||||
erralgo = "mac c->s";
|
||||
goto error;
|
||||
@ -740,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, NULL, NULL);
|
||||
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
|
||||
if (s2c_hash_algo == NULL) {
|
||||
erralgo = "mac s->c";
|
||||
goto error;
|
||||
@ -748,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, NULL, NULL);
|
||||
c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
|
||||
if (c2s_comp_algo == NULL) {
|
||||
erralgo = "comp c->s";
|
||||
goto error;
|
||||
@ -756,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, NULL, NULL);
|
||||
s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
|
||||
if (s2c_comp_algo == NULL) {
|
||||
erralgo = "comp s->c";
|
||||
goto error;
|
||||
|
@ -169,13 +169,6 @@ struct sshsession {
|
||||
concluded (ie, while dataallowed was unset)*/
|
||||
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
|
||||
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 */
|
||||
ses.packettypes = svr_packettypes;
|
||||
ses.buf_match_algo = svr_buf_match_algo;
|
||||
|
||||
ses.isserver = 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user