summaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c181
1 files changed, 152 insertions, 29 deletions
diff --git a/mux.c b/mux.c
index 825fb7a9a..5c3857ee8 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.14 2010/01/30 02:54:53 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -71,6 +71,7 @@
71#include "xmalloc.h" 71#include "xmalloc.h"
72#include "log.h" 72#include "log.h"
73#include "ssh.h" 73#include "ssh.h"
74#include "ssh2.h"
74#include "pathnames.h" 75#include "pathnames.h"
75#include "misc.h" 76#include "misc.h"
76#include "match.h" 77#include "match.h"
@@ -106,6 +107,14 @@ struct mux_session_confirm_ctx {
106 char *term; 107 char *term;
107 struct termios tio; 108 struct termios tio;
108 char **env; 109 char **env;
110 u_int rid;
111};
112
113/* Context for global channel callback */
114struct mux_channel_confirm_ctx {
115 u_int cid; /* channel id */
116 u_int rid; /* request id */
117 int fid; /* forward id */
109}; 118};
110 119
111/* fd to control socket */ 120/* fd to control socket */
@@ -143,13 +152,14 @@ struct mux_master_state {
143#define MUX_S_EXIT_MESSAGE 0x80000004 152#define MUX_S_EXIT_MESSAGE 0x80000004
144#define MUX_S_ALIVE 0x80000005 153#define MUX_S_ALIVE 0x80000005
145#define MUX_S_SESSION_OPENED 0x80000006 154#define MUX_S_SESSION_OPENED 0x80000006
155#define MUX_S_REMOTE_PORT 0x80000007
146 156
147/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ 157/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
148#define MUX_FWD_LOCAL 1 158#define MUX_FWD_LOCAL 1
149#define MUX_FWD_REMOTE 2 159#define MUX_FWD_REMOTE 2
150#define MUX_FWD_DYNAMIC 3 160#define MUX_FWD_DYNAMIC 3
151 161
152static void mux_session_confirm(int, void *); 162static void mux_session_confirm(int, int, void *);
153 163
154static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); 164static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
155static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); 165static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
@@ -206,7 +216,7 @@ mux_master_control_cleanup_cb(int cid, void *unused)
206 fatal("%s: channel_by_id(%i) == NULL", __func__, cid); 216 fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
207 if (c->remote_id != -1) { 217 if (c->remote_id != -1) {
208 if ((sc = channel_by_id(c->remote_id)) == NULL) 218 if ((sc = channel_by_id(c->remote_id)) == NULL)
209 debug2("%s: channel %d n session channel %d", 219 fatal("%s: channel %d missing session channel %d",
210 __func__, c->self, c->remote_id); 220 __func__, c->self, c->remote_id);
211 c->remote_id = -1; 221 c->remote_id = -1;
212 sc->ctl_chan = -1; 222 sc->ctl_chan = -1;
@@ -301,6 +311,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
301 /* Reply for SSHMUX_COMMAND_OPEN */ 311 /* Reply for SSHMUX_COMMAND_OPEN */
302 cctx = xcalloc(1, sizeof(*cctx)); 312 cctx = xcalloc(1, sizeof(*cctx));
303 cctx->term = NULL; 313 cctx->term = NULL;
314 cctx->rid = rid;
304 cmd = reserved = NULL; 315 cmd = reserved = NULL;
305 if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || 316 if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
306 buffer_get_int_ret(&cctx->want_tty, m) != 0 || 317 buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
@@ -454,14 +465,10 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
454 465
455 channel_send_open(nc->self); 466 channel_send_open(nc->self);
456 channel_register_open_confirm(nc->self, mux_session_confirm, cctx); 467 channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
457 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0); 468 c->mux_pause = 1; /* stop handling messages until open_confirm done */
458 469 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
459 /* prepare reply */
460 /* XXX defer until mux_session_confirm() fires */
461 buffer_put_int(r, MUX_S_SESSION_OPENED);
462 buffer_put_int(r, rid);
463 buffer_put_int(r, nc->self);
464 470
471 /* reply is deferred, sent by mux_session_confirm */
465 return 0; 472 return 0;
466} 473}
467 474
@@ -559,6 +566,61 @@ compare_forward(Forward *a, Forward *b)
559 return 1; 566 return 1;
560} 567}
561 568
569static void
570mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
571{
572 struct mux_channel_confirm_ctx *fctx = ctxt;
573 char *failmsg = NULL;
574 Forward *rfwd;
575 Channel *c;
576 Buffer out;
577
578 if ((c = channel_by_id(fctx->cid)) == NULL) {
579 /* no channel for reply */
580 error("%s: unknown channel", __func__);
581 return;
582 }
583 buffer_init(&out);
584 if (fctx->fid >= options.num_remote_forwards) {
585 xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid);
586 goto fail;
587 }
588 rfwd = &options.remote_forwards[fctx->fid];
589 debug("%s: %s for: listen %d, connect %s:%d", __func__,
590 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
591 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
592 if (type == SSH2_MSG_REQUEST_SUCCESS) {
593 if (rfwd->listen_port == 0) {
594 rfwd->allocated_port = packet_get_int();
595 logit("Allocated port %u for mux remote forward"
596 " to %s:%d", rfwd->allocated_port,
597 rfwd->connect_host, rfwd->connect_port);
598 buffer_put_int(&out, MUX_S_REMOTE_PORT);
599 buffer_put_int(&out, fctx->rid);
600 buffer_put_int(&out, rfwd->allocated_port);
601 } else {
602 buffer_put_int(&out, MUX_S_OK);
603 buffer_put_int(&out, fctx->rid);
604 }
605 goto out;
606 } else {
607 xasprintf(&failmsg, "remote port forwarding failed for "
608 "listen port %d", rfwd->listen_port);
609 }
610 fail:
611 error("%s: %s", __func__, failmsg);
612 buffer_put_int(&out, MUX_S_FAILURE);
613 buffer_put_int(&out, fctx->rid);
614 buffer_put_cstring(&out, failmsg);
615 xfree(failmsg);
616 out:
617 buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
618 buffer_free(&out);
619 if (c->mux_pause <= 0)
620 fatal("%s: mux_pause %d", __func__, c->mux_pause);
621 c->mux_pause = 0; /* start processing messages again */
622}
623
562static int 624static int
563process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 625process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
564{ 626{
@@ -594,15 +656,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
594 ftype != MUX_FWD_DYNAMIC) { 656 ftype != MUX_FWD_DYNAMIC) {
595 logit("%s: invalid forwarding type %u", __func__, ftype); 657 logit("%s: invalid forwarding type %u", __func__, ftype);
596 invalid: 658 invalid:
597 xfree(fwd.listen_host); 659 if (fwd.listen_host)
598 xfree(fwd.connect_host); 660 xfree(fwd.listen_host);
661 if (fwd.connect_host)
662 xfree(fwd.connect_host);
599 buffer_put_int(r, MUX_S_FAILURE); 663 buffer_put_int(r, MUX_S_FAILURE);
600 buffer_put_int(r, rid); 664 buffer_put_int(r, rid);
601 buffer_put_cstring(r, "Invalid forwarding request"); 665 buffer_put_cstring(r, "Invalid forwarding request");
602 return 0; 666 return 0;
603 } 667 }
604 /* XXX support rport0 forwarding with reply of port assigned */ 668 if (fwd.listen_port >= 65536) {
605 if (fwd.listen_port == 0 || fwd.listen_port >= 65536) {
606 logit("%s: invalid listen port %u", __func__, 669 logit("%s: invalid listen port %u", __func__,
607 fwd.listen_port); 670 fwd.listen_port);
608 goto invalid; 671 goto invalid;
@@ -637,8 +700,17 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
637 case MUX_FWD_REMOTE: 700 case MUX_FWD_REMOTE:
638 for (i = 0; i < options.num_remote_forwards; i++) { 701 for (i = 0; i < options.num_remote_forwards; i++) {
639 if (compare_forward(&fwd, 702 if (compare_forward(&fwd,
640 options.remote_forwards + i)) 703 options.remote_forwards + i)) {
641 goto exists; 704 if (fwd.listen_port != 0)
705 goto exists;
706 debug2("%s: found allocated port",
707 __func__);
708 buffer_put_int(r, MUX_S_REMOTE_PORT);
709 buffer_put_int(r, rid);
710 buffer_put_int(r,
711 options.remote_forwards[i].allocated_port);
712 goto out;
713 }
642 } 714 }
643 break; 715 break;
644 } 716 }
@@ -655,9 +727,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
655 } 727 }
656 728
657 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { 729 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
658 if (options.num_local_forwards + 1 >= 730 if (channel_setup_local_fwd_listener(fwd.listen_host,
659 SSH_MAX_FORWARDS_PER_DIRECTION ||
660 channel_setup_local_fwd_listener(fwd.listen_host,
661 fwd.listen_port, fwd.connect_host, fwd.connect_port, 731 fwd.listen_port, fwd.connect_host, fwd.connect_port,
662 options.gateway_ports) < 0) { 732 options.gateway_ports) < 0) {
663 fail: 733 fail:
@@ -670,14 +740,22 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
670 add_local_forward(&options, &fwd); 740 add_local_forward(&options, &fwd);
671 freefwd = 0; 741 freefwd = 0;
672 } else { 742 } else {
673 /* XXX wait for remote to confirm */ 743 struct mux_channel_confirm_ctx *fctx;
674 if (options.num_remote_forwards + 1 >= 744
675 SSH_MAX_FORWARDS_PER_DIRECTION || 745 if (channel_request_remote_forwarding(fwd.listen_host,
676 channel_request_remote_forwarding(fwd.listen_host,
677 fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) 746 fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
678 goto fail; 747 goto fail;
679 add_remote_forward(&options, &fwd); 748 add_remote_forward(&options, &fwd);
749 fctx = xcalloc(1, sizeof(*fctx));
750 fctx->cid = c->self;
751 fctx->rid = rid;
752 fctx->fid = options.num_remote_forwards - 1;
753 client_register_global_confirm(mux_confirm_remote_forward,
754 fctx);
680 freefwd = 0; 755 freefwd = 0;
756 c->mux_pause = 1; /* wait for mux_confirm_remote_forward */
757 /* delayed reply in mux_confirm_remote_forward */
758 goto out;
681 } 759 }
682 buffer_put_int(r, MUX_S_OK); 760 buffer_put_int(r, MUX_S_OK);
683 buffer_put_int(r, rid); 761 buffer_put_int(r, rid);
@@ -826,7 +904,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
826 debug2("%s: channel_new: %d linked to control channel %d", 904 debug2("%s: channel_new: %d linked to control channel %d",
827 __func__, nc->self, nc->ctl_chan); 905 __func__, nc->self, nc->ctl_chan);
828 906
829 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0); 907 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
830 908
831 /* prepare reply */ 909 /* prepare reply */
832 /* XXX defer until channel confirmed */ 910 /* XXX defer until channel confirmed */
@@ -849,7 +927,7 @@ mux_master_read_cb(Channel *c)
849 927
850 /* Setup ctx and */ 928 /* Setup ctx and */
851 if (c->mux_ctx == NULL) { 929 if (c->mux_ctx == NULL) {
852 state = xcalloc(1, sizeof(state)); 930 state = xcalloc(1, sizeof(*state));
853 c->mux_ctx = state; 931 c->mux_ctx = state;
854 channel_register_cleanup(c->self, 932 channel_register_cleanup(c->self,
855 mux_master_control_cleanup_cb, 0); 933 mux_master_control_cleanup_cb, 0);
@@ -1000,26 +1078,43 @@ muxserver_listen(void)
1000 1078
1001/* Callback on open confirmation in mux master for a mux client session. */ 1079/* Callback on open confirmation in mux master for a mux client session. */
1002static void 1080static void
1003mux_session_confirm(int id, void *arg) 1081mux_session_confirm(int id, int success, void *arg)
1004{ 1082{
1005 struct mux_session_confirm_ctx *cctx = arg; 1083 struct mux_session_confirm_ctx *cctx = arg;
1006 const char *display; 1084 const char *display;
1007 Channel *c; 1085 Channel *c, *cc;
1008 int i; 1086 int i;
1087 Buffer reply;
1009 1088
1010 if (cctx == NULL) 1089 if (cctx == NULL)
1011 fatal("%s: cctx == NULL", __func__); 1090 fatal("%s: cctx == NULL", __func__);
1012 if ((c = channel_by_id(id)) == NULL) 1091 if ((c = channel_by_id(id)) == NULL)
1013 fatal("%s: no channel for id %d", __func__, id); 1092 fatal("%s: no channel for id %d", __func__, id);
1093 if ((cc = channel_by_id(c->ctl_chan)) == NULL)
1094 fatal("%s: channel %d lacks control channel %d", __func__,
1095 id, c->ctl_chan);
1096
1097 if (!success) {
1098 debug3("%s: sending failure reply", __func__);
1099 /* prepare reply */
1100 buffer_init(&reply);
1101 buffer_put_int(&reply, MUX_S_FAILURE);
1102 buffer_put_int(&reply, cctx->rid);
1103 buffer_put_cstring(&reply, "Session open refused by peer");
1104 goto done;
1105 }
1014 1106
1015 display = getenv("DISPLAY"); 1107 display = getenv("DISPLAY");
1016 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { 1108 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
1017 char *proto, *data; 1109 char *proto, *data;
1110
1018 /* Get reasonable local authentication information. */ 1111 /* Get reasonable local authentication information. */
1019 client_x11_get_proto(display, options.xauth_location, 1112 client_x11_get_proto(display, options.xauth_location,
1020 options.forward_x11_trusted, &proto, &data); 1113 options.forward_x11_trusted, options.forward_x11_timeout,
1114 &proto, &data);
1021 /* Request forwarding with authentication spoofing. */ 1115 /* Request forwarding with authentication spoofing. */
1022 debug("Requesting X11 forwarding with authentication spoofing."); 1116 debug("Requesting X11 forwarding with authentication "
1117 "spoofing.");
1023 x11_request_forwarding_with_spoofing(id, display, proto, data); 1118 x11_request_forwarding_with_spoofing(id, display, proto, data);
1024 /* XXX wait for reply */ 1119 /* XXX wait for reply */
1025 } 1120 }
@@ -1033,6 +1128,21 @@ mux_session_confirm(int id, void *arg)
1033 client_session2_setup(id, cctx->want_tty, cctx->want_subsys, 1128 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
1034 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); 1129 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
1035 1130
1131 debug3("%s: sending success reply", __func__);
1132 /* prepare reply */
1133 buffer_init(&reply);
1134 buffer_put_int(&reply, MUX_S_SESSION_OPENED);
1135 buffer_put_int(&reply, cctx->rid);
1136 buffer_put_int(&reply, c->self);
1137
1138 done:
1139 /* Send reply */
1140 buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
1141 buffer_free(&reply);
1142
1143 if (cc->mux_pause <= 0)
1144 fatal("%s: mux_pause %d", __func__, cc->mux_pause);
1145 cc->mux_pause = 0; /* start processing messages again */
1036 c->open_confirm_ctx = NULL; 1146 c->open_confirm_ctx = NULL;
1037 buffer_free(&cctx->cmd); 1147 buffer_free(&cctx->cmd);
1038 xfree(cctx->term); 1148 xfree(cctx->term);
@@ -1365,6 +1475,15 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
1365 switch (type) { 1475 switch (type) {
1366 case MUX_S_OK: 1476 case MUX_S_OK:
1367 break; 1477 break;
1478 case MUX_S_REMOTE_PORT:
1479 fwd->allocated_port = buffer_get_int(&m);
1480 logit("Allocated port %u for remote forward to %s:%d",
1481 fwd->allocated_port,
1482 fwd->connect_host ? fwd->connect_host : "",
1483 fwd->connect_port);
1484 if (muxclient_command == SSHMUX_COMMAND_FORWARD)
1485 fprintf(stdout, "%u\n", fwd->allocated_port);
1486 break;
1368 case MUX_S_PERMISSION_DENIED: 1487 case MUX_S_PERMISSION_DENIED:
1369 e = buffer_get_string(&m, NULL); 1488 e = buffer_get_string(&m, NULL);
1370 buffer_free(&m); 1489 buffer_free(&m);
@@ -1731,6 +1850,10 @@ muxclient(const char *path)
1731 mux_client_request_terminate(sock); 1850 mux_client_request_terminate(sock);
1732 fprintf(stderr, "Exit request sent.\r\n"); 1851 fprintf(stderr, "Exit request sent.\r\n");
1733 exit(0); 1852 exit(0);
1853 case SSHMUX_COMMAND_FORWARD:
1854 if (mux_client_request_forwards(sock) != 0)
1855 fatal("%s: master forward request failed", __func__);
1856 exit(0);
1734 case SSHMUX_COMMAND_OPEN: 1857 case SSHMUX_COMMAND_OPEN:
1735 if (mux_client_request_forwards(sock) != 0) { 1858 if (mux_client_request_forwards(sock) != 0) {
1736 error("%s: master forward request failed", __func__); 1859 error("%s: master forward request failed", __func__);