Mercurial > dropbear
comparison common-session.c @ 726:78eda530c000
send out our kexinit packet before blocking to read the SSH version string
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 31 Mar 2013 00:40:00 +0800 |
parents | 2e573f39b88e |
children | 70811267715c |
comparison
equal
deleted
inserted
replaced
725:49f68a7b7a55 | 726:78eda530c000 |
---|---|
37 #include "runopts.h" | 37 #include "runopts.h" |
38 | 38 |
39 static void checktimeouts(); | 39 static void checktimeouts(); |
40 static long select_timeout(); | 40 static long select_timeout(); |
41 static int ident_readln(int fd, char* buf, int count); | 41 static int ident_readln(int fd, char* buf, int count); |
42 static void read_session_identification(); | |
42 | 43 |
43 struct sshsession ses; /* GLOBAL */ | 44 struct sshsession ses; /* GLOBAL */ |
44 | 45 |
45 /* need to know if the session struct has been initialised, this way isn't the | 46 /* need to know if the session struct has been initialised, this way isn't the |
46 * cleanest, but works OK */ | 47 * cleanest, but works OK */ |
139 timeout.tv_sec = select_timeout(); | 140 timeout.tv_sec = select_timeout(); |
140 timeout.tv_usec = 0; | 141 timeout.tv_usec = 0; |
141 FD_ZERO(&writefd); | 142 FD_ZERO(&writefd); |
142 FD_ZERO(&readfd); | 143 FD_ZERO(&readfd); |
143 dropbear_assert(ses.payload == NULL); | 144 dropbear_assert(ses.payload == NULL); |
144 if (ses.sock_in != -1) { | 145 |
146 /* during initial setup we flush out the KEXINIT packet before | |
147 * attempting to read the remote version string, which might block */ | |
148 if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { | |
145 FD_SET(ses.sock_in, &readfd); | 149 FD_SET(ses.sock_in, &readfd); |
146 } | 150 } |
147 if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { | 151 if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { |
148 FD_SET(ses.sock_out, &writefd); | 152 FD_SET(ses.sock_out, &writefd); |
149 } | 153 } |
193 } | 197 } |
194 } | 198 } |
195 | 199 |
196 if (ses.sock_in != -1) { | 200 if (ses.sock_in != -1) { |
197 if (FD_ISSET(ses.sock_in, &readfd)) { | 201 if (FD_ISSET(ses.sock_in, &readfd)) { |
198 read_packet(); | 202 if (!ses.remoteident) { |
203 /* blocking read of the version string */ | |
204 read_session_identification(); | |
205 } else { | |
206 read_packet(); | |
207 } | |
199 } | 208 } |
200 | 209 |
201 /* Process the decrypted packet. After this, the read buffer | 210 /* Process the decrypted packet. After this, the read buffer |
202 * will be ready for a new packet */ | 211 * will be ready for a new packet */ |
203 if (ses.payload != NULL) { | 212 if (ses.payload != NULL) { |
243 | 252 |
244 TRACE(("leave session_cleanup")) | 253 TRACE(("leave session_cleanup")) |
245 } | 254 } |
246 | 255 |
247 | 256 |
248 void session_identification() { | 257 void send_session_identification() { |
249 | 258 /* write our version string, this blocks */ |
259 if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n", | |
260 strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { | |
261 ses.remoteclosed(); | |
262 } | |
263 } | |
264 | |
265 static void read_session_identification() { | |
250 /* max length of 255 chars */ | 266 /* max length of 255 chars */ |
251 char linebuf[256]; | 267 char linebuf[256]; |
252 int len = 0; | 268 int len = 0; |
253 char done = 0; | 269 char done = 0; |
254 int i; | 270 int i; |
255 | |
256 /* write our version string, this blocks */ | |
257 if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n", | |
258 strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { | |
259 ses.remoteclosed(); | |
260 } | |
261 | |
262 /* If they send more than 50 lines, something is wrong */ | 271 /* If they send more than 50 lines, something is wrong */ |
263 for (i = 0; i < 50; i++) { | 272 for (i = 0; i < 50; i++) { |
264 len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf)); | 273 len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf)); |
265 | 274 |
266 if (len < 0 && errno != EINTR) { | 275 if (len < 0 && errno != EINTR) { |