diff options
author | Colin Watson <cjwatson@debian.org> | 2014-10-07 13:33:15 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2014-10-07 14:27:30 +0100 |
commit | f0b009aea83e9ff3a50be30f51012099a5143c16 (patch) | |
tree | 3825e6f7e3b7ea4481d06ed89aba9a7a95150df5 /mux.c | |
parent | 47f0bad4330b16ec3bad870fcf9839c196e42c12 (diff) | |
parent | 762c062828f5a8f6ed189ed6e44ad38fd92f8b36 (diff) |
Merge 6.7p1.
* New upstream release (http://www.openssh.com/txt/release-6.7):
- sshd(8): The default set of ciphers and MACs has been altered to
remove unsafe algorithms. In particular, CBC ciphers and arcfour* are
disabled by default. The full set of algorithms remains available if
configured explicitly via the Ciphers and MACs sshd_config options.
- ssh(1), sshd(8): Add support for Unix domain socket forwarding. A
remote TCP port may be forwarded to a local Unix domain socket and
vice versa or both ends may be a Unix domain socket (closes: #236718).
- ssh(1), ssh-keygen(1): Add support for SSHFP DNS records for ED25519
key types.
- sftp(1): Allow resumption of interrupted uploads.
- ssh(1): When rekeying, skip file/DNS lookups of the hostkey if it is
the same as the one sent during initial key exchange.
- sshd(8): Allow explicit ::1 and 127.0.0.1 forwarding bind addresses
when GatewayPorts=no; allows client to choose address family.
- sshd(8): Add a sshd_config PermitUserRC option to control whether
~/.ssh/rc is executed, mirroring the no-user-rc authorized_keys
option.
- ssh(1): Add a %C escape sequence for LocalCommand and ControlPath that
expands to a unique identifer based on a hash of the tuple of (local
host, remote user, hostname, port). Helps avoid exceeding miserly
pathname limits for Unix domain sockets in multiplexing control paths.
- sshd(8): Make the "Too many authentication failures" message include
the user, source address, port and protocol in a format similar to the
authentication success / failure messages.
- Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC when it is
available. It considers time spent suspended, thereby ensuring
timeouts (e.g. for expiring agent keys) fire correctly (closes:
#734553).
- Use prctl() to prevent sftp-server from accessing
/proc/self/{mem,maps}.
* Restore TCP wrappers support, removed upstream in 6.7. It is true that
dropping this reduces preauth attack surface in sshd. On the other
hand, this support seems to be quite widely used, and abruptly dropping
it (from the perspective of users who don't read openssh-unix-dev) could
easily cause more serious problems in practice. It's not entirely clear
what the right long-term answer for Debian is, but it at least probably
doesn't involve dropping this feature shortly before a freeze.
* Replace patch to disable OpenSSL version check with an updated version
of Kurt Roeckx's patch from #732940 to just avoid checking the status
field.
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 275 |
1 files changed, 180 insertions, 95 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.44 2013/07/12 00:19:58 djm Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.48 2014/07/17 07:22:19 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 | * |
@@ -105,6 +105,11 @@ struct mux_session_confirm_ctx { | |||
105 | u_int rid; | 105 | u_int rid; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | /* Context for stdio fwd open confirmation callback */ | ||
109 | struct mux_stdio_confirm_ctx { | ||
110 | u_int rid; | ||
111 | }; | ||
112 | |||
108 | /* Context for global channel callback */ | 113 | /* Context for global channel callback */ |
109 | struct mux_channel_confirm_ctx { | 114 | struct mux_channel_confirm_ctx { |
110 | u_int cid; /* channel id */ | 115 | u_int cid; /* channel id */ |
@@ -157,6 +162,7 @@ struct mux_master_state { | |||
157 | #define MUX_FWD_DYNAMIC 3 | 162 | #define MUX_FWD_DYNAMIC 3 |
158 | 163 | ||
159 | static void mux_session_confirm(int, int, void *); | 164 | static void mux_session_confirm(int, int, void *); |
165 | static void mux_stdio_confirm(int, int, void *); | ||
160 | 166 | ||
161 | static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); | 167 | static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); |
162 | static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); | 168 | static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); |
@@ -509,29 +515,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
509 | } | 515 | } |
510 | 516 | ||
511 | static char * | 517 | static char * |
512 | format_forward(u_int ftype, Forward *fwd) | 518 | format_forward(u_int ftype, struct Forward *fwd) |
513 | { | 519 | { |
514 | char *ret; | 520 | char *ret; |
515 | 521 | ||
516 | switch (ftype) { | 522 | switch (ftype) { |
517 | case MUX_FWD_LOCAL: | 523 | case MUX_FWD_LOCAL: |
518 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", | 524 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", |
525 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
519 | (fwd->listen_host == NULL) ? | 526 | (fwd->listen_host == NULL) ? |
520 | (options.gateway_ports ? "*" : "LOCALHOST") : | 527 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
521 | fwd->listen_host, fwd->listen_port, | 528 | fwd->listen_host, fwd->listen_port, |
529 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
522 | fwd->connect_host, fwd->connect_port); | 530 | fwd->connect_host, fwd->connect_port); |
523 | break; | 531 | break; |
524 | case MUX_FWD_DYNAMIC: | 532 | case MUX_FWD_DYNAMIC: |
525 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", | 533 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", |
526 | (fwd->listen_host == NULL) ? | 534 | (fwd->listen_host == NULL) ? |
527 | (options.gateway_ports ? "*" : "LOCALHOST") : | 535 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
528 | fwd->listen_host, fwd->listen_port); | 536 | fwd->listen_host, fwd->listen_port); |
529 | break; | 537 | break; |
530 | case MUX_FWD_REMOTE: | 538 | case MUX_FWD_REMOTE: |
531 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", | 539 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", |
540 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
532 | (fwd->listen_host == NULL) ? | 541 | (fwd->listen_host == NULL) ? |
533 | "LOCALHOST" : fwd->listen_host, | 542 | "LOCALHOST" : fwd->listen_host, |
534 | fwd->listen_port, | 543 | fwd->listen_port, |
544 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
535 | fwd->connect_host, fwd->connect_port); | 545 | fwd->connect_host, fwd->connect_port); |
536 | break; | 546 | break; |
537 | default: | 547 | default: |
@@ -551,14 +561,18 @@ compare_host(const char *a, const char *b) | |||
551 | } | 561 | } |
552 | 562 | ||
553 | static int | 563 | static int |
554 | compare_forward(Forward *a, Forward *b) | 564 | compare_forward(struct Forward *a, struct Forward *b) |
555 | { | 565 | { |
556 | if (!compare_host(a->listen_host, b->listen_host)) | 566 | if (!compare_host(a->listen_host, b->listen_host)) |
557 | return 0; | 567 | return 0; |
568 | if (!compare_host(a->listen_path, b->listen_path)) | ||
569 | return 0; | ||
558 | if (a->listen_port != b->listen_port) | 570 | if (a->listen_port != b->listen_port) |
559 | return 0; | 571 | return 0; |
560 | if (!compare_host(a->connect_host, b->connect_host)) | 572 | if (!compare_host(a->connect_host, b->connect_host)) |
561 | return 0; | 573 | return 0; |
574 | if (!compare_host(a->connect_path, b->connect_path)) | ||
575 | return 0; | ||
562 | if (a->connect_port != b->connect_port) | 576 | if (a->connect_port != b->connect_port) |
563 | return 0; | 577 | return 0; |
564 | 578 | ||
@@ -570,7 +584,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
570 | { | 584 | { |
571 | struct mux_channel_confirm_ctx *fctx = ctxt; | 585 | struct mux_channel_confirm_ctx *fctx = ctxt; |
572 | char *failmsg = NULL; | 586 | char *failmsg = NULL; |
573 | Forward *rfwd; | 587 | struct Forward *rfwd; |
574 | Channel *c; | 588 | Channel *c; |
575 | Buffer out; | 589 | Buffer out; |
576 | 590 | ||
@@ -587,7 +601,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
587 | rfwd = &options.remote_forwards[fctx->fid]; | 601 | rfwd = &options.remote_forwards[fctx->fid]; |
588 | debug("%s: %s for: listen %d, connect %s:%d", __func__, | 602 | debug("%s: %s for: listen %d, connect %s:%d", __func__, |
589 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 603 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
590 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 604 | rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : |
605 | rfwd->connect_host, rfwd->connect_port); | ||
591 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 606 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
592 | if (rfwd->listen_port == 0) { | 607 | if (rfwd->listen_port == 0) { |
593 | rfwd->allocated_port = packet_get_int(); | 608 | rfwd->allocated_port = packet_get_int(); |
@@ -607,8 +622,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
607 | } else { | 622 | } else { |
608 | if (rfwd->listen_port == 0) | 623 | if (rfwd->listen_port == 0) |
609 | channel_update_permitted_opens(rfwd->handle, -1); | 624 | channel_update_permitted_opens(rfwd->handle, -1); |
610 | xasprintf(&failmsg, "remote port forwarding failed for " | 625 | if (rfwd->listen_path != NULL) |
611 | "listen port %d", rfwd->listen_port); | 626 | xasprintf(&failmsg, "remote port forwarding failed for " |
627 | "listen path %s", rfwd->listen_path); | ||
628 | else | ||
629 | xasprintf(&failmsg, "remote port forwarding failed for " | ||
630 | "listen port %d", rfwd->listen_port); | ||
612 | } | 631 | } |
613 | fail: | 632 | fail: |
614 | error("%s: %s", __func__, failmsg); | 633 | error("%s: %s", __func__, failmsg); |
@@ -627,34 +646,46 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
627 | static int | 646 | static int |
628 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 647 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
629 | { | 648 | { |
630 | Forward fwd; | 649 | struct Forward fwd; |
631 | char *fwd_desc = NULL; | 650 | char *fwd_desc = NULL; |
651 | char *listen_addr, *connect_addr; | ||
632 | u_int ftype; | 652 | u_int ftype; |
633 | u_int lport, cport; | 653 | u_int lport, cport; |
634 | int i, ret = 0, freefwd = 1; | 654 | int i, ret = 0, freefwd = 1; |
635 | 655 | ||
636 | fwd.listen_host = fwd.connect_host = NULL; | 656 | /* XXX - lport/cport check redundant */ |
637 | if (buffer_get_int_ret(&ftype, m) != 0 || | 657 | if (buffer_get_int_ret(&ftype, m) != 0 || |
638 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 658 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
639 | buffer_get_int_ret(&lport, m) != 0 || | 659 | buffer_get_int_ret(&lport, m) != 0 || |
640 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 660 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
641 | buffer_get_int_ret(&cport, m) != 0 || | 661 | buffer_get_int_ret(&cport, m) != 0 || |
642 | lport > 65535 || cport > 65535) { | 662 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
663 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
643 | error("%s: malformed message", __func__); | 664 | error("%s: malformed message", __func__); |
644 | ret = -1; | 665 | ret = -1; |
645 | goto out; | 666 | goto out; |
646 | } | 667 | } |
647 | fwd.listen_port = lport; | 668 | if (*listen_addr == '\0') { |
648 | fwd.connect_port = cport; | 669 | free(listen_addr); |
649 | if (*fwd.listen_host == '\0') { | 670 | listen_addr = NULL; |
650 | free(fwd.listen_host); | ||
651 | fwd.listen_host = NULL; | ||
652 | } | 671 | } |
653 | if (*fwd.connect_host == '\0') { | 672 | if (*connect_addr == '\0') { |
654 | free(fwd.connect_host); | 673 | free(connect_addr); |
655 | fwd.connect_host = NULL; | 674 | connect_addr = NULL; |
656 | } | 675 | } |
657 | 676 | ||
677 | memset(&fwd, 0, sizeof(fwd)); | ||
678 | fwd.listen_port = lport; | ||
679 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
680 | fwd.listen_path = listen_addr; | ||
681 | else | ||
682 | fwd.listen_host = listen_addr; | ||
683 | fwd.connect_port = cport; | ||
684 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
685 | fwd.connect_path = connect_addr; | ||
686 | else | ||
687 | fwd.connect_host = connect_addr; | ||
688 | |||
658 | debug2("%s: channel %d: request %s", __func__, c->self, | 689 | debug2("%s: channel %d: request %s", __func__, c->self, |
659 | (fwd_desc = format_forward(ftype, &fwd))); | 690 | (fwd_desc = format_forward(ftype, &fwd))); |
660 | 691 | ||
@@ -662,25 +693,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
662 | ftype != MUX_FWD_DYNAMIC) { | 693 | ftype != MUX_FWD_DYNAMIC) { |
663 | logit("%s: invalid forwarding type %u", __func__, ftype); | 694 | logit("%s: invalid forwarding type %u", __func__, ftype); |
664 | invalid: | 695 | invalid: |
665 | free(fwd.listen_host); | 696 | free(listen_addr); |
666 | free(fwd.connect_host); | 697 | free(connect_addr); |
667 | buffer_put_int(r, MUX_S_FAILURE); | 698 | buffer_put_int(r, MUX_S_FAILURE); |
668 | buffer_put_int(r, rid); | 699 | buffer_put_int(r, rid); |
669 | buffer_put_cstring(r, "Invalid forwarding request"); | 700 | buffer_put_cstring(r, "Invalid forwarding request"); |
670 | return 0; | 701 | return 0; |
671 | } | 702 | } |
672 | if (fwd.listen_port >= 65536) { | 703 | if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { |
704 | logit("%s: streamlocal and dynamic forwards " | ||
705 | "are mutually exclusive", __func__); | ||
706 | goto invalid; | ||
707 | } | ||
708 | if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { | ||
673 | logit("%s: invalid listen port %u", __func__, | 709 | logit("%s: invalid listen port %u", __func__, |
674 | fwd.listen_port); | 710 | fwd.listen_port); |
675 | goto invalid; | 711 | goto invalid; |
676 | } | 712 | } |
677 | if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && | 713 | if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) |
678 | ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { | 714 | || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { |
679 | logit("%s: invalid connect port %u", __func__, | 715 | logit("%s: invalid connect port %u", __func__, |
680 | fwd.connect_port); | 716 | fwd.connect_port); |
681 | goto invalid; | 717 | goto invalid; |
682 | } | 718 | } |
683 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { | 719 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { |
684 | logit("%s: missing connect host", __func__); | 720 | logit("%s: missing connect host", __func__); |
685 | goto invalid; | 721 | goto invalid; |
686 | } | 722 | } |
@@ -731,9 +767,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
731 | } | 767 | } |
732 | 768 | ||
733 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { | 769 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { |
734 | if (!channel_setup_local_fwd_listener(fwd.listen_host, | 770 | if (!channel_setup_local_fwd_listener(&fwd, |
735 | fwd.listen_port, fwd.connect_host, fwd.connect_port, | 771 | &options.fwd_opts)) { |
736 | options.gateway_ports)) { | ||
737 | fail: | 772 | fail: |
738 | logit("slave-requested %s failed", fwd_desc); | 773 | logit("slave-requested %s failed", fwd_desc); |
739 | buffer_put_int(r, MUX_S_FAILURE); | 774 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -746,8 +781,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
746 | } else { | 781 | } else { |
747 | struct mux_channel_confirm_ctx *fctx; | 782 | struct mux_channel_confirm_ctx *fctx; |
748 | 783 | ||
749 | fwd.handle = channel_request_remote_forwarding(fwd.listen_host, | 784 | fwd.handle = channel_request_remote_forwarding(&fwd); |
750 | fwd.listen_port, fwd.connect_host, fwd.connect_port); | ||
751 | if (fwd.handle < 0) | 785 | if (fwd.handle < 0) |
752 | goto fail; | 786 | goto fail; |
753 | add_remote_forward(&options, &fwd); | 787 | add_remote_forward(&options, &fwd); |
@@ -768,7 +802,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
768 | free(fwd_desc); | 802 | free(fwd_desc); |
769 | if (freefwd) { | 803 | if (freefwd) { |
770 | free(fwd.listen_host); | 804 | free(fwd.listen_host); |
805 | free(fwd.listen_path); | ||
771 | free(fwd.connect_host); | 806 | free(fwd.connect_host); |
807 | free(fwd.connect_path); | ||
772 | } | 808 | } |
773 | return ret; | 809 | return ret; |
774 | } | 810 | } |
@@ -776,36 +812,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
776 | static int | 812 | static int |
777 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 813 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
778 | { | 814 | { |
779 | Forward fwd, *found_fwd; | 815 | struct Forward fwd, *found_fwd; |
780 | char *fwd_desc = NULL; | 816 | char *fwd_desc = NULL; |
781 | const char *error_reason = NULL; | 817 | const char *error_reason = NULL; |
818 | char *listen_addr = NULL, *connect_addr = NULL; | ||
782 | u_int ftype; | 819 | u_int ftype; |
783 | int i, listen_port, ret = 0; | 820 | int i, ret = 0; |
784 | u_int lport, cport; | 821 | u_int lport, cport; |
785 | 822 | ||
786 | fwd.listen_host = fwd.connect_host = NULL; | ||
787 | if (buffer_get_int_ret(&ftype, m) != 0 || | 823 | if (buffer_get_int_ret(&ftype, m) != 0 || |
788 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 824 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
789 | buffer_get_int_ret(&lport, m) != 0 || | 825 | buffer_get_int_ret(&lport, m) != 0 || |
790 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 826 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
791 | buffer_get_int_ret(&cport, m) != 0 || | 827 | buffer_get_int_ret(&cport, m) != 0 || |
792 | lport > 65535 || cport > 65535) { | 828 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
829 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
793 | error("%s: malformed message", __func__); | 830 | error("%s: malformed message", __func__); |
794 | ret = -1; | 831 | ret = -1; |
795 | goto out; | 832 | goto out; |
796 | } | 833 | } |
797 | fwd.listen_port = lport; | ||
798 | fwd.connect_port = cport; | ||
799 | 834 | ||
800 | if (*fwd.listen_host == '\0') { | 835 | if (*listen_addr == '\0') { |
801 | free(fwd.listen_host); | 836 | free(listen_addr); |
802 | fwd.listen_host = NULL; | 837 | listen_addr = NULL; |
803 | } | 838 | } |
804 | if (*fwd.connect_host == '\0') { | 839 | if (*connect_addr == '\0') { |
805 | free(fwd.connect_host); | 840 | free(connect_addr); |
806 | fwd.connect_host = NULL; | 841 | connect_addr = NULL; |
807 | } | 842 | } |
808 | 843 | ||
844 | memset(&fwd, 0, sizeof(fwd)); | ||
845 | fwd.listen_port = lport; | ||
846 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
847 | fwd.listen_path = listen_addr; | ||
848 | else | ||
849 | fwd.listen_host = listen_addr; | ||
850 | fwd.connect_port = cport; | ||
851 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
852 | fwd.connect_path = connect_addr; | ||
853 | else | ||
854 | fwd.connect_host = connect_addr; | ||
855 | |||
809 | debug2("%s: channel %d: request cancel %s", __func__, c->self, | 856 | debug2("%s: channel %d: request cancel %s", __func__, c->self, |
810 | (fwd_desc = format_forward(ftype, &fwd))); | 857 | (fwd_desc = format_forward(ftype, &fwd))); |
811 | 858 | ||
@@ -840,18 +887,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
840 | * This shouldn't fail unless we confused the host/port | 887 | * This shouldn't fail unless we confused the host/port |
841 | * between options.remote_forwards and permitted_opens. | 888 | * between options.remote_forwards and permitted_opens. |
842 | * However, for dynamic allocated listen ports we need | 889 | * However, for dynamic allocated listen ports we need |
843 | * to lookup the actual listen port. | 890 | * to use the actual listen port. |
844 | */ | 891 | */ |
845 | listen_port = (fwd.listen_port == 0) ? | 892 | if (channel_request_rforward_cancel(found_fwd) == -1) |
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"; | 893 | error_reason = "port not in permitted opens"; |
850 | } else { /* local and dynamic forwards */ | 894 | } else { /* local and dynamic forwards */ |
851 | /* Ditto */ | 895 | /* Ditto */ |
852 | if (channel_cancel_lport_listener(fwd.listen_host, | 896 | if (channel_cancel_lport_listener(&fwd, fwd.connect_port, |
853 | fwd.listen_port, fwd.connect_port, | 897 | &options.fwd_opts) == -1) |
854 | options.gateway_ports) == -1) | ||
855 | error_reason = "port not found"; | 898 | error_reason = "port not found"; |
856 | } | 899 | } |
857 | 900 | ||
@@ -860,8 +903,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
860 | buffer_put_int(r, rid); | 903 | buffer_put_int(r, rid); |
861 | 904 | ||
862 | free(found_fwd->listen_host); | 905 | free(found_fwd->listen_host); |
906 | free(found_fwd->listen_path); | ||
863 | free(found_fwd->connect_host); | 907 | free(found_fwd->connect_host); |
908 | free(found_fwd->connect_path); | ||
864 | found_fwd->listen_host = found_fwd->connect_host = NULL; | 909 | found_fwd->listen_host = found_fwd->connect_host = NULL; |
910 | found_fwd->listen_path = found_fwd->connect_path = NULL; | ||
865 | found_fwd->listen_port = found_fwd->connect_port = 0; | 911 | found_fwd->listen_port = found_fwd->connect_port = 0; |
866 | } else { | 912 | } else { |
867 | buffer_put_int(r, MUX_S_FAILURE); | 913 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -870,8 +916,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
870 | } | 916 | } |
871 | out: | 917 | out: |
872 | free(fwd_desc); | 918 | free(fwd_desc); |
873 | free(fwd.listen_host); | 919 | free(listen_addr); |
874 | free(fwd.connect_host); | 920 | free(connect_addr); |
875 | 921 | ||
876 | return ret; | 922 | return ret; |
877 | } | 923 | } |
@@ -883,6 +929,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
883 | char *reserved, *chost; | 929 | char *reserved, *chost; |
884 | u_int cport, i, j; | 930 | u_int cport, i, j; |
885 | int new_fd[2]; | 931 | int new_fd[2]; |
932 | struct mux_stdio_confirm_ctx *cctx; | ||
886 | 933 | ||
887 | chost = reserved = NULL; | 934 | chost = reserved = NULL; |
888 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || | 935 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || |
@@ -962,15 +1009,60 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
962 | 1009 | ||
963 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); | 1010 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); |
964 | 1011 | ||
965 | /* prepare reply */ | 1012 | cctx = xcalloc(1, sizeof(*cctx)); |
966 | /* XXX defer until channel confirmed */ | 1013 | cctx->rid = rid; |
967 | buffer_put_int(r, MUX_S_SESSION_OPENED); | 1014 | channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); |
968 | buffer_put_int(r, rid); | 1015 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ |
969 | buffer_put_int(r, nc->self); | ||
970 | 1016 | ||
1017 | /* reply is deferred, sent by mux_session_confirm */ | ||
971 | return 0; | 1018 | return 0; |
972 | } | 1019 | } |
973 | 1020 | ||
1021 | /* Callback on open confirmation in mux master for a mux stdio fwd session. */ | ||
1022 | static void | ||
1023 | mux_stdio_confirm(int id, int success, void *arg) | ||
1024 | { | ||
1025 | struct mux_stdio_confirm_ctx *cctx = arg; | ||
1026 | Channel *c, *cc; | ||
1027 | Buffer reply; | ||
1028 | |||
1029 | if (cctx == NULL) | ||
1030 | fatal("%s: cctx == NULL", __func__); | ||
1031 | if ((c = channel_by_id(id)) == NULL) | ||
1032 | fatal("%s: no channel for id %d", __func__, id); | ||
1033 | if ((cc = channel_by_id(c->ctl_chan)) == NULL) | ||
1034 | fatal("%s: channel %d lacks control channel %d", __func__, | ||
1035 | id, c->ctl_chan); | ||
1036 | |||
1037 | if (!success) { | ||
1038 | debug3("%s: sending failure reply", __func__); | ||
1039 | /* prepare reply */ | ||
1040 | buffer_init(&reply); | ||
1041 | buffer_put_int(&reply, MUX_S_FAILURE); | ||
1042 | buffer_put_int(&reply, cctx->rid); | ||
1043 | buffer_put_cstring(&reply, "Session open refused by peer"); | ||
1044 | goto done; | ||
1045 | } | ||
1046 | |||
1047 | debug3("%s: sending success reply", __func__); | ||
1048 | /* prepare reply */ | ||
1049 | buffer_init(&reply); | ||
1050 | buffer_put_int(&reply, MUX_S_SESSION_OPENED); | ||
1051 | buffer_put_int(&reply, cctx->rid); | ||
1052 | buffer_put_int(&reply, c->self); | ||
1053 | |||
1054 | done: | ||
1055 | /* Send reply */ | ||
1056 | buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); | ||
1057 | buffer_free(&reply); | ||
1058 | |||
1059 | if (cc->mux_pause <= 0) | ||
1060 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); | ||
1061 | cc->mux_pause = 0; /* start processing messages again */ | ||
1062 | c->open_confirm_ctx = NULL; | ||
1063 | free(cctx); | ||
1064 | } | ||
1065 | |||
974 | static int | 1066 | static int |
975 | process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | 1067 | process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) |
976 | { | 1068 | { |
@@ -1010,7 +1102,7 @@ mux_master_read_cb(Channel *c) | |||
1010 | { | 1102 | { |
1011 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 1103 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
1012 | Buffer in, out; | 1104 | Buffer in, out; |
1013 | void *ptr; | 1105 | const u_char *ptr; |
1014 | u_int type, rid, have, i; | 1106 | u_int type, rid, have, i; |
1015 | int ret = -1; | 1107 | int ret = -1; |
1016 | 1108 | ||
@@ -1133,12 +1225,11 @@ mux_tty_alloc_failed(Channel *c) | |||
1133 | void | 1225 | void |
1134 | muxserver_listen(void) | 1226 | muxserver_listen(void) |
1135 | { | 1227 | { |
1136 | struct sockaddr_un addr; | ||
1137 | socklen_t sun_len; | ||
1138 | mode_t old_umask; | 1228 | mode_t old_umask; |
1139 | char *orig_control_path = options.control_path; | 1229 | char *orig_control_path = options.control_path; |
1140 | char rbuf[16+1]; | 1230 | char rbuf[16+1]; |
1141 | u_int i, r; | 1231 | u_int i, r; |
1232 | int oerrno; | ||
1142 | 1233 | ||
1143 | if (options.control_path == NULL || | 1234 | if (options.control_path == NULL || |
1144 | options.control_master == SSHCTL_MASTER_NO) | 1235 | options.control_master == SSHCTL_MASTER_NO) |
@@ -1163,24 +1254,12 @@ muxserver_listen(void) | |||
1163 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); | 1254 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); |
1164 | debug3("%s: temporary control path %s", __func__, options.control_path); | 1255 | debug3("%s: temporary control path %s", __func__, options.control_path); |
1165 | 1256 | ||
1166 | memset(&addr, '\0', sizeof(addr)); | ||
1167 | addr.sun_family = AF_UNIX; | ||
1168 | sun_len = offsetof(struct sockaddr_un, sun_path) + | ||
1169 | strlen(options.control_path) + 1; | ||
1170 | |||
1171 | if (strlcpy(addr.sun_path, options.control_path, | ||
1172 | sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { | ||
1173 | error("ControlPath \"%s\" too long for Unix domain socket", | ||
1174 | options.control_path); | ||
1175 | goto disable_mux_master; | ||
1176 | } | ||
1177 | |||
1178 | if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | ||
1179 | fatal("%s socket(): %s", __func__, strerror(errno)); | ||
1180 | |||
1181 | old_umask = umask(0177); | 1257 | old_umask = umask(0177); |
1182 | if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { | 1258 | muxserver_sock = unix_listener(options.control_path, 64, 0); |
1183 | if (errno == EINVAL || errno == EADDRINUSE) { | 1259 | oerrno = errno; |
1260 | umask(old_umask); | ||
1261 | if (muxserver_sock < 0) { | ||
1262 | if (oerrno == EINVAL || oerrno == EADDRINUSE) { | ||
1184 | error("ControlSocket %s already exists, " | 1263 | error("ControlSocket %s already exists, " |
1185 | "disabling multiplexing", options.control_path); | 1264 | "disabling multiplexing", options.control_path); |
1186 | disable_mux_master: | 1265 | disable_mux_master: |
@@ -1193,13 +1272,11 @@ muxserver_listen(void) | |||
1193 | options.control_path = NULL; | 1272 | options.control_path = NULL; |
1194 | options.control_master = SSHCTL_MASTER_NO; | 1273 | options.control_master = SSHCTL_MASTER_NO; |
1195 | return; | 1274 | return; |
1196 | } else | 1275 | } else { |
1197 | fatal("%s bind(): %s", __func__, strerror(errno)); | 1276 | /* unix_listener() logs the error */ |
1277 | cleanup_exit(255); | ||
1278 | } | ||
1198 | } | 1279 | } |
1199 | umask(old_umask); | ||
1200 | |||
1201 | if (listen(muxserver_sock, 64) == -1) | ||
1202 | fatal("%s listen(): %s", __func__, strerror(errno)); | ||
1203 | 1280 | ||
1204 | /* Now atomically "move" the mux socket into position */ | 1281 | /* Now atomically "move" the mux socket into position */ |
1205 | if (link(options.control_path, orig_control_path) != 0) { | 1282 | if (link(options.control_path, orig_control_path) != 0) { |
@@ -1429,7 +1506,7 @@ mux_client_read_packet(int fd, Buffer *m) | |||
1429 | { | 1506 | { |
1430 | Buffer queue; | 1507 | Buffer queue; |
1431 | u_int need, have; | 1508 | u_int need, have; |
1432 | void *ptr; | 1509 | const u_char *ptr; |
1433 | int oerrno; | 1510 | int oerrno; |
1434 | 1511 | ||
1435 | buffer_init(&queue); | 1512 | buffer_init(&queue); |
@@ -1593,7 +1670,7 @@ mux_client_request_terminate(int fd) | |||
1593 | } | 1670 | } |
1594 | 1671 | ||
1595 | static int | 1672 | static int |
1596 | mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) | 1673 | mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) |
1597 | { | 1674 | { |
1598 | Buffer m; | 1675 | Buffer m; |
1599 | char *e, *fwd_desc; | 1676 | char *e, *fwd_desc; |
@@ -1608,11 +1685,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) | |||
1608 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); | 1685 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); |
1609 | buffer_put_int(&m, muxclient_request_id); | 1686 | buffer_put_int(&m, muxclient_request_id); |
1610 | buffer_put_int(&m, ftype); | 1687 | buffer_put_int(&m, ftype); |
1611 | buffer_put_cstring(&m, | 1688 | if (fwd->listen_path != NULL) { |
1612 | fwd->listen_host == NULL ? "" : fwd->listen_host); | 1689 | buffer_put_cstring(&m, fwd->listen_path); |
1690 | } else { | ||
1691 | buffer_put_cstring(&m, | ||
1692 | fwd->listen_host == NULL ? "" : fwd->listen_host); | ||
1693 | } | ||
1613 | buffer_put_int(&m, fwd->listen_port); | 1694 | buffer_put_int(&m, fwd->listen_port); |
1614 | buffer_put_cstring(&m, | 1695 | if (fwd->connect_path != NULL) { |
1615 | fwd->connect_host == NULL ? "" : fwd->connect_host); | 1696 | buffer_put_cstring(&m, fwd->connect_path); |
1697 | } else { | ||
1698 | buffer_put_cstring(&m, | ||
1699 | fwd->connect_host == NULL ? "" : fwd->connect_host); | ||
1700 | } | ||
1616 | buffer_put_int(&m, fwd->connect_port); | 1701 | buffer_put_int(&m, fwd->connect_port); |
1617 | 1702 | ||
1618 | if (mux_client_write_packet(fd, &m) != 0) | 1703 | if (mux_client_write_packet(fd, &m) != 0) |
@@ -1922,7 +2007,7 @@ mux_client_request_stdio_fwd(int fd) | |||
1922 | case MUX_S_FAILURE: | 2007 | case MUX_S_FAILURE: |
1923 | e = buffer_get_string(&m, NULL); | 2008 | e = buffer_get_string(&m, NULL); |
1924 | buffer_free(&m); | 2009 | buffer_free(&m); |
1925 | fatal("%s: stdio forwarding request failed: %s", __func__, e); | 2010 | fatal("Stdio forwarding request failed: %s", e); |
1926 | default: | 2011 | default: |
1927 | buffer_free(&m); | 2012 | buffer_free(&m); |
1928 | error("%s: unexpected response from master 0x%08x", | 2013 | error("%s: unexpected response from master 0x%08x", |