diff options
author | Damien Miller <djm@mindrot.org> | 2014-07-18 14:11:24 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-07-18 14:11:24 +1000 |
commit | 7acefbbcbeab725420ea07397ae35992f505f702 (patch) | |
tree | bfb07917715d425438dab987a47ccd7a8d7f118b /mux.c | |
parent | 6262d760e00714523633bd989d62e273a3dca99a (diff) |
- millert@cvs.openbsd.org 2014/07/15 15:54:14
[PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
[auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
[auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
[clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
[readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
[ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
[sshd_config.5 sshlogin.c]
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. This is a reimplementation
of the streamlocal patches by William Ahern from:
http://www.25thandclement.com/~william/projects/streamlocal.html
OK djm@ markus@
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 203 |
1 files changed, 117 insertions, 86 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.45 2014/04/28 03:09:18 djm Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.46 2014/07/15 15:54:14 millert 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 | * |
@@ -509,29 +509,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
509 | } | 509 | } |
510 | 510 | ||
511 | static char * | 511 | static char * |
512 | format_forward(u_int ftype, Forward *fwd) | 512 | format_forward(u_int ftype, struct Forward *fwd) |
513 | { | 513 | { |
514 | char *ret; | 514 | char *ret; |
515 | 515 | ||
516 | switch (ftype) { | 516 | switch (ftype) { |
517 | case MUX_FWD_LOCAL: | 517 | case MUX_FWD_LOCAL: |
518 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", | 518 | xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", |
519 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
519 | (fwd->listen_host == NULL) ? | 520 | (fwd->listen_host == NULL) ? |
520 | (options.gateway_ports ? "*" : "LOCALHOST") : | 521 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
521 | fwd->listen_host, fwd->listen_port, | 522 | fwd->listen_host, fwd->listen_port, |
523 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
522 | fwd->connect_host, fwd->connect_port); | 524 | fwd->connect_host, fwd->connect_port); |
523 | break; | 525 | break; |
524 | case MUX_FWD_DYNAMIC: | 526 | case MUX_FWD_DYNAMIC: |
525 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", | 527 | xasprintf(&ret, "dynamic forward %.200s:%d -> *", |
526 | (fwd->listen_host == NULL) ? | 528 | (fwd->listen_host == NULL) ? |
527 | (options.gateway_ports ? "*" : "LOCALHOST") : | 529 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
528 | fwd->listen_host, fwd->listen_port); | 530 | fwd->listen_host, fwd->listen_port); |
529 | break; | 531 | break; |
530 | case MUX_FWD_REMOTE: | 532 | case MUX_FWD_REMOTE: |
531 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", | 533 | xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", |
534 | (fwd->listen_path != NULL) ? fwd->listen_path : | ||
532 | (fwd->listen_host == NULL) ? | 535 | (fwd->listen_host == NULL) ? |
533 | "LOCALHOST" : fwd->listen_host, | 536 | "LOCALHOST" : fwd->listen_host, |
534 | fwd->listen_port, | 537 | fwd->listen_port, |
538 | (fwd->connect_path != NULL) ? fwd->connect_path : | ||
535 | fwd->connect_host, fwd->connect_port); | 539 | fwd->connect_host, fwd->connect_port); |
536 | break; | 540 | break; |
537 | default: | 541 | default: |
@@ -551,14 +555,18 @@ compare_host(const char *a, const char *b) | |||
551 | } | 555 | } |
552 | 556 | ||
553 | static int | 557 | static int |
554 | compare_forward(Forward *a, Forward *b) | 558 | compare_forward(struct Forward *a, struct Forward *b) |
555 | { | 559 | { |
556 | if (!compare_host(a->listen_host, b->listen_host)) | 560 | if (!compare_host(a->listen_host, b->listen_host)) |
557 | return 0; | 561 | return 0; |
562 | if (!compare_host(a->listen_path, b->listen_path)) | ||
563 | return 0; | ||
558 | if (a->listen_port != b->listen_port) | 564 | if (a->listen_port != b->listen_port) |
559 | return 0; | 565 | return 0; |
560 | if (!compare_host(a->connect_host, b->connect_host)) | 566 | if (!compare_host(a->connect_host, b->connect_host)) |
561 | return 0; | 567 | return 0; |
568 | if (!compare_host(a->connect_path, b->connect_path)) | ||
569 | return 0; | ||
562 | if (a->connect_port != b->connect_port) | 570 | if (a->connect_port != b->connect_port) |
563 | return 0; | 571 | return 0; |
564 | 572 | ||
@@ -570,7 +578,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
570 | { | 578 | { |
571 | struct mux_channel_confirm_ctx *fctx = ctxt; | 579 | struct mux_channel_confirm_ctx *fctx = ctxt; |
572 | char *failmsg = NULL; | 580 | char *failmsg = NULL; |
573 | Forward *rfwd; | 581 | struct Forward *rfwd; |
574 | Channel *c; | 582 | Channel *c; |
575 | Buffer out; | 583 | Buffer out; |
576 | 584 | ||
@@ -587,7 +595,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
587 | rfwd = &options.remote_forwards[fctx->fid]; | 595 | rfwd = &options.remote_forwards[fctx->fid]; |
588 | debug("%s: %s for: listen %d, connect %s:%d", __func__, | 596 | debug("%s: %s for: listen %d, connect %s:%d", __func__, |
589 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 597 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
590 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 598 | rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : |
599 | rfwd->connect_host, rfwd->connect_port); | ||
591 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 600 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
592 | if (rfwd->listen_port == 0) { | 601 | if (rfwd->listen_port == 0) { |
593 | rfwd->allocated_port = packet_get_int(); | 602 | rfwd->allocated_port = packet_get_int(); |
@@ -607,8 +616,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
607 | } else { | 616 | } else { |
608 | if (rfwd->listen_port == 0) | 617 | if (rfwd->listen_port == 0) |
609 | channel_update_permitted_opens(rfwd->handle, -1); | 618 | channel_update_permitted_opens(rfwd->handle, -1); |
610 | xasprintf(&failmsg, "remote port forwarding failed for " | 619 | if (rfwd->listen_path != NULL) |
611 | "listen port %d", rfwd->listen_port); | 620 | xasprintf(&failmsg, "remote port forwarding failed for " |
621 | "listen path %s", rfwd->listen_path); | ||
622 | else | ||
623 | xasprintf(&failmsg, "remote port forwarding failed for " | ||
624 | "listen port %d", rfwd->listen_port); | ||
612 | } | 625 | } |
613 | fail: | 626 | fail: |
614 | error("%s: %s", __func__, failmsg); | 627 | error("%s: %s", __func__, failmsg); |
@@ -627,34 +640,46 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
627 | static int | 640 | static int |
628 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 641 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
629 | { | 642 | { |
630 | Forward fwd; | 643 | struct Forward fwd; |
631 | char *fwd_desc = NULL; | 644 | char *fwd_desc = NULL; |
645 | char *listen_addr, *connect_addr; | ||
632 | u_int ftype; | 646 | u_int ftype; |
633 | u_int lport, cport; | 647 | u_int lport, cport; |
634 | int i, ret = 0, freefwd = 1; | 648 | int i, ret = 0, freefwd = 1; |
635 | 649 | ||
636 | fwd.listen_host = fwd.connect_host = NULL; | 650 | /* XXX - lport/cport check redundant */ |
637 | if (buffer_get_int_ret(&ftype, m) != 0 || | 651 | if (buffer_get_int_ret(&ftype, m) != 0 || |
638 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 652 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
639 | buffer_get_int_ret(&lport, m) != 0 || | 653 | buffer_get_int_ret(&lport, m) != 0 || |
640 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 654 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
641 | buffer_get_int_ret(&cport, m) != 0 || | 655 | buffer_get_int_ret(&cport, m) != 0 || |
642 | lport > 65535 || cport > 65535) { | 656 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
657 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
643 | error("%s: malformed message", __func__); | 658 | error("%s: malformed message", __func__); |
644 | ret = -1; | 659 | ret = -1; |
645 | goto out; | 660 | goto out; |
646 | } | 661 | } |
647 | fwd.listen_port = lport; | 662 | if (*listen_addr == '\0') { |
648 | fwd.connect_port = cport; | 663 | free(listen_addr); |
649 | if (*fwd.listen_host == '\0') { | 664 | listen_addr = NULL; |
650 | free(fwd.listen_host); | ||
651 | fwd.listen_host = NULL; | ||
652 | } | 665 | } |
653 | if (*fwd.connect_host == '\0') { | 666 | if (*connect_addr == '\0') { |
654 | free(fwd.connect_host); | 667 | free(connect_addr); |
655 | fwd.connect_host = NULL; | 668 | connect_addr = NULL; |
656 | } | 669 | } |
657 | 670 | ||
671 | memset(&fwd, 0, sizeof(fwd)); | ||
672 | fwd.listen_port = lport; | ||
673 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
674 | fwd.listen_path = listen_addr; | ||
675 | else | ||
676 | fwd.listen_host = listen_addr; | ||
677 | fwd.connect_port = cport; | ||
678 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
679 | fwd.connect_path = connect_addr; | ||
680 | else | ||
681 | fwd.connect_host = connect_addr; | ||
682 | |||
658 | debug2("%s: channel %d: request %s", __func__, c->self, | 683 | debug2("%s: channel %d: request %s", __func__, c->self, |
659 | (fwd_desc = format_forward(ftype, &fwd))); | 684 | (fwd_desc = format_forward(ftype, &fwd))); |
660 | 685 | ||
@@ -662,25 +687,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
662 | ftype != MUX_FWD_DYNAMIC) { | 687 | ftype != MUX_FWD_DYNAMIC) { |
663 | logit("%s: invalid forwarding type %u", __func__, ftype); | 688 | logit("%s: invalid forwarding type %u", __func__, ftype); |
664 | invalid: | 689 | invalid: |
665 | free(fwd.listen_host); | 690 | free(listen_addr); |
666 | free(fwd.connect_host); | 691 | free(connect_addr); |
667 | buffer_put_int(r, MUX_S_FAILURE); | 692 | buffer_put_int(r, MUX_S_FAILURE); |
668 | buffer_put_int(r, rid); | 693 | buffer_put_int(r, rid); |
669 | buffer_put_cstring(r, "Invalid forwarding request"); | 694 | buffer_put_cstring(r, "Invalid forwarding request"); |
670 | return 0; | 695 | return 0; |
671 | } | 696 | } |
672 | if (fwd.listen_port >= 65536) { | 697 | if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { |
698 | logit("%s: streamlocal and dynamic forwards " | ||
699 | "are mutually exclusive", __func__); | ||
700 | goto invalid; | ||
701 | } | ||
702 | if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { | ||
673 | logit("%s: invalid listen port %u", __func__, | 703 | logit("%s: invalid listen port %u", __func__, |
674 | fwd.listen_port); | 704 | fwd.listen_port); |
675 | goto invalid; | 705 | goto invalid; |
676 | } | 706 | } |
677 | if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && | 707 | if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) |
678 | ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { | 708 | || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { |
679 | logit("%s: invalid connect port %u", __func__, | 709 | logit("%s: invalid connect port %u", __func__, |
680 | fwd.connect_port); | 710 | fwd.connect_port); |
681 | goto invalid; | 711 | goto invalid; |
682 | } | 712 | } |
683 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { | 713 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { |
684 | logit("%s: missing connect host", __func__); | 714 | logit("%s: missing connect host", __func__); |
685 | goto invalid; | 715 | goto invalid; |
686 | } | 716 | } |
@@ -731,9 +761,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
731 | } | 761 | } |
732 | 762 | ||
733 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { | 763 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { |
734 | if (!channel_setup_local_fwd_listener(fwd.listen_host, | 764 | if (!channel_setup_local_fwd_listener(&fwd, |
735 | fwd.listen_port, fwd.connect_host, fwd.connect_port, | 765 | &options.fwd_opts)) { |
736 | options.gateway_ports)) { | ||
737 | fail: | 766 | fail: |
738 | logit("slave-requested %s failed", fwd_desc); | 767 | logit("slave-requested %s failed", fwd_desc); |
739 | buffer_put_int(r, MUX_S_FAILURE); | 768 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -746,8 +775,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
746 | } else { | 775 | } else { |
747 | struct mux_channel_confirm_ctx *fctx; | 776 | struct mux_channel_confirm_ctx *fctx; |
748 | 777 | ||
749 | fwd.handle = channel_request_remote_forwarding(fwd.listen_host, | 778 | fwd.handle = channel_request_remote_forwarding(&fwd); |
750 | fwd.listen_port, fwd.connect_host, fwd.connect_port); | ||
751 | if (fwd.handle < 0) | 779 | if (fwd.handle < 0) |
752 | goto fail; | 780 | goto fail; |
753 | add_remote_forward(&options, &fwd); | 781 | add_remote_forward(&options, &fwd); |
@@ -768,7 +796,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
768 | free(fwd_desc); | 796 | free(fwd_desc); |
769 | if (freefwd) { | 797 | if (freefwd) { |
770 | free(fwd.listen_host); | 798 | free(fwd.listen_host); |
799 | free(fwd.listen_path); | ||
771 | free(fwd.connect_host); | 800 | free(fwd.connect_host); |
801 | free(fwd.connect_path); | ||
772 | } | 802 | } |
773 | return ret; | 803 | return ret; |
774 | } | 804 | } |
@@ -776,36 +806,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
776 | static int | 806 | static int |
777 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 807 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
778 | { | 808 | { |
779 | Forward fwd, *found_fwd; | 809 | struct Forward fwd, *found_fwd; |
780 | char *fwd_desc = NULL; | 810 | char *fwd_desc = NULL; |
781 | const char *error_reason = NULL; | 811 | const char *error_reason = NULL; |
812 | char *listen_addr = NULL, *connect_addr = NULL; | ||
782 | u_int ftype; | 813 | u_int ftype; |
783 | int i, listen_port, ret = 0; | 814 | int i, ret = 0; |
784 | u_int lport, cport; | 815 | u_int lport, cport; |
785 | 816 | ||
786 | fwd.listen_host = fwd.connect_host = NULL; | ||
787 | if (buffer_get_int_ret(&ftype, m) != 0 || | 817 | if (buffer_get_int_ret(&ftype, m) != 0 || |
788 | (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || | 818 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || |
789 | buffer_get_int_ret(&lport, m) != 0 || | 819 | buffer_get_int_ret(&lport, m) != 0 || |
790 | (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || | 820 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || |
791 | buffer_get_int_ret(&cport, m) != 0 || | 821 | buffer_get_int_ret(&cport, m) != 0 || |
792 | lport > 65535 || cport > 65535) { | 822 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
823 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | ||
793 | error("%s: malformed message", __func__); | 824 | error("%s: malformed message", __func__); |
794 | ret = -1; | 825 | ret = -1; |
795 | goto out; | 826 | goto out; |
796 | } | 827 | } |
797 | fwd.listen_port = lport; | ||
798 | fwd.connect_port = cport; | ||
799 | 828 | ||
800 | if (*fwd.listen_host == '\0') { | 829 | if (*listen_addr == '\0') { |
801 | free(fwd.listen_host); | 830 | free(listen_addr); |
802 | fwd.listen_host = NULL; | 831 | listen_addr = NULL; |
803 | } | 832 | } |
804 | if (*fwd.connect_host == '\0') { | 833 | if (*connect_addr == '\0') { |
805 | free(fwd.connect_host); | 834 | free(connect_addr); |
806 | fwd.connect_host = NULL; | 835 | connect_addr = NULL; |
807 | } | 836 | } |
808 | 837 | ||
838 | memset(&fwd, 0, sizeof(fwd)); | ||
839 | fwd.listen_port = lport; | ||
840 | if (fwd.listen_port == PORT_STREAMLOCAL) | ||
841 | fwd.listen_path = listen_addr; | ||
842 | else | ||
843 | fwd.listen_host = listen_addr; | ||
844 | fwd.connect_port = cport; | ||
845 | if (fwd.connect_port == PORT_STREAMLOCAL) | ||
846 | fwd.connect_path = connect_addr; | ||
847 | else | ||
848 | fwd.connect_host = connect_addr; | ||
849 | |||
809 | debug2("%s: channel %d: request cancel %s", __func__, c->self, | 850 | debug2("%s: channel %d: request cancel %s", __func__, c->self, |
810 | (fwd_desc = format_forward(ftype, &fwd))); | 851 | (fwd_desc = format_forward(ftype, &fwd))); |
811 | 852 | ||
@@ -840,18 +881,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 | 881 | * This shouldn't fail unless we confused the host/port |
841 | * between options.remote_forwards and permitted_opens. | 882 | * between options.remote_forwards and permitted_opens. |
842 | * However, for dynamic allocated listen ports we need | 883 | * However, for dynamic allocated listen ports we need |
843 | * to lookup the actual listen port. | 884 | * to use the actual listen port. |
844 | */ | 885 | */ |
845 | listen_port = (fwd.listen_port == 0) ? | 886 | 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"; | 887 | error_reason = "port not in permitted opens"; |
850 | } else { /* local and dynamic forwards */ | 888 | } else { /* local and dynamic forwards */ |
851 | /* Ditto */ | 889 | /* Ditto */ |
852 | if (channel_cancel_lport_listener(fwd.listen_host, | 890 | if (channel_cancel_lport_listener(&fwd, fwd.connect_port, |
853 | fwd.listen_port, fwd.connect_port, | 891 | &options.fwd_opts) == -1) |
854 | options.gateway_ports) == -1) | ||
855 | error_reason = "port not found"; | 892 | error_reason = "port not found"; |
856 | } | 893 | } |
857 | 894 | ||
@@ -860,8 +897,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
860 | buffer_put_int(r, rid); | 897 | buffer_put_int(r, rid); |
861 | 898 | ||
862 | free(found_fwd->listen_host); | 899 | free(found_fwd->listen_host); |
900 | free(found_fwd->listen_path); | ||
863 | free(found_fwd->connect_host); | 901 | free(found_fwd->connect_host); |
902 | free(found_fwd->connect_path); | ||
864 | found_fwd->listen_host = found_fwd->connect_host = NULL; | 903 | found_fwd->listen_host = found_fwd->connect_host = NULL; |
904 | found_fwd->listen_path = found_fwd->connect_path = NULL; | ||
865 | found_fwd->listen_port = found_fwd->connect_port = 0; | 905 | found_fwd->listen_port = found_fwd->connect_port = 0; |
866 | } else { | 906 | } else { |
867 | buffer_put_int(r, MUX_S_FAILURE); | 907 | buffer_put_int(r, MUX_S_FAILURE); |
@@ -870,8 +910,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
870 | } | 910 | } |
871 | out: | 911 | out: |
872 | free(fwd_desc); | 912 | free(fwd_desc); |
873 | free(fwd.listen_host); | 913 | free(listen_addr); |
874 | free(fwd.connect_host); | 914 | free(connect_addr); |
875 | 915 | ||
876 | return ret; | 916 | return ret; |
877 | } | 917 | } |
@@ -1133,8 +1173,6 @@ mux_tty_alloc_failed(Channel *c) | |||
1133 | void | 1173 | void |
1134 | muxserver_listen(void) | 1174 | muxserver_listen(void) |
1135 | { | 1175 | { |
1136 | struct sockaddr_un addr; | ||
1137 | socklen_t sun_len; | ||
1138 | mode_t old_umask; | 1176 | mode_t old_umask; |
1139 | char *orig_control_path = options.control_path; | 1177 | char *orig_control_path = options.control_path; |
1140 | char rbuf[16+1]; | 1178 | char rbuf[16+1]; |
@@ -1163,23 +1201,10 @@ muxserver_listen(void) | |||
1163 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); | 1201 | xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); |
1164 | debug3("%s: temporary control path %s", __func__, options.control_path); | 1202 | debug3("%s: temporary control path %s", __func__, options.control_path); |
1165 | 1203 | ||
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); | 1204 | old_umask = umask(0177); |
1182 | if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { | 1205 | muxserver_sock = unix_listener(options.control_path, 64, 0); |
1206 | umask(old_umask); | ||
1207 | if (muxserver_sock < 0) { | ||
1183 | if (errno == EINVAL || errno == EADDRINUSE) { | 1208 | if (errno == EINVAL || errno == EADDRINUSE) { |
1184 | error("ControlSocket %s already exists, " | 1209 | error("ControlSocket %s already exists, " |
1185 | "disabling multiplexing", options.control_path); | 1210 | "disabling multiplexing", options.control_path); |
@@ -1193,13 +1218,11 @@ muxserver_listen(void) | |||
1193 | options.control_path = NULL; | 1218 | options.control_path = NULL; |
1194 | options.control_master = SSHCTL_MASTER_NO; | 1219 | options.control_master = SSHCTL_MASTER_NO; |
1195 | return; | 1220 | return; |
1196 | } else | 1221 | } else { |
1197 | fatal("%s bind(): %s", __func__, strerror(errno)); | 1222 | /* unix_listener() logs the error */ |
1223 | cleanup_exit(255); | ||
1224 | } | ||
1198 | } | 1225 | } |
1199 | umask(old_umask); | ||
1200 | |||
1201 | if (listen(muxserver_sock, 64) == -1) | ||
1202 | fatal("%s listen(): %s", __func__, strerror(errno)); | ||
1203 | 1226 | ||
1204 | /* Now atomically "move" the mux socket into position */ | 1227 | /* Now atomically "move" the mux socket into position */ |
1205 | if (link(options.control_path, orig_control_path) != 0) { | 1228 | if (link(options.control_path, orig_control_path) != 0) { |
@@ -1593,7 +1616,7 @@ mux_client_request_terminate(int fd) | |||
1593 | } | 1616 | } |
1594 | 1617 | ||
1595 | static int | 1618 | static int |
1596 | mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) | 1619 | mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) |
1597 | { | 1620 | { |
1598 | Buffer m; | 1621 | Buffer m; |
1599 | char *e, *fwd_desc; | 1622 | char *e, *fwd_desc; |
@@ -1608,11 +1631,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); | 1631 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); |
1609 | buffer_put_int(&m, muxclient_request_id); | 1632 | buffer_put_int(&m, muxclient_request_id); |
1610 | buffer_put_int(&m, ftype); | 1633 | buffer_put_int(&m, ftype); |
1611 | buffer_put_cstring(&m, | 1634 | if (fwd->listen_path != NULL) { |
1612 | fwd->listen_host == NULL ? "" : fwd->listen_host); | 1635 | buffer_put_cstring(&m, fwd->listen_path); |
1636 | } else { | ||
1637 | buffer_put_cstring(&m, | ||
1638 | fwd->listen_host == NULL ? "" : fwd->listen_host); | ||
1639 | } | ||
1613 | buffer_put_int(&m, fwd->listen_port); | 1640 | buffer_put_int(&m, fwd->listen_port); |
1614 | buffer_put_cstring(&m, | 1641 | if (fwd->connect_path != NULL) { |
1615 | fwd->connect_host == NULL ? "" : fwd->connect_host); | 1642 | buffer_put_cstring(&m, fwd->connect_path); |
1643 | } else { | ||
1644 | buffer_put_cstring(&m, | ||
1645 | fwd->connect_host == NULL ? "" : fwd->connect_host); | ||
1646 | } | ||
1616 | buffer_put_int(&m, fwd->connect_port); | 1647 | buffer_put_int(&m, fwd->connect_port); |
1617 | 1648 | ||
1618 | if (mux_client_write_packet(fd, &m) != 0) | 1649 | if (mux_client_write_packet(fd, &m) != 0) |