summaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-05-21 14:57:35 +1000
committerDamien Miller <djm@mindrot.org>2010-05-21 14:57:35 +1000
commit388f6fc48561851dcedd5433aff75f60af573fb2 (patch)
tree4ac7be863c3ba9be98df80c6d66953608cd77a6c /mux.c
parentd530f5f471491b6be9edb58a063f2590e4dce48d (diff)
- markus@cvs.openbsd.org 2010/05/16 12:55:51
[PROTOCOL.mux clientloop.h mux.c readconf.c readconf.h ssh.1 ssh.c] mux support for remote forwarding with dynamic port allocation, use with LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost` feedback and ok djm@
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c113
1 files changed, 105 insertions, 8 deletions
diff --git a/mux.c b/mux.c
index 18dfd99f3..3f5babccc 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.17 2010/05/14 23:29:23 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.18 2010/05/16 12:55:51 markus 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"
@@ -109,6 +110,13 @@ struct mux_session_confirm_ctx {
109 u_int rid; 110 u_int rid;
110}; 111};
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 */
118};
119
112/* fd to control socket */ 120/* fd to control socket */
113int muxserver_sock = -1; 121int muxserver_sock = -1;
114 122
@@ -144,6 +152,7 @@ struct mux_master_state {
144#define MUX_S_EXIT_MESSAGE 0x80000004 152#define MUX_S_EXIT_MESSAGE 0x80000004
145#define MUX_S_ALIVE 0x80000005 153#define MUX_S_ALIVE 0x80000005
146#define MUX_S_SESSION_OPENED 0x80000006 154#define MUX_S_SESSION_OPENED 0x80000006
155#define MUX_S_REMOTE_PORT 0x80000007
147 156
148/* 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 */
149#define MUX_FWD_LOCAL 1 158#define MUX_FWD_LOCAL 1
@@ -557,6 +566,61 @@ compare_forward(Forward *a, Forward *b)
557 return 1; 566 return 1;
558} 567}
559 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
560static int 624static int
561process_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)
562{ 626{
@@ -592,15 +656,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
592 ftype != MUX_FWD_DYNAMIC) { 656 ftype != MUX_FWD_DYNAMIC) {
593 logit("%s: invalid forwarding type %u", __func__, ftype); 657 logit("%s: invalid forwarding type %u", __func__, ftype);
594 invalid: 658 invalid:
595 xfree(fwd.listen_host); 659 if (fwd.listen_host)
596 xfree(fwd.connect_host); 660 xfree(fwd.listen_host);
661 if (fwd.connect_host)
662 xfree(fwd.connect_host);
597 buffer_put_int(r, MUX_S_FAILURE); 663 buffer_put_int(r, MUX_S_FAILURE);
598 buffer_put_int(r, rid); 664 buffer_put_int(r, rid);
599 buffer_put_cstring(r, "Invalid forwarding request"); 665 buffer_put_cstring(r, "Invalid forwarding request");
600 return 0; 666 return 0;
601 } 667 }
602 /* XXX support rport0 forwarding with reply of port assigned */ 668 if (fwd.listen_port >= 65536) {
603 if (fwd.listen_port == 0 || fwd.listen_port >= 65536) {
604 logit("%s: invalid listen port %u", __func__, 669 logit("%s: invalid listen port %u", __func__,
605 fwd.listen_port); 670 fwd.listen_port);
606 goto invalid; 671 goto invalid;
@@ -635,8 +700,17 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
635 case MUX_FWD_REMOTE: 700 case MUX_FWD_REMOTE:
636 for (i = 0; i < options.num_remote_forwards; i++) { 701 for (i = 0; i < options.num_remote_forwards; i++) {
637 if (compare_forward(&fwd, 702 if (compare_forward(&fwd,
638 options.remote_forwards + i)) 703 options.remote_forwards + i)) {
639 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 }
640 } 714 }
641 break; 715 break;
642 } 716 }
@@ -668,14 +742,24 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
668 add_local_forward(&options, &fwd); 742 add_local_forward(&options, &fwd);
669 freefwd = 0; 743 freefwd = 0;
670 } else { 744 } else {
671 /* XXX wait for remote to confirm */ 745 struct mux_channel_confirm_ctx *fctx;
746
672 if (options.num_remote_forwards + 1 >= 747 if (options.num_remote_forwards + 1 >=
673 SSH_MAX_FORWARDS_PER_DIRECTION || 748 SSH_MAX_FORWARDS_PER_DIRECTION ||
674 channel_request_remote_forwarding(fwd.listen_host, 749 channel_request_remote_forwarding(fwd.listen_host,
675 fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) 750 fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
676 goto fail; 751 goto fail;
677 add_remote_forward(&options, &fwd); 752 add_remote_forward(&options, &fwd);
753 fctx = xcalloc(1, sizeof(*fctx));
754 fctx->cid = c->self;
755 fctx->rid = rid;
756 fctx->fid = options.num_remote_forwards-1;
757 client_register_global_confirm(mux_confirm_remote_forward,
758 fctx);
678 freefwd = 0; 759 freefwd = 0;
760 c->mux_pause = 1; /* wait for mux_confirm_remote_forward */
761 /* delayed reply in mux_confirm_remote_forward */
762 goto out;
679 } 763 }
680 buffer_put_int(r, MUX_S_OK); 764 buffer_put_int(r, MUX_S_OK);
681 buffer_put_int(r, rid); 765 buffer_put_int(r, rid);
@@ -1392,6 +1476,15 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
1392 switch (type) { 1476 switch (type) {
1393 case MUX_S_OK: 1477 case MUX_S_OK:
1394 break; 1478 break;
1479 case MUX_S_REMOTE_PORT:
1480 fwd->allocated_port = buffer_get_int(&m);
1481 logit("Allocated port %u for remote forward to %s:%d",
1482 fwd->allocated_port,
1483 fwd->connect_host ? fwd->connect_host : "",
1484 fwd->connect_port);
1485 if (muxclient_command == SSHMUX_COMMAND_FORWARD)
1486 fprintf(stdout, "%u\n", fwd->allocated_port);
1487 break;
1395 case MUX_S_PERMISSION_DENIED: 1488 case MUX_S_PERMISSION_DENIED:
1396 e = buffer_get_string(&m, NULL); 1489 e = buffer_get_string(&m, NULL);
1397 buffer_free(&m); 1490 buffer_free(&m);
@@ -1758,6 +1851,10 @@ muxclient(const char *path)
1758 mux_client_request_terminate(sock); 1851 mux_client_request_terminate(sock);
1759 fprintf(stderr, "Exit request sent.\r\n"); 1852 fprintf(stderr, "Exit request sent.\r\n");
1760 exit(0); 1853 exit(0);
1854 case SSHMUX_COMMAND_FORWARD:
1855 if (mux_client_request_forwards(sock) != 0)
1856 fatal("%s: master forward request failed", __func__);
1857 exit(0);
1761 case SSHMUX_COMMAND_OPEN: 1858 case SSHMUX_COMMAND_OPEN:
1762 if (mux_client_request_forwards(sock) != 0) { 1859 if (mux_client_request_forwards(sock) != 0) {
1763 error("%s: master forward request failed", __func__); 1860 error("%s: master forward request failed", __func__);