summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2013-03-31 00:40:00 +0800
committerMatt Johnston <matt@ucc.asn.au>2013-03-31 00:40:00 +0800
commit895fe322a841c036d091bce323cb1afa2547cbd7 (patch)
tree6785311f05a596f90946a764bbe6a608e51863e9
parent97c2588e7f15ecbd92d08d7c29e65bad76aef344 (diff)
downloaddropbear-895fe322a841c036d091bce323cb1afa2547cbd7.tar.gz
send out our kexinit packet before blocking to read the SSH version string
-rw-r--r--cli-session.c2
-rw-r--r--common-session.c29
-rw-r--r--session.h7
-rw-r--r--svr-session.c2
4 files changed, 26 insertions, 14 deletions
diff --git a/cli-session.c b/cli-session.c
index e58fdbd..f862bc8 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -99,7 +99,7 @@ void cli_session(int sock_in, int sock_out) {
sessinitdone = 1;
/* Exchange identification */
- session_identification();
+ send_session_identification();
send_msg_kexinit();
diff --git a/common-session.c b/common-session.c
index f4fa579..ec5c9ed 100644
--- a/common-session.c
+++ b/common-session.c
@@ -39,6 +39,7 @@
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 */
@@ -141,7 +142,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 +199,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
@@ -245,20 +254,20 @@ void common_session_cleanup() {
}
-void session_identification() {
-
- /* max length of 255 chars */
- char linebuf[256];
- int len = 0;
- char done = 0;
- int i;
-
+void send_session_identification() {
/* 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();
}
+}
+static void read_session_identification() {
+ /* max length of 255 chars */
+ char linebuf[256];
+ int len = 0;
+ char done = 0;
+ int i;
/* 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));
diff --git a/session.h b/session.h
index 0719e34..d524226 100644
--- a/session.h
+++ b/session.h
@@ -45,7 +45,7 @@ extern int exitflag;
void common_session_init(int sock_in, int sock_out);
void session_loop(void(*loophandler)());
void common_session_cleanup();
-void session_identification();
+void send_session_identification();
void send_msg_ignore();
const char* get_user_shell();
@@ -111,7 +111,10 @@ struct sshsession {
int sock_in;
int sock_out;
- unsigned char *remoteident;
+ /* remotehost will be initially NULL as we delay
+ * reading the remote version string. it will be set
+ * by the time any recv_() packet methods are called */
+ unsigned char *remoteident;
int maxfd; /* the maximum file descriptor to check with select() */
diff --git a/svr-session.c b/svr-session.c
index cf82289..7234f4a 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -114,7 +114,7 @@ void svr_session(int sock, int childpipe) {
sessinitdone = 1;
/* exchange identification, version etc */
- session_identification();
+ send_session_identification();
/* start off with key exchange */
send_msg_kexinit();