comparison common-channel.c @ 435:337c45621e81

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