changeset 741:eafdf8b363f5 kexguess

Get rid of client/server specific buf_match_algo, use single function with a couple of if statements instead
author Matt Johnston <matt@ucc.asn.au>
date Sat, 30 Mar 2013 23:55:05 +0800
parents 3062da90dab8
children cd201dc2da9a
files Makefile.in algo.h cli-algo.c cli-session.c common-algo.c common-kex.c session.h svr-algo.c svr-session.c
diffstat 9 files changed, 128 insertions(+), 267 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.in	Fri Mar 29 23:29:48 2013 +0800
+++ b/Makefile.in	Sat Mar 30 23:55:05 2013 +0800
@@ -28,12 +28,12 @@
 		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
--- a/algo.h	Fri Mar 29 23:29:48 2013 +0800
+++ b/algo.h	Sat Mar 30 23:55:05 2013 +0800
@@ -93,9 +93,7 @@
 #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
--- a/cli-algo.c	Fri Mar 29 23:29:48 2013 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
-
--- a/cli-session.c	Fri Mar 29 23:29:48 2013 +0800
+++ b/cli-session.c	Sat Mar 30 23:55:05 2013 +0800
@@ -148,7 +148,6 @@
 
 	/* 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;
--- a/common-algo.c	Fri Mar 29 23:29:48 2013 +0800
+++ b/common-algo.c	Sat Mar 30 23:55:05 2013 +0800
@@ -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 @@
 	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
--- a/common-kex.c	Fri Mar 29 23:29:48 2013 +0800
+++ b/common-kex.c	Sat Mar 30 23:55:05 2013 +0800
@@ -695,7 +695,7 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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;
--- a/session.h	Fri Mar 29 23:29:48 2013 +0800
+++ b/session.h	Sat Mar 30 23:55:05 2013 +0800
@@ -169,13 +169,6 @@
 	   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 */
 
--- a/svr-algo.c	Fri Mar 29 23:29:48 2013 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/svr-session.c	Fri Mar 29 23:29:48 2013 +0800
+++ b/svr-session.c	Sat Mar 30 23:55:05 2013 +0800
@@ -106,7 +106,6 @@
 
 	/* packet handlers */
 	ses.packettypes = svr_packettypes;
-	ses.buf_match_algo = svr_buf_match_algo;
 
 	ses.isserver = 1;