The unified diff between revisions [fdd44441..] and [1d86a4f0..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "INSTALL"
#  from [9efe85a4525184ca98a93c02802a1d42a24f2bcc]
#    to [52b3298eab1a71cead9d4b3364a2ec9090262bf2]
#
# patch "buffer.c"
#  from [2fe54eba701ee5c354f265c40914f2733519af16]
#    to [8818b6d266850c114615e8780d216c588f89d3c1]
#
# patch "channel.h"
#  from [2616df4031a05a3fea394b765fd1004944677ef5]
#    to [2efb08417ba19492fb560c445117e1b1f7c10ae1]
#
# patch "circbuffer.c"
#  from [b56cdc09c658edcbf0fdc60a86c561026e97dd69]
#    to [93e513140e4cc4cbde3d3ece44364ea0715e2a4d]
#
# patch "common-algo.c"
#  from [37d9d05401ab9d81872628b05045b6437296e78b]
#    to [2d5cf5bffa626ee7d0e560e0e5c4005c33d57d71]
#
# patch "common-channel.c"
#  from [522b3539ac8ac8feb32efd8c3e7a0490e51b29c3]
#    to [42c4b46eac09d7abf45f066a008e5d2cafbb0127]
#
# patch "common-kex.c"
#  from [960bfda8deaa204b5866f14647f3cd86d262d93f]
#    to [979eab5eb46970985d3fd14408deed0253dadccb]
#
# patch "common-session.c"
#  from [f88bf6d805c423879d9fd1d9d6e4e19b506bac21]
#    to [2469aa8351074283ffeaaf89f3c56a87f15cc0ed]
#
# patch "dbutil.c"
#  from [9440c0ae5ca45076f63b0f295585bfaeb82dd57c]
#    to [af6e2b48222871a432cf61a0d56ea71ddf82882c]
#
# patch "dbutil.h"
#  from [3806a1758a9a15ee7a1e3b75e3a49c0d27a7343a]
#    to [76eb992fc016821fd1584982e59abe7ac66c5671]
#
# patch "dss.c"
#  from [e72e0ab248024c0d858b55fdd382a414aeb31317]
#    to [d58b7df483ca328e4102dbc59fab1cf85494263e]
#
# patch "kex.h"
#  from [4aedb4c80abfbc1df32da43a4903b34e8cddc56a]
#    to [596a833742cc5ab88d3930e46214f19e129347f2]
#
# patch "keyimport.c"
#  from [38a61bdea3196db5ff2a57fd389236948142b4ef]
#    to [7501b09ed19acd430f1316c2f77eb873b5e93598]
#
# patch "options.h"
#  from [323eba2e14c100c6ed74e49dd07d1fd2507ab448]
#    to [bbbe23e7f3e5b7da71171834bface2d0daf76146]
#
# patch "packet.c"
#  from [f42120b1a2c08b96954a8fa0180b07fa48f22e0f]
#    to [6ec289d04a1bb71593461e80acce2d37fa1eb536]
#
# patch "queue.c"
#  from [ccb24cf04c2fae9ff0008f7181239fff1e93f82b]
#    to [0b2bee6c831b234a3fba77c4ae6d598126a3c07c]
#
# patch "rsa.c"
#  from [a5bd0348ccf9497600f633057ec6028e8cf3c329]
#    to [af6a357404e3480445b0b2835065a3e4666ee812]
#
# patch "signkey.c"
#  from [0b42ca44158bc9c2057064ddf12aa3ab11fb76b4]
#    to [c0ce28d518a22769fdee4e64e6fcd77a9100e61f]
#
# patch "svr-authpam.c"
#  from [48afbf9c99df79c7ba65ddbed8180fc4e2036386]
#    to [d2e49b9902777338e827e1935b24457b86fce347]
#
# patch "svr-authpubkey.c"
#  from [a659d961ca849841adc5ac41a68f360a135763d5]
#    to [57092a2fd0fe65bb974313da25052b87f68f9708]
#
# patch "svr-chansession.c"
#  from [14640c883f2d3f5a07cb5614102eeb7762aa9b79]
#    to [3099235a9ac5121a5c38efd5dadc977998f2fea2]
#
# patch "svr-main.c"
#  from [2fc23167fe2aadc2a1fd5199fb071b742ca41ce1]
#    to [70ce3f2fbdf3eecdc7de06e6a3288456a569d8b6]
#
============================================================
--- INSTALL	9efe85a4525184ca98a93c02802a1d42a24f2bcc
+++ INSTALL	52b3298eab1a71cead9d4b3364a2ec9090262bf2
@@ -28,6 +28,11 @@ Binaries can be strippd with "make strip

 ============================================================================

+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
============================================================
--- buffer.c	2fe54eba701ee5c354f265c40914f2733519af16
+++ buffer.c	8818b6d266850c114615e8780d216c588f89d3c1
@@ -153,7 +153,7 @@ unsigned char buf_getbyte(buffer* buf) {
 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 @@ void buf_putmpint(buffer* buf, mp_int *
 	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");
============================================================
--- channel.h	2616df4031a05a3fea394b765fd1004944677ef5
+++ channel.h	2efb08417ba19492fb560c445117e1b1f7c10ae1
@@ -81,6 +81,10 @@ struct Channel {
 	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 @@ struct ChanType {

 };

-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 @@ void common_recv_msg_channel_data(struct
 		circbuffer * buf);

 #ifdef DROPBEAR_CLIENT
-const struct ChanType clichansess;
+extern const struct ChanType clichansess;
 #endif

 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
============================================================
--- circbuffer.c	b56cdc09c658edcbf0fdc60a86c561026e97dd69
+++ circbuffer.c	93e513140e4cc4cbde3d3ece44364ea0715e2a4d
@@ -66,8 +66,8 @@ unsigned int cbuf_readlen(circbuffer *cb

 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 *c

 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 @@ void cbuf_incrwrite(circbuffer *cbuf, un
 	}

 	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 @@ void cbuf_incrread(circbuffer *cbuf, uns
 		dropbear_exit("bad cbuf read");
 	}

-	assert(cbuf->used >= len);
+	dropbear_assert(cbuf->used >= len);
 	cbuf->used -= len;
 	cbuf->readpos = (cbuf->readpos + len) % cbuf->size;
 }
============================================================
--- common-algo.c	37d9d05401ab9d81872628b05045b6437296e78b
+++ common-algo.c	2d5cf5bffa626ee7d0e560e0e5c4005c33d57d71
@@ -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 @@ const struct dropbear_cipher dropbear_no
    {&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 @@ algo_type sshciphers[] = {
 #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() {
 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 @@ void buf_put_algolist(buffer * buf, algo
 /* 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);
 }
============================================================
--- common-channel.c	522b3539ac8ac8feb32efd8c3e7a0490e51b29c3
+++ common-channel.c	42c4b46eac09d7abf45f066a008e5d2cafbb0127
@@ -147,6 +147,7 @@ struct Channel* newchannel(unsigned int
 	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 @@ static void writechannel(struct Channel*
 		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 @@ static void send_msg_channel_data(struct

 	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 @@ void common_recv_msg_channel_data(struct
 		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 @@ int send_msg_channel_open_init(int fd, c
 	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 @@ void recv_msg_channel_open_confirmation(
 		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 @@ void recv_msg_channel_open_failure() {
 		dropbear_exit("Unknown channel");
 	}

+	if (!channel->await_open) {
+		dropbear_exit("unexpected channel reply");
+	}
+	channel->await_open = 0;
+
 	removechannel(channel);
 }
 #endif /* USING_LISTENERS */
============================================================
--- common-kex.c	960bfda8deaa204b5866f14647f3cd86d262d93f
+++ common-kex.c	979eab5eb46970985d3fd14408deed0253dadccb
@@ -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 @@ const unsigned char dh_p_val[] = {
 	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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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 @@ static void read_kex_algos() {
 		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;
============================================================
--- common-session.c	f88bf6d805c423879d9fd1d9d6e4e19b506bac21
+++ common-session.c	2469aa8351074283ffeaaf89f3c56a87f15cc0ed
@@ -62,7 +62,6 @@ void common_session_init(int sock, char*
 	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 @@ void session_loop(void(*loophandler)())
 		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)) {
============================================================
--- dbutil.c	9440c0ae5ca45076f63b0f295585bfaeb82dd57c
+++ dbutil.c	af6e2b48222871a432cf61a0d56ea71ddf82882c
@@ -110,6 +110,10 @@ static void generic_dropbear_exit(int ex
 	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 @@ int dropbear_listen(const char* address,
 			*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 @@ int dropbear_listen(const char* address,
 		nsock++;
 	}

+	if (res0) {
+		freeaddrinfo(res0);
+		res0 = NULL;
+	}
+
 	if (nsock == 0) {
 		if (errstring != NULL && *errstring == NULL) {
 			int len;
============================================================
--- dbutil.h	3806a1758a9a15ee7a1e3b75e3a49c0d27a7343a
+++ dbutil.h	76eb992fc016821fd1584982e59abe7ac66c5671
@@ -39,6 +39,7 @@ void dropbear_log(int priority, const ch
 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 @@ void setnonblocking(int fd);
 /* 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_ */
============================================================
--- dss.c	e72e0ab248024c0d858b55fdd382a414aeb31317
+++ dss.c	d58b7df483ca328e4102dbc59fab1cf85494263e
@@ -46,7 +46,7 @@ int buf_get_dss_pub_key(buffer* buf, dss
 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 buf_get_dss_priv_key(buffer* buf, ds

 	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, ds
  */
 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 @@ void buf_put_dss_priv_key(buffer* buf, d
 /* 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 buf_dss_verify(buffer* buf, dss_key
 	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 @@ void buf_put_dss_sign(buffer* buf, dss_k
 	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 @@ void buf_put_dss_sign(buffer* buf, dss_k
 	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 @@ void buf_put_dss_sign(buffer* buf, dss_k
 	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);
============================================================
--- kex.h	4aedb4c80abfbc1df32da43a4903b34e8cddc56a
+++ kex.h	596a833742cc5ab88d3930e46214f19e129347f2
@@ -42,11 +42,6 @@ void recv_msg_kexdh_reply(); /* client *
 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 */
============================================================
--- keyimport.c	38a61bdea3196db5ff2a57fd389236948142b4ef
+++ keyimport.c	7501b09ed19acd430f1316c2f77eb873b5e93598
@@ -203,7 +203,7 @@ static void base64_encode_fp(FILE * fp,
 	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 @@ static int openssh_write(const char *fil
 	}
 #endif

-	assert(keytype != -1);
+	dropbear_assert(keytype != -1);

 	/*
 	 * Fetch the key blobs.
@@ -913,7 +913,7 @@ static int openssh_write(const char *fil
 	 * 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 @@ sign_key *sshcom_read(const char *filena
 		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 @@ int sshcom_write(const char *filename, s
 		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 @@ int sshcom_write(const char *filename, s
 		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 @@ int sshcom_write(const char *filename, s
 		initial_zero = 1;
 		type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
 	} else {
-		assert(0);					 /* zoinks! */
+		dropbear_assert(0);					 /* zoinks! */
 	}

 	/*
@@ -1637,13 +1637,13 @@ int sshcom_write(const char *filename, s
 	}
 	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.
============================================================
--- options.h	323eba2e14c100c6ed74e49dd07d1fd2507ab448
+++ options.h	bbbe23e7f3e5b7da71171834bface2d0daf76146
@@ -65,25 +65,30 @@ etc) slower (perhaps by 50%). Recommende
 #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_3DES_CBC
+#define DROPBEAR_AES256_CBC
 #define DROPBEAR_BLOWFISH_CBC
+#define DROPBEAR_TWOFISH256_CBC
 #define DROPBEAR_TWOFISH128_CBC
-#define DROPBEAR_3DES_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 @@ etc) slower (perhaps by 50%). Recommende
 #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 @@ etc) slower (perhaps by 50%). Recommende

 #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
============================================================
--- packet.c	f42120b1a2c08b96954a8fa0180b07fa48f22e0f
+++ packet.c	6ec289d04a1bb71593461e80acce2d37fa1eb536
@@ -53,13 +53,13 @@ void write_packet() {
 	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 @@ void read_packet() {

 	/* 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 @@ static void read_packet_init() {
 	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 @@ static void read_packet_init() {
 	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 @@ static int checkmac(buffer* macbuf, buff
  * 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 @@ static int checkmac(buffer* macbuf, buff
 		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 @@ static void writemac(buffer * outputbuff
 /* 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 @@ static void writemac(buffer * outputbuff
 			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 @@ static void buf_compress(buffer * dest,
 			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(),
============================================================
--- queue.c	ccb24cf04c2fae9ff0008f7181239fff1e93f82b
+++ queue.c	0b2bee6c831b234a3fba77c4ae6d598126a3c07c
@@ -42,7 +42,7 @@ void* dequeue(struct Queue* queue) {

 	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) {

 void *examine(struct Queue* queue) {

-	assert(!isempty(queue));
+	dropbear_assert(!isempty(queue));
 	return queue->head->item;
 }

============================================================
--- rsa.c	a5bd0348ccf9497600f633057ec6028e8cf3c329
+++ rsa.c	af6a357404e3480445b0b2835065a3e4666ee812
@@ -49,7 +49,7 @@ int buf_get_rsa_pub_key(buffer* buf, rsa
 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 @@ int buf_get_rsa_priv_key(buffer* buf, rs
  * 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, rs
 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 @@ void buf_put_rsa_priv_key(buffer* buf, r

 	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 @@ int buf_rsa_verify(buffer * buf, rsa_key

 	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 @@ void buf_put_rsa_sign(buffer* buf, rsa_k
 	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 @@ void buf_put_rsa_sign(buffer* buf, rsa_k
 	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 @@ static void rsa_pad_em(rsa_key * key,
 	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 @@ static void rsa_pad_em(rsa_key * key,
 	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);
============================================================
--- signkey.c	0b42ca44158bc9c2057064ddf12aa3ab11fb76b4
+++ signkey.c	c0ce28d518a22769fdee4e64e6fcd77a9100e61f
@@ -404,6 +404,9 @@ int buf_verify(buffer * buf, sign_key *k
 	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 @@ int buf_verify(buffer * buf, sign_key *k
 #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
============================================================
--- svr-authpam.c	48afbf9c99df79c7ba65ddbed8180fc4e2036386
+++ svr-authpam.c	d2e49b9902777338e827e1935b24457b86fce347
@@ -54,34 +54,58 @@ pamConvFunc(int num_msg,
 	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 @@ pamConvFunc(int num_msg,

 		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 @@ pamConvFunc(int num_msg,
 			break;
 	}

+	m_free(compare_message);
 	TRACE(("leave pamConvFunc, rc %d", rc))

 	return rc;
============================================================
--- svr-authpubkey.c	a659d961ca849841adc5ac41a68f360a135763d5
+++ svr-authpubkey.c	57092a2fd0fe65bb974313da25052b87f68f9708
@@ -266,7 +266,6 @@ static int checkpubkeyperms() {

 	TRACE(("enter checkpubkeyperms"))

-	assert(ses.authstate.pw);
 	if (ses.authstate.pw->pw_dir == NULL) {
 		goto out;
 	}
============================================================
--- svr-chansession.c	14640c883f2d3f5a07cb5614102eeb7762aa9b79
+++ svr-chansession.c	3099235a9ac5121a5c38efd5dadc977998f2fea2
@@ -148,8 +148,8 @@ static void send_msg_chansess_exitstatus
 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 @@ static void send_msg_chansess_exitsignal
 	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 @@ static int newchansess(struct Channel *c

 	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 @@ static void closechansess(struct Channel
 	/* 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 @@ static void chansessionrequest(struct Ch
 	}

 	chansess = (struct ChanSess*)channel->typedata;
-	assert(chansess != NULL);
+	dropbear_assert(chansess != NULL);
 	TRACE(("type is %s", type))

 	if (strcmp(type, "window-change") == 0) {
============================================================
--- svr-main.c	2fc23167fe2aadc2a1fd5199fb071b742ca41ce1
+++ svr-main.c	70ce3f2fbdf3eecdc7de06e6a3288456a569d8b6
@@ -290,7 +290,7 @@ void main_noinetd() {
 								getaddrhostname(&remoteaddr),
 								addrstring);
 				/* don't return */
-				assert(0);
+				dropbear_assert(0);
 			}

 			/* parent */