diff options
author | Matt Johnston <matt@ucc.asn.au> | 2013-05-21 12:09:35 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2013-05-21 12:09:35 +0800 |
commit | 04518e9e801ee57bd6d4caab470da8dc0ec98fd7 (patch) | |
tree | 5e46adedc7cd70e6f7b0547a200544cbcf80b96b /common-session.c | |
parent | 41f531ceafc86507c82847f44f9c9e126d798c48 (diff) | |
parent | a57947c513a53e77de0b2eaa67ca6404f444a29f (diff) |
merge in HEAD
--HG--
branch : ecc
Diffstat (limited to 'common-session.c')
-rw-r--r-- | common-session.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/common-session.c b/common-session.c index ef8e6fa..470d1f6 100644 --- a/common-session.c +++ b/common-session.c @@ -33,12 +33,12 @@ #include "random.h" #include "kex.h" #include "channel.h" -#include "atomicio.h" #include "runopts.h" static void checktimeouts(); static long select_timeout(); static int ident_readln(int fd, char* buf, int count); +static void read_session_identification(); struct sshsession ses; /* GLOBAL */ @@ -49,8 +49,6 @@ int sessinitdone = 0; /* GLOBAL */ /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ int exitflag = 0; /* GLOBAL */ - - /* called only at the start of a session, set up initial state */ void common_session_init(int sock_in, int sock_out) { @@ -84,7 +82,7 @@ void common_session_init(int sock_in, int sock_out) { initqueue(&ses.writequeue); - ses.requirenext = SSH_MSG_KEXINIT; + ses.requirenext[0] = SSH_MSG_KEXINIT; ses.dataallowed = 1; /* we can send data until we actually send the SSH_MSG_KEXINIT */ ses.ignorenext = 0; @@ -141,7 +139,10 @@ void session_loop(void(*loophandler)()) { FD_ZERO(&writefd); FD_ZERO(&readfd); dropbear_assert(ses.payload == NULL); - if (ses.sock_in != -1) { + + /* during initial setup we flush out the KEXINIT packet before + * attempting to read the remote version string, which might block */ + if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { FD_SET(ses.sock_in, &readfd); } if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { @@ -195,7 +196,12 @@ void session_loop(void(*loophandler)()) { if (ses.sock_in != -1) { if (FD_ISSET(ses.sock_in, &readfd)) { - read_packet(); + if (!ses.remoteident) { + /* blocking read of the version string */ + read_session_identification(); + } else { + read_packet(); + } } /* Process the decrypted packet. After this, the read buffer @@ -225,7 +231,7 @@ void session_loop(void(*loophandler)()) { } /* clean up a session on exit */ -void common_session_cleanup() { +void session_cleanup() { TRACE(("enter session_cleanup")) @@ -234,6 +240,10 @@ void common_session_cleanup() { TRACE(("leave session_cleanup: !sessinitdone")) return; } + + if (ses.extra_session_cleanup) { + ses.extra_session_cleanup(); + } if (ses.session_id) { buf_burn(ses.session_id); @@ -253,21 +263,20 @@ void common_session_cleanup() { TRACE(("leave session_cleanup")) } +void send_session_identification() { + buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1); + buf_putbytes(writebuf, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n")); + buf_putbyte(writebuf, 0x0); // packet type + buf_setpos(writebuf, 0); + enqueue(&ses.writequeue, writebuf); +} -void session_identification() { - +static void read_session_identification() { /* max length of 255 chars */ char linebuf[256]; int len = 0; char done = 0; int i; - - /* write our version string, this blocks */ - if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n", - strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { - ses.remoteclosed(); - } - /* If they send more than 50 lines, something is wrong */ for (i = 0; i < 50; i++) { len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf)); |