changeset 247:c07de41b53d7 contrib-blacklist

propagate from branch 'au.asn.ucc.matt.dropbear' (head c9347a030ac9ef5454b7a84f4915e91dc44efd6c) to branch 'au.asn.ucc.matt.dropbear.contrib.blacklist' (head 8662c7148e4b738e2511a6fce9a4cbd959ecb6b8)
author Matt Johnston <matt@ucc.asn.au>
date Tue, 06 Sep 2005 04:57:14 +0000
parents b24730e11c83 (diff) f4cf0415fec1 (current diff)
children 9d110777f345
files options.h svr-main.c
diffstat 22 files changed, 235 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/INSTALL	Tue Sep 06 04:52:46 2005 +0000
+++ b/INSTALL	Tue Sep 06 04:57:14 2005 +0000
@@ -28,6 +28,11 @@
 
 ============================================================================
 
+If you're compiling for a 386-class CPU, you will probably need to add
+CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
+
+============================================================================
+
 Compiling with uClibc:
 
 Firstly, make sure you have at least uclibc 0.9.17, as getusershell() in prior
--- a/buffer.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/buffer.c	Tue Sep 06 04:57:14 2005 +0000
@@ -153,7 +153,7 @@
 unsigned char buf_getbyte(buffer* buf) {
 
 	/* This check is really just ==, but the >= allows us to check for the
-	 * assert()able case of pos > len, which should _never_ happen. */
+	 * bad case of pos > len, which should _never_ happen. */
 	if (buf->pos >= buf->len) {
 		dropbear_exit("bad buf_getbyte");
 	}
@@ -270,7 +270,7 @@
 	unsigned int len, pad = 0;
 	TRACE(("enter buf_putmpint"))
 
-	assert(mp != NULL);
+	dropbear_assert(mp != NULL);
 
 	if (SIGN(mp) == MP_NEG) {
 		dropbear_exit("negative bignum");
--- a/channel.h	Tue Sep 06 04:52:46 2005 +0000
+++ b/channel.h	Tue Sep 06 04:57:14 2005 +0000
@@ -81,6 +81,10 @@
 	int initconn; /* used for TCP forwarding, whether the channel has been
 					 fully initialised */
 
+	int await_open; /* flag indicating whether we've sent an open request
+					   for this channel (and are awaiting a confirmation
+					   or failure). */
+
 	const struct ChanType* type;
 
 };
@@ -96,7 +100,7 @@
 
 };
 
-void chaninitialise();
+void chaninitialise(const struct ChanType *chantypes[]);
 void chancleanup();
 void setchannelfds(fd_set *readfd, fd_set *writefd);
 void channelio(fd_set *readfd, fd_set *writefd);
@@ -119,7 +123,7 @@
 		circbuffer * buf);
 
 #ifdef DROPBEAR_CLIENT
-const struct ChanType clichansess;
+extern const struct ChanType clichansess;
 #endif
 
 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
--- a/circbuffer.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/circbuffer.c	Tue Sep 06 04:57:14 2005 +0000
@@ -66,8 +66,8 @@
 
 unsigned int cbuf_readlen(circbuffer *cbuf) {
 
-	assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
-	assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
+	dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
+	dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
 
 	if (cbuf->used == 0) {
 		TRACE(("cbuf_readlen: unused buffer"))
@@ -83,9 +83,9 @@
 
 unsigned int cbuf_writelen(circbuffer *cbuf) {
 
-	assert(cbuf->used <= cbuf->size);
-	assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
-	assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
+	dropbear_assert(cbuf->used <= cbuf->size);
+	dropbear_assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size);
+	dropbear_assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size);
 
 	if (cbuf->used == cbuf->size) {
 		TRACE(("cbuf_writelen: full buffer"))
@@ -122,7 +122,7 @@
 	}
 
 	cbuf->used += len;
-	assert(cbuf->used <= cbuf->size);
+	dropbear_assert(cbuf->used <= cbuf->size);
 	cbuf->writepos = (cbuf->writepos + len) % cbuf->size;
 }
 
@@ -132,7 +132,7 @@
 		dropbear_exit("bad cbuf read");
 	}
 
-	assert(cbuf->used >= len);
+	dropbear_assert(cbuf->used >= len);
 	cbuf->used -= len;
 	cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
 }
--- a/common-algo.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/common-algo.c	Tue Sep 06 04:57:14 2005 +0000
@@ -32,20 +32,28 @@
 /* Mappings for ciphers, parameters are
    {&cipher_desc, keysize, blocksize} */
 
+#ifdef DROPBEAR_AES256_CBC
+static const struct dropbear_cipher dropbear_aes256 = 
+	{&aes_desc, 32, 16};
+#endif
 #ifdef DROPBEAR_AES128_CBC
-const struct dropbear_cipher dropbear_aes128 = 
+static const struct dropbear_cipher dropbear_aes128 = 
 	{&aes_desc, 16, 16};
 #endif
 #ifdef DROPBEAR_BLOWFISH_CBC
-const struct dropbear_cipher dropbear_blowfish = 
+static const struct dropbear_cipher dropbear_blowfish = 
 	{&blowfish_desc, 16, 8};
 #endif
+#ifdef DROPBEAR_TWOFISH256_CBC
+static const struct dropbear_cipher dropbear_twofish256 = 
+	{&twofish_desc, 32, 16};
+#endif
 #ifdef DROPBEAR_TWOFISH128_CBC
-const struct dropbear_cipher dropbear_twofish128 = 
+static const struct dropbear_cipher dropbear_twofish128 = 
 	{&twofish_desc, 16, 16};
 #endif
 #ifdef DROPBEAR_3DES_CBC
-const struct dropbear_cipher dropbear_3des = 
+static const struct dropbear_cipher dropbear_3des = 
 	{&des3_desc, 24, 8};
 #endif
 
@@ -57,11 +65,15 @@
    {&hash_desc, keysize, hashsize} */
 
 #ifdef DROPBEAR_SHA1_HMAC
-const struct dropbear_hash dropbear_sha1 = 
+static const struct dropbear_hash dropbear_sha1 = 
 	{&sha1_desc, 20, 20};
 #endif
+#ifdef DROPBEAR_SHA1_96_HMAC
+static const struct dropbear_hash dropbear_sha1_96 = 
+	{&sha1_desc, 20, 12};
+#endif
 #ifdef DROPBEAR_MD5_HMAC
-const struct dropbear_hash dropbear_md5 = 
+static const struct dropbear_hash dropbear_md5 = 
 	{&md5_desc, 16, 16};
 #endif
 
@@ -75,19 +87,29 @@
 #ifdef DROPBEAR_AES128_CBC
 	{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
 #endif
-#ifdef DROPBEAR_BLOWFISH_CBC
-	{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
+#ifdef DROPBEAR_3DES_CBC
+	{"3des-cbc", 0, (void*)&dropbear_3des, 1},
+#endif
+#ifdef DROPBEAR_AES256_CBC
+	{"aes256-cbc", 0, (void*)&dropbear_aes256, 1},
+#endif
+#ifdef DROPBEAR_TWOFISH256_CBC
+	{"twofish256-cbc", 0, (void*)&dropbear_twofish256, 1},
+	{"twofish-cbc", 0, (void*)&dropbear_twofish256, 1},
 #endif
 #ifdef DROPBEAR_TWOFISH128_CBC
-	{"twofish-cbc", 0, (void*)&dropbear_twofish128, 1},
+	{"twofish128-cbc", 0, (void*)&dropbear_twofish128, 1},
 #endif
-#ifdef DROPBEAR_3DES_CBC
-	{"3des-cbc", 0, (void*)&dropbear_3des, 1},
+#ifdef DROPBEAR_BLOWFISH_CBC
+	{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
 #endif
 	{NULL, 0, NULL, 0}
 };
 
 algo_type sshhashes[] = {
+#ifdef DROPBEAR_SHA1_96_HMAC
+	{"hmac-sha1-96", 0, (void*)&dropbear_sha1_96, 1},
+#endif
 #ifdef DROPBEAR_SHA1_HMAC
 	{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
 #endif
@@ -126,13 +148,13 @@
 void crypto_init() {
 
 	const struct ltc_cipher_descriptor *regciphers[] = {
-#ifdef DROPBEAR_AES128_CBC
+#ifdef DROPBEAR_AES_CBC
 		&aes_desc,
 #endif
 #ifdef DROPBEAR_BLOWFISH_CBC
 		&blowfish_desc,
 #endif
-#ifdef DROPBEAR_TWOFISH128_CBC
+#ifdef DROPBEAR_TWOFISH_CBC
 		&twofish_desc,
 #endif
 #ifdef DROPBEAR_3DES_CBC
@@ -187,21 +209,20 @@
 /* Output a comma separated list of algorithms to a buffer */
 void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
 
-	unsigned int pos = 0, i, len;
-	char str[50]; /* enough for local algo storage */
+	unsigned int i, len;
+	unsigned int donefirst = 0;
+	buffer *algolist = NULL;
 
+	algolist = buf_new(100);
 	for (i = 0; localalgos[i].name != NULL; i++) {
 		if (localalgos[i].usable) {
-			/* Avoid generating a trailing comma */
-			if (pos)
-			    str[pos++] = ',';
+			if (donefirst)
+				buf_putbyte(algolist, ',');
+			donefirst = 1;
 			len = strlen(localalgos[i].name);
-			memcpy(&str[pos], localalgos[i].name, len);
-			pos += len;
+			buf_putbytes(algolist, localalgos[i].name, len);
 		}
 	}
-	str[pos]=0;
-	/* Debug this */
-	TRACE(("buf_put_algolist: %s", str))
-	buf_putstring(buf, str, pos);
+	buf_putstring(buf, algolist->data, algolist->len);
+	buf_free(algolist);
 }
--- a/common-channel.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/common-channel.c	Tue Sep 06 04:57:14 2005 +0000
@@ -147,6 +147,7 @@
 	newchan->outfd = FD_UNINIT;
 	newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
 	newchan->initconn = 0;
+	newchan->await_open = 0;
 
 	newchan->writebuf = cbuf_new(RECV_MAXWINDOW);
 	newchan->extrabuf = NULL; /* The user code can set it up */
@@ -409,9 +410,9 @@
 		channel->recvdonelen = 0;
 	}
 
-	assert(channel->recvwindow <= RECV_MAXWINDOW);
-	assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
-	assert(channel->extrabuf == NULL ||
+	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
+	dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
+	dropbear_assert(channel->extrabuf == NULL ||
 			channel->recvwindow <= cbuf_getavail(channel->extrabuf));
 	
 	
@@ -603,14 +604,14 @@
 
 	CHECKCLEARTOWRITE();
 
-	assert(!channel->sentclosed);
+	dropbear_assert(!channel->sentclosed);
 
 	if (isextended) {
 		fd = channel->errfd;
 	} else {
 		fd = channel->outfd;
 	}
-	assert(fd >= 0);
+	dropbear_assert(fd >= 0);
 
 	maxlen = MIN(channel->transwindow, channel->transmaxpacket);
 	/* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and 
@@ -718,9 +719,9 @@
 		len -= buflen;
 	}
 
-	assert(channel->recvwindow >= datalen);
+	dropbear_assert(channel->recvwindow >= datalen);
 	channel->recvwindow -= datalen;
-	assert(channel->recvwindow <= RECV_MAXWINDOW);
+	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
 
 	TRACE(("leave recv_msg_channel_data"))
 }
@@ -933,6 +934,8 @@
 	chan->infd = chan->outfd = fd;
 	ses.maxfd = MAX(ses.maxfd, fd);
 
+	chan->await_open = 1;
+
 	/* now open the channel connection */
 	CHECKCLEARTOWRITE();
 
@@ -960,6 +963,11 @@
 		dropbear_exit("Unknown channel");
 	}
 
+	if (!channel->await_open) {
+		dropbear_exit("unexpected channel reply");
+	}
+	channel->await_open = 0;
+
 	channel->remotechan =  buf_getint(ses.payload);
 	channel->transwindow = buf_getint(ses.payload);
 	channel->transmaxpacket = buf_getint(ses.payload);
@@ -990,6 +998,11 @@
 		dropbear_exit("Unknown channel");
 	}
 
+	if (!channel->await_open) {
+		dropbear_exit("unexpected channel reply");
+	}
+	channel->await_open = 0;
+
 	removechannel(channel);
 }
 #endif /* USING_LISTENERS */
--- a/common-kex.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/common-kex.c	Tue Sep 06 04:57:14 2005 +0000
@@ -35,7 +35,7 @@
 #include "random.h"
 
 /* diffie-hellman-group1-sha1 value for p */
-const unsigned char dh_p_val[] = {
+static const unsigned char dh_p_val[] = {
 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
     0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
 	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
@@ -47,8 +47,9 @@
 	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
 	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+#define DH_P_LEN sizeof(dh_p_val)
 
-const int DH_G_VAL = 2;
+static const int DH_G_VAL = 2;
 
 static void kexinitialise();
 void gen_new_keys();
@@ -621,7 +622,7 @@
 		erralgo = "enc c->s";
 		goto error;
 	}
-	TRACE(("c2s is  %s", c2s_cipher_algo->name))
+	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);
@@ -629,7 +630,7 @@
 		erralgo = "enc s->c";
 		goto error;
 	}
-	TRACE(("s2c is  %s", s2c_cipher_algo->name))
+	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);
@@ -637,6 +638,7 @@
 		erralgo = "mac c->s";
 		goto error;
 	}
+	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);
@@ -644,6 +646,7 @@
 		erralgo = "mac s->c";
 		goto error;
 	}
+	TRACE(("hash s2c is  %s", s2c_hash_algo->name))
 
 	/* compression_algorithms_client_to_server */
 	c2s_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
@@ -651,6 +654,7 @@
 		erralgo = "comp c->s";
 		goto error;
 	}
+	TRACE(("hash c2s is  %s", c2s_comp_algo->name))
 
 	/* compression_algorithms_server_to_client */
 	s2c_comp_algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
@@ -658,6 +662,7 @@
 		erralgo = "comp s->c";
 		goto error;
 	}
+	TRACE(("hash s2c is  %s", s2c_comp_algo->name))
 
 	/* languages_client_to_server */
 	buf_eatstring(ses.payload);
@@ -700,13 +705,6 @@
 		ses.newkeys->trans_algo_comp = s2c_comp_algo->val;
 	}
 
-	TRACE(("enc algo recv %s", algo->name))
-	TRACE(("enc algo trans %s", algo->name))
-	TRACE(("mac algo recv %s", algo->name))
-	TRACE(("mac algo trans %s", algo->name))
-	TRACE(("comp algo recv %s", algo->name))
-	TRACE(("comp algo trans %s", algo->name))
-
 	/* reserved for future extensions */
 	buf_getint(ses.payload);
 	return;
--- a/common-session.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/common-session.c	Tue Sep 06 04:57:14 2005 +0000
@@ -62,7 +62,6 @@
 	ses.connecttimeout = 0;
 	
 	kexfirstinitialise(); /* initialise the kex state */
-	chaninitialise(); /* initialise the channel state */
 
 	ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
 	ses.transseq = 0;
@@ -126,7 +125,7 @@
 		timeout.tv_usec = 0;
 		FD_ZERO(&writefd);
 		FD_ZERO(&readfd);
-		assert(ses.payload == NULL);
+		dropbear_assert(ses.payload == NULL);
 		if (ses.sock != -1) {
 			FD_SET(ses.sock, &readfd);
 			if (!isempty(&ses.writequeue)) {
--- a/dbutil.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/dbutil.c	Tue Sep 06 04:57:14 2005 +0000
@@ -110,6 +110,10 @@
 	exit(exitcode);
 }
 
+void fail_assert(const char* expr, const char* file, int line) {
+	dropbear_exit("failed assertion (%s:%d): `%s'", file, line, expr);
+}
+
 static void generic_dropbear_log(int UNUSED(priority), const char* format, 
 		va_list param) {
 
@@ -186,6 +190,10 @@
 			*errstring = (char*)m_malloc(len);
 			snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
 		}
+		if (res0) {
+			freeaddrinfo(res0);
+			res0 = NULL;
+		}
 		TRACE(("leave dropbear_listen: failed resolving"))
 		return -1;
 	}
@@ -237,6 +245,11 @@
 		nsock++;
 	}
 
+	if (res0) {
+		freeaddrinfo(res0);
+		res0 = NULL;
+	}
+
 	if (nsock == 0) {
 		if (errstring != NULL && *errstring == NULL) {
 			int len;
--- a/dbutil.h	Tue Sep 06 04:52:46 2005 +0000
+++ b/dbutil.h	Tue Sep 06 04:57:14 2005 +0000
@@ -39,6 +39,7 @@
 void dropbear_exit(const char* format, ...);
 void dropbear_close(const char* format, ...);
 void dropbear_log(int priority, const char* format, ...);
+void fail_assert(const char* expr, const char* file, int line);
 #ifdef DEBUG_TRACE
 void dropbear_trace(const char* format, ...);
 void printhex(const char * label, const unsigned char * buf, int len);
@@ -66,4 +67,7 @@
 /* Used to force mp_ints to be initialised */
 #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
 
+/* Dropbear assertion */
+#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
+
 #endif /* _DBUTIL_H_ */
--- a/dss.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/dss.c	Tue Sep 06 04:57:14 2005 +0000
@@ -46,7 +46,7 @@
 int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
 
 	TRACE(("enter buf_get_dss_pub_key"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	key->p = m_malloc(sizeof(mp_int));
 	key->q = m_malloc(sizeof(mp_int));
 	key->g = m_malloc(sizeof(mp_int));
@@ -80,7 +80,7 @@
 
 	int ret = DROPBEAR_FAILURE;
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	ret = buf_get_dss_pub_key(buf, key);
 	if (ret == DROPBEAR_FAILURE) {
@@ -137,7 +137,7 @@
  */
 void buf_put_dss_pub_key(buffer* buf, dss_key *key) {
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
 	buf_putmpint(buf, key->p);
 	buf_putmpint(buf, key->q);
@@ -149,7 +149,7 @@
 /* Same as buf_put_dss_pub_key, but with the private "x" key appended */
 void buf_put_dss_priv_key(buffer* buf, dss_key *key) {
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	buf_put_dss_pub_key(buf, key);
 	buf_putmpint(buf, key->x);
 
@@ -172,7 +172,7 @@
 	int stringlen;
 
 	TRACE(("enter buf_dss_verify"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
 
@@ -310,7 +310,7 @@
 	hash_state hs;
 	
 	TRACE(("enter buf_put_dss_sign"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	
 	/* hash the data */
 	sha1_init(&hs);
@@ -380,7 +380,7 @@
 	buf_putint(buf, 2*SHA1_HASH_SIZE);
 
 	writelen = mp_unsigned_bin_size(&dss_r);
-	assert(writelen <= SHA1_HASH_SIZE);
+	dropbear_assert(writelen <= SHA1_HASH_SIZE);
 	/* need to pad to 160 bits with leading zeros */
 	for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
 		buf_putbyte(buf, 0);
@@ -393,7 +393,7 @@
 	buf_incrwritepos(buf, writelen);
 
 	writelen = mp_unsigned_bin_size(&dss_s);
-	assert(writelen <= SHA1_HASH_SIZE);
+	dropbear_assert(writelen <= SHA1_HASH_SIZE);
 	/* need to pad to 160 bits with leading zeros */
 	for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
 		buf_putbyte(buf, 0);
--- a/kex.h	Tue Sep 06 04:52:46 2005 +0000
+++ b/kex.h	Tue Sep 06 04:57:14 2005 +0000
@@ -42,11 +42,6 @@
 void send_msg_kexdh_init(); /* client */
 void recv_msg_kexdh_reply(); /* client */
 
-extern const unsigned char dh_p_val[];
-#define DH_P_LEN 128 /* The length of the dh_p_val array */
-
-extern const int DH_G_VAL; /* == 2 */
-
 struct KEXState {
 
 	unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
--- a/keyimport.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/keyimport.c	Tue Sep 06 04:57:14 2005 +0000
@@ -203,7 +203,7 @@
 	unsigned long outlen;
 	int rawcpl;
 	rawcpl = cpl * 3 / 4;
-	assert((unsigned int)cpl < sizeof(out));
+	dropbear_assert((unsigned int)cpl < sizeof(out));
 
     while (datalen > 0) {
 		n = (datalen < rawcpl ? datalen : rawcpl);
@@ -714,7 +714,7 @@
 	}
 #endif
 
-	assert(keytype != -1);
+	dropbear_assert(keytype != -1);
 
 	/*
 	 * Fetch the key blobs.
@@ -913,7 +913,7 @@
 	 * with the same value. Those are all removed and the rest is
 	 * returned.
 	 */
-	assert(pos == len);
+	dropbear_assert(pos == len);
 	while (pos < outlen) {
 		outblob[pos++] = outlen - len;
 	}
@@ -1491,7 +1491,7 @@
 		privlen = pos - publen;
 	}
 
-	assert(privlen > 0);			   /* should have bombed by now if not */
+	dropbear_assert(privlen > 0);			   /* should have bombed by now if not */
 
 	retkey = snew(struct ssh2_userkey);
 	retkey->alg = alg;
@@ -1557,7 +1557,7 @@
 		pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
 		pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
 
-		assert(e.start && iqmp.start); /* can't go wrong */
+		dropbear_assert(e.start && iqmp.start); /* can't go wrong */
 
 		numbers[0] = e;
 		numbers[1] = d;
@@ -1581,7 +1581,7 @@
 		pos = 0;
 		pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
 
-		assert(y.start && x.start); /* can't go wrong */
+		dropbear_assert(y.start && x.start); /* can't go wrong */
 
 		numbers[0] = p;
 		numbers[1] = g;
@@ -1593,7 +1593,7 @@
 		initial_zero = 1;
 		type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
 	} else {
-		assert(0);					 /* zoinks! */
+		dropbear_assert(0);					 /* zoinks! */
 	}
 
 	/*
@@ -1637,13 +1637,13 @@
 	}
 	ciphertext = (char *)outblob+lenpos+4;
 	cipherlen = pos - (lenpos+4);
-	assert(!passphrase || cipherlen % 8 == 0);
+	dropbear_assert(!passphrase || cipherlen % 8 == 0);
 	/* Wrap up the encrypted blob string. */
 	PUT_32BIT(outblob+lenpos, cipherlen);
 	/* And finally fill in the total length field. */
 	PUT_32BIT(outblob+4, pos);
 
-	assert(pos < outlen);
+	dropbear_assert(pos < outlen);
 
 	/*
 	 * Encrypt the key.
--- a/options.h	Tue Sep 06 04:52:46 2005 +0000
+++ b/options.h	Tue Sep 06 04:57:14 2005 +0000
@@ -65,25 +65,30 @@
 #define ENABLE_AGENTFWD
 
 /* Encryption - at least one required.
- * RFC Draft requires 3DES, and recommends Blowfish, AES128 & Twofish128 */
+ * RFC Draft requires 3DES and recommends AES128 for interoperability.
+ * Including multiple keysize variants the same cipher 
+ * (eg AES256 as well as AES128) will result in a minimal size increase.*/
 #define DROPBEAR_AES128_CBC
-#define DROPBEAR_BLOWFISH_CBC
-#define DROPBEAR_TWOFISH128_CBC
 #define DROPBEAR_3DES_CBC
+#define DROPBEAR_AES256_CBC
+#define DROPBEAR_BLOWFISH_CBC
+#define DROPBEAR_TWOFISH256_CBC
+#define DROPBEAR_TWOFISH128_CBC
 
-/* Integrity - at least one required.
- * RFC Draft requires sha1-hmac, and recommends md5-hmac.
+/* Message Integrity - at least one required.
+ * RFC Draft requires sha1 and recommends sha1-96.
+ * sha1-96 may be of use for slow links, as it has a smaller overhead.
  *
- * Note: there's no point disabling sha1 to save space, since it's used in the
+ * Note: there's no point disabling sha1 to save space, since it's used
  * for the random number generator and public-key cryptography anyway.
  * Disabling it here will just stop it from being used as the integrity portion
  * of the ssh protocol.
  *
- * These are also used for key fingerprints in logs (when pubkey auth is used),
- * MD5 fingerprints are printed if available, however SHA1 fingerprints will be
- * generated otherwise. This isn't exactly optimal, although SHA1 fingerprints
- * are not too hard to create from pubkeys if required. */
+ * These hashes are also used for public key fingerprints in logs.
+ * If you disable MD5, Dropbear will fall back to SHA1 fingerprints,
+ * which are not the standard form. */
 #define DROPBEAR_SHA1_HMAC
+#define DROPBEAR_SHA1_96_HMAC
 #define DROPBEAR_MD5_HMAC
 
 /* Hostkey/public key algorithms - at least one required, these are used
@@ -276,7 +281,7 @@
 #define MAX_MAC_LEN SHA1_HASH_SIZE
 
 
-#define MAX_KEY_LEN 24 /* 3DES requires a 24 byte key */
+#define MAX_KEY_LEN 32 /* 256 bits for aes256 etc */
 #define MAX_IV_LEN 20 /* must be same as max blocksize, 
 						 and >= SHA1_HASH_SIZE */
 #define MAX_MAC_KEY 20
@@ -313,6 +318,14 @@
 
 #define DROPBEAR_MAX_CLI_PASS 1024
 
+#if defined(DROPBEAR_AES256_CBC) || defined(DROPBEAR_AES128_CBC)
+#define DROPBEAR_AES_CBC
+#endif
+
+#if defined(DROPBEAR_TWOFISH256_CBC) || defined(DROPBEAR_TWOFISH128_CBC)
+#define DROPBEAR_TWOFISH_CBC
+#endif
+
 #ifndef ENABLE_X11FWD
 #define DISABLE_X11FWD
 #endif
--- a/packet.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/packet.c	Tue Sep 06 04:57:14 2005 +0000
@@ -53,13 +53,13 @@
 	buffer * writebuf = NULL;
 	
 	TRACE(("enter write_packet"))
-	assert(!isempty(&ses.writequeue));
+	dropbear_assert(!isempty(&ses.writequeue));
 
 	/* Get the next buffer in the queue of encrypted packets to write*/
 	writebuf = (buffer*)examine(&ses.writequeue);
 
 	len = writebuf->len - writebuf->pos;
-	assert(len > 0);
+	dropbear_assert(len > 0);
 	/* Try to write as much as possible */
 	written = write(ses.sock, buf_getptr(writebuf, len), len);
 
@@ -118,7 +118,7 @@
 
 	/* Attempt to read the remainder of the packet, note that there
 	 * mightn't be any available (EAGAIN) */
-	assert(ses.readbuf != NULL);
+	dropbear_assert(ses.readbuf != NULL);
 	maxlen = ses.readbuf->len - ses.readbuf->pos;
 	len = read(ses.sock, buf_getptr(ses.readbuf, maxlen), maxlen);
 
@@ -162,7 +162,7 @@
 	if (ses.readbuf == NULL) {
 		/* start of a new packet */
 		ses.readbuf = buf_new(INIT_READBUF);
-		assert(ses.decryptreadbuf == NULL);
+		dropbear_assert(ses.decryptreadbuf == NULL);
 		ses.decryptreadbuf = buf_new(blocksize);
 	}
 
@@ -215,7 +215,7 @@
 	if ((len > MAX_PACKET_LEN) ||
 		(len < MIN_PACKET_LEN + macsize) ||
 		((len - macsize) % blocksize != 0)) {
-		dropbear_exit("bad packet size");
+		dropbear_exit("bad packet size %d", len);
 	}
 
 	buf_resize(ses.readbuf, len);
@@ -314,14 +314,13 @@
  * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
 static int checkmac(buffer* macbuf, buffer* sourcebuf) {
 
-	unsigned char macsize;
+	unsigned int macsize;
 	hmac_state hmac;
 	unsigned char tempbuf[MAX_MAC_LEN];
-	unsigned long hashsize;
-	int len;
+	unsigned long bufsize;
+	unsigned int len;
 
 	macsize = ses.keys->recv_algo_mac->hashsize;
-
 	if (macsize == 0) {
 		return DROPBEAR_SUCCESS;
 	}
@@ -347,8 +346,8 @@
 		dropbear_exit("HMAC error");
 	}
 
-	hashsize = sizeof(tempbuf);
-	if (hmac_done(&hmac, tempbuf, &hashsize) != CRYPT_OK) {
+	bufsize = sizeof(tempbuf);
+	if (hmac_done(&hmac, tempbuf, &bufsize) != CRYPT_OK) {
 		dropbear_exit("HMAC error");
 	}
 
@@ -524,15 +523,15 @@
 /* Create the packet mac, and append H(seqno|clearbuf) to the output */
 static void writemac(buffer * outputbuffer, buffer * clearwritebuf) {
 
-	int macsize;
+	unsigned int macsize;
 	unsigned char seqbuf[4];
-	unsigned long hashsize;
+	unsigned char tempbuf[MAX_MAC_LEN];
+	unsigned long bufsize;
 	hmac_state hmac;
 
 	TRACE(("enter writemac"))
 
 	macsize = ses.keys->trans_algo_mac->hashsize;
-
 	if (macsize > 0) {
 		/* calculate the mac */
 		if (hmac_init(&hmac, 
@@ -557,12 +556,12 @@
 			dropbear_exit("HMAC error");
 		}
 	
-		hashsize = macsize;
-		if (hmac_done(&hmac, buf_getwriteptr(outputbuffer, macsize), &hashsize) 
+		bufsize = sizeof(tempbuf);
+		if (hmac_done(&hmac, tempbuf, &bufsize) 
 				!= CRYPT_OK) {
 			dropbear_exit("HMAC error");
 		}
-		buf_incrwritepos(outputbuffer, macsize);
+		buf_putbytes(outputbuffer, tempbuf, macsize);
 	}
 	TRACE(("leave writemac"))
 }
@@ -601,7 +600,7 @@
 			break;
 		}
 
-		assert(ses.keys->trans_zstream->avail_out == 0);
+		dropbear_assert(ses.keys->trans_zstream->avail_out == 0);
 
 		/* the buffer has been filled, we must extend. This only happens in
 		 * unusual circumstances where the data grows in size after deflate(),
--- a/queue.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/queue.c	Tue Sep 06 04:57:14 2005 +0000
@@ -42,7 +42,7 @@
 
 	void* ret;
 	struct Link* oldhead;
-	assert(!isempty(queue));
+	dropbear_assert(!isempty(queue));
 	
 	ret = queue->head->item;
 	oldhead = queue->head;
@@ -62,7 +62,7 @@
 
 void *examine(struct Queue* queue) {
 
-	assert(!isempty(queue));
+	dropbear_assert(!isempty(queue));
 	return queue->head->item;
 }
 
--- a/rsa.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/rsa.c	Tue Sep 06 04:57:14 2005 +0000
@@ -49,7 +49,7 @@
 int buf_get_rsa_pub_key(buffer* buf, rsa_key *key) {
 
 	TRACE(("enter buf_get_rsa_pub_key"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	key->e = m_malloc(sizeof(mp_int));
 	key->n = m_malloc(sizeof(mp_int));
 	m_mp_init_multi(key->e, key->n, NULL);
@@ -80,7 +80,7 @@
  * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
 int buf_get_rsa_priv_key(buffer* buf, rsa_key *key) {
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	TRACE(("enter buf_get_rsa_priv_key"))
 
@@ -163,7 +163,7 @@
 void buf_put_rsa_pub_key(buffer* buf, rsa_key *key) {
 
 	TRACE(("enter buf_put_rsa_pub_key"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
 	buf_putmpint(buf, key->e);
@@ -178,7 +178,7 @@
 
 	TRACE(("enter buf_put_rsa_priv_key"))
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 	buf_put_rsa_pub_key(buf, key);
 	buf_putmpint(buf, key->d);
 
@@ -209,7 +209,7 @@
 
 	TRACE(("enter buf_rsa_verify"))
 
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
 
@@ -267,7 +267,7 @@
 	unsigned char *tmpbuf;
 	
 	TRACE(("enter buf_put_rsa_sign"))
-	assert(key != NULL);
+	dropbear_assert(key != NULL);
 
 	m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
 
@@ -320,7 +320,7 @@
 	buf_putint(buf, nsize);
 	/* pad out s to same length as n */
 	ssize = mp_unsigned_bin_size(&rsa_s);
-	assert(ssize <= nsize);
+	dropbear_assert(ssize <= nsize);
 	for (i = 0; i < nsize-ssize; i++) {
 		buf_putbyte(buf, 0x00);
 	}
@@ -365,8 +365,8 @@
 	hash_state hs;
 	unsigned int nsize;
 	
-	assert(key != NULL);
-	assert(data != NULL);
+	dropbear_assert(key != NULL);
+	dropbear_assert(data != NULL);
 	nsize = mp_unsigned_bin_size(key->n);
 
 	rsa_EM = buf_new(nsize-1);
@@ -387,7 +387,7 @@
 	sha1_done(&hs, buf_getwriteptr(rsa_EM, SHA1_HASH_SIZE));
 	buf_incrwritepos(rsa_EM, SHA1_HASH_SIZE);
 
-	assert(rsa_EM->pos == rsa_EM->size);
+	dropbear_assert(rsa_EM->pos == rsa_EM->size);
 
 	/* Create the mp_int from the encoded bytes */
 	buf_setpos(rsa_EM, 0);
--- a/signkey.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/signkey.c	Tue Sep 06 04:57:14 2005 +0000
@@ -404,6 +404,9 @@
 	if (bloblen == DSS_SIGNATURE_SIZE &&
 			memcmp(ident, SSH_SIGNKEY_DSS, identlen) == 0) {
 		m_free(ident);
+		if (key->dsskey == NULL) {
+			dropbear_exit("no dss key to verify signature");
+		}
 		return buf_dss_verify(buf, key->dsskey, data, len);
 	}
 #endif
@@ -411,6 +414,9 @@
 #ifdef DROPBEAR_RSA
 	if (memcmp(ident, SSH_SIGNKEY_RSA, identlen) == 0) {
 		m_free(ident);
+		if (key->rsakey == NULL) {
+			dropbear_exit("no rsa key to verify signature");
+		}
 		return buf_rsa_verify(buf, key->rsakey, data, len);
 	}
 #endif
--- a/svr-authpam.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/svr-authpam.c	Tue Sep 06 04:57:14 2005 +0000
@@ -54,34 +54,58 @@
 	int rc = PAM_SUCCESS;
 	struct pam_response* resp = NULL;
 	struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr;
+	unsigned int msg_len = 0;
+	unsigned int i = 0;
 
 	const char* message = (*msg)->msg;
 
+	// make a copy we can strip
+	char * compare_message = m_strdup(message);
+
 	TRACE(("enter pamConvFunc"))
 
 	if (num_msg != 1) {
 		/* If you're getting here - Dropbear probably can't support your pam
 		 * modules. This whole file is a bit of a hack around lack of
-		 * asynchronocity in PAM anyway */
+		 * asynchronocity in PAM anyway. */
 		dropbear_log(LOG_INFO, "pamConvFunc() called with >1 messages: not supported.");
 		return PAM_CONV_ERR;
 	}
 	
 	TRACE(("msg_style is %d", (*msg)->msg_style))
-	if (message) {
-		TRACE(("message is '%s'", message))
+	if (compare_message) {
+		TRACE(("message is '%s'", compare_message))
 	} else {
 		TRACE(("null message"))
 	}
 
+
+	// Make the string lowercase.
+	msg_len = strlen(compare_message);
+	for (i = 0; i < msg_len; i++) {
+		compare_message[i] = tolower(compare_message[i]);
+	}
+
+	// If the string ends with ": ", remove the space.
+	// ie "login: " vs "login:"
+	if (msg_len > 2 
+			&& compare_message[msg_len-2] == ':' 
+			&& compare_message[msg_len-1] == ' ') {
+		compare_message[msg_len-1] = '\0';
+	}
+
 	switch((*msg)->msg_style) {
 
 		case PAM_PROMPT_ECHO_OFF:
 
-			if (strcmp(message, "Password:") != 0) {
-					TRACE(("PAM_PROMPT_ECHO_OFF: unrecognized prompt"))
-					rc = PAM_CONV_ERR;
-					break;
+			if (!(strcmp(compare_message, "password:") == 0)) {
+				// We don't recognise the prompt as asking for a password,
+				// so can't handle it. Add more above as required for
+				// different pam modules/implementations
+				dropbear_log(LOG_NOTICE, "PAM unknown prompt %s (no echo)",
+						compare_message);
+				rc = PAM_CONV_ERR;
+				break;
 			}
 
 			/* You have to read the PAM module-writers' docs (do we look like
@@ -99,10 +123,13 @@
 
 		case PAM_PROMPT_ECHO_ON:
 
-			if ((strcmp(message, "login: " ) != 0) 
-					&& (strcmp(message, "login:" ) != 0)
-					&& (strcmp(message, "Please enter username: " ) != 0)) {
-				TRACE(("PAM_PROMPT_ECHO_ON: unrecognized prompt"))
+			if (!((strcmp(compare_message, "login:" ) == 0) 
+				|| (strcmp(compare_message, "please enter username:") == 0))) {
+				// We don't recognise the prompt as asking for a username,
+				// so can't handle it. Add more above as required for
+				// different pam modules/implementations
+				dropbear_log(LOG_NOTICE, "PAM unknown prompt %s (with echo)",
+						compare_message);
 				rc = PAM_CONV_ERR;
 				break;
 			}
@@ -125,6 +152,7 @@
 			break;      
 	}
 
+	m_free(compare_message);
 	TRACE(("leave pamConvFunc, rc %d", rc))
 
 	return rc;
--- a/svr-authpubkey.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/svr-authpubkey.c	Tue Sep 06 04:57:14 2005 +0000
@@ -266,7 +266,6 @@
 
 	TRACE(("enter checkpubkeyperms"))
 
-	assert(ses.authstate.pw);
 	if (ses.authstate.pw->pw_dir == NULL) {
 		goto out;
 	}
--- a/svr-chansession.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/svr-chansession.c	Tue Sep 06 04:57:14 2005 +0000
@@ -148,8 +148,8 @@
 static void send_msg_chansess_exitstatus(struct Channel * channel,
 		struct ChanSess * chansess) {
 
-	assert(chansess->exit.exitpid != -1);
-	assert(chansess->exit.exitsignal == -1);
+	dropbear_assert(chansess->exit.exitpid != -1);
+	dropbear_assert(chansess->exit.exitsignal == -1);
 
 	CHECKCLEARTOWRITE();
 
@@ -170,8 +170,8 @@
 	int i;
 	char* signame = NULL;
 
-	assert(chansess->exit.exitpid != -1);
-	assert(chansess->exit.exitsignal > 0);
+	dropbear_assert(chansess->exit.exitpid != -1);
+	dropbear_assert(chansess->exit.exitsignal > 0);
 
 	CHECKCLEARTOWRITE();
 
@@ -205,7 +205,7 @@
 
 	struct ChanSess *chansess;
 
-	assert(channel->typedata == NULL);
+	dropbear_assert(channel->typedata == NULL);
 
 	chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
 	chansess->cmd = NULL;
@@ -279,7 +279,7 @@
 	/* clear child pid entries */
 	for (i = 0; i < svr_ses.childpidsize; i++) {
 		if (svr_ses.childpids[i].chansess == chansess) {
-			assert(svr_ses.childpids[i].pid > 0);
+			dropbear_assert(svr_ses.childpids[i].pid > 0);
 			TRACE(("closing pid %d", svr_ses.childpids[i].pid))
 			TRACE(("exitpid = %d", chansess->exit.exitpid))
 			svr_ses.childpids[i].pid = -1;
@@ -313,7 +313,7 @@
 	}
 
 	chansess = (struct ChanSess*)channel->typedata;
-	assert(chansess != NULL);
+	dropbear_assert(chansess != NULL);
 	TRACE(("type is %s", type))
 
 	if (strcmp(type, "window-change") == 0) {
--- a/svr-main.c	Tue Sep 06 04:52:46 2005 +0000
+++ b/svr-main.c	Tue Sep 06 04:57:14 2005 +0000
@@ -290,7 +290,7 @@
 								getaddrhostname(&remoteaddr),
 								addrstring);
 				/* don't return */
-				assert(0);
+				dropbear_assert(0);
 			}
 			
 			/* parent */