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

Reply via email to