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) {