comparison common-channel.c @ 402:173a5f89666c channel-fix

propagate from branch 'au.asn.ucc.matt.dropbear' (head b1dd3b94e60a07a176dba2b035ac79968595990a) to branch 'au.asn.ucc.matt.dropbear.channel-fix' (head fc77c3dea87a7c0f374e738d055f0b455495cbc3)
author Matt Johnston <matt@ucc.asn.au>
date Sat, 03 Feb 2007 08:22:58 +0000
parents a707e6148060 a7eb64b9966a
children 8b9aba1d5fa4
comparison
equal deleted inserted replaced
399:a707e6148060 402:173a5f89666c
41 unsigned int recvwindow, 41 unsigned int recvwindow,
42 unsigned int recvmaxpacket); 42 unsigned int recvmaxpacket);
43 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf); 43 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
44 static void send_msg_channel_window_adjust(struct Channel *channel, 44 static void send_msg_channel_window_adjust(struct Channel *channel,
45 unsigned int incr); 45 unsigned int incr);
46 static void send_msg_channel_data(struct Channel *channel, int isextended, 46 static void send_msg_channel_data(struct Channel *channel, int isextended);
47 unsigned int exttype);
48 static void send_msg_channel_eof(struct Channel *channel); 47 static void send_msg_channel_eof(struct Channel *channel);
49 static void send_msg_channel_close(struct Channel *channel); 48 static void send_msg_channel_close(struct Channel *channel);
50 static void removechannel(struct Channel *channel); 49 static void remove_channel(struct Channel *channel);
51 static void deletechannel(struct Channel *channel); 50 static void delete_channel(struct Channel *channel);
52 static void checkinitdone(struct Channel *channel); 51 static void check_in_progress(struct Channel *channel);
53 static void checkclose(struct Channel *channel); 52 static unsigned int write_pending(struct Channel * channel);
54 53 static void check_close(struct Channel *channel);
55 static void closewritefd(struct Channel * channel); 54 static void close_chan_fd(struct Channel *channel, int fd, int how);
56 static void closereadfd(struct Channel * channel, int fd);
57 static void closechanfd(struct Channel *channel, int fd, int how);
58 55
59 #define FD_UNINIT (-2) 56 #define FD_UNINIT (-2)
60 #define FD_CLOSED (-1) 57 #define FD_CLOSED (-1)
58
59 #define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60 #define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
61 61
62 /* Initialise all the channels */ 62 /* Initialise all the channels */
63 void chaninitialise(const struct ChanType *chantypes[]) { 63 void chaninitialise(const struct ChanType *chantypes[]) {
64 64
65 /* may as well create space for a single channel */ 65 /* may as well create space for a single channel */
83 83
84 TRACE(("enter chancleanup")) 84 TRACE(("enter chancleanup"))
85 for (i = 0; i < ses.chansize; i++) { 85 for (i = 0; i < ses.chansize; i++) {
86 if (ses.channels[i] != NULL) { 86 if (ses.channels[i] != NULL) {
87 TRACE(("channel %d closing", i)) 87 TRACE(("channel %d closing", i))
88 removechannel(ses.channels[i]); 88 remove_channel(ses.channels[i]);
89 } 89 }
90 } 90 }
91 m_free(ses.channels); 91 m_free(ses.channels);
92 TRACE(("leave chancleanup")) 92 TRACE(("leave chancleanup"))
93 } 93 }
133 } 133 }
134 134
135 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); 135 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
136 newchan->type = type; 136 newchan->type = type;
137 newchan->index = i; 137 newchan->index = i;
138 newchan->sentclosed = newchan->recvclosed = 0; 138 newchan->sent_close = newchan->recv_close = 0;
139 newchan->senteof = newchan->recveof = 0; 139 newchan->sent_eof = newchan->recv_eof = 0;
140 140
141 newchan->remotechan = remotechan; 141 newchan->remotechan = remotechan;
142 newchan->transwindow = transwindow; 142 newchan->transwindow = transwindow;
143 newchan->transmaxpacket = transmaxpacket; 143 newchan->transmaxpacket = transmaxpacket;
144 144
162 162
163 return newchan; 163 return newchan;
164 } 164 }
165 165
166 /* Returns the channel structure corresponding to the channel in the current 166 /* Returns the channel structure corresponding to the channel in the current
167 * data packet (ses.payload must be positioned appropriately) */ 167 * data packet (ses.payload must be positioned appropriately).
168 struct Channel* getchannel() { 168 * A valid channel is always returns, it will fail fatally with an unknown
169 * channel */
170 static struct Channel* getchannel_msg(const char* kind) {
169 171
170 unsigned int chan; 172 unsigned int chan;
171 173
172 chan = buf_getint(ses.payload); 174 chan = buf_getint(ses.payload);
173 if (chan >= ses.chansize || ses.channels[chan] == NULL) { 175 if (chan >= ses.chansize || ses.channels[chan] == NULL) {
174 return NULL; 176 if (kind) {
177 dropbear_exit("%s for unknown channel %d", kind, chan);
178 } else {
179 dropbear_exit("Unknown channel %d", chan);
180 }
175 } 181 }
176 return ses.channels[chan]; 182 return ses.channels[chan];
183 }
184
185 struct Channel* getchannel() {
186 return getchannel_msg(NULL);
187 }
188
189 /* In order to tell if a writefd is closed, we put it in the readfd FD_SET.
190 We then just try reading a single byte from it. It'll give EAGAIN or something
191 if the socket is still alive (but the FD probably shouldn't be set anyway?)*/
192 static void check_closed_writefd(struct Channel* channel, int fd) {
193 char c;
194 int ret;
195 TRACE(("enter check_closed_writefd fd %d", fd))
196 if (fd < 0) {
197 TRACE(("leave check_closed_writefd."))
198 return;
199 }
200
201 /* Read something. doing read(fd,x,0) seems to become a NOP on some platforms */
202 ret = read(fd, &c, 1);
203 TRACE(("ret %d errno %d", ret, errno))
204 if (ret > 0 || (ret < 0 && (errno == EINTR || errno == EAGAIN))) {
205 TRACE(("leave check_closed_writefd"))
206 return;
207 }
208 close_chan_fd(channel, fd, SHUT_WR);
209 TRACE(("leave check_closed_writefd after closing %d", fd))
177 } 210 }
178 211
179 /* Iterate through the channels, performing IO if available */ 212 /* Iterate through the channels, performing IO if available */
180 void channelio(fd_set *readfds, fd_set *writefds) { 213 void channelio(fd_set *readfds, fd_set *writefds) {
181 214
182 struct Channel *channel; 215 struct Channel *channel;
183 unsigned int i; 216 unsigned int i;
184 217
185 /* iterate through all the possible channels */ 218 /* foreach channel */
186 for (i = 0; i < ses.chansize; i++) { 219 for (i = 0; i < ses.chansize; i++) {
187 220
188 channel = ses.channels[i]; 221 channel = ses.channels[i];
189 if (channel == NULL) { 222 if (channel == NULL) {
190 /* only process in-use channels */ 223 /* only process in-use channels */
191 continue; 224 continue;
192 } 225 }
193 226
194 /* read data and send it over the wire */ 227 /* read data and send it over the wire */
195 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) { 228 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
196 send_msg_channel_data(channel, 0, 0); 229 send_msg_channel_data(channel, 0);
197 } 230 }
198 231
199 /* read stderr data and send it over the wire */ 232 /* read stderr data and send it over the wire */
200 if (channel->extrabuf == NULL && 233 if (ERRFD_IS_READ(channel) &&
201 channel->errfd >= 0 && FD_ISSET(channel->errfd, readfds)) { 234 channel->errfd >= 0 && FD_ISSET(channel->errfd, readfds)) {
202 send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); 235 send_msg_channel_data(channel, 1);
203 } 236 }
204 237
205 /* write to program/pipe stdin */ 238 /* write to program/pipe stdin */
206 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) { 239 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
207 if (channel->initconn) { 240 if (channel->initconn) {
208 checkinitdone(channel); 241 /* XXX should this go somewhere cleaner? */
242 check_in_progress(channel);
209 continue; /* Important not to use the channel after 243 continue; /* Important not to use the channel after
210 checkinitdone(), as it may be NULL */ 244 check_in_progress(), as it may be NULL */
211 } 245 }
212 writechannel(channel, channel->writefd, channel->writebuf); 246 writechannel(channel, channel->writefd, channel->writebuf);
213 } 247 }
214 248
215 /* stderr for client mode */ 249 /* stderr for client mode */
216 if (channel->extrabuf != NULL 250 if (ERRFD_IS_WRITE(channel)
217 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) { 251 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
218 writechannel(channel, channel->errfd, channel->extrabuf); 252 writechannel(channel, channel->errfd, channel->extrabuf);
219 } 253 }
220 254
221 /* now handle any of the channel-closing type stuff */ 255 /* Check writefds for close, even if we don't have anything
222 checkclose(channel); 256 to write into them. */
223 257 if (channel->writefd >= 0) {
224 } /* foreach channel */ 258 check_closed_writefd(channel, channel->writefd);
259 }
260 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0) {
261 check_closed_writefd(channel, channel->errfd);
262 }
263
264
265 /* handle any channel closing etc */
266 check_close(channel);
267
268 }
225 269
226 /* Listeners such as TCP, X11, agent-auth */ 270 /* Listeners such as TCP, X11, agent-auth */
227 #ifdef USING_LISTENERS 271 #ifdef USING_LISTENERS
228 handle_listeners(readfds); 272 handle_listeners(readfds);
229 #endif 273 #endif
230 } 274 }
231 275
232 276
233 /* do all the EOF/close type stuff checking for a channel */ 277 /* Returns true if there is data remaining to be written to stdin or
234 static void checkclose(struct Channel *channel) { 278 * stderr of a channel's endpoint. */
235 279 static unsigned int write_pending(struct Channel * channel) {
236 TRACE(("checkclose: writefd %d, readfd %d, errfd %d, sentclosed %d, recvclosed %d", 280
281 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
282 return 1;
283 } else if (channel->errfd >= 0 && channel->extrabuf &&
284 cbuf_getused(channel->extrabuf) > 0) {
285 return 1;
286 }
287 return 0;
288 }
289
290
291 /* EOF/close handling */
292 static void check_close(struct Channel *channel) {
293
294 TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
237 channel->writefd, channel->readfd, 295 channel->writefd, channel->readfd,
238 channel->errfd, channel->sentclosed, channel->recvclosed)) 296 channel->errfd, channel->sent_close, channel->recv_close))
239 TRACE(("writebuf size %d extrabuf ptr 0x%x extrabuf size %d", 297 TRACE(("writebuf size %d extrabuf size %d",
240 cbuf_getused(channel->writebuf), 298 cbuf_getused(channel->writebuf),
241 channel->writebuf, 299 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
242 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) 300
243 301 if (channel->recv_close && !write_pending(channel)) {
244 if (!channel->sentclosed) { 302 if (! channel->sent_close) {
245
246 /* check for exited - currently only used for server sessions,
247 * if the shell has exited etc */
248 if (channel->type->checkclose) {
249 if (channel->type->checkclose(channel)) {
250 closewritefd(channel);
251 }
252 }
253
254 if (!channel->senteof
255 && channel->readfd == FD_CLOSED
256 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
257 send_msg_channel_eof(channel);
258 }
259
260 if (channel->writefd == FD_CLOSED
261 && channel->readfd == FD_CLOSED
262 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
263 send_msg_channel_close(channel);
264 }
265 }
266
267 /* When either party wishes to terminate the channel, it sends
268 * SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST
269 * send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this
270 * message for the channel. The channel is considered closed for a
271 * party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and
272 * the party may then reuse the channel number. A party MAY send
273 * SSH_MSG_CHANNEL_CLOSE without having sent or received
274 * SSH_MSG_CHANNEL_EOF.
275 * (from draft-ietf-secsh-connect)
276 */
277 if (channel->recvclosed) {
278 if (! channel->sentclosed) {
279 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same.")) 303 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
280 send_msg_channel_close(channel); 304 send_msg_channel_close(channel);
281 } 305 }
282 removechannel(channel); 306 remove_channel(channel);
283 } 307 return;
308 }
309
310 if (channel->recv_eof && !write_pending(channel)) {
311 close_chan_fd(channel, channel->writefd, SHUT_WR);
312 }
313
314 /* If we're not going to send any more data, send EOF */
315 if (!channel->sent_eof
316 && channel->readfd == FD_CLOSED
317 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
318 send_msg_channel_eof(channel);
319 }
320
321 /* And if we can't receive any more data from them either, close up */
322 if (!channel->sent_close
323 && channel->writefd == FD_CLOSED
324 && channel->readfd == FD_CLOSED
325 && channel->errfd == FD_CLOSED) {
326 send_msg_channel_close(channel);
327 }
328
284 } 329 }
285 330
286 331
287 /* Check whether a deferred (EINPROGRESS) connect() was successful, and 332 /* Check whether a deferred (EINPROGRESS) connect() was successful, and
288 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so 333 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
289 * it is important that the channel reference isn't used after a call to this 334 * it is important that the channel reference isn't used after a call to this
290 * function */ 335 * function */
291 static void checkinitdone(struct Channel *channel) { 336 static void check_in_progress(struct Channel *channel) {
292 337
293 int val; 338 int val;
294 socklen_t vallen = sizeof(val); 339 socklen_t vallen = sizeof(val);
295 340
296 TRACE(("enter checkinitdone")) 341 TRACE(("enter check_in_progress"))
297 342
298 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen) 343 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
299 || val != 0) { 344 || val != 0) {
300 send_msg_channel_open_failure(channel->remotechan, 345 send_msg_channel_open_failure(channel->remotechan,
301 SSH_OPEN_CONNECT_FAILED, "", ""); 346 SSH_OPEN_CONNECT_FAILED, "", "");
302 close(channel->writefd); 347 close(channel->writefd);
303 deletechannel(channel); 348 delete_channel(channel);
304 TRACE(("leave checkinitdone: fail")) 349 TRACE(("leave check_in_progress: fail"))
305 } else { 350 } else {
306 send_msg_channel_open_confirmation(channel, channel->recvwindow, 351 send_msg_channel_open_confirmation(channel, channel->recvwindow,
307 channel->recvmaxpacket); 352 channel->recvmaxpacket);
308 channel->readfd = channel->writefd; 353 channel->readfd = channel->writefd;
309 channel->initconn = 0; 354 channel->initconn = 0;
310 TRACE(("leave checkinitdone: success")) 355 TRACE(("leave check_in_progress: success"))
311 } 356 }
312 } 357 }
313
314 358
315 359
316 /* Send the close message and set the channel as closed */ 360 /* Send the close message and set the channel as closed */
317 static void send_msg_channel_close(struct Channel *channel) { 361 static void send_msg_channel_close(struct Channel *channel) {
318 362
319 TRACE(("enter send_msg_channel_close")) 363 TRACE(("enter send_msg_channel_close"))
320 /* XXX server */
321 if (channel->type->closehandler) { 364 if (channel->type->closehandler) {
322 channel->type->closehandler(channel); 365 channel->type->closehandler(channel);
323 } 366 }
324 367
325 CHECKCLEARTOWRITE(); 368 CHECKCLEARTOWRITE();
327 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); 370 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
328 buf_putint(ses.writepayload, channel->remotechan); 371 buf_putint(ses.writepayload, channel->remotechan);
329 372
330 encrypt_packet(); 373 encrypt_packet();
331 374
332 channel->senteof = 1; 375 channel->sent_eof = 1;
333 channel->sentclosed = 1; 376 channel->sent_close = 1;
334 TRACE(("leave send_msg_channel_close")) 377 TRACE(("leave send_msg_channel_close"))
335 } 378 }
336 379
337 /* call this when trans/eof channels are closed */ 380 /* call this when trans/eof channels are closed */
338 static void send_msg_channel_eof(struct Channel *channel) { 381 static void send_msg_channel_eof(struct Channel *channel) {
343 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF); 386 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
344 buf_putint(ses.writepayload, channel->remotechan); 387 buf_putint(ses.writepayload, channel->remotechan);
345 388
346 encrypt_packet(); 389 encrypt_packet();
347 390
348 channel->senteof = 1; 391 channel->sent_eof = 1;
349 392
350 TRACE(("leave send_msg_channel_eof")) 393 TRACE(("leave send_msg_channel_eof"))
351 } 394 }
352 395
353 /* Called to write data out to the local side of the channel. 396 /* Called to write data out to the local side of the channel.
355 * possible */ 398 * possible */
356 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) { 399 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
357 400
358 int len, maxlen; 401 int len, maxlen;
359 402
360 TRACE(("enter writechannel")) 403 TRACE(("enter writechannel fd %d", fd))
361 404
362 maxlen = cbuf_readlen(cbuf); 405 maxlen = cbuf_readlen(cbuf);
363 406
364 /* Write the data out */ 407 /* Write the data out */
365 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); 408 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
366 if (len <= 0) { 409 if (len <= 0) {
410 TRACE(("errno %d len %d", errno, len))
367 if (len < 0 && errno != EINTR) { 411 if (len < 0 && errno != EINTR) {
368 /* no more to write - we close it even if the fd was stderr, since 412 close_chan_fd(channel, fd, SHUT_WR);
369 * that's a nasty failure too */
370 closewritefd(channel);
371 } 413 }
372 TRACE(("leave writechannel: len <= 0")) 414 TRACE(("leave writechannel: len <= 0"))
373 return; 415 return;
374 } 416 }
417 TRACE(("writechannel wrote %d", len))
375 418
376 cbuf_incrread(cbuf, len); 419 cbuf_incrread(cbuf, len);
377 channel->recvdonelen += len; 420 channel->recvdonelen += len;
378
379 if (fd == channel->writefd && cbuf_getused(cbuf) == 0 && channel->recveof) {
380 /* Check if we're closing up */
381 closewritefd(channel);
382 TRACE(("leave writechannel: recveof set"))
383 return;
384 }
385 421
386 /* Window adjust handling */ 422 /* Window adjust handling */
387 if (channel->recvdonelen >= RECV_WINDOWEXTEND) { 423 if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
388 /* Set it back to max window */ 424 /* Set it back to max window */
389 send_msg_channel_window_adjust(channel, channel->recvdonelen); 425 send_msg_channel_window_adjust(channel, channel->recvdonelen);
394 dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW); 430 dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
395 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf)); 431 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
396 dropbear_assert(channel->extrabuf == NULL || 432 dropbear_assert(channel->extrabuf == NULL ||
397 channel->recvwindow <= cbuf_getavail(channel->extrabuf)); 433 channel->recvwindow <= cbuf_getavail(channel->extrabuf));
398 434
399
400 TRACE(("leave writechannel")) 435 TRACE(("leave writechannel"))
401 } 436 }
402 437
403 /* Set the file descriptors for the main select in session.c 438 /* Set the file descriptors for the main select in session.c
404 * This avoid channels which don't have any window available, are closed, etc*/ 439 * This avoid channels which don't have any window available, are closed, etc*/
419 454
420 if (channel->readfd >= 0) { 455 if (channel->readfd >= 0) {
421 FD_SET(channel->readfd, readfds); 456 FD_SET(channel->readfd, readfds);
422 } 457 }
423 458
424 if (channel->extrabuf == NULL && channel->errfd >= 0) { 459 if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
425 FD_SET(channel->errfd, readfds); 460 FD_SET(channel->errfd, readfds);
426 } 461 }
427 } 462 }
428 463
429 /* Stuff from the wire */ 464 /* Stuff from the wire */
430 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 ) 465 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
431 || channel->initconn) { 466 || channel->initconn) {
432
433 FD_SET(channel->writefd, writefds); 467 FD_SET(channel->writefd, writefds);
434 } 468 }
435 469
436 if (channel->extrabuf != NULL && channel->errfd >= 0 470 if (ERRFD_IS_WRITE(channel) != NULL && channel->errfd >= 0
437 && cbuf_getused(channel->extrabuf) > 0 ) { 471 && cbuf_getused(channel->extrabuf) > 0 ) {
438 FD_SET(channel->errfd, writefds); 472 FD_SET(channel->errfd, writefds);
439 } 473 }
474
475 /* We also set the writefds for reading, so that we will be notified of close */
476 if (channel->writefd >= 0) {
477 FD_SET(channel->writefd, readfds);
478 }
479 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0) {
480 FD_SET(channel->errfd, readfds);
481 }
482
483
440 484
441 } /* foreach channel */ 485 } /* foreach channel */
442 486
443 #ifdef USING_LISTENERS 487 #ifdef USING_LISTENERS
444 set_listener_fds(readfds); 488 set_listener_fds(readfds);
453 497
454 struct Channel * channel; 498 struct Channel * channel;
455 499
456 TRACE(("enter recv_msg_channel_eof")) 500 TRACE(("enter recv_msg_channel_eof"))
457 501
458 channel = getchannel(); 502 channel = getchannel_msg("EOF");
459 if (channel == NULL) { 503
460 dropbear_exit("EOF for unknown channel"); 504 channel->recv_eof = 1;
461 } 505
462 506 check_close(channel);
463 channel->recveof = 1;
464 if (cbuf_getused(channel->writebuf) == 0
465 && (channel->extrabuf == NULL
466 || cbuf_getused(channel->extrabuf) == 0)) {
467 closewritefd(channel);
468 }
469
470 TRACE(("leave recv_msg_channel_eof")) 507 TRACE(("leave recv_msg_channel_eof"))
471 } 508 }
472 509
473 510
474 /* Handle channel closure(), respond in kind and close the channels */ 511 /* Handle channel closure(), respond in kind and close the channels */
476 513
477 struct Channel * channel; 514 struct Channel * channel;
478 515
479 TRACE(("enter recv_msg_channel_close")) 516 TRACE(("enter recv_msg_channel_close"))
480 517
481 channel = getchannel(); 518 channel = getchannel_msg("Close");
482 if (channel == NULL) { 519
483 /* disconnect ? */ 520 channel->recv_eof = 1;
484 dropbear_exit("Close for unknown channel"); 521 channel->recv_close = 1;
485 } 522
486 523 check_close(channel);
487 channel->recveof = 1;
488 channel->recvclosed = 1;
489
490 if (channel->sentclosed) {
491 removechannel(channel);
492 }
493
494 TRACE(("leave recv_msg_channel_close")) 524 TRACE(("leave recv_msg_channel_close"))
495 } 525 }
496 526
497 /* Remove a channel entry, this is only executed after both sides have sent 527 /* Remove a channel entry, this is only executed after both sides have sent
498 * channel close */ 528 * channel close */
499 static void removechannel(struct Channel * channel) { 529 static void remove_channel(struct Channel * channel) {
500 530
501 TRACE(("enter removechannel")) 531 TRACE(("enter remove_channel"))
502 TRACE(("channel index is %d", channel->index)) 532 TRACE(("channel index is %d", channel->index))
503 533
504 cbuf_free(channel->writebuf); 534 cbuf_free(channel->writebuf);
505 channel->writebuf = NULL; 535 channel->writebuf = NULL;
506 536
509 channel->extrabuf = NULL; 539 channel->extrabuf = NULL;
510 } 540 }
511 541
512 542
513 /* close the FDs in case they haven't been done 543 /* close the FDs in case they haven't been done
514 * yet (ie they were shutdown etc */ 544 * yet (they might have been shutdown etc) */
545 TRACE(("CLOSE writefd %d", channel->writefd))
515 close(channel->writefd); 546 close(channel->writefd);
547 TRACE(("CLOSE readfd %d", channel->readfd))
516 close(channel->readfd); 548 close(channel->readfd);
549 TRACE(("CLOSE errfd %d", channel->errfd))
517 close(channel->errfd); 550 close(channel->errfd);
518 551
519 channel->typedata = NULL; 552 channel->typedata = NULL;
520 553
521 deletechannel(channel); 554 delete_channel(channel);
522 555
523 TRACE(("leave removechannel")) 556 TRACE(("leave remove_channel"))
524 } 557 }
525 558
526 /* Remove a channel entry */ 559 /* Remove a channel entry */
527 static void deletechannel(struct Channel *channel) { 560 static void delete_channel(struct Channel *channel) {
528 561
529 ses.channels[channel->index] = NULL; 562 ses.channels[channel->index] = NULL;
530 m_free(channel); 563 m_free(channel);
531 ses.chancount--; 564 ses.chancount--;
532 565
540 struct Channel *channel; 573 struct Channel *channel;
541 574
542 TRACE(("enter recv_msg_channel_request")) 575 TRACE(("enter recv_msg_channel_request"))
543 576
544 channel = getchannel(); 577 channel = getchannel();
545 if (channel == NULL) {
546 /* disconnect ? */
547 dropbear_exit("Unknown channel");
548 }
549 578
550 if (channel->type->reqhandler) { 579 if (channel->type->reqhandler) {
551 channel->type->reqhandler(channel); 580 channel->type->reqhandler(channel);
552 } else { 581 } else {
553 send_msg_channel_failure(channel); 582 send_msg_channel_failure(channel);
560 /* Reads data from the server's program/shell/etc, and puts it in a 589 /* Reads data from the server's program/shell/etc, and puts it in a
561 * channel_data packet to send. 590 * channel_data packet to send.
562 * chan is the remote channel, isextended is 0 if it is normal data, 1 591 * chan is the remote channel, isextended is 0 if it is normal data, 1
563 * if it is extended data. if it is extended, then the type is in 592 * if it is extended data. if it is extended, then the type is in
564 * exttype */ 593 * exttype */
565 static void send_msg_channel_data(struct Channel *channel, int isextended, 594 static void send_msg_channel_data(struct Channel *channel, int isextended) {
566 unsigned int exttype) { 595
567
568 buffer *buf;
569 int len; 596 int len;
570 unsigned int maxlen; 597 size_t maxlen, size_pos;
571 int fd; 598 int fd;
572 599
573 /* TRACE(("enter send_msg_channel_data"))
574 TRACE(("extended = %d type = %d", isextended, exttype))*/
575
576 CHECKCLEARTOWRITE(); 600 CHECKCLEARTOWRITE();
577 601
578 dropbear_assert(!channel->sentclosed); 602 dropbear_assert(!channel->sent_close);
579 603
580 if (isextended) { 604 if (isextended) {
581 fd = channel->errfd; 605 fd = channel->errfd;
582 } else { 606 } else {
583 fd = channel->readfd; 607 fd = channel->readfd;
584 } 608 }
609 TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
585 dropbear_assert(fd >= 0); 610 dropbear_assert(fd >= 0);
586 611
587 maxlen = MIN(channel->transwindow, channel->transmaxpacket); 612 maxlen = MIN(channel->transwindow, channel->transmaxpacket);
588 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and 613 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
589 * exttype if is extended */ 614 * exttype if is extended */
590 maxlen = MIN(maxlen, 615 maxlen = MIN(maxlen,
591 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0)); 616 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
617 TRACE(("maxlen %d", maxlen))
592 if (maxlen == 0) { 618 if (maxlen == 0) {
593 TRACE(("leave send_msg_channel_data: no window")) 619 TRACE(("leave send_msg_channel_data: no window"))
594 return; /* the data will get written later */
595 }
596
597 /* read the data */
598 TRACE(("maxlen %d", maxlen))
599 buf = buf_new(maxlen);
600 TRACE(("buf pos %d data %x", buf->pos, buf->data))
601 len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
602 if (len <= 0) {
603 /* on error/eof, send eof */
604 if (len == 0 || errno != EINTR) {
605 closereadfd(channel, fd);
606 }
607 buf_free(buf);
608 buf = NULL;
609 TRACE(("leave send_msg_channel_data: read err or EOF for fd %d",
610 channel->index));
611 return; 620 return;
612 } 621 }
613 buf_incrlen(buf, len);
614 622
615 buf_putbyte(ses.writepayload, 623 buf_putbyte(ses.writepayload,
616 isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA); 624 isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
617 buf_putint(ses.writepayload, channel->remotechan); 625 buf_putint(ses.writepayload, channel->remotechan);
618
619 if (isextended) { 626 if (isextended) {
620 buf_putint(ses.writepayload, exttype); 627 buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
621 } 628 }
622 629 /* a dummy size first ...*/
623 buf_putstring(ses.writepayload, buf_getptr(buf, len), len); 630 size_pos = ses.writepayload->pos;
624 buf_free(buf); 631 buf_putint(ses.writepayload, 0);
625 buf = NULL; 632
633 /* read the data */
634 len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
635 if (len <= 0) {
636 if (len == 0 || errno != EINTR) {
637 close_chan_fd(channel, fd, SHUT_RD);
638 }
639 ses.writepayload->len = ses.writepayload->pos = 0;
640 TRACE(("leave send_msg_channel_data: len %d read err or EOF for fd %d",
641 len, channel->index));
642 return;
643 }
644 buf_incrwritepos(ses.writepayload, len);
645 /* ... real size here */
646 buf_setpos(ses.writepayload, size_pos);
647 buf_putint(ses.writepayload, len);
626 648
627 channel->transwindow -= len; 649 channel->transwindow -= len;
628 650
629 encrypt_packet(); 651 encrypt_packet();
630 TRACE(("leave send_msg_channel_data")) 652 TRACE(("leave send_msg_channel_data"))
634 void recv_msg_channel_data() { 656 void recv_msg_channel_data() {
635 657
636 struct Channel *channel; 658 struct Channel *channel;
637 659
638 channel = getchannel(); 660 channel = getchannel();
639 if (channel == NULL) {
640 dropbear_exit("Unknown channel");
641 }
642 661
643 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf); 662 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
644 } 663 }
645 664
646 /* Shared for data and stderr data - when we receive data, put it in a buffer 665 /* Shared for data and stderr data - when we receive data, put it in a buffer
653 unsigned int buflen; 672 unsigned int buflen;
654 unsigned int len; 673 unsigned int len;
655 674
656 TRACE(("enter recv_msg_channel_data")) 675 TRACE(("enter recv_msg_channel_data"))
657 676
658 if (channel->recveof) { 677 if (channel->recv_eof) {
659 dropbear_exit("received data after eof"); 678 dropbear_exit("received data after eof");
660 } 679 }
661 680
662 if (fd < 0) { 681 if (fd < 0) {
663 dropbear_exit("received data with bad writefd"); 682 /* If we have encountered failed write, the far side might still
683 * be sending data without having yet received our close notification.
684 * We just drop the data. */
685 return;
664 } 686 }
665 687
666 datalen = buf_getint(ses.payload); 688 datalen = buf_getint(ses.payload);
667 689 TRACE(("length %d", datalen))
668 690
669 maxdata = cbuf_getavail(cbuf); 691 maxdata = cbuf_getavail(cbuf);
670 692
671 /* Whilst the spec says we "MAY ignore data past the end" this could 693 /* Whilst the spec says we "MAY ignore data past the end" this could
672 * lead to corrupted file transfers etc (chunks missed etc). It's better to 694 * lead to corrupted file transfers etc (chunks missed etc). It's better to
704 726
705 struct Channel * channel; 727 struct Channel * channel;
706 unsigned int incr; 728 unsigned int incr;
707 729
708 channel = getchannel(); 730 channel = getchannel();
709 if (channel == NULL) {
710 dropbear_exit("Unknown channel");
711 }
712 731
713 incr = buf_getint(ses.payload); 732 incr = buf_getint(ses.payload);
714 TRACE(("received window increment %d", incr)) 733 TRACE(("received window increment %d", incr))
715 incr = MIN(incr, MAX_TRANS_WIN_INCR); 734 incr = MIN(incr, MAX_TRANS_WIN_INCR);
716 735
733 752
734 encrypt_packet(); 753 encrypt_packet();
735 } 754 }
736 755
737 /* Handle a new channel request, performing any channel-type-specific setup */ 756 /* Handle a new channel request, performing any channel-type-specific setup */
738 /* XXX server */
739 void recv_msg_channel_open() { 757 void recv_msg_channel_open() {
740 758
741 unsigned char *type; 759 unsigned char *type;
742 unsigned int typelen; 760 unsigned int typelen;
743 unsigned int remotechan, transwindow, transmaxpacket; 761 unsigned int remotechan, transwindow, transmaxpacket;
790 goto failure; 808 goto failure;
791 } 809 }
792 810
793 if (channel->type->inithandler) { 811 if (channel->type->inithandler) {
794 ret = channel->type->inithandler(channel); 812 ret = channel->type->inithandler(channel);
813 if (ret == SSH_OPEN_IN_PROGRESS) {
814 /* We'll send the confirmation later */
815 goto cleanup;
816 }
795 if (ret > 0) { 817 if (ret > 0) {
796 if (ret == SSH_OPEN_IN_PROGRESS) {
797 /* We'll send the confirmation later */
798 goto cleanup;
799 }
800 errtype = ret; 818 errtype = ret;
801 deletechannel(channel); 819 delete_channel(channel);
802 TRACE(("inithandler returned failure %d", ret)) 820 TRACE(("inithandler returned failure %d", ret))
803 goto failure; 821 goto failure;
804 } 822 }
805 } 823 }
806 824
879 buf_putint(ses.writepayload, recvmaxpacket); 897 buf_putint(ses.writepayload, recvmaxpacket);
880 898
881 encrypt_packet(); 899 encrypt_packet();
882 TRACE(("leave send_msg_channel_open_confirmation")) 900 TRACE(("leave send_msg_channel_open_confirmation"))
883 } 901 }
902
903 /* close a fd, how is SHUT_RD or SHUT_WR */
904 static void close_chan_fd(struct Channel *channel, int fd, int how) {
905
906 int closein = 0, closeout = 0;
907
908 if (channel->type->sepfds) {
909 TRACE(("SHUTDOWN(%d, %d)", fd, how))
910 shutdown(fd, how);
911 if (how == 0) {
912 closeout = 1;
913 } else {
914 closein = 1;
915 }
916 } else {
917 TRACE(("CLOSE some fd %d", fd))
918 close(fd);
919 closein = closeout = 1;
920 }
921
922 if (closeout && (fd == channel->readfd)) {
923 channel->readfd = FD_CLOSED;
924 }
925 if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
926 channel->errfd = FD_CLOSED;
927 }
928
929 if (closein && fd == channel->writefd) {
930 channel->writefd = FD_CLOSED;
931 }
932 if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
933 channel->errfd = FD_CLOSED;
934 }
935
936 /* if we called shutdown on it and all references are gone, then we
937 * need to close() it to stop it lingering */
938 if (channel->type->sepfds && channel->readfd == FD_CLOSED
939 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
940 TRACE(("CLOSE (finally) of %d", fd))
941 close(fd);
942 }
943 }
944
884 945
885 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT) 946 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
886 /* Create a new channel, and start the open request. This is intended 947 /* Create a new channel, and start the open request. This is intended
887 * for X11, agent, tcp forwarding, and should be filled with channel-specific 948 * for X11, agent, tcp forwarding, and should be filled with channel-specific
888 * options, with the calling function calling encrypt_packet() after 949 * options, with the calling function calling encrypt_packet() after
928 int ret; 989 int ret;
929 990
930 TRACE(("enter recv_msg_channel_open_confirmation")) 991 TRACE(("enter recv_msg_channel_open_confirmation"))
931 992
932 channel = getchannel(); 993 channel = getchannel();
933 if (channel == NULL) {
934 dropbear_exit("Unknown channel");
935 }
936 994
937 if (!channel->await_open) { 995 if (!channel->await_open) {
938 dropbear_exit("unexpected channel reply"); 996 dropbear_exit("unexpected channel reply");
939 } 997 }
940 channel->await_open = 0; 998 channel->await_open = 0;
948 1006
949 /* Run the inithandler callback */ 1007 /* Run the inithandler callback */
950 if (channel->type->inithandler) { 1008 if (channel->type->inithandler) {
951 ret = channel->type->inithandler(channel); 1009 ret = channel->type->inithandler(channel);
952 if (ret > 0) { 1010 if (ret > 0) {
953 removechannel(channel); 1011 remove_channel(channel);
954 TRACE(("inithandler returned failure %d", ret)) 1012 TRACE(("inithandler returned failure %d", ret))
955 } 1013 }
956 } 1014 }
957 1015
958 1016
963 void recv_msg_channel_open_failure() { 1021 void recv_msg_channel_open_failure() {
964 1022
965 struct Channel * channel; 1023 struct Channel * channel;
966 1024
967 channel = getchannel(); 1025 channel = getchannel();
968 if (channel == NULL) {
969 dropbear_exit("Unknown channel");
970 }
971 1026
972 if (!channel->await_open) { 1027 if (!channel->await_open) {
973 dropbear_exit("unexpected channel reply"); 1028 dropbear_exit("unexpected channel reply");
974 } 1029 }
975 channel->await_open = 0; 1030 channel->await_open = 0;
976 1031
977 removechannel(channel); 1032 remove_channel(channel);
978 } 1033 }
979 #endif /* USING_LISTENERS */ 1034 #endif /* USING_LISTENERS */
980
981 /* close a stdout/stderr fd */
982 static void closereadfd(struct Channel * channel, int fd) {
983
984 /* don't close it if it is the same as writefd,
985 * unless writefd is already set -1 */
986 TRACE(("enter closereadfd"))
987 closechanfd(channel, fd, 0);
988 TRACE(("leave closereadfd"))
989 }
990
991 /* close a stdin fd */
992 static void closewritefd(struct Channel * channel) {
993
994 TRACE(("enter closewritefd"))
995 closechanfd(channel, channel->writefd, 1);
996 TRACE(("leave closewritefd"))
997 }
998
999 /* close a fd, how is 0 for stdout/stderr, 1 for stdin */
1000 static void closechanfd(struct Channel *channel, int fd, int how) {
1001
1002 int closein = 0, closeout = 0;
1003
1004 /* XXX server */
1005 if (channel->type->sepfds) {
1006 TRACE(("shutdown((%d), %d)", fd, how))
1007 shutdown(fd, how);
1008 if (how == 0) {
1009 closeout = 1;
1010 } else {
1011 closein = 1;
1012 }
1013 } else {
1014 close(fd);
1015 closein = closeout = 1;
1016 }
1017
1018 if (closeout && fd == channel->readfd) {
1019 channel->readfd = FD_CLOSED;
1020 }
1021 if (closeout && (channel->extrabuf == NULL) && (fd == channel->errfd)) {
1022 channel->errfd = FD_CLOSED;
1023 }
1024
1025 if (closein && fd == channel->writefd) {
1026 channel->writefd = FD_CLOSED;
1027 }
1028 if (closein && (channel->extrabuf != NULL) && (fd == channel->errfd)) {
1029 channel->errfd = FD_CLOSED;
1030 }
1031
1032 /* if we called shutdown on it and all references are gone, then we
1033 * need to close() it to stop it lingering */
1034 if (channel->type->sepfds && channel->readfd == FD_CLOSED
1035 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
1036 close(fd);
1037 }
1038 }