Attached is a patch to address many of the out of memory handling issues
in libssh2 (plus a couple of spelling mistakes). There are more, but
this is a good start.
>>> Dan
--
http://www.MoveAnnouncer.com The web change of address service
Let webmasters know that your web site has moved
Index: channel.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/channel.c,v
retrieving revision 1.39
diff -u -r1.39 channel.c
--- channel.c 31 Mar 2007 20:28:29 -0000 1.39
+++ channel.c 9 Apr 2007 18:38:27 -0000
@@ -233,7 +233,7 @@
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate temporary space for packet",
0);
- return NULL;
+ goto channel_error;
}
*(s++) = SSH_MSG_CHANNEL_OPEN;
libssh2_htonu32(s, channel_type_len);
@@ -958,7 +958,7 @@
unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4)
*/
if (!force && (adjustment + channel->adjust_queue <
LIBSSH2_CHANNEL_MINADJUST)) {
- _libssh2_debug(channel->session, LIBSSH2_DBG_CONN, "Queing %lu
bytes for receive window adjustment for channel %lu/%lu", adjustment,
channel->local.id, channel->remote.id);
+ _libssh2_debug(channel->session, LIBSSH2_DBG_CONN, "Queueing
%lu bytes for receive window adjustment for channel %lu/%lu", adjustment,
channel->local.id, channel->remote.id);
channel->adjust_queue += adjustment;
return channel->remote.window_size;
}
@@ -1240,7 +1240,7 @@
rc = libssh2_packet_read(session);
if (rc < 0) {
- /* Error or EAGAIN occured, disconnect? */
+ /* Error or EAGAIN occurred, disconnect? */
return rc;
}
Index: comp.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/comp.c,v
retrieving revision 1.9
diff -u -r1.9 comp.c
--- comp.c 4 Apr 2007 14:44:50 -0000 1.9
+++ comp.c 9 Apr 2007 18:39:16 -0000
@@ -191,6 +191,7 @@
}
if (strm->avail_in) {
unsigned long out_ofs = out_maxlen - strm->avail_out;
+ char *newout;
out_maxlen += compress ? (strm->avail_in + 4) : (2 *
strm->avail_in);
@@ -202,11 +203,13 @@
return -1;
}
- out = LIBSSH2_REALLOC(session, out, out_maxlen);
- if (!out) {
+ newout = LIBSSH2_REALLOC(session, out, out_maxlen);
+ if (!newout) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand compress/decompression buffer", 0);
+ LIBSSH2_FREE(session, out);
return -1;
}
+ out = newout;
strm->next_out = (unsigned char *)out + out_ofs;
strm->avail_out += compress ? (strm->avail_in + 4) : (2
* strm->avail_in);
} else while (!strm->avail_out) {
@@ -214,6 +217,7 @@
* Or potentially many bytes if it's a decompress
*/
int grow_size = compress ? 8 : 1024;
+ char *newout;
if (out_maxlen >= (int)payload_limit) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase", 0);
@@ -228,11 +232,13 @@
out_maxlen += grow_size;
strm->avail_out = grow_size;
- out = LIBSSH2_REALLOC(session, out, out_maxlen);
- if (!out) {
+ newout = LIBSSH2_REALLOC(session, out, out_maxlen);
+ if (!newout) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final compress/decompress buffer", 0);
+ LIBSSH2_FREE(session, out);
return -1;
}
+ out = newout;
strm->next_out = (unsigned char *)out + out_maxlen -
grow_size;
Index: packet.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/packet.c,v
retrieving revision 1.48
diff -u -r1.48 packet.c
--- packet.c 5 Apr 2007 09:31:38 -0000 1.48
+++ packet.c 9 Apr 2007 18:41:20 -0000
@@ -368,7 +368,7 @@
if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, (char *)data + 4,
datalen - 5);
}
- LIBSSH2_FREE(session, (char *)data);
+ LIBSSH2_FREE(session, data);
return 0;
break;
case SSH_MSG_DEBUG:
@@ -549,6 +549,11 @@
}
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
+ if (!packet) {
+ _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, "Unable to
allocate memory for LIBSSH2_PACKET");
+ LIBSSH2_FREE(session, data);
+ return -1;
+ }
memset(packet, 0, sizeof(LIBSSH2_PACKET));
packet->data = data;
Index: publickey.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/publickey.c,v
retrieving revision 1.6
diff -u -r1.6 publickey.c
--- publickey.c 2 Feb 2007 23:23:37 -0000 1.6
+++ publickey.c 9 Apr 2007 18:42:25 -0000
@@ -600,13 +600,15 @@
case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
/* What we want */
if (keys >= max_keys) {
+ libssh2_publickey_list *newlist;
/* Grow the key list if necessary */
max_keys += 8;
- list = LIBSSH2_REALLOC(session, list,
(max_keys + 1) * sizeof(libssh2_publickey_list));
- if (!list) {
+ newlist = LIBSSH2_REALLOC(session,
list, (max_keys + 1) * sizeof(libssh2_publickey_list));
+ if (!newlist) {
libssh2_error(session,
LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey list", 0);
goto err_exit;
}
+ list = newlist;
}
if (pkey->version == 1) {
unsigned long comment_len;
Index: session.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/session.c,v
retrieving revision 1.37
diff -u -r1.37 session.c
--- session.c 5 Apr 2007 09:31:38 -0000 1.37
+++ session.c 9 Apr 2007 18:42:58 -0000
@@ -132,6 +132,10 @@
if (!banner_len) return 1;
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
+ if (!session->remote.banner) {
+ libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocating
space for remote banner", 0);
+ return 1;
+ }
memcpy(session->remote.banner, banner, banner_len);
session->remote.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s",
session->remote.banner);
@@ -233,15 +237,16 @@
local_realloc = my_realloc;
session = local_alloc(sizeof(LIBSSH2_SESSION), abstract);
- memset(session, 0, sizeof(LIBSSH2_SESSION));
- session->alloc = local_alloc;
- session->free = local_free;
- session->realloc = local_realloc;
- session->abstract = abstract;
- _libssh2_debug(session, LIBSSH2_DBG_TRANS,
- "New session resource allocated");
- libssh2_crypto_init ();
-
+ if (session) {
+ memset(session, 0, sizeof(LIBSSH2_SESSION));
+ session->alloc = local_alloc;
+ session->free = local_free;
+ session->realloc = local_realloc;
+ session->abstract = abstract;
+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
+ "New session resource allocated");
+ libssh2_crypto_init ();
+ }
return session;
}
/* }}} */
Index: userauth.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/userauth.c,v
retrieving revision 1.20
diff -u -r1.20 userauth.c
--- userauth.c 2 Feb 2007 23:23:37 -0000 1.20
+++ userauth.c 9 Apr 2007 18:45:25 -0000
@@ -182,6 +182,7 @@
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for userauth-password-change request", 0);
+ LIBSSH2_FREE(session, newpw);
return -1;
}
@@ -206,6 +207,7 @@
if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session,
LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password-change request",
0);
LIBSSH2_FREE(session, data);
+ LIBSSH2_FREE(session, newpw);
return -1;
}
LIBSSH2_FREE(session, data);
@@ -373,6 +375,10 @@
/* Preallocate space for an overall length, method name again,
* and the signature, which won't be any larger than the size of the
publickeydata itself */
s = packet = LIBSSH2_ALLOC(session, packet_len + 4 + (4 + method_len) +
(4 + pubkeydata_len));
+ if (!packet) {
+ LIBSSH2_FREE(session, method);
+ return -1;
+ }
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
@@ -423,14 +429,18 @@
privkeyobj->dtor(session, &abstract);
}
- if (sig_len > pubkeydata_len ) {
+ if (sig_len > pubkeydata_len) {
+ unsigned char *newpacket;
/* Should *NEVER* happen, but...well.. better safe than sorry */
- packet = LIBSSH2_REALLOC(session, packet, packet_len + 4 + (4 +
method_len) + (4 + sig_len)); /* PK sigblob */
- if (!packet) {
+ newpacket = LIBSSH2_REALLOC(session, packet, packet_len + 4 +
(4 + method_len) + (4 + sig_len)); /* PK sigblob */
+ if (!newpacket) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed
allocating additional space for userauth-hostbased packet", 0);
+ LIBSSH2_FREE(session, sig);
+ LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
return -1;
}
+ packet = newpacket;
}
s = packet + packet_len;
@@ -499,6 +509,11 @@
/* Preallocate space for an overall length, method name again,
* and the signature, which won't be any larger than the size of the
publickeydata itself */
s = packet = LIBSSH2_ALLOC(session, packet_len + 4 + (4 + method_len) +
(4 + pubkeydata_len));
+ if (!packet) {
+ LIBSSH2_FREE(session, method);
+ LIBSSH2_FREE(session, pubkeydata);
+ return -1;
+ }
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
@@ -518,20 +533,19 @@
libssh2_htonu32(s, pubkeydata_len); s += 4;
memcpy(s, pubkeydata, pubkeydata_len); s +=
pubkeydata_len;
+ LIBSSH2_FREE(session, pubkeydata);
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting publickey
authentication");
if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to
send userauth-publickey request", 0);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
- LIBSSH2_FREE(session, pubkeydata);
return -1;
}
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
- LIBSSH2_FREE(session, pubkeydata);
return -1;
}
@@ -541,7 +555,6 @@
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
- LIBSSH2_FREE(session, pubkeydata);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
@@ -551,14 +564,12 @@
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
- LIBSSH2_FREE(session, pubkeydata);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED,
"Username/PublicKey combination invalid", 0);
return -1;
}
/* Semi-Success! */
LIBSSH2_FREE(session, data);
- LIBSSH2_FREE(session, pubkeydata);
if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract,
method, method_len, privatekey, passphrase)) {
LIBSSH2_FREE(session, method);
@@ -590,13 +601,17 @@
}
if (sig_len > pubkeydata_len) {
+ unsigned char *newpacket;
/* Should *NEVER* happen, but...well.. better safe than sorry */
- packet = LIBSSH2_REALLOC(session, packet, packet_len + 4 + (4 +
method_len) + (4 + sig_len)); /* PK sigblob */
- if (!packet) {
+ newpacket = LIBSSH2_REALLOC(session, packet, packet_len + 4 +
(4 + method_len) + (4 + sig_len)); /* PK sigblob */
+ if (!newpacket) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed
allocating additional space for userauth-publickey packet", 0);
+ LIBSSH2_FREE(session, sig);
+ LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
return -1;
}
+ packet = newpacket;
}
s = packet + packet_len;
Index: kex.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/kex.c,v
retrieving revision 1.26
diff -u -r1.26 kex.c
--- kex.c 2 Feb 2007 23:23:36 -0000 1.26
+++ kex.c 9 Apr 2007 18:52:57 -0000
@@ -44,21 +44,22 @@
libssh2_sha1_ctx hash; \
unsigned long len = 0; \
if (!(value)) { \
- value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
- } \
- while (len < reqlen) { \
- libssh2_sha1_init(&hash); \
- libssh2_sha1_update(hash, k_value, k_value_len); \
- libssh2_sha1_update(hash, h_sig_comp, SHA_DIGEST_LENGTH); \
- if (len > 0) { \
- libssh2_sha1_update(hash, value, len); \
- } else { \
- libssh2_sha1_update(hash, (version), 1); \
- libssh2_sha1_update(hash, session->session_id,
session->session_id_len); \
- } \
- libssh2_sha1_final(hash, (value) + len); \
- len += SHA_DIGEST_LENGTH; \
- } \
+ value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH);
\
+ }
\
+ if (value)
\
+ while (len < reqlen) {
\
+ libssh2_sha1_init(&hash);
\
+ libssh2_sha1_update(hash, k_value, k_value_len);
\
+ libssh2_sha1_update(hash, h_sig_comp,
SHA_DIGEST_LENGTH); \
+ if (len > 0) {
\
+ libssh2_sha1_update(hash, value, len);
\
+ } else {
\
+ libssh2_sha1_update(hash, (version), 1);
\
+ libssh2_sha1_update(hash, session->session_id,
session->session_id_len); \
+ }
\
+ libssh2_sha1_final(hash, (value) + len);
\
+ len += SHA_DIGEST_LENGTH;
\
+ }
\
}
/* {{{ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
@@ -334,7 +335,16 @@
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->local.crypt->iv_len, "A");
+ if (!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->local.crypt->secret_len, "C");
+ if (!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = -1;
+ goto clean_exit;
+ }
if (session->local.crypt->init(session, session->local.crypt,
iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
@@ -365,7 +375,16 @@
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->remote.crypt->iv_len, "B");
+ if (!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->remote.crypt->secret_len, "D");
+ if (!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = -1;
+ goto clean_exit;
+ }
if (session->remote.crypt->init(session, session->remote.crypt,
iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
@@ -394,6 +413,10 @@
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->local.mac->key_len, "E");
+ if (!key) {
+ ret = -1;
+ goto clean_exit;
+ }
session->local.mac->init(session, key, &free_key,
&session->local.mac_abstract);
if (free_key) {
@@ -412,6 +435,10 @@
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->remote.mac->key_len, "F");
+ if (!key) {
+ ret = -1;
+ goto clean_exit;
+ }
session->remote.mac->init(session, key, &free_key,
&session->remote.mac_abstract);
if (free_key) {
@@ -1218,6 +1245,7 @@
{
unsigned char *data;
unsigned long data_len;
+ int rc = 0;
/* Prevent loop in packet_add() */
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
@@ -1259,13 +1287,15 @@
session->remote.kexinit_len = data_len;
if (libssh2_kex_agree_methods(session, data, data_len)) {
- return -3;
+ rc = -3;
}
}
- if (session->kex->exchange_keys(session)) {
- libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys", 0);
- return -4;
+ if (rc == 0) {
+ if (session->kex->exchange_keys(session)) {
+ libssh2_error(session,
LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, "Unrecoverable error exchanging keys", 0);
+ rc = -4;
+ }
}
/* Done with kexinit buffers */
@@ -1280,7 +1310,7 @@
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
- return 0;
+ return rc;
}
/* }}} */
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
libssh2-devel mailing list
libssh2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel