summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2016-09-30 09:19:13 +0000
committerDamien Miller <djm@mindrot.org>2016-10-01 02:45:10 +1000
commit8d0578478586e283e751ca51e7b0690631da139a (patch)
tree3621da2b97213f8ff0b434f5fd239dfd4f50d83d /channels.c
parentb7689155f3f5c4999846c07a852b1c7a43b09cec (diff)
upstream commit
ssh proxy mux mode (-O proxy; idea from Simon Tatham): - mux client speaks the ssh-packet protocol directly over unix-domain socket. - mux server acts as a proxy, translates channel IDs and relays to the server. - no filedescriptor passing necessary. - combined with unix-domain forwarding it's even possible to run mux client and server on different machines. feedback & ok djm@ Upstream-ID: 666a2fb79f58e5c50e246265fb2b9251e505c25b
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c392
1 files changed, 380 insertions, 12 deletions
diff --git a/channels.c b/channels.c
index 5d8c2a0c0..ae248414b 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.353 2016/09/19 07:52:42 natano Exp $ */ 1/* $OpenBSD: channels.c,v 1.354 2016/09/30 09:19:13 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -71,6 +71,7 @@
71#include "ssh.h" 71#include "ssh.h"
72#include "ssh1.h" 72#include "ssh1.h"
73#include "ssh2.h" 73#include "ssh2.h"
74#include "ssherr.h"
74#include "packet.h" 75#include "packet.h"
75#include "log.h" 76#include "log.h"
76#include "misc.h" 77#include "misc.h"
@@ -120,6 +121,7 @@ typedef struct {
120 char *listen_host; /* Remote side should listen address. */ 121 char *listen_host; /* Remote side should listen address. */
121 char *listen_path; /* Remote side should listen path. */ 122 char *listen_path; /* Remote side should listen path. */
122 int listen_port; /* Remote side should listen port. */ 123 int listen_port; /* Remote side should listen port. */
124 Channel *downstream; /* Downstream mux*/
123} ForwardPermission; 125} ForwardPermission;
124 126
125/* List of all permitted host/port pairs to connect by the user. */ 127/* List of all permitted host/port pairs to connect by the user. */
@@ -183,6 +185,7 @@ static int IPv4or6 = AF_UNSPEC;
183 185
184/* helper */ 186/* helper */
185static void port_open_helper(Channel *c, char *rtype); 187static void port_open_helper(Channel *c, char *rtype);
188static const char *channel_rfwd_bind_host(const char *listen_host);
186 189
187/* non-blocking connect helpers */ 190/* non-blocking connect helpers */
188static int connect_next(struct channel_connect *); 191static int connect_next(struct channel_connect *);
@@ -207,6 +210,20 @@ channel_by_id(int id)
207 return c; 210 return c;
208} 211}
209 212
213Channel *
214channel_by_remote_id(int remote_id)
215{
216 Channel *c;
217 u_int i;
218
219 for (i = 0; i < channels_alloc; i++) {
220 c = channels[i];
221 if (c != NULL && c->remote_id == remote_id)
222 return c;
223 }
224 return NULL;
225}
226
210/* 227/*
211 * Returns the channel if it is allowed to receive protocol messages. 228 * Returns the channel if it is allowed to receive protocol messages.
212 * Private channels, like listening sockets, may not receive messages. 229 * Private channels, like listening sockets, may not receive messages.
@@ -229,6 +246,7 @@ channel_lookup(int id)
229 case SSH_CHANNEL_INPUT_DRAINING: 246 case SSH_CHANNEL_INPUT_DRAINING:
230 case SSH_CHANNEL_OUTPUT_DRAINING: 247 case SSH_CHANNEL_OUTPUT_DRAINING:
231 case SSH_CHANNEL_ABANDONED: 248 case SSH_CHANNEL_ABANDONED:
249 case SSH_CHANNEL_MUX_PROXY:
232 return (c); 250 return (c);
233 } 251 }
234 logit("Non-public channel %d, type %d.", id, c->type); 252 logit("Non-public channel %d, type %d.", id, c->type);
@@ -410,14 +428,56 @@ channel_free(Channel *c)
410{ 428{
411 char *s; 429 char *s;
412 u_int i, n; 430 u_int i, n;
431 Channel *other;
413 struct channel_confirm *cc; 432 struct channel_confirm *cc;
414 433
415 for (n = 0, i = 0; i < channels_alloc; i++) 434 for (n = 0, i = 0; i < channels_alloc; i++) {
416 if (channels[i]) 435 if ((other = channels[i]) != NULL) {
417 n++; 436 n++;
437
438 /* detach from mux client and prepare for closing */
439 if (c->type == SSH_CHANNEL_MUX_CLIENT &&
440 other->type == SSH_CHANNEL_MUX_PROXY &&
441 other->mux_ctx == c) {
442 other->mux_ctx = NULL;
443 other->type = SSH_CHANNEL_OPEN;
444 other->istate = CHAN_INPUT_CLOSED;
445 other->ostate = CHAN_OUTPUT_CLOSED;
446 }
447 }
448 }
418 debug("channel %d: free: %s, nchannels %u", c->self, 449 debug("channel %d: free: %s, nchannels %u", c->self,
419 c->remote_name ? c->remote_name : "???", n); 450 c->remote_name ? c->remote_name : "???", n);
420 451
452 /* XXX more MUX cleanup: remove remote forwardings */
453 if (c->type == SSH_CHANNEL_MUX_CLIENT) {
454 for (i = 0; i < (u_int)num_permitted_opens; i++) {
455 if (permitted_opens[i].downstream != c)
456 continue;
457 /* cancel on the server, since mux client is gone */
458 debug("channel %d: cleanup remote forward for %s:%u",
459 c->self,
460 permitted_opens[i].listen_host,
461 permitted_opens[i].listen_port);
462 packet_start(SSH2_MSG_GLOBAL_REQUEST);
463 packet_put_cstring("cancel-tcpip-forward");
464 packet_put_char(0);
465 packet_put_cstring(channel_rfwd_bind_host(
466 permitted_opens[i].listen_host));
467 packet_put_int(permitted_opens[i].listen_port);
468 packet_send();
469 /* unregister */
470 permitted_opens[i].listen_port = 0;
471 permitted_opens[i].port_to_connect = 0;
472 free(permitted_opens[i].host_to_connect);
473 permitted_opens[i].host_to_connect = NULL;
474 free(permitted_opens[i].listen_host);
475 permitted_opens[i].listen_host = NULL;
476 permitted_opens[i].listen_path = NULL;
477 permitted_opens[i].downstream = NULL;
478 }
479 }
480
421 s = channel_open_message(); 481 s = channel_open_message();
422 debug3("channel %d: status: %s", c->self, s); 482 debug3("channel %d: status: %s", c->self, s);
423 free(s); 483 free(s);
@@ -563,6 +623,7 @@ channel_still_open(void)
563 case SSH_CHANNEL_OPEN: 623 case SSH_CHANNEL_OPEN:
564 case SSH_CHANNEL_X11_OPEN: 624 case SSH_CHANNEL_X11_OPEN:
565 case SSH_CHANNEL_MUX_CLIENT: 625 case SSH_CHANNEL_MUX_CLIENT:
626 case SSH_CHANNEL_MUX_PROXY:
566 return 1; 627 return 1;
567 case SSH_CHANNEL_INPUT_DRAINING: 628 case SSH_CHANNEL_INPUT_DRAINING:
568 case SSH_CHANNEL_OUTPUT_DRAINING: 629 case SSH_CHANNEL_OUTPUT_DRAINING:
@@ -596,6 +657,7 @@ channel_find_open(void)
596 case SSH_CHANNEL_RPORT_LISTENER: 657 case SSH_CHANNEL_RPORT_LISTENER:
597 case SSH_CHANNEL_MUX_LISTENER: 658 case SSH_CHANNEL_MUX_LISTENER:
598 case SSH_CHANNEL_MUX_CLIENT: 659 case SSH_CHANNEL_MUX_CLIENT:
660 case SSH_CHANNEL_MUX_PROXY:
599 case SSH_CHANNEL_OPENING: 661 case SSH_CHANNEL_OPENING:
600 case SSH_CHANNEL_CONNECTING: 662 case SSH_CHANNEL_CONNECTING:
601 case SSH_CHANNEL_ZOMBIE: 663 case SSH_CHANNEL_ZOMBIE:
@@ -621,7 +683,6 @@ channel_find_open(void)
621 return -1; 683 return -1;
622} 684}
623 685
624
625/* 686/*
626 * Returns a message describing the currently open forwarded connections, 687 * Returns a message describing the currently open forwarded connections,
627 * suitable for sending to the client. The message contains crlf pairs for 688 * suitable for sending to the client. The message contains crlf pairs for
@@ -650,7 +711,6 @@ channel_open_message(void)
650 case SSH_CHANNEL_AUTH_SOCKET: 711 case SSH_CHANNEL_AUTH_SOCKET:
651 case SSH_CHANNEL_ZOMBIE: 712 case SSH_CHANNEL_ZOMBIE:
652 case SSH_CHANNEL_ABANDONED: 713 case SSH_CHANNEL_ABANDONED:
653 case SSH_CHANNEL_MUX_CLIENT:
654 case SSH_CHANNEL_MUX_LISTENER: 714 case SSH_CHANNEL_MUX_LISTENER:
655 case SSH_CHANNEL_UNIX_LISTENER: 715 case SSH_CHANNEL_UNIX_LISTENER:
656 case SSH_CHANNEL_RUNIX_LISTENER: 716 case SSH_CHANNEL_RUNIX_LISTENER:
@@ -663,6 +723,8 @@ channel_open_message(void)
663 case SSH_CHANNEL_X11_OPEN: 723 case SSH_CHANNEL_X11_OPEN:
664 case SSH_CHANNEL_INPUT_DRAINING: 724 case SSH_CHANNEL_INPUT_DRAINING:
665 case SSH_CHANNEL_OUTPUT_DRAINING: 725 case SSH_CHANNEL_OUTPUT_DRAINING:
726 case SSH_CHANNEL_MUX_PROXY:
727 case SSH_CHANNEL_MUX_CLIENT:
666 snprintf(buf, sizeof buf, 728 snprintf(buf, sizeof buf,
667 " #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n", 729 " #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n",
668 c->self, c->remote_name, 730 c->self, c->remote_name,
@@ -2360,6 +2422,278 @@ channel_output_poll(void)
2360 } 2422 }
2361} 2423}
2362 2424
2425/* -- mux proxy support */
2426
2427/*
2428 * When multiplexing channel messages for mux clients we have to deal
2429 * with downstream messages from the mux client and upstream messages
2430 * from the ssh server:
2431 * 1) Handling downstream messages is straightforward and happens
2432 * in channel_proxy_downstream():
2433 * - We forward all messages (mostly) unmodified to the server.
2434 * - However, in order to route messages from upstream to the correct
2435 * downstream client, we have to replace the channel IDs used by the
2436 * mux clients with a unique channel ID because the mux clients might
2437 * use conflicting channel IDs.
2438 * - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and
2439 * SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local
2440 * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
2441 * with the newly allocated channel ID.
2442 * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
2443 * channels and procesed by channel_proxy_upstream(). The local channel ID
2444 * is then translated back to the original mux client ID.
2445 * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
2446 * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
2447 * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the
2448 * downstream mux client are removed.
2449 * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server
2450 * requires more work, because they are not addressed to a specific
2451 * channel. E.g. client_request_forwarded_tcpip() needs to figure
2452 * out whether the request is addressed to the local client or a
2453 * specific downstream client based on the listen-address/port.
2454 * 6) Agent and X11-Forwarding have a similar problem and are currenly
2455 * not supported as the matching session/channel cannot be identified
2456 * easily.
2457 */
2458
2459/*
2460 * receive packets from downstream mux clients:
2461 * channel callback fired on read from mux client, creates
2462 * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs
2463 * on channel creation.
2464 */
2465int
2466channel_proxy_downstream(Channel *downstream)
2467{
2468 Channel *c = NULL;
2469 struct ssh *ssh = active_state;
2470 struct sshbuf *original = NULL, *modified = NULL;
2471 const u_char *cp;
2472 char *ctype = NULL, *listen_host = NULL;
2473 u_char type;
2474 size_t have;
2475 int ret = -1, r, id, remote_id, listen_port, idx;
2476
2477 /* sshbuf_dump(&downstream->input, stderr); */
2478 if ((r = sshbuf_get_string_direct(&downstream->input, &cp, &have))
2479 != 0) {
2480 error("%s: malformed message: %s", __func__, ssh_err(r));
2481 return -1;
2482 }
2483 if (have < 2) {
2484 error("%s: short message", __func__);
2485 return -1;
2486 }
2487 type = cp[1];
2488 /* skip padlen + type */
2489 cp += 2;
2490 have -= 2;
2491 if (ssh_packet_log_type(type))
2492 debug3("%s: channel %u: down->up: type %u", __func__,
2493 downstream->self, type);
2494
2495 switch (type) {
2496 case SSH2_MSG_CHANNEL_OPEN:
2497 if ((original = sshbuf_from(cp, have)) == NULL ||
2498 (modified = sshbuf_new()) == NULL) {
2499 error("%s: alloc", __func__);
2500 goto out;
2501 }
2502 if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||
2503 (r = sshbuf_get_u32(original, &id)) != 0) {
2504 error("%s: parse error %s", __func__, ssh_err(r));
2505 goto out;
2506 }
2507 c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY,
2508 -1, -1, -1, 0, 0, 0, ctype, 1);
2509 c->mux_ctx = downstream; /* point to mux client */
2510 c->mux_downstream_id = id; /* original downstream id */
2511 if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
2512 (r = sshbuf_put_u32(modified, c->self)) != 0 ||
2513 (r = sshbuf_putb(modified, original)) != 0) {
2514 error("%s: compose error %s", __func__, ssh_err(r));
2515 channel_free(c);
2516 goto out;
2517 }
2518 break;
2519 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
2520 /*
2521 * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we
2522 * need to parse 'remote_id' instead of 'ctype'.
2523 */
2524 if ((original = sshbuf_from(cp, have)) == NULL ||
2525 (modified = sshbuf_new()) == NULL) {
2526 error("%s: alloc", __func__);
2527 goto out;
2528 }
2529 if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
2530 (r = sshbuf_get_u32(original, &id)) != 0) {
2531 error("%s: parse error %s", __func__, ssh_err(r));
2532 goto out;
2533 }
2534 c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY,
2535 -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
2536 c->mux_ctx = downstream; /* point to mux client */
2537 c->mux_downstream_id = id;
2538 c->remote_id = remote_id;
2539 if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
2540 (r = sshbuf_put_u32(modified, c->self)) != 0 ||
2541 (r = sshbuf_putb(modified, original)) != 0) {
2542 error("%s: compose error %s", __func__, ssh_err(r));
2543 channel_free(c);
2544 goto out;
2545 }
2546 break;
2547 case SSH2_MSG_GLOBAL_REQUEST:
2548 if ((original = sshbuf_from(cp, have)) == NULL) {
2549 error("%s: alloc", __func__);
2550 goto out;
2551 }
2552 if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {
2553 error("%s: parse error %s", __func__, ssh_err(r));
2554 goto out;
2555 }
2556 if (strcmp(ctype, "tcpip-forward") != 0) {
2557 error("%s: unsupported request %s", __func__, ctype);
2558 goto out;
2559 }
2560 if ((r = sshbuf_get_u8(original, NULL)) != 0 ||
2561 (r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||
2562 (r = sshbuf_get_u32(original, &listen_port)) != 0) {
2563 error("%s: parse error %s", __func__, ssh_err(r));
2564 goto out;
2565 }
2566 /* Record that connection to this host/port is permitted. */
2567 permitted_opens = xreallocarray(permitted_opens,
2568 num_permitted_opens + 1, sizeof(*permitted_opens));
2569 idx = num_permitted_opens++;
2570 permitted_opens[idx].host_to_connect = xstrdup("<mux>");
2571 permitted_opens[idx].port_to_connect = -1;
2572 permitted_opens[idx].listen_host = listen_host;
2573 permitted_opens[idx].listen_port = listen_port;
2574 permitted_opens[idx].downstream = downstream;
2575 listen_host = NULL;
2576 break;
2577 case SSH2_MSG_CHANNEL_CLOSE:
2578 if (have < 4)
2579 break;
2580 remote_id = PEEK_U32(cp);
2581 if ((c = channel_by_remote_id(remote_id)) != NULL) {
2582 if (c->flags & CHAN_CLOSE_RCVD)
2583 channel_free(c);
2584 else
2585 c->flags |= CHAN_CLOSE_SENT;
2586 }
2587 break;
2588 }
2589 if (modified) {
2590 if ((r = sshpkt_start(ssh, type)) != 0 ||
2591 (r = sshpkt_putb(ssh, modified)) != 0 ||
2592 (r = sshpkt_send(ssh)) != 0) {
2593 error("%s: send %s", __func__, ssh_err(r));
2594 goto out;
2595 }
2596 } else {
2597 if ((r = sshpkt_start(ssh, type)) != 0 ||
2598 (r = sshpkt_put(ssh, cp, have)) != 0 ||
2599 (r = sshpkt_send(ssh)) != 0) {
2600 error("%s: send %s", __func__, ssh_err(r));
2601 goto out;
2602 }
2603 }
2604 ret = 0;
2605 out:
2606 free(ctype);
2607 free(listen_host);
2608 sshbuf_free(original);
2609 sshbuf_free(modified);
2610 return ret;
2611}
2612
2613/*
2614 * receive packets from upstream server and de-multiplex packets
2615 * to correct downstream:
2616 * implemented as a helper for channel input handlers,
2617 * replaces local (proxy) channel ID with downstream channel ID.
2618 */
2619int
2620channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt)
2621{
2622 struct ssh *ssh = active_state;
2623 struct sshbuf *b = NULL;
2624 Channel *downstream;
2625 const u_char *cp = NULL;
2626 size_t len;
2627 int r;
2628
2629 /*
2630 * When receiving packets from the peer we need to check whether we
2631 * need to forward the packets to the mux client. In this case we
2632 * restore the orignal channel id and keep track of CLOSE messages,
2633 * so we can cleanup the channel.
2634 */
2635 if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)
2636 return 0;
2637 if ((downstream = c->mux_ctx) == NULL)
2638 return 0;
2639 switch (type) {
2640 case SSH2_MSG_CHANNEL_CLOSE:
2641 case SSH2_MSG_CHANNEL_DATA:
2642 case SSH2_MSG_CHANNEL_EOF:
2643 case SSH2_MSG_CHANNEL_EXTENDED_DATA:
2644 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
2645 case SSH2_MSG_CHANNEL_OPEN_FAILURE:
2646 case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
2647 case SSH2_MSG_CHANNEL_SUCCESS:
2648 case SSH2_MSG_CHANNEL_FAILURE:
2649 case SSH2_MSG_CHANNEL_REQUEST:
2650 break;
2651 default:
2652 debug2("%s: channel %u: unsupported type %u", __func__,
2653 c->self, type);
2654 return 0;
2655 }
2656 if ((b = sshbuf_new()) == NULL) {
2657 error("%s: alloc reply", __func__);
2658 goto out;
2659 }
2660 /* get remaining payload (after id) */
2661 cp = sshpkt_ptr(ssh, &len);
2662 if (cp == NULL) {
2663 error("%s: no packet", __func__);
2664 goto out;
2665 }
2666 /* translate id and send to muxclient */
2667 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
2668 (r = sshbuf_put_u8(b, type)) != 0 ||
2669 (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
2670 (r = sshbuf_put(b, cp, len)) != 0 ||
2671 (r = sshbuf_put_stringb(&downstream->output, b)) != 0) {
2672 error("%s: compose for muxclient %s", __func__, ssh_err(r));
2673 goto out;
2674 }
2675 /* sshbuf_dump(b, stderr); */
2676 if (ssh_packet_log_type(type))
2677 debug3("%s: channel %u: up->down: type %u", __func__, c->self,
2678 type);
2679 out:
2680 /* update state */
2681 switch (type) {
2682 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
2683 /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */
2684 if (cp && len > 4)
2685 c->remote_id = PEEK_U32(cp);
2686 break;
2687 case SSH2_MSG_CHANNEL_CLOSE:
2688 if (c->flags & CHAN_CLOSE_SENT)
2689 channel_free(c);
2690 else
2691 c->flags |= CHAN_CLOSE_RCVD;
2692 break;
2693 }
2694 sshbuf_free(b);
2695 return 1;
2696}
2363 2697
2364/* -- protocol input */ 2698/* -- protocol input */
2365 2699
@@ -2377,6 +2711,8 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2377 c = channel_lookup(id); 2711 c = channel_lookup(id);
2378 if (c == NULL) 2712 if (c == NULL)
2379 packet_disconnect("Received data for nonexistent channel %d.", id); 2713 packet_disconnect("Received data for nonexistent channel %d.", id);
2714 if (channel_proxy_upstream(c, type, seq, ctxt))
2715 return 0;
2380 2716
2381 /* Ignore any data for non-open channels (might happen on close) */ 2717 /* Ignore any data for non-open channels (might happen on close) */
2382 if (c->type != SSH_CHANNEL_OPEN && 2718 if (c->type != SSH_CHANNEL_OPEN &&
@@ -2439,6 +2775,8 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
2439 2775
2440 if (c == NULL) 2776 if (c == NULL)
2441 packet_disconnect("Received extended_data for bad channel %d.", id); 2777 packet_disconnect("Received extended_data for bad channel %d.", id);
2778 if (channel_proxy_upstream(c, type, seq, ctxt))
2779 return 0;
2442 if (c->type != SSH_CHANNEL_OPEN) { 2780 if (c->type != SSH_CHANNEL_OPEN) {
2443 logit("channel %d: ext data for non open", id); 2781 logit("channel %d: ext data for non open", id);
2444 return 0; 2782 return 0;
@@ -2484,6 +2822,8 @@ channel_input_ieof(int type, u_int32_t seq, void *ctxt)
2484 c = channel_lookup(id); 2822 c = channel_lookup(id);
2485 if (c == NULL) 2823 if (c == NULL)
2486 packet_disconnect("Received ieof for nonexistent channel %d.", id); 2824 packet_disconnect("Received ieof for nonexistent channel %d.", id);
2825 if (channel_proxy_upstream(c, type, seq, ctxt))
2826 return 0;
2487 chan_rcvd_ieof(c); 2827 chan_rcvd_ieof(c);
2488 2828
2489 /* XXX force input close */ 2829 /* XXX force input close */
@@ -2508,7 +2848,8 @@ channel_input_close(int type, u_int32_t seq, void *ctxt)
2508 c = channel_lookup(id); 2848 c = channel_lookup(id);
2509 if (c == NULL) 2849 if (c == NULL)
2510 packet_disconnect("Received close for nonexistent channel %d.", id); 2850 packet_disconnect("Received close for nonexistent channel %d.", id);
2511 2851 if (channel_proxy_upstream(c, type, seq, ctxt))
2852 return 0;
2512 /* 2853 /*
2513 * Send a confirmation that we have closed the channel and no more 2854 * Send a confirmation that we have closed the channel and no more
2514 * data is coming for it. 2855 * data is coming for it.
@@ -2543,9 +2884,11 @@ channel_input_oclose(int type, u_int32_t seq, void *ctxt)
2543 int id = packet_get_int(); 2884 int id = packet_get_int();
2544 Channel *c = channel_lookup(id); 2885 Channel *c = channel_lookup(id);
2545 2886
2546 packet_check_eom();
2547 if (c == NULL) 2887 if (c == NULL)
2548 packet_disconnect("Received oclose for nonexistent channel %d.", id); 2888 packet_disconnect("Received oclose for nonexistent channel %d.", id);
2889 if (channel_proxy_upstream(c, type, seq, ctxt))
2890 return 0;
2891 packet_check_eom();
2549 chan_rcvd_oclose(c); 2892 chan_rcvd_oclose(c);
2550 return 0; 2893 return 0;
2551} 2894}
@@ -2557,10 +2900,12 @@ channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt)
2557 int id = packet_get_int(); 2900 int id = packet_get_int();
2558 Channel *c = channel_lookup(id); 2901 Channel *c = channel_lookup(id);
2559 2902
2560 packet_check_eom();
2561 if (c == NULL) 2903 if (c == NULL)
2562 packet_disconnect("Received close confirmation for " 2904 packet_disconnect("Received close confirmation for "
2563 "out-of-range channel %d.", id); 2905 "out-of-range channel %d.", id);
2906 if (channel_proxy_upstream(c, type, seq, ctxt))
2907 return 0;
2908 packet_check_eom();
2564 if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED) 2909 if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED)
2565 packet_disconnect("Received close confirmation for " 2910 packet_disconnect("Received close confirmation for "
2566 "non-closed channel %d (type %d).", id, c->type); 2911 "non-closed channel %d (type %d).", id, c->type);
@@ -2578,7 +2923,12 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
2578 id = packet_get_int(); 2923 id = packet_get_int();
2579 c = channel_lookup(id); 2924 c = channel_lookup(id);
2580 2925
2581 if (c==NULL || c->type != SSH_CHANNEL_OPENING) 2926 if (c==NULL)
2927 packet_disconnect("Received open confirmation for "
2928 "unknown channel %d.", id);
2929 if (channel_proxy_upstream(c, type, seq, ctxt))
2930 return 0;
2931 if (c->type != SSH_CHANNEL_OPENING)
2582 packet_disconnect("Received open confirmation for " 2932 packet_disconnect("Received open confirmation for "
2583 "non-opening channel %d.", id); 2933 "non-opening channel %d.", id);
2584 remote_id = packet_get_int(); 2934 remote_id = packet_get_int();
@@ -2628,7 +2978,12 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
2628 id = packet_get_int(); 2978 id = packet_get_int();
2629 c = channel_lookup(id); 2979 c = channel_lookup(id);
2630 2980
2631 if (c==NULL || c->type != SSH_CHANNEL_OPENING) 2981 if (c==NULL)
2982 packet_disconnect("Received open failure for "
2983 "unknown channel %d.", id);
2984 if (channel_proxy_upstream(c, type, seq, ctxt))
2985 return 0;
2986 if (c->type != SSH_CHANNEL_OPENING)
2632 packet_disconnect("Received open failure for " 2987 packet_disconnect("Received open failure for "
2633 "non-opening channel %d.", id); 2988 "non-opening channel %d.", id);
2634 if (compat20) { 2989 if (compat20) {
@@ -2672,6 +3027,8 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
2672 logit("Received window adjust for non-open channel %d.", id); 3027 logit("Received window adjust for non-open channel %d.", id);
2673 return 0; 3028 return 0;
2674 } 3029 }
3030 if (channel_proxy_upstream(c, type, seq, ctxt))
3031 return 0;
2675 adjust = packet_get_int(); 3032 adjust = packet_get_int();
2676 packet_check_eom(); 3033 packet_check_eom();
2677 debug2("channel %d: rcvd adjust %u", id, adjust); 3034 debug2("channel %d: rcvd adjust %u", id, adjust);
@@ -2726,14 +3083,15 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
2726 packet_set_alive_timeouts(0); 3083 packet_set_alive_timeouts(0);
2727 3084
2728 id = packet_get_int(); 3085 id = packet_get_int();
2729 packet_check_eom();
2730
2731 debug2("channel_input_status_confirm: type %d id %d", type, id); 3086 debug2("channel_input_status_confirm: type %d id %d", type, id);
2732 3087
2733 if ((c = channel_lookup(id)) == NULL) { 3088 if ((c = channel_lookup(id)) == NULL) {
2734 logit("channel_input_status_confirm: %d: unknown", id); 3089 logit("channel_input_status_confirm: %d: unknown", id);
2735 return 0; 3090 return 0;
2736 } 3091 }
3092 if (channel_proxy_upstream(c, type, seq, ctxt))
3093 return 0;
3094 packet_check_eom();
2737 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) 3095 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
2738 return 0; 3096 return 0;
2739 cc->cb(type, c, cc->ctx); 3097 cc->cb(type, c, cc->ctx);
@@ -3287,6 +3645,7 @@ channel_request_remote_forwarding(struct Forward *fwd)
3287 permitted_opens[idx].listen_path = NULL; 3645 permitted_opens[idx].listen_path = NULL;
3288 permitted_opens[idx].listen_port = fwd->listen_port; 3646 permitted_opens[idx].listen_port = fwd->listen_port;
3289 } 3647 }
3648 permitted_opens[idx].downstream = NULL;
3290 } 3649 }
3291 return (idx); 3650 return (idx);
3292} 3651}
@@ -3382,6 +3741,7 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port)
3382 free(permitted_opens[i].listen_host); 3741 free(permitted_opens[i].listen_host);
3383 permitted_opens[i].listen_host = NULL; 3742 permitted_opens[i].listen_host = NULL;
3384 permitted_opens[i].listen_path = NULL; 3743 permitted_opens[i].listen_path = NULL;
3744 permitted_opens[i].downstream = NULL;
3385 3745
3386 return 0; 3746 return 0;
3387} 3747}
@@ -3419,6 +3779,7 @@ channel_request_rforward_cancel_streamlocal(const char *path)
3419 permitted_opens[i].listen_host = NULL; 3779 permitted_opens[i].listen_host = NULL;
3420 free(permitted_opens[i].listen_path); 3780 free(permitted_opens[i].listen_path);
3421 permitted_opens[i].listen_path = NULL; 3781 permitted_opens[i].listen_path = NULL;
3782 permitted_opens[i].downstream = NULL;
3422 3783
3423 return 0; 3784 return 0;
3424} 3785}
@@ -3501,6 +3862,7 @@ channel_add_permitted_opens(char *host, int port)
3501 permitted_opens[num_permitted_opens].listen_host = NULL; 3862 permitted_opens[num_permitted_opens].listen_host = NULL;
3502 permitted_opens[num_permitted_opens].listen_path = NULL; 3863 permitted_opens[num_permitted_opens].listen_path = NULL;
3503 permitted_opens[num_permitted_opens].listen_port = 0; 3864 permitted_opens[num_permitted_opens].listen_port = 0;
3865 permitted_opens[num_permitted_opens].downstream = NULL;
3504 num_permitted_opens++; 3866 num_permitted_opens++;
3505 3867
3506 all_opens_permitted = 0; 3868 all_opens_permitted = 0;
@@ -3763,6 +4125,10 @@ connect_to(const char *name, int port, char *ctype, char *rname)
3763 return c; 4125 return c;
3764} 4126}
3765 4127
4128/*
4129 * returns either the newly connected channel or the downstream channel
4130 * that needs to deal with this connection.
4131 */
3766Channel * 4132Channel *
3767channel_connect_by_listen_address(const char *listen_host, 4133channel_connect_by_listen_address(const char *listen_host,
3768 u_short listen_port, char *ctype, char *rname) 4134 u_short listen_port, char *ctype, char *rname)
@@ -3772,6 +4138,8 @@ channel_connect_by_listen_address(const char *listen_host,
3772 for (i = 0; i < num_permitted_opens; i++) { 4138 for (i = 0; i < num_permitted_opens; i++) {
3773 if (open_listen_match_tcpip(&permitted_opens[i], listen_host, 4139 if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
3774 listen_port, 1)) { 4140 listen_port, 1)) {
4141 if (permitted_opens[i].downstream)
4142 return permitted_opens[i].downstream;
3775 return connect_to( 4143 return connect_to(
3776 permitted_opens[i].host_to_connect, 4144 permitted_opens[i].host_to_connect,
3777 permitted_opens[i].port_to_connect, ctype, rname); 4145 permitted_opens[i].port_to_connect, ctype, rname);