Subject: [ libssh2-Bugs-1932587 ] Unable to re-exchange keys with openssh

[ libssh2-Bugs-1932587 ] Unable to re-exchange keys with openssh

From: SourceForge.net <noreply_at_sourceforge.net>
Date: Thu, 07 May 2009 16:51:51 +0000

Bugs item #1932587, was opened at 2008-04-02 22:09
Message generated for change (Comment added) made by bagder
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=703942&aid=1932587&group_id=125852

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
>Status: Pending
>Resolution: Out of Date
Priority: 5
Private: No
Submitted By: Nobody/Anonymous (nobody)
>Assigned to: Daniel Stenberg (bagder)
Summary: Unable to re-exchange keys with openssh

Initial Comment:
When using sftp client to upload a very large file (mine is roughly 3 GB) libssh goes into an infinite loop. I've had this occur using several sshd servers including openssh. The crash is due to a stack overflow.

This is the constant backtrace:

...
fullpacket

libssh2_packet_read
libssh2_packet_require_ex
libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange
libssh2_kex_exchange
libssh2_packet_add
fullpacket

It's easier to repro this if you tweak openssh sshd.c to cause key re-exchange sooner. Currently the settings are after ~1 GB of data xfered. The reccomended settings in the RFC.(http://www.ietf.org/rfc/rfc4253.txt)

Any help would be greatly appreciated.

Thanks,
Mike

----------------------------------------------------------------------

>Comment By: Daniel Stenberg (bagder)
Date: 2009-05-07 18:51

Message:
Does this still happen? Do (any of) you have a proper patch for this
problem if so?

----------------------------------------------------------------------

Comment By: Mike Giancola (mikegiancola99)
Date: 2008-04-08 17:00

Message:
Logged In: YES
user_id=2052992
Originator: NO

in packet.c add_packet method, line ~912 in the conditional,

    if ((data[0] == SSH_MSG_KEXINIT &&
         !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
        (session->packAdd_state == libssh2_NB_state_sent2)) {
        if (session->packAdd_state == libssh2_NB_state_sent1) {

why do we need the
    || (session->packAdd_state == libssh2_NB_state_sent2) check?

----------------------------------------------------------------------

Comment By: Nobody/Anonymous (nobody)
Date: 2008-04-07 21:52

Message:
Logged In: NO

I have a "fix" in place, looking to clean it up now.

Changes made (both in packet.c):

In the libssh2_packet_add method, there is a gate around the call to
libssh2_kex_exchange to check if we are in the process of exchanging keys.
However, the OR statement causes this call to be executed even if we're in
the process of exchanging keys. This is why we get stuck in the infinite
loop. My current hack is to put a gate around the call to
libssh2_kex_exchange make sure we only do this once. I'm attempting to
rework the logic in the if statement to accomplish the same goal, only call
this method once if we are exchanging keys.

Additionally, in the libssh2_packet_add if we are in the idle state, we
clear out the packAdd_key_state object in the session. This holds the
components we need to complete the new key exchange. My current hack is to
put a gate around this call to only empty it if we are not exchanging
keys.

With these 2 hacks in place, i'm able to transfer over 4 GB of data. I'm
attempting to find a better solution now.

----------------------------------------------------------------------

Comment By: Mike Giancola (mikegiancola99)
Date: 2008-04-03 15:11

Message:
Logged In: YES
user_id=2052992
Originator: NO

With trace turned on, it appears we're waiting on packet w/ id 31
(SSH_MSG_KEXDH_REPLY). Inside transport.c ::libssh2_packet_read method, i
believe we are parsing either the 31 id'ed packet incorrectly, or the
previous. The encrypted flag is true, but the numdecrypt variable is set to
a negative #. (the p->total_num equals the p->data_num. This causes the
value of numdecrypt to be equal to -skip.

Since numdecrypt is < 0 and numbytes is equal to 0, the readidx and wptr
are never incremented.

Additionally, since total_num and data_num are the same, remainpack == 0,
so we loop again into full packet.

We also never do a recv again to wait on another packet.

----------------------------------------------------------------------

Comment By: Mike Giancola (mikegiancola99)
Date: 2008-04-03 15:05

Message:
Logged In: YES
user_id=2052992
Originator: NO

I changed the sftp.c file in the example/simple/sftp.c to upload a file
instead of receive a file. I believe receive will also have same crash:

    /* ********************************************* */
    /* Send a file instead of receive */
    /* ********************************************* */
    LIBSSH2_SFTP_HANDLE* sftp_dir = 0;
    sftp_dir = libssh2_sftp_opendir(sftp_session, "/");

    sftp_handle = libssh2_sftp_open(sftp_session, "bigfile.data",
                                   
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
                                   
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
                                   
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);

    /* Request a file via SFTP */
// sftp_handle =
// libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, 0);

    if (!sftp_handle)
    {
         printf ("mikeg big trouble 1\n");

        fprintf(stderr, "Unable to open file with SFTP\n");
        goto shutdown;
    }

    const char* inFile = "/home/mgiancola/test/bigfile.data";

    FILE* filePtr = fopen(inFile, "rb");
   
    if (!filePtr)
    {
       printf ("unable to open file \n");
       return -1;
    }

    size_t nread = 0;
    size_t my_rc = 0;
    char mem[32768]; // 32k
    char* ptr = 0;

    nread = fread(mem, 1, sizeof(mem), filePtr);
    while (nread > 0)
    {
      ptr = mem;
      my_rc = libssh2_sftp_write(sftp_handle, ptr, nread);
      while ((my_rc > 0) && (nread > 0))
      {
         ptr += rc;
         nread -= rc;

         if (nread > 0)
            my_rc = libssh2_sftp_write(sftp_handle, ptr, nread);
      }
      
      nread = fread(mem, 1, sizeof(mem), filePtr);
   }

   fclose (filePtr);

    /* ********************************************* */
    /* End of send file */
    /* ********************************************* */

----------------------------------------------------------------------

Comment By: Nobody/Anonymous (nobody)
Date: 2008-04-02 22:45

Message:
Logged In: NO

I have a modified version of the simple/sftp.c that exhibits this seg
fault. I can send to anyone for help.

It appears that the failure is around the SSH_MSG_KEXDH_REPLY message. I
see the SSH_MSG_KEXINIT message and i see the client / server agreement on
kex method, host key etc, but then we crash.

----------------------------------------------------------------------

You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=703942&aid=1932587&group_id=125852

------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
libssh2-devel mailing list
libssh2-devel_at_lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel
Received on 2009-05-07