On Thu, Jun 26, 2008 at 05:48:29PM -0400, Sean Peterson wrote: > I've remade the patches in the 'diff -u' format.
Thanks! > Index: kex.c > =================================================================== > RCS file: /cvsroot/libssh2/libssh2/src/kex.c,v > retrieving revision 1.36 > diff -u -r1.36 kex.c > --- kex.c 18 Nov 2007 20:57:13 -0000 1.36 > +++ kex.c 26 Jun 2008 21:32:50 -0000 > @@ -1680,6 +1680,8 @@ > int rc = 0; > int retcode; > > + session->state |= LIBSSH2_STATE_KEX_ACTIVE; > + > if (key_state->state == libssh2_NB_state_idle) { > /* Prevent loop in packet_add() */ > session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; > @@ -1711,11 +1713,14 @@ > if (key_state->state == libssh2_NB_state_sent) { > retcode = libssh2_kexinit(session); > if (retcode == PACKET_EAGAIN) { > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > return PACKET_EAGAIN; > } else if (retcode) { > session->local.kexinit = key_state->oldlocal; > session->local.kexinit_len = key_state->oldlocal_len; > key_state->state = libssh2_NB_state_idle; > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > + session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; > return -1; > } > > @@ -1729,6 +1734,7 @@ > &key_state->data_len, 0, NULL, 0, > &key_state->req_state); > if (retcode == PACKET_EAGAIN) { > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > return PACKET_EAGAIN; > } else if (retcode) { > if (session->local.kexinit) { > @@ -1737,6 +1743,8 @@ > session->local.kexinit = key_state->oldlocal; > session->local.kexinit_len = key_state->oldlocal_len; > key_state->state = libssh2_NB_state_idle; > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > + session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; > return -1; > } > > @@ -1763,6 +1771,7 @@ > session->kex->exchange_keys(session, > &key_state->key_state_low); > if (retcode == PACKET_EAGAIN) { > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > return PACKET_EAGAIN; > } else if (retcode) { > libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, > @@ -1782,6 +1791,7 @@ > session->remote.kexinit = NULL; > } > > + session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; > session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; > > key_state->state = libssh2_NB_state_idle; > Index: libssh2_priv.h > =================================================================== > RCS file: /cvsroot/libssh2/libssh2/src/libssh2_priv.h,v > retrieving revision 1.35 > diff -u -r1.35 libssh2_priv.h > --- libssh2_priv.h 6 Aug 2007 20:48:06 -0000 1.35 > +++ libssh2_priv.h 26 Jun 2008 21:32:05 -0000 > @@ -833,6 +833,7 @@ > #define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001 > #define LIBSSH2_STATE_NEWKEYS 0x00000002 > #define LIBSSH2_STATE_AUTHENTICATED 0x00000004 > +#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008 > > /* session.flag helpers */ > #ifdef MSG_NOSIGNAL > Index: packet.c > =================================================================== > RCS file: /cvsroot/libssh2/libssh2/src/packet.c,v > retrieving revision 1.55 > diff -u -r1.55 packet.c > --- packet.c 6 Aug 2007 20:48:07 -0000 1.55 > +++ packet.c 26 Jun 2008 21:33:09 -0000 > @@ -914,11 +914,31 @@ > > session->packAdd_state = libssh2_NB_state_sent2; > } > + > + /* > + * The KEXINIT message has been added to the queue. > + * The packAdd and readPack states need to be reset > + * because libssh2_kex_exchange (eventually) calls upon > + * libssh2_packet_read to read the rest of the key exchange > + * conversation. > + */ > + session->readPack_state = libssh2_NB_state_idle; > + session->packet.total_num = 0; > + session->packAdd_state = libssh2_NB_state_idle; > + session->fullpacket_state = libssh2_NB_state_idle; > + > + /* > + * Also, don't use packAdd_key_state for key re-exchange, > + * as it will be wiped out in the middle of the exchange. > + * How about re-using the startup_key_state? > + */ > + memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t)); > + > /* > * If there was a key reexchange failure, let's just hope we didn't > * send NEWKEYS yet, otherwise remote will drop us like a rock > */ > - rc = libssh2_kex_exchange(session, 1, &session->packAdd_key_state); > + rc = libssh2_kex_exchange(session, 1, &session->startup_key_state); > if (rc == PACKET_EAGAIN) { > return PACKET_EAGAIN; > } > Index: transport.c > =================================================================== > RCS file: /cvsroot/libssh2/libssh2/src/transport.c,v > retrieving revision 1.13 > diff -u -r1.13 transport.c > --- transport.c 8 Nov 2007 13:51:23 -0000 1.13 > +++ transport.c 26 Jun 2008 21:34:04 -0000 > @@ -269,6 +269,40 @@ > int blocksize; > int encrypted = 1; > > + int status; > + > + /* > + * All channels, systems, subsystems, etc eventually make it down here > + * when looking for more incoming data. If a key exchange is going on > + * (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end > + * will ONLY send key exchange related traffic. In non-blocking mode, > + * there is a chance to break out of the kex_exchange function with an > + * EAGAIN status, and never come back to it. If > LIBSSH2_STATE_EXCHANGING_KEYS > + * is active, then we must redirect to the key exchange. However, > + * if kex_exchange is active (as in it is the one that calls this > execution > + * of packet_read, then don't redirect, as that would be an infinite > loop! > + */ > + > + if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && > + !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { > + > + /* Whoever wants a packet won't get anything until the key > re-exchange > + * is done! > + */ > + _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the" > + " key re-exchange"); > + status = libssh2_kex_exchange(session, 1, > &session->startup_key_state); > + if (status == PACKET_EAGAIN) { > + libssh2_error(session, LIBSSH2_ERROR_EAGAIN, > + "Would block exchanging encryption keys", 0); > + return PACKET_EAGAIN; > + } else if (status) { > + libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, > + "Unable to exchange encryption keys",0); > + return LIBSSH2_ERROR_KEX_FAILURE; > + } > + } > + > /* > * =============================== NOTE =============================== > * I know this is very ugly and not a really good use of "goto", but > @@ -527,8 +561,21 @@ > libssh2_packet_read_point1: > rc = fullpacket(session, encrypted); > if (rc == PACKET_EAGAIN) { > - session->readPack_encrypted = encrypted; > - session->readPack_state = libssh2_NB_state_jump1; > + > + if (session->packAdd_state != libssh2_NB_state_idle) > + { > + /* fullpacket only returns PACKET_EAGAIN if > + * libssh2_packet_add returns PACKET_EAGAIN. If that > + * returns PACKET_EAGAIN but the packAdd_state is idle, > + * then the packet has been added to the brigade, but > some > + * immediate action that was taken based on the packet > + * type (such as key re-exchange) is not yet complete. > + * Clear the way for a new packet to be read in. > + */ > + session->readPack_encrypted = encrypted; > + session->readPack_state = libssh2_NB_state_jump1; > + } > + > return PACKET_EAGAIN; > } > Can I ack or vote for this? What is the process? Please commit it. //Peter ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ libssh2-devel mailing list libssh2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libssh2-devel