1 /* 2 * Copyright (c) 1999 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $"); 27 28 #include "ssh.h" 29 30 #include "buffer.h" 31 #include "packet.h" 32 #include "channels.h" 33 #include "nchan.h" 34 35 #include "ssh2.h" 36 #include "compat.h" 37 38 /* functions manipulating channel states */ 39 /* 40 * EVENTS update channel input/output states execute ACTIONS 41 */ 42 /* events concerning the INPUT from socket for channel (istate) */ 43 chan_event_fn *chan_rcvd_oclose = NULL; 44 chan_event_fn *chan_read_failed = NULL; 45 chan_event_fn *chan_ibuf_empty = NULL; 46 /* events concerning the OUTPUT from channel for socket (ostate) */ 47 chan_event_fn *chan_rcvd_ieof = NULL; 48 chan_event_fn *chan_write_failed = NULL; 49 chan_event_fn *chan_obuf_empty = NULL; 50 /* 51 * ACTIONS: should never update the channel states 52 */ 53 static void chan_send_ieof1(Channel *c); 54 static void chan_send_oclose1(Channel *c); 55 static void chan_send_close2(Channel *c); 56 static void chan_send_eof2(Channel *c); 57 58 /* channel cleanup */ 59 chan_event_fn *chan_delete_if_full_closed = NULL; 60 61 /* helper */ 62 static void chan_shutdown_write(Channel *c); 63 static void chan_shutdown_read(Channel *c); 64 65 /* 66 * SSH1 specific implementation of event functions 67 */ 68 69 static void 70 chan_rcvd_oclose1(Channel *c) 71 { 72 debug("channel %d: rcvd oclose", c->self); 73 switch (c->istate) { 74 case CHAN_INPUT_WAIT_OCLOSE: 75 debug("channel %d: input wait_oclose -> closed", c->self); 76 c->istate = CHAN_INPUT_CLOSED; 77 break; 78 case CHAN_INPUT_OPEN: 79 debug("channel %d: input open -> closed", c->self); 80 chan_shutdown_read(c); 81 chan_send_ieof1(c); 82 c->istate = CHAN_INPUT_CLOSED; 83 break; 84 case CHAN_INPUT_WAIT_DRAIN: 85 /* both local read_failed and remote write_failed */ 86 log("channel %d: input drain -> closed", c->self); 87 chan_send_ieof1(c); 88 c->istate = CHAN_INPUT_CLOSED; 89 break; 90 default: 91 error("channel %d: protocol error: chan_rcvd_oclose for istate %d", 92 c->self, c->istate); 93 return; 94 } 95 } 96 static void 97 chan_read_failed_12(Channel *c) 98 { 99 debug("channel %d: read failed", c->self); 100 switch (c->istate) { 101 case CHAN_INPUT_OPEN: 102 debug("channel %d: input open -> drain", c->self); 103 chan_shutdown_read(c); 104 c->istate = CHAN_INPUT_WAIT_DRAIN; 105 if (buffer_len(&c->input) == 0) { 106 debug("channel %d: input: no drain shortcut", c->self); 107 chan_ibuf_empty(c); 108 } 109 break; 110 default: 111 error("channel %d: internal error: we do not read, but chan_read_failed for istate %d", 112 c->self, c->istate); 113 break; 114 } 115 } 116 static void 117 chan_ibuf_empty1(Channel *c) 118 { 119 debug("channel %d: ibuf empty", c->self); 120 if (buffer_len(&c->input)) { 121 error("channel %d: internal error: chan_ibuf_empty for non empty buffer", 122 c->self); 123 return; 124 } 125 switch (c->istate) { 126 case CHAN_INPUT_WAIT_DRAIN: 127 debug("channel %d: input drain -> wait_oclose", c->self); 128 chan_send_ieof1(c); 129 c->istate = CHAN_INPUT_WAIT_OCLOSE; 130 break; 131 default: 132 error("channel %d: internal error: chan_ibuf_empty for istate %d", 133 c->self, c->istate); 134 break; 135 } 136 } 137 static void 138 chan_rcvd_ieof1(Channel *c) 139 { 140 debug("channel %d: rcvd ieof", c->self); 141 if (c->type != SSH_CHANNEL_OPEN) { 142 debug("channel %d: non-open", c->self); 143 if (c->istate == CHAN_INPUT_OPEN) { 144 debug("channel %d: non-open: input open -> wait_oclose", c->self); 145 chan_shutdown_read(c); 146 chan_send_ieof1(c); 147 c->istate = CHAN_INPUT_WAIT_OCLOSE; 148 } else { 149 error("channel %d: istate %d != open", c->self, c->istate); 150 } 151 if (c->ostate == CHAN_OUTPUT_OPEN) { 152 debug("channel %d: non-open: output open -> closed", c->self); 153 chan_send_oclose1(c); 154 c->ostate = CHAN_OUTPUT_CLOSED; 155 } else { 156 error("channel %d: ostate %d != open", c->self, c->ostate); 157 } 158 return; 159 } 160 switch (c->ostate) { 161 case CHAN_OUTPUT_OPEN: 162 debug("channel %d: output open -> drain", c->self); 163 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 164 break; 165 case CHAN_OUTPUT_WAIT_IEOF: 166 debug("channel %d: output wait_ieof -> closed", c->self); 167 c->ostate = CHAN_OUTPUT_CLOSED; 168 break; 169 default: 170 error("channel %d: protocol error: chan_rcvd_ieof for ostate %d", 171 c->self, c->ostate); 172 break; 173 } 174 } 175 static void 176 chan_write_failed1(Channel *c) 177 { 178 debug("channel %d: write failed", c->self); 179 switch (c->ostate) { 180 case CHAN_OUTPUT_OPEN: 181 debug("channel %d: output open -> wait_ieof", c->self); 182 chan_send_oclose1(c); 183 c->ostate = CHAN_OUTPUT_WAIT_IEOF; 184 break; 185 case CHAN_OUTPUT_WAIT_DRAIN: 186 debug("channel %d: output wait_drain -> closed", c->self); 187 chan_send_oclose1(c); 188 c->ostate = CHAN_OUTPUT_CLOSED; 189 break; 190 default: 191 error("channel %d: internal error: chan_write_failed for ostate %d", 192 c->self, c->ostate); 193 break; 194 } 195 } 196 static void 197 chan_obuf_empty1(Channel *c) 198 { 199 debug("channel %d: obuf empty", c->self); 200 if (buffer_len(&c->output)) { 201 error("channel %d: internal error: chan_obuf_empty for non empty buffer", 202 c->self); 203 return; 204 } 205 switch (c->ostate) { 206 case CHAN_OUTPUT_WAIT_DRAIN: 207 debug("channel %d: output drain -> closed", c->self); 208 chan_send_oclose1(c); 209 c->ostate = CHAN_OUTPUT_CLOSED; 210 break; 211 default: 212 error("channel %d: internal error: chan_obuf_empty for ostate %d", 213 c->self, c->ostate); 214 break; 215 } 216 } 217 static void 218 chan_send_ieof1(Channel *c) 219 { 220 debug("channel %d: send ieof", c->self); 221 switch (c->istate) { 222 case CHAN_INPUT_OPEN: 223 case CHAN_INPUT_WAIT_DRAIN: 224 packet_start(SSH_MSG_CHANNEL_INPUT_EOF); 225 packet_put_int(c->remote_id); 226 packet_send(); 227 break; 228 default: 229 error("channel %d: internal error: cannot send ieof for istate %d", 230 c->self, c->istate); 231 break; 232 } 233 } 234 static void 235 chan_send_oclose1(Channel *c) 236 { 237 debug("channel %d: send oclose", c->self); 238 switch (c->ostate) { 239 case CHAN_OUTPUT_OPEN: 240 case CHAN_OUTPUT_WAIT_DRAIN: 241 chan_shutdown_write(c); 242 buffer_consume(&c->output, buffer_len(&c->output)); 243 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); 244 packet_put_int(c->remote_id); 245 packet_send(); 246 break; 247 default: 248 error("channel %d: internal error: cannot send oclose for ostate %d", 249 c->self, c->ostate); 250 break; 251 } 252 } 253 static void 254 chan_delete_if_full_closed1(Channel *c) 255 { 256 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { 257 debug("channel %d: full closed", c->self); 258 channel_free(c->self); 259 } 260 } 261 262 /* 263 * the same for SSH2 264 */ 265 static void 266 chan_rcvd_oclose2(Channel *c) 267 { 268 debug("channel %d: rcvd close", c->self); 269 if (c->flags & CHAN_CLOSE_RCVD) 270 error("channel %d: protocol error: close rcvd twice", c->self); 271 c->flags |= CHAN_CLOSE_RCVD; 272 if (c->type == SSH_CHANNEL_LARVAL) { 273 /* tear down larval channels immediately */ 274 c->ostate = CHAN_OUTPUT_CLOSED; 275 c->istate = CHAN_INPUT_CLOSED; 276 return; 277 } 278 switch (c->ostate) { 279 case CHAN_OUTPUT_OPEN: 280 /* wait until a data from the channel is consumed if a CLOSE is received */ 281 debug("channel %d: output open -> drain", c->self); 282 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 283 break; 284 } 285 switch (c->istate) { 286 case CHAN_INPUT_OPEN: 287 debug("channel %d: input open -> closed", c->self); 288 chan_shutdown_read(c); 289 break; 290 case CHAN_INPUT_WAIT_DRAIN: 291 debug("channel %d: input drain -> closed", c->self); 292 chan_send_eof2(c); 293 break; 294 } 295 c->istate = CHAN_INPUT_CLOSED; 296 } 297 static void 298 chan_ibuf_empty2(Channel *c) 299 { 300 debug("channel %d: ibuf empty", c->self); 301 if (buffer_len(&c->input)) { 302 error("channel %d: internal error: chan_ibuf_empty for non empty buffer", 303 c->self); 304 return; 305 } 306 switch (c->istate) { 307 case CHAN_INPUT_WAIT_DRAIN: 308 debug("channel %d: input drain -> closed", c->self); 309 if (!(c->flags & CHAN_CLOSE_SENT)) 310 chan_send_eof2(c); 311 c->istate = CHAN_INPUT_CLOSED; 312 break; 313 default: 314 error("channel %d: internal error: chan_ibuf_empty for istate %d", 315 c->self, c->istate); 316 break; 317 } 318 } 319 static void 320 chan_rcvd_ieof2(Channel *c) 321 { 322 debug("channel %d: rcvd eof", c->self); 323 if (c->ostate == CHAN_OUTPUT_OPEN) { 324 debug("channel %d: output open -> drain", c->self); 325 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 326 } 327 } 328 static void 329 chan_write_failed2(Channel *c) 330 { 331 debug("channel %d: write failed", c->self); 332 switch (c->ostate) { 333 case CHAN_OUTPUT_OPEN: 334 debug("channel %d: output open -> closed", c->self); 335 chan_shutdown_write(c); /* ?? */ 336 c->ostate = CHAN_OUTPUT_CLOSED; 337 break; 338 case CHAN_OUTPUT_WAIT_DRAIN: 339 debug("channel %d: output drain -> closed", c->self); 340 chan_shutdown_write(c); 341 c->ostate = CHAN_OUTPUT_CLOSED; 342 break; 343 default: 344 error("channel %d: internal error: chan_write_failed for ostate %d", 345 c->self, c->ostate); 346 break; 347 } 348 } 349 static void 350 chan_obuf_empty2(Channel *c) 351 { 352 debug("channel %d: obuf empty", c->self); 353 if (buffer_len(&c->output)) { 354 error("internal error: chan_obuf_empty %d for non empty buffer", 355 c->self); 356 return; 357 } 358 switch (c->ostate) { 359 case CHAN_OUTPUT_WAIT_DRAIN: 360 debug("channel %d: output drain -> closed", c->self); 361 chan_shutdown_write(c); 362 c->ostate = CHAN_OUTPUT_CLOSED; 363 break; 364 default: 365 error("channel %d: internal error: chan_obuf_empty for ostate %d", 366 c->self, c->ostate); 367 break; 368 } 369 } 370 static void 371 chan_send_eof2(Channel *c) 372 { 373 debug("channel %d: send eof", c->self); 374 switch (c->istate) { 375 case CHAN_INPUT_WAIT_DRAIN: 376 packet_start(SSH2_MSG_CHANNEL_EOF); 377 packet_put_int(c->remote_id); 378 packet_send(); 379 break; 380 default: 381 error("channel %d: internal error: cannot send eof for istate %d", 382 c->self, c->istate); 383 break; 384 } 385 } 386 static void 387 chan_send_close2(Channel *c) 388 { 389 debug("channel %d: send close", c->self); 390 if (c->ostate != CHAN_OUTPUT_CLOSED || 391 c->istate != CHAN_INPUT_CLOSED) { 392 error("channel %d: internal error: cannot send close for istate/ostate %d/%d", 393 c->self, c->istate, c->ostate); 394 } else if (c->flags & CHAN_CLOSE_SENT) { 395 error("channel %d: internal error: already sent close", c->self); 396 } else { 397 packet_start(SSH2_MSG_CHANNEL_CLOSE); 398 packet_put_int(c->remote_id); 399 packet_send(); 400 c->flags |= CHAN_CLOSE_SENT; 401 } 402 } 403 static void 404 chan_delete_if_full_closed2(Channel *c) 405 { 406 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { 407 if (!(c->flags & CHAN_CLOSE_SENT)) { 408 chan_send_close2(c); 409 } 410 if ((c->flags & CHAN_CLOSE_SENT) && 411 (c->flags & CHAN_CLOSE_RCVD)) { 412 debug("channel %d: full closed2", c->self); 413 channel_free(c->self); 414 } 415 } 416 } 417 418 /* shared */ 419 void 420 chan_init_iostates(Channel *c) 421 { 422 c->ostate = CHAN_OUTPUT_OPEN; 423 c->istate = CHAN_INPUT_OPEN; 424 c->flags = 0; 425 } 426 427 /* init */ 428 void 429 chan_init(void) 430 { 431 if (compat20) { 432 chan_rcvd_oclose = chan_rcvd_oclose2; 433 chan_read_failed = chan_read_failed_12; 434 chan_ibuf_empty = chan_ibuf_empty2; 435 436 chan_rcvd_ieof = chan_rcvd_ieof2; 437 chan_write_failed = chan_write_failed2; 438 chan_obuf_empty = chan_obuf_empty2; 439 440 chan_delete_if_full_closed = chan_delete_if_full_closed2; 441 } else { 442 chan_rcvd_oclose = chan_rcvd_oclose1; 443 chan_read_failed = chan_read_failed_12; 444 chan_ibuf_empty = chan_ibuf_empty1; 445 446 chan_rcvd_ieof = chan_rcvd_ieof1; 447 chan_write_failed = chan_write_failed1; 448 chan_obuf_empty = chan_obuf_empty1; 449 450 chan_delete_if_full_closed = chan_delete_if_full_closed1; 451 } 452 } 453 454 /* helper */ 455 static void 456 chan_shutdown_write(Channel *c) 457 { 458 buffer_consume(&c->output, buffer_len(&c->output)); 459 if (compat20 && c->type == SSH_CHANNEL_LARVAL) 460 return; 461 /* shutdown failure is allowed if write failed already */ 462 debug("channel %d: close_write", c->self); 463 if (c->sock != -1) { 464 if (shutdown(c->sock, SHUT_WR) < 0) 465 debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s", 466 c->self, c->sock, strerror(errno)); 467 } else { 468 if (close(c->wfd) < 0) 469 log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s", 470 c->self, c->wfd, strerror(errno)); 471 c->wfd = -1; 472 } 473 } 474 static void 475 chan_shutdown_read(Channel *c) 476 { 477 if (compat20 && c->type == SSH_CHANNEL_LARVAL) 478 return; 479 debug("channel %d: close_read", c->self); 480 if (c->sock != -1) { 481 if (shutdown(c->sock, SHUT_RD) < 0) 482 error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s", 483 c->self, c->sock, c->istate, c->ostate, strerror(errno)); 484 } else { 485 if (close(c->rfd) < 0) 486 log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s", 487 c->self, c->rfd, strerror(errno)); 488 c->rfd = -1; 489 } 490 } 491