diff options
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 121 |
1 files changed, 95 insertions, 26 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 djm Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.34 2012/01/07 21:11: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 | * |
@@ -341,10 +341,8 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
341 | env_len = 0; | 341 | env_len = 0; |
342 | while (buffer_len(m) > 0) { | 342 | while (buffer_len(m) > 0) { |
343 | #define MUX_MAX_ENV_VARS 4096 | 343 | #define MUX_MAX_ENV_VARS 4096 |
344 | if ((cp = buffer_get_string_ret(m, &len)) == NULL) { | 344 | if ((cp = buffer_get_string_ret(m, &len)) == NULL) |
345 | xfree(cmd); | ||
346 | goto malf; | 345 | goto malf; |
347 | } | ||
348 | if (!env_permitted(cp)) { | 346 | if (!env_permitted(cp)) { |
349 | xfree(cp); | 347 | xfree(cp); |
350 | continue; | 348 | continue; |
@@ -601,12 +599,16 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
601 | buffer_put_int(&out, MUX_S_REMOTE_PORT); | 599 | buffer_put_int(&out, MUX_S_REMOTE_PORT); |
602 | buffer_put_int(&out, fctx->rid); | 600 | buffer_put_int(&out, fctx->rid); |
603 | buffer_put_int(&out, rfwd->allocated_port); | 601 | buffer_put_int(&out, rfwd->allocated_port); |
602 | channel_update_permitted_opens(rfwd->handle, | ||
603 | rfwd->allocated_port); | ||
604 | } else { | 604 | } else { |
605 | buffer_put_int(&out, MUX_S_OK); | 605 | buffer_put_int(&out, MUX_S_OK); |
606 | buffer_put_int(&out, fctx->rid); | 606 | buffer_put_int(&out, fctx->rid); |
607 | } | 607 | } |
608 | goto out; | 608 | goto out; |
609 | } else { | 609 | } else { |
610 | if (rfwd->listen_port == 0) | ||
611 | channel_update_permitted_opens(rfwd->handle, -1); | ||
610 | xasprintf(&failmsg, "remote port forwarding failed for " | 612 | xasprintf(&failmsg, "remote port forwarding failed for " |
611 | "listen port %d", rfwd->listen_port); | 613 | "listen port %d", rfwd->listen_port); |
612 | } | 614 | } |
@@ -745,8 +747,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
745 | } else { | 747 | } else { |
746 | struct mux_channel_confirm_ctx *fctx; | 748 | struct mux_channel_confirm_ctx *fctx; |
747 | 749 | ||
748 | if (channel_request_remote_forwarding(fwd.listen_host, | 750 | fwd.handle = channel_request_remote_forwarding(fwd.listen_host, |
749 | fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) | 751 | fwd.listen_port, fwd.connect_host, fwd.connect_port); |
752 | if (fwd.handle < 0) | ||
750 | goto fail; | 753 | goto fail; |
751 | add_remote_forward(&options, &fwd); | 754 | add_remote_forward(&options, &fwd); |
752 | fctx = xcalloc(1, sizeof(*fctx)); | 755 | fctx = xcalloc(1, sizeof(*fctx)); |
@@ -777,10 +780,11 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
777 | static int | 780 | static int |
778 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 781 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
779 | { | 782 | { |
780 | Forward fwd; | 783 | Forward fwd, *found_fwd; |
781 | char *fwd_desc = NULL; | 784 | char *fwd_desc = NULL; |
785 | const char *error_reason = NULL; | ||
782 | u_int ftype; | 786 | u_int ftype; |
783 | int ret = 0; | 787 | int i, listen_port, ret = 0; |
784 | 788 | ||
785 | fwd.listen_host = fwd.connect_host = NULL; | 789 | fwd.listen_host = fwd.connect_host = NULL; |
786 | if (buffer_get_int_ret(&ftype, m) != 0 || | 790 | if (buffer_get_int_ret(&ftype, m) != 0 || |
@@ -802,14 +806,70 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
802 | fwd.connect_host = NULL; | 806 | fwd.connect_host = NULL; |
803 | } | 807 | } |
804 | 808 | ||
805 | debug2("%s: channel %d: request %s", __func__, c->self, | 809 | debug2("%s: channel %d: request cancel %s", __func__, c->self, |
806 | (fwd_desc = format_forward(ftype, &fwd))); | 810 | (fwd_desc = format_forward(ftype, &fwd))); |
807 | 811 | ||
808 | /* XXX implement this */ | 812 | /* make sure this has been requested */ |
809 | buffer_put_int(r, MUX_S_FAILURE); | 813 | found_fwd = NULL; |
810 | buffer_put_int(r, rid); | 814 | switch (ftype) { |
811 | buffer_put_cstring(r, "unimplemented"); | 815 | case MUX_FWD_LOCAL: |
816 | case MUX_FWD_DYNAMIC: | ||
817 | for (i = 0; i < options.num_local_forwards; i++) { | ||
818 | if (compare_forward(&fwd, | ||
819 | options.local_forwards + i)) { | ||
820 | found_fwd = options.local_forwards + i; | ||
821 | break; | ||
822 | } | ||
823 | } | ||
824 | break; | ||
825 | case MUX_FWD_REMOTE: | ||
826 | for (i = 0; i < options.num_remote_forwards; i++) { | ||
827 | if (compare_forward(&fwd, | ||
828 | options.remote_forwards + i)) { | ||
829 | found_fwd = options.remote_forwards + i; | ||
830 | break; | ||
831 | } | ||
832 | } | ||
833 | break; | ||
834 | } | ||
812 | 835 | ||
836 | if (found_fwd == NULL) | ||
837 | error_reason = "port not forwarded"; | ||
838 | else if (ftype == MUX_FWD_REMOTE) { | ||
839 | /* | ||
840 | * This shouldn't fail unless we confused the host/port | ||
841 | * between options.remote_forwards and permitted_opens. | ||
842 | * However, for dynamic allocated listen ports we need | ||
843 | * to lookup the actual listen port. | ||
844 | */ | ||
845 | listen_port = (fwd.listen_port == 0) ? | ||
846 | found_fwd->allocated_port : fwd.listen_port; | ||
847 | if (channel_request_rforward_cancel(fwd.listen_host, | ||
848 | listen_port) == -1) | ||
849 | error_reason = "port not in permitted opens"; | ||
850 | } else { /* local and dynamic forwards */ | ||
851 | /* Ditto */ | ||
852 | if (channel_cancel_lport_listener(fwd.listen_host, | ||
853 | fwd.listen_port, fwd.connect_port, | ||
854 | options.gateway_ports) == -1) | ||
855 | error_reason = "port not found"; | ||
856 | } | ||
857 | |||
858 | if (error_reason == NULL) { | ||
859 | buffer_put_int(r, MUX_S_OK); | ||
860 | buffer_put_int(r, rid); | ||
861 | |||
862 | if (found_fwd->listen_host != NULL) | ||
863 | xfree(found_fwd->listen_host); | ||
864 | if (found_fwd->connect_host != NULL) | ||
865 | xfree(found_fwd->connect_host); | ||
866 | found_fwd->listen_host = found_fwd->connect_host = NULL; | ||
867 | found_fwd->listen_port = found_fwd->connect_port = 0; | ||
868 | } else { | ||
869 | buffer_put_int(r, MUX_S_FAILURE); | ||
870 | buffer_put_int(r, rid); | ||
871 | buffer_put_cstring(r, error_reason); | ||
872 | } | ||
813 | out: | 873 | out: |
814 | if (fwd_desc != NULL) | 874 | if (fwd_desc != NULL) |
815 | xfree(fwd_desc); | 875 | xfree(fwd_desc); |
@@ -1537,18 +1597,19 @@ mux_client_request_terminate(int fd) | |||
1537 | } | 1597 | } |
1538 | 1598 | ||
1539 | static int | 1599 | static int |
1540 | mux_client_request_forward(int fd, u_int ftype, Forward *fwd) | 1600 | mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) |
1541 | { | 1601 | { |
1542 | Buffer m; | 1602 | Buffer m; |
1543 | char *e, *fwd_desc; | 1603 | char *e, *fwd_desc; |
1544 | u_int type, rid; | 1604 | u_int type, rid; |
1545 | 1605 | ||
1546 | fwd_desc = format_forward(ftype, fwd); | 1606 | fwd_desc = format_forward(ftype, fwd); |
1547 | debug("Requesting %s", fwd_desc); | 1607 | debug("Requesting %s %s", |
1608 | cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); | ||
1548 | xfree(fwd_desc); | 1609 | xfree(fwd_desc); |
1549 | 1610 | ||
1550 | buffer_init(&m); | 1611 | buffer_init(&m); |
1551 | buffer_put_int(&m, MUX_C_OPEN_FWD); | 1612 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); |
1552 | buffer_put_int(&m, muxclient_request_id); | 1613 | buffer_put_int(&m, muxclient_request_id); |
1553 | buffer_put_int(&m, ftype); | 1614 | buffer_put_int(&m, ftype); |
1554 | buffer_put_cstring(&m, | 1615 | buffer_put_cstring(&m, |
@@ -1577,6 +1638,8 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) | |||
1577 | case MUX_S_OK: | 1638 | case MUX_S_OK: |
1578 | break; | 1639 | break; |
1579 | case MUX_S_REMOTE_PORT: | 1640 | case MUX_S_REMOTE_PORT: |
1641 | if (cancel_flag) | ||
1642 | fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); | ||
1580 | fwd->allocated_port = buffer_get_int(&m); | 1643 | fwd->allocated_port = buffer_get_int(&m); |
1581 | logit("Allocated port %u for remote forward to %s:%d", | 1644 | logit("Allocated port %u for remote forward to %s:%d", |
1582 | fwd->allocated_port, | 1645 | fwd->allocated_port, |
@@ -1606,27 +1669,28 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) | |||
1606 | } | 1669 | } |
1607 | 1670 | ||
1608 | static int | 1671 | static int |
1609 | mux_client_request_forwards(int fd) | 1672 | mux_client_forwards(int fd, int cancel_flag) |
1610 | { | 1673 | { |
1611 | int i; | 1674 | int i, ret = 0; |
1612 | 1675 | ||
1613 | debug3("%s: requesting forwardings: %d local, %d remote", __func__, | 1676 | debug3("%s: %s forwardings: %d local, %d remote", __func__, |
1677 | cancel_flag ? "cancel" : "request", | ||
1614 | options.num_local_forwards, options.num_remote_forwards); | 1678 | options.num_local_forwards, options.num_remote_forwards); |
1615 | 1679 | ||
1616 | /* XXX ExitOnForwardingFailure */ | 1680 | /* XXX ExitOnForwardingFailure */ |
1617 | for (i = 0; i < options.num_local_forwards; i++) { | 1681 | for (i = 0; i < options.num_local_forwards; i++) { |
1618 | if (mux_client_request_forward(fd, | 1682 | if (mux_client_forward(fd, cancel_flag, |
1619 | options.local_forwards[i].connect_port == 0 ? | 1683 | options.local_forwards[i].connect_port == 0 ? |
1620 | MUX_FWD_DYNAMIC : MUX_FWD_LOCAL, | 1684 | MUX_FWD_DYNAMIC : MUX_FWD_LOCAL, |
1621 | options.local_forwards + i) != 0) | 1685 | options.local_forwards + i) != 0) |
1622 | return -1; | 1686 | ret = -1; |
1623 | } | 1687 | } |
1624 | for (i = 0; i < options.num_remote_forwards; i++) { | 1688 | for (i = 0; i < options.num_remote_forwards; i++) { |
1625 | if (mux_client_request_forward(fd, MUX_FWD_REMOTE, | 1689 | if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE, |
1626 | options.remote_forwards + i) != 0) | 1690 | options.remote_forwards + i) != 0) |
1627 | return -1; | 1691 | ret = -1; |
1628 | } | 1692 | } |
1629 | return 0; | 1693 | return ret; |
1630 | } | 1694 | } |
1631 | 1695 | ||
1632 | static int | 1696 | static int |
@@ -2014,11 +2078,11 @@ muxclient(const char *path) | |||
2014 | fprintf(stderr, "Exit request sent.\r\n"); | 2078 | fprintf(stderr, "Exit request sent.\r\n"); |
2015 | exit(0); | 2079 | exit(0); |
2016 | case SSHMUX_COMMAND_FORWARD: | 2080 | case SSHMUX_COMMAND_FORWARD: |
2017 | if (mux_client_request_forwards(sock) != 0) | 2081 | if (mux_client_forwards(sock, 0) != 0) |
2018 | fatal("%s: master forward request failed", __func__); | 2082 | fatal("%s: master forward request failed", __func__); |
2019 | exit(0); | 2083 | exit(0); |
2020 | case SSHMUX_COMMAND_OPEN: | 2084 | case SSHMUX_COMMAND_OPEN: |
2021 | if (mux_client_request_forwards(sock) != 0) { | 2085 | if (mux_client_forwards(sock, 0) != 0) { |
2022 | error("%s: master forward request failed", __func__); | 2086 | error("%s: master forward request failed", __func__); |
2023 | return; | 2087 | return; |
2024 | } | 2088 | } |
@@ -2031,6 +2095,11 @@ muxclient(const char *path) | |||
2031 | mux_client_request_stop_listening(sock); | 2095 | mux_client_request_stop_listening(sock); |
2032 | fprintf(stderr, "Stop listening request sent.\r\n"); | 2096 | fprintf(stderr, "Stop listening request sent.\r\n"); |
2033 | exit(0); | 2097 | exit(0); |
2098 | case SSHMUX_COMMAND_CANCEL_FWD: | ||
2099 | if (mux_client_forwards(sock, 1) != 0) | ||
2100 | error("%s: master cancel forward request failed", | ||
2101 | __func__); | ||
2102 | exit(0); | ||
2034 | default: | 2103 | default: |
2035 | fatal("unrecognised muxclient_command %d", muxclient_command); | 2104 | fatal("unrecognised muxclient_command %d", muxclient_command); |
2036 | } | 2105 | } |