summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c693
1 files changed, 559 insertions, 134 deletions
diff --git a/channels.c b/channels.c
index 9efe89c9c..d67fdf48b 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.336 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,6 +42,7 @@
42#include "includes.h" 42#include "includes.h"
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/stat.h>
45#include <sys/ioctl.h> 46#include <sys/ioctl.h>
46#include <sys/un.h> 47#include <sys/un.h>
47#include <sys/socket.h> 48#include <sys/socket.h>
@@ -107,10 +108,15 @@ static int channel_max_fd = 0;
107 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local 108 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
108 * network (which might be behind a firewall). 109 * network (which might be behind a firewall).
109 */ 110 */
111/* XXX: streamlocal wants a path instead of host:port */
112/* Overload host_to_connect; we could just make this match Forward */
113/* XXX - can we use listen_host instead of listen_path? */
110typedef struct { 114typedef struct {
111 char *host_to_connect; /* Connect to 'host'. */ 115 char *host_to_connect; /* Connect to 'host'. */
112 u_short port_to_connect; /* Connect to 'port'. */ 116 int port_to_connect; /* Connect to 'port'. */
113 u_short listen_port; /* Remote side should listen port number. */ 117 char *listen_host; /* Remote side should listen address. */
118 char *listen_path; /* Remote side should listen path. */
119 int listen_port; /* Remote side should listen port. */
114} ForwardPermission; 120} ForwardPermission;
115 121
116/* List of all permitted host/port pairs to connect by the user. */ 122/* List of all permitted host/port pairs to connect by the user. */
@@ -473,6 +479,8 @@ channel_stop_listening(void)
473 case SSH_CHANNEL_PORT_LISTENER: 479 case SSH_CHANNEL_PORT_LISTENER:
474 case SSH_CHANNEL_RPORT_LISTENER: 480 case SSH_CHANNEL_RPORT_LISTENER:
475 case SSH_CHANNEL_X11_LISTENER: 481 case SSH_CHANNEL_X11_LISTENER:
482 case SSH_CHANNEL_UNIX_LISTENER:
483 case SSH_CHANNEL_RUNIX_LISTENER:
476 channel_close_fd(&c->sock); 484 channel_close_fd(&c->sock);
477 channel_free(c); 485 channel_free(c);
478 break; 486 break;
@@ -535,6 +543,8 @@ channel_still_open(void)
535 case SSH_CHANNEL_CONNECTING: 543 case SSH_CHANNEL_CONNECTING:
536 case SSH_CHANNEL_ZOMBIE: 544 case SSH_CHANNEL_ZOMBIE:
537 case SSH_CHANNEL_ABANDONED: 545 case SSH_CHANNEL_ABANDONED:
546 case SSH_CHANNEL_UNIX_LISTENER:
547 case SSH_CHANNEL_RUNIX_LISTENER:
538 continue; 548 continue;
539 case SSH_CHANNEL_LARVAL: 549 case SSH_CHANNEL_LARVAL:
540 if (!compat20) 550 if (!compat20)
@@ -581,6 +591,8 @@ channel_find_open(void)
581 case SSH_CHANNEL_CONNECTING: 591 case SSH_CHANNEL_CONNECTING:
582 case SSH_CHANNEL_ZOMBIE: 592 case SSH_CHANNEL_ZOMBIE:
583 case SSH_CHANNEL_ABANDONED: 593 case SSH_CHANNEL_ABANDONED:
594 case SSH_CHANNEL_UNIX_LISTENER:
595 case SSH_CHANNEL_RUNIX_LISTENER:
584 continue; 596 continue;
585 case SSH_CHANNEL_LARVAL: 597 case SSH_CHANNEL_LARVAL:
586 case SSH_CHANNEL_AUTH_SOCKET: 598 case SSH_CHANNEL_AUTH_SOCKET:
@@ -631,6 +643,8 @@ channel_open_message(void)
631 case SSH_CHANNEL_ABANDONED: 643 case SSH_CHANNEL_ABANDONED:
632 case SSH_CHANNEL_MUX_CLIENT: 644 case SSH_CHANNEL_MUX_CLIENT:
633 case SSH_CHANNEL_MUX_LISTENER: 645 case SSH_CHANNEL_MUX_LISTENER:
646 case SSH_CHANNEL_UNIX_LISTENER:
647 case SSH_CHANNEL_RUNIX_LISTENER:
634 continue; 648 continue;
635 case SSH_CHANNEL_LARVAL: 649 case SSH_CHANNEL_LARVAL:
636 case SSH_CHANNEL_OPENING: 650 case SSH_CHANNEL_OPENING:
@@ -1386,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1386static void 1400static void
1387port_open_helper(Channel *c, char *rtype) 1401port_open_helper(Channel *c, char *rtype)
1388{ 1402{
1389 int direct;
1390 char buf[1024]; 1403 char buf[1024];
1391 char *local_ipaddr = get_local_ipaddr(c->sock); 1404 char *local_ipaddr = get_local_ipaddr(c->sock);
1392 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); 1405 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
@@ -1400,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype)
1400 remote_port = 65535; 1413 remote_port = 65535;
1401 } 1414 }
1402 1415
1403 direct = (strcmp(rtype, "direct-tcpip") == 0);
1404
1405 snprintf(buf, sizeof buf, 1416 snprintf(buf, sizeof buf,
1406 "%s: listening port %d for %.100s port %d, " 1417 "%s: listening port %d for %.100s port %d, "
1407 "connect from %.200s port %d to %.100s port %d", 1418 "connect from %.200s port %d to %.100s port %d",
@@ -1417,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype)
1417 packet_put_int(c->self); 1428 packet_put_int(c->self);
1418 packet_put_int(c->local_window_max); 1429 packet_put_int(c->local_window_max);
1419 packet_put_int(c->local_maxpacket); 1430 packet_put_int(c->local_maxpacket);
1420 if (direct) { 1431 if (strcmp(rtype, "direct-tcpip") == 0) {
1421 /* target host, port */ 1432 /* target host, port */
1422 packet_put_cstring(c->path); 1433 packet_put_cstring(c->path);
1423 packet_put_int(c->host_port); 1434 packet_put_int(c->host_port);
1435 } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
1436 /* target path */
1437 packet_put_cstring(c->path);
1438 } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1439 /* listen path */
1440 packet_put_cstring(c->path);
1424 } else { 1441 } else {
1425 /* listen address, port */ 1442 /* listen address, port */
1426 packet_put_cstring(c->path); 1443 packet_put_cstring(c->path);
1427 packet_put_int(local_port); 1444 packet_put_int(local_port);
1428 } 1445 }
1429 /* originator host and port */ 1446 if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1430 packet_put_cstring(remote_ipaddr); 1447 /* reserved for future owner/mode info */
1431 packet_put_int((u_int)remote_port); 1448 packet_put_cstring("");
1449 } else {
1450 /* originator host and port */
1451 packet_put_cstring(remote_ipaddr);
1452 packet_put_int((u_int)remote_port);
1453 }
1432 packet_send(); 1454 packet_send();
1433 } else { 1455 } else {
1434 packet_start(SSH_MSG_PORT_OPEN); 1456 packet_start(SSH_MSG_PORT_OPEN);
@@ -1478,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1478 if (c->type == SSH_CHANNEL_RPORT_LISTENER) { 1500 if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
1479 nextstate = SSH_CHANNEL_OPENING; 1501 nextstate = SSH_CHANNEL_OPENING;
1480 rtype = "forwarded-tcpip"; 1502 rtype = "forwarded-tcpip";
1503 } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
1504 nextstate = SSH_CHANNEL_OPENING;
1505 rtype = "forwarded-streamlocal@openssh.com";
1506 } else if (c->host_port == PORT_STREAMLOCAL) {
1507 nextstate = SSH_CHANNEL_OPENING;
1508 rtype = "direct-streamlocal@openssh.com";
1509 } else if (c->host_port == 0) {
1510 nextstate = SSH_CHANNEL_DYNAMIC;
1511 rtype = "dynamic-tcpip";
1481 } else { 1512 } else {
1482 if (c->host_port == 0) { 1513 nextstate = SSH_CHANNEL_OPENING;
1483 nextstate = SSH_CHANNEL_DYNAMIC; 1514 rtype = "direct-tcpip";
1484 rtype = "dynamic-tcpip";
1485 } else {
1486 nextstate = SSH_CHANNEL_OPENING;
1487 rtype = "direct-tcpip";
1488 }
1489 } 1515 }
1490 1516
1491 addrlen = sizeof(addr); 1517 addrlen = sizeof(addr);
@@ -1498,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1498 c->notbefore = monotime() + 1; 1524 c->notbefore = monotime() + 1;
1499 return; 1525 return;
1500 } 1526 }
1501 set_nodelay(newsock); 1527 if (c->host_port != PORT_STREAMLOCAL)
1528 set_nodelay(newsock);
1502 nc = channel_new(rtype, nextstate, newsock, newsock, -1, 1529 nc = channel_new(rtype, nextstate, newsock, newsock, -1,
1503 c->local_window_max, c->local_maxpacket, 0, rtype, 1); 1530 c->local_window_max, c->local_maxpacket, 0, rtype, 1);
1504 nc->listening_port = c->listening_port; 1531 nc->listening_port = c->listening_port;
@@ -1987,6 +2014,8 @@ channel_handler_init_20(void)
1987 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; 2014 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
1988 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; 2015 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
1989 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; 2016 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
2017 channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
2018 channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
1990 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; 2019 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
1991 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 2020 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
1992 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 2021 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
@@ -1997,6 +2026,8 @@ channel_handler_init_20(void)
1997 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; 2026 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
1998 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 2027 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
1999 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; 2028 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
2029 channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
2030 channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
2000 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 2031 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2001 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 2032 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2002 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 2033 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
@@ -2315,7 +2346,7 @@ void
2315channel_input_data(int type, u_int32_t seq, void *ctxt) 2346channel_input_data(int type, u_int32_t seq, void *ctxt)
2316{ 2347{
2317 int id; 2348 int id;
2318 char *data; 2349 const u_char *data;
2319 u_int data_len, win_len; 2350 u_int data_len, win_len;
2320 Channel *c; 2351 Channel *c;
2321 2352
@@ -2637,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2637 originator_string = xstrdup("unknown (remote did not supply name)"); 2668 originator_string = xstrdup("unknown (remote did not supply name)");
2638 } 2669 }
2639 packet_check_eom(); 2670 packet_check_eom();
2640 c = channel_connect_to(host, host_port, 2671 c = channel_connect_to_port(host, host_port,
2641 "connected socket", originator_string); 2672 "connected socket", originator_string);
2642 free(originator_string); 2673 free(originator_string);
2643 free(host); 2674 free(host);
@@ -2700,23 +2731,24 @@ channel_set_af(int af)
2700 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR 2731 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2701 * "" (empty string), "*" -> wildcard v4/v6 2732 * "" (empty string), "*" -> wildcard v4/v6
2702 * "localhost" -> loopback v4/v6 2733 * "localhost" -> loopback v4/v6
2734 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
2703 */ 2735 */
2704static const char * 2736static const char *
2705channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, 2737channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2706 int is_client, int gateway_ports) 2738 int is_client, struct ForwardOptions *fwd_opts)
2707{ 2739{
2708 const char *addr = NULL; 2740 const char *addr = NULL;
2709 int wildcard = 0; 2741 int wildcard = 0;
2710 2742
2711 if (listen_addr == NULL) { 2743 if (listen_addr == NULL) {
2712 /* No address specified: default to gateway_ports setting */ 2744 /* No address specified: default to gateway_ports setting */
2713 if (gateway_ports) 2745 if (fwd_opts->gateway_ports)
2714 wildcard = 1; 2746 wildcard = 1;
2715 } else if (gateway_ports || is_client) { 2747 } else if (fwd_opts->gateway_ports || is_client) {
2716 if (((datafellows & SSH_OLD_FORWARD_ADDR) && 2748 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2717 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || 2749 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2718 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || 2750 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2719 (!is_client && gateway_ports == 1)) { 2751 (!is_client && fwd_opts->gateway_ports == 1)) {
2720 wildcard = 1; 2752 wildcard = 1;
2721 /* 2753 /*
2722 * Notify client if they requested a specific listen 2754 * Notify client if they requested a specific listen
@@ -2729,9 +2761,20 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2729 "\"%s\" overridden by server " 2761 "\"%s\" overridden by server "
2730 "GatewayPorts", listen_addr); 2762 "GatewayPorts", listen_addr);
2731 } 2763 }
2732 } 2764 } else if (strcmp(listen_addr, "localhost") != 0 ||
2733 else if (strcmp(listen_addr, "localhost") != 0) 2765 strcmp(listen_addr, "127.0.0.1") == 0 ||
2766 strcmp(listen_addr, "::1") == 0) {
2767 /* Accept localhost address when GatewayPorts=yes */
2734 addr = listen_addr; 2768 addr = listen_addr;
2769 }
2770 } else if (strcmp(listen_addr, "127.0.0.1") == 0 ||
2771 strcmp(listen_addr, "::1") == 0) {
2772 /*
2773 * If a specific IPv4/IPv6 localhost address has been
2774 * requested then accept it even if gateway_ports is in
2775 * effect. This allows the client to prefer IPv4 or IPv6.
2776 */
2777 addr = listen_addr;
2735 } 2778 }
2736 if (wildcardp != NULL) 2779 if (wildcardp != NULL)
2737 *wildcardp = wildcard; 2780 *wildcardp = wildcard;
@@ -2739,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2739} 2782}
2740 2783
2741static int 2784static int
2742channel_setup_fwd_listener(int type, const char *listen_addr, 2785channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
2743 u_short listen_port, int *allocated_listen_port, 2786 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2744 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2745{ 2787{
2746 Channel *c; 2788 Channel *c;
2747 int sock, r, success = 0, wildcard = 0, is_client; 2789 int sock, r, success = 0, wildcard = 0, is_client;
@@ -2751,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2751 in_port_t *lport_p; 2793 in_port_t *lport_p;
2752 2794
2753 host = (type == SSH_CHANNEL_RPORT_LISTENER) ? 2795 host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2754 listen_addr : host_to_connect; 2796 fwd->listen_host : fwd->connect_host;
2755 is_client = (type == SSH_CHANNEL_PORT_LISTENER); 2797 is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2756 2798
2757 if (host == NULL) { 2799 if (host == NULL) {
@@ -2764,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2764 } 2806 }
2765 2807
2766 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ 2808 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
2767 addr = channel_fwd_bind_addr(listen_addr, &wildcard, 2809 addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
2768 is_client, gateway_ports); 2810 is_client, fwd_opts);
2769 debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", 2811 debug3("%s: type %d wildcard %d addr %s", __func__,
2770 type, wildcard, (addr == NULL) ? "NULL" : addr); 2812 type, wildcard, (addr == NULL) ? "NULL" : addr);
2771 2813
2772 /* 2814 /*
@@ -2777,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2777 hints.ai_family = IPv4or6; 2819 hints.ai_family = IPv4or6;
2778 hints.ai_flags = wildcard ? AI_PASSIVE : 0; 2820 hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2779 hints.ai_socktype = SOCK_STREAM; 2821 hints.ai_socktype = SOCK_STREAM;
2780 snprintf(strport, sizeof strport, "%d", listen_port); 2822 snprintf(strport, sizeof strport, "%d", fwd->listen_port);
2781 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { 2823 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2782 if (addr == NULL) { 2824 if (addr == NULL) {
2783 /* This really shouldn't happen */ 2825 /* This really shouldn't happen */
2784 packet_disconnect("getaddrinfo: fatal error: %s", 2826 packet_disconnect("getaddrinfo: fatal error: %s",
2785 ssh_gai_strerror(r)); 2827 ssh_gai_strerror(r));
2786 } else { 2828 } else {
2787 error("channel_setup_fwd_listener: " 2829 error("%s: getaddrinfo(%.64s): %s", __func__, addr,
2788 "getaddrinfo(%.64s): %s", addr,
2789 ssh_gai_strerror(r)); 2830 ssh_gai_strerror(r));
2790 } 2831 }
2791 return 0; 2832 return 0;
@@ -2809,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2809 * If allocating a port for -R forwards, then use the 2850 * If allocating a port for -R forwards, then use the
2810 * same port for all address families. 2851 * same port for all address families.
2811 */ 2852 */
2812 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2853 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2813 allocated_listen_port != NULL && *allocated_listen_port > 0) 2854 allocated_listen_port != NULL && *allocated_listen_port > 0)
2814 *lport_p = htons(*allocated_listen_port); 2855 *lport_p = htons(*allocated_listen_port);
2815 2856
2816 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 2857 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2817 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 2858 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2818 error("channel_setup_fwd_listener: getnameinfo failed"); 2859 error("%s: getnameinfo failed", __func__);
2819 continue; 2860 continue;
2820 } 2861 }
2821 /* Create a port to listen for the host. */ 2862 /* Create a port to listen for the host. */
@@ -2852,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2852 } 2893 }
2853 2894
2854 /* 2895 /*
2855 * listen_port == 0 requests a dynamically allocated port - 2896 * fwd->listen_port == 0 requests a dynamically allocated port -
2856 * record what we got. 2897 * record what we got.
2857 */ 2898 */
2858 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2899 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2859 allocated_listen_port != NULL && 2900 allocated_listen_port != NULL &&
2860 *allocated_listen_port == 0) { 2901 *allocated_listen_port == 0) {
2861 *allocated_listen_port = get_sock_port(sock, 1); 2902 *allocated_listen_port = get_sock_port(sock, 1);
@@ -2868,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2868 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 2909 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2869 0, "port listener", 1); 2910 0, "port listener", 1);
2870 c->path = xstrdup(host); 2911 c->path = xstrdup(host);
2871 c->host_port = port_to_connect; 2912 c->host_port = fwd->connect_port;
2872 c->listening_addr = addr == NULL ? NULL : xstrdup(addr); 2913 c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
2873 if (listen_port == 0 && allocated_listen_port != NULL && 2914 if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
2874 !(datafellows & SSH_BUG_DYNAMIC_RPORT)) 2915 !(datafellows & SSH_BUG_DYNAMIC_RPORT))
2875 c->listening_port = *allocated_listen_port; 2916 c->listening_port = *allocated_listen_port;
2876 else 2917 else
2877 c->listening_port = listen_port; 2918 c->listening_port = fwd->listen_port;
2878 success = 1; 2919 success = 1;
2879 } 2920 }
2880 if (success == 0) 2921 if (success == 0)
2881 error("channel_setup_fwd_listener: cannot listen to port: %d", 2922 error("%s: cannot listen to port: %d", __func__,
2882 listen_port); 2923 fwd->listen_port);
2883 freeaddrinfo(aitop); 2924 freeaddrinfo(aitop);
2884 return success; 2925 return success;
2885} 2926}
2886 2927
2887int 2928static int
2888channel_cancel_rport_listener(const char *host, u_short port) 2929channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
2930 struct ForwardOptions *fwd_opts)
2931{
2932 struct sockaddr_un sunaddr;
2933 const char *path;
2934 Channel *c;
2935 int port, sock;
2936 mode_t omask;
2937
2938 switch (type) {
2939 case SSH_CHANNEL_UNIX_LISTENER:
2940 if (fwd->connect_path != NULL) {
2941 if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
2942 error("Local connecting path too long: %s",
2943 fwd->connect_path);
2944 return 0;
2945 }
2946 path = fwd->connect_path;
2947 port = PORT_STREAMLOCAL;
2948 } else {
2949 if (fwd->connect_host == NULL) {
2950 error("No forward host name.");
2951 return 0;
2952 }
2953 if (strlen(fwd->connect_host) >= NI_MAXHOST) {
2954 error("Forward host name too long.");
2955 return 0;
2956 }
2957 path = fwd->connect_host;
2958 port = fwd->connect_port;
2959 }
2960 break;
2961 case SSH_CHANNEL_RUNIX_LISTENER:
2962 path = fwd->listen_path;
2963 port = PORT_STREAMLOCAL;
2964 break;
2965 default:
2966 error("%s: unexpected channel type %d", __func__, type);
2967 return 0;
2968 }
2969
2970 if (fwd->listen_path == NULL) {
2971 error("No forward path name.");
2972 return 0;
2973 }
2974 if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
2975 error("Local listening path too long: %s", fwd->listen_path);
2976 return 0;
2977 }
2978
2979 debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
2980
2981 /* Start a Unix domain listener. */
2982 omask = umask(fwd_opts->streamlocal_bind_mask);
2983 sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
2984 fwd_opts->streamlocal_bind_unlink);
2985 umask(omask);
2986 if (sock < 0)
2987 return 0;
2988
2989 debug("Local forwarding listening on path %s.", fwd->listen_path);
2990
2991 /* Allocate a channel number for the socket. */
2992 c = channel_new("unix listener", type, sock, sock, -1,
2993 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2994 0, "unix listener", 1);
2995 c->path = xstrdup(path);
2996 c->host_port = port;
2997 c->listening_port = PORT_STREAMLOCAL;
2998 c->listening_addr = xstrdup(fwd->listen_path);
2999 return 1;
3000}
3001
3002static int
3003channel_cancel_rport_listener_tcpip(const char *host, u_short port)
2889{ 3004{
2890 u_int i; 3005 u_int i;
2891 int found = 0; 3006 int found = 0;
@@ -2904,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
2904 return (found); 3019 return (found);
2905} 3020}
2906 3021
3022static int
3023channel_cancel_rport_listener_streamlocal(const char *path)
3024{
3025 u_int i;
3026 int found = 0;
3027
3028 for (i = 0; i < channels_alloc; i++) {
3029 Channel *c = channels[i];
3030 if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
3031 continue;
3032 if (c->path == NULL)
3033 continue;
3034 if (strcmp(c->path, path) == 0) {
3035 debug2("%s: close channel %d", __func__, i);
3036 channel_free(c);
3037 found = 1;
3038 }
3039 }
3040
3041 return (found);
3042}
3043
2907int 3044int
2908channel_cancel_lport_listener(const char *lhost, u_short lport, 3045channel_cancel_rport_listener(struct Forward *fwd)
2909 int cport, int gateway_ports) 3046{
3047 if (fwd->listen_path != NULL)
3048 return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
3049 else
3050 return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
3051}
3052
3053static int
3054channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
3055 int cport, struct ForwardOptions *fwd_opts)
2910{ 3056{
2911 u_int i; 3057 u_int i;
2912 int found = 0; 3058 int found = 0;
2913 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); 3059 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
2914 3060
2915 for (i = 0; i < channels_alloc; i++) { 3061 for (i = 0; i < channels_alloc; i++) {
2916 Channel *c = channels[i]; 3062 Channel *c = channels[i];
@@ -2939,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
2939 return (found); 3085 return (found);
2940} 3086}
2941 3087
3088static int
3089channel_cancel_lport_listener_streamlocal(const char *path)
3090{
3091 u_int i;
3092 int found = 0;
3093
3094 if (path == NULL) {
3095 error("%s: no path specified.", __func__);
3096 return 0;
3097 }
3098
3099 for (i = 0; i < channels_alloc; i++) {
3100 Channel *c = channels[i];
3101 if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
3102 continue;
3103 if (c->listening_addr == NULL)
3104 continue;
3105 if (strcmp(c->listening_addr, path) == 0) {
3106 debug2("%s: close channel %d", __func__, i);
3107 channel_free(c);
3108 found = 1;
3109 }
3110 }
3111
3112 return (found);
3113}
3114
3115int
3116channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
3117{
3118 if (fwd->listen_path != NULL)
3119 return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
3120 else
3121 return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
3122}
3123
2942/* protocol local port fwd, used by ssh (and sshd in v1) */ 3124/* protocol local port fwd, used by ssh (and sshd in v1) */
2943int 3125int
2944channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, 3126channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
2945 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2946{ 3127{
2947 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, 3128 if (fwd->listen_path != NULL) {
2948 listen_host, listen_port, NULL, host_to_connect, port_to_connect, 3129 return channel_setup_fwd_listener_streamlocal(
2949 gateway_ports); 3130 SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
3131 } else {
3132 return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
3133 fwd, NULL, fwd_opts);
3134 }
2950} 3135}
2951 3136
2952/* protocol v2 remote port fwd, used by sshd */ 3137/* protocol v2 remote port fwd, used by sshd */
2953int 3138int
2954channel_setup_remote_fwd_listener(const char *listen_address, 3139channel_setup_remote_fwd_listener(struct Forward *fwd,
2955 u_short listen_port, int *allocated_listen_port, int gateway_ports) 3140 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2956{ 3141{
2957 return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, 3142 if (fwd->listen_path != NULL) {
2958 listen_address, listen_port, allocated_listen_port, 3143 return channel_setup_fwd_listener_streamlocal(
2959 NULL, 0, gateway_ports); 3144 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
3145 } else {
3146 return channel_setup_fwd_listener_tcpip(
3147 SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
3148 fwd_opts);
3149 }
2960} 3150}
2961 3151
2962/* 3152/*
@@ -2987,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host)
2987 * channel_update_permitted_opens(). 3177 * channel_update_permitted_opens().
2988 */ 3178 */
2989int 3179int
2990channel_request_remote_forwarding(const char *listen_host, u_short listen_port, 3180channel_request_remote_forwarding(struct Forward *fwd)
2991 const char *host_to_connect, u_short port_to_connect)
2992{ 3181{
2993 int type, success = 0, idx = -1; 3182 int type, success = 0, idx = -1;
2994 3183
2995 /* Send the forward request to the remote side. */ 3184 /* Send the forward request to the remote side. */
2996 if (compat20) { 3185 if (compat20) {
2997 packet_start(SSH2_MSG_GLOBAL_REQUEST); 3186 packet_start(SSH2_MSG_GLOBAL_REQUEST);
2998 packet_put_cstring("tcpip-forward"); 3187 if (fwd->listen_path != NULL) {
2999 packet_put_char(1); /* boolean: want reply */ 3188 packet_put_cstring("streamlocal-forward@openssh.com");
3000 packet_put_cstring(channel_rfwd_bind_host(listen_host)); 3189 packet_put_char(1); /* boolean: want reply */
3001 packet_put_int(listen_port); 3190 packet_put_cstring(fwd->listen_path);
3191 } else {
3192 packet_put_cstring("tcpip-forward");
3193 packet_put_char(1); /* boolean: want reply */
3194 packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
3195 packet_put_int(fwd->listen_port);
3196 }
3002 packet_send(); 3197 packet_send();
3003 packet_write_wait(); 3198 packet_write_wait();
3004 /* Assume that server accepts the request */ 3199 /* Assume that server accepts the request */
3005 success = 1; 3200 success = 1;
3006 } else { 3201 } else if (fwd->listen_path == NULL) {
3007 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); 3202 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
3008 packet_put_int(listen_port); 3203 packet_put_int(fwd->listen_port);
3009 packet_put_cstring(host_to_connect); 3204 packet_put_cstring(fwd->connect_host);
3010 packet_put_int(port_to_connect); 3205 packet_put_int(fwd->connect_port);
3011 packet_send(); 3206 packet_send();
3012 packet_write_wait(); 3207 packet_write_wait();
3013 3208
@@ -3024,25 +3219,102 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
3024 packet_disconnect("Protocol error for port forward request:" 3219 packet_disconnect("Protocol error for port forward request:"
3025 "received packet type %d.", type); 3220 "received packet type %d.", type);
3026 } 3221 }
3222 } else {
3223 logit("Warning: Server does not support remote stream local forwarding.");
3027 } 3224 }
3028 if (success) { 3225 if (success) {
3029 /* Record that connection to this host/port is permitted. */ 3226 /* Record that connection to this host/port is permitted. */
3030 permitted_opens = xrealloc(permitted_opens, 3227 permitted_opens = xrealloc(permitted_opens,
3031 num_permitted_opens + 1, sizeof(*permitted_opens)); 3228 num_permitted_opens + 1, sizeof(*permitted_opens));
3032 idx = num_permitted_opens++; 3229 idx = num_permitted_opens++;
3033 permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); 3230 if (fwd->connect_path != NULL) {
3034 permitted_opens[idx].port_to_connect = port_to_connect; 3231 permitted_opens[idx].host_to_connect =
3035 permitted_opens[idx].listen_port = listen_port; 3232 xstrdup(fwd->connect_path);
3233 permitted_opens[idx].port_to_connect =
3234 PORT_STREAMLOCAL;
3235 } else {
3236 permitted_opens[idx].host_to_connect =
3237 xstrdup(fwd->connect_host);
3238 permitted_opens[idx].port_to_connect =
3239 fwd->connect_port;
3240 }
3241 if (fwd->listen_path != NULL) {
3242 permitted_opens[idx].listen_host = NULL;
3243 permitted_opens[idx].listen_path =
3244 xstrdup(fwd->listen_path);
3245 permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
3246 } else {
3247 permitted_opens[idx].listen_host =
3248 fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
3249 permitted_opens[idx].listen_path = NULL;
3250 permitted_opens[idx].listen_port = fwd->listen_port;
3251 }
3036 } 3252 }
3037 return (idx); 3253 return (idx);
3038} 3254}
3039 3255
3256static int
3257open_match(ForwardPermission *allowed_open, const char *requestedhost,
3258 int requestedport)
3259{
3260 if (allowed_open->host_to_connect == NULL)
3261 return 0;
3262 if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
3263 allowed_open->port_to_connect != requestedport)
3264 return 0;
3265 if (strcmp(allowed_open->host_to_connect, requestedhost) != 0)
3266 return 0;
3267 return 1;
3268}
3269
3270/*
3271 * Note that in the listen host/port case
3272 * we don't support FWD_PERMIT_ANY_PORT and
3273 * need to translate between the configured-host (listen_host)
3274 * and what we've sent to the remote server (channel_rfwd_bind_host)
3275 */
3276static int
3277open_listen_match_tcpip(ForwardPermission *allowed_open,
3278 const char *requestedhost, u_short requestedport, int translate)
3279{
3280 const char *allowed_host;
3281
3282 if (allowed_open->host_to_connect == NULL)
3283 return 0;
3284 if (allowed_open->listen_port != requestedport)
3285 return 0;
3286 if (!translate && allowed_open->listen_host == NULL &&
3287 requestedhost == NULL)
3288 return 1;
3289 allowed_host = translate ?
3290 channel_rfwd_bind_host(allowed_open->listen_host) :
3291 allowed_open->listen_host;
3292 if (allowed_host == NULL ||
3293 strcmp(allowed_host, requestedhost) != 0)
3294 return 0;
3295 return 1;
3296}
3297
3298static int
3299open_listen_match_streamlocal(ForwardPermission *allowed_open,
3300 const char *requestedpath)
3301{
3302 if (allowed_open->host_to_connect == NULL)
3303 return 0;
3304 if (allowed_open->listen_port != PORT_STREAMLOCAL)
3305 return 0;
3306 if (allowed_open->listen_path == NULL ||
3307 strcmp(allowed_open->listen_path, requestedpath) != 0)
3308 return 0;
3309 return 1;
3310}
3311
3040/* 3312/*
3041 * Request cancellation of remote forwarding of connection host:port from 3313 * Request cancellation of remote forwarding of connection host:port from
3042 * local side. 3314 * local side.
3043 */ 3315 */
3044int 3316static int
3045channel_request_rforward_cancel(const char *host, u_short port) 3317channel_request_rforward_cancel_tcpip(const char *host, u_short port)
3046{ 3318{
3047 int i; 3319 int i;
3048 3320
@@ -3050,8 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
3050 return -1; 3322 return -1;
3051 3323
3052 for (i = 0; i < num_permitted_opens; i++) { 3324 for (i = 0; i < num_permitted_opens; i++) {
3053 if (permitted_opens[i].host_to_connect != NULL && 3325 if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
3054 permitted_opens[i].listen_port == port)
3055 break; 3326 break;
3056 } 3327 }
3057 if (i >= num_permitted_opens) { 3328 if (i >= num_permitted_opens) {
@@ -3069,9 +3340,64 @@ channel_request_rforward_cancel(const char *host, u_short port)
3069 permitted_opens[i].port_to_connect = 0; 3340 permitted_opens[i].port_to_connect = 0;
3070 free(permitted_opens[i].host_to_connect); 3341 free(permitted_opens[i].host_to_connect);
3071 permitted_opens[i].host_to_connect = NULL; 3342 permitted_opens[i].host_to_connect = NULL;
3343 free(permitted_opens[i].listen_host);
3344 permitted_opens[i].listen_host = NULL;
3345 permitted_opens[i].listen_path = NULL;
3346
3347 return 0;
3348}
3349
3350/*
3351 * Request cancellation of remote forwarding of Unix domain socket
3352 * path from local side.
3353 */
3354static int
3355channel_request_rforward_cancel_streamlocal(const char *path)
3356{
3357 int i;
3358
3359 if (!compat20)
3360 return -1;
3361
3362 for (i = 0; i < num_permitted_opens; i++) {
3363 if (open_listen_match_streamlocal(&permitted_opens[i], path))
3364 break;
3365 }
3366 if (i >= num_permitted_opens) {
3367 debug("%s: requested forward not found", __func__);
3368 return -1;
3369 }
3370 packet_start(SSH2_MSG_GLOBAL_REQUEST);
3371 packet_put_cstring("cancel-streamlocal-forward@openssh.com");
3372 packet_put_char(0);
3373 packet_put_cstring(path);
3374 packet_send();
3375
3376 permitted_opens[i].listen_port = 0;
3377 permitted_opens[i].port_to_connect = 0;
3378 free(permitted_opens[i].host_to_connect);
3379 permitted_opens[i].host_to_connect = NULL;
3380 permitted_opens[i].listen_host = NULL;
3381 free(permitted_opens[i].listen_path);
3382 permitted_opens[i].listen_path = NULL;
3072 3383
3073 return 0; 3384 return 0;
3074} 3385}
3386
3387/*
3388 * Request cancellation of remote forwarding of a connection from local side.
3389 */
3390int
3391channel_request_rforward_cancel(struct Forward *fwd)
3392{
3393 if (fwd->listen_path != NULL) {
3394 return (channel_request_rforward_cancel_streamlocal(
3395 fwd->listen_path));
3396 } else {
3397 return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
3398 fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
3399 }
3400}
3075 3401
3076/* 3402/*
3077 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates 3403 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
@@ -3079,36 +3405,35 @@ channel_request_rforward_cancel(const char *host, u_short port)
3079 * message if there was an error). 3405 * message if there was an error).
3080 */ 3406 */
3081int 3407int
3082channel_input_port_forward_request(int is_root, int gateway_ports) 3408channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
3083{ 3409{
3084 u_short port, host_port;
3085 int success = 0; 3410 int success = 0;
3086 char *hostname; 3411 struct Forward fwd;
3087 3412
3088 /* Get arguments from the packet. */ 3413 /* Get arguments from the packet. */
3089 port = packet_get_int(); 3414 memset(&fwd, 0, sizeof(fwd));
3090 hostname = packet_get_string(NULL); 3415 fwd.listen_port = packet_get_int();
3091 host_port = packet_get_int(); 3416 fwd.connect_host = packet_get_string(NULL);
3417 fwd.connect_port = packet_get_int();
3092 3418
3093#ifndef HAVE_CYGWIN 3419#ifndef HAVE_CYGWIN
3094 /* 3420 /*
3095 * Check that an unprivileged user is not trying to forward a 3421 * Check that an unprivileged user is not trying to forward a
3096 * privileged port. 3422 * privileged port.
3097 */ 3423 */
3098 if (port < IPPORT_RESERVED && !is_root) 3424 if (fwd.listen_port < IPPORT_RESERVED && !is_root)
3099 packet_disconnect( 3425 packet_disconnect(
3100 "Requested forwarding of port %d but user is not root.", 3426 "Requested forwarding of port %d but user is not root.",
3101 port); 3427 fwd.listen_port);
3102 if (host_port == 0) 3428 if (fwd.connect_port == 0)
3103 packet_disconnect("Dynamic forwarding denied."); 3429 packet_disconnect("Dynamic forwarding denied.");
3104#endif 3430#endif
3105 3431
3106 /* Initiate forwarding */ 3432 /* Initiate forwarding */
3107 success = channel_setup_local_fwd_listener(NULL, port, hostname, 3433 success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
3108 host_port, gateway_ports);
3109 3434
3110 /* Free the argument string. */ 3435 /* Free the argument string. */
3111 free(hostname); 3436 free(fwd.connect_host);
3112 3437
3113 return (success ? 0 : -1); 3438 return (success ? 0 : -1);
3114} 3439}
@@ -3134,6 +3459,9 @@ channel_add_permitted_opens(char *host, int port)
3134 num_permitted_opens + 1, sizeof(*permitted_opens)); 3459 num_permitted_opens + 1, sizeof(*permitted_opens));
3135 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); 3460 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
3136 permitted_opens[num_permitted_opens].port_to_connect = port; 3461 permitted_opens[num_permitted_opens].port_to_connect = port;
3462 permitted_opens[num_permitted_opens].listen_host = NULL;
3463 permitted_opens[num_permitted_opens].listen_path = NULL;
3464 permitted_opens[num_permitted_opens].listen_port = 0;
3137 num_permitted_opens++; 3465 num_permitted_opens++;
3138 3466
3139 all_opens_permitted = 0; 3467 all_opens_permitted = 0;
@@ -3165,6 +3493,10 @@ channel_update_permitted_opens(int idx, int newport)
3165 permitted_opens[idx].port_to_connect = 0; 3493 permitted_opens[idx].port_to_connect = 0;
3166 free(permitted_opens[idx].host_to_connect); 3494 free(permitted_opens[idx].host_to_connect);
3167 permitted_opens[idx].host_to_connect = NULL; 3495 permitted_opens[idx].host_to_connect = NULL;
3496 free(permitted_opens[idx].listen_host);
3497 permitted_opens[idx].listen_host = NULL;
3498 free(permitted_opens[idx].listen_path);
3499 permitted_opens[idx].listen_path = NULL;
3168 } 3500 }
3169} 3501}
3170 3502
@@ -3178,6 +3510,9 @@ channel_add_adm_permitted_opens(char *host, int port)
3178 permitted_adm_opens[num_adm_permitted_opens].host_to_connect 3510 permitted_adm_opens[num_adm_permitted_opens].host_to_connect
3179 = xstrdup(host); 3511 = xstrdup(host);
3180 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; 3512 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
3513 permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
3514 permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
3515 permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
3181 return ++num_adm_permitted_opens; 3516 return ++num_adm_permitted_opens;
3182} 3517}
3183 3518
@@ -3195,8 +3530,11 @@ channel_clear_permitted_opens(void)
3195{ 3530{
3196 int i; 3531 int i;
3197 3532
3198 for (i = 0; i < num_permitted_opens; i++) 3533 for (i = 0; i < num_permitted_opens; i++) {
3199 free(permitted_opens[i].host_to_connect); 3534 free(permitted_opens[i].host_to_connect);
3535 free(permitted_opens[i].listen_host);
3536 free(permitted_opens[i].listen_path);
3537 }
3200 free(permitted_opens); 3538 free(permitted_opens);
3201 permitted_opens = NULL; 3539 permitted_opens = NULL;
3202 num_permitted_opens = 0; 3540 num_permitted_opens = 0;
@@ -3207,8 +3545,11 @@ channel_clear_adm_permitted_opens(void)
3207{ 3545{
3208 int i; 3546 int i;
3209 3547
3210 for (i = 0; i < num_adm_permitted_opens; i++) 3548 for (i = 0; i < num_adm_permitted_opens; i++) {
3211 free(permitted_adm_opens[i].host_to_connect); 3549 free(permitted_adm_opens[i].host_to_connect);
3550 free(permitted_adm_opens[i].listen_host);
3551 free(permitted_adm_opens[i].listen_path);
3552 }
3212 free(permitted_adm_opens); 3553 free(permitted_adm_opens);
3213 permitted_adm_opens = NULL; 3554 permitted_adm_opens = NULL;
3214 num_adm_permitted_opens = 0; 3555 num_adm_permitted_opens = 0;
@@ -3246,30 +3587,32 @@ permitopen_port(const char *p)
3246 return -1; 3587 return -1;
3247} 3588}
3248 3589
3249static int
3250port_match(u_short allowedport, u_short requestedport)
3251{
3252 if (allowedport == FWD_PERMIT_ANY_PORT ||
3253 allowedport == requestedport)
3254 return 1;
3255 return 0;
3256}
3257
3258/* Try to start non-blocking connect to next host in cctx list */ 3590/* Try to start non-blocking connect to next host in cctx list */
3259static int 3591static int
3260connect_next(struct channel_connect *cctx) 3592connect_next(struct channel_connect *cctx)
3261{ 3593{
3262 int sock, saved_errno; 3594 int sock, saved_errno;
3263 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 3595 struct sockaddr_un *sunaddr;
3596 char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
3264 3597
3265 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { 3598 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
3266 if (cctx->ai->ai_family != AF_INET && 3599 switch (cctx->ai->ai_family) {
3267 cctx->ai->ai_family != AF_INET6) 3600 case AF_UNIX:
3268 continue; 3601 /* unix:pathname instead of host:port */
3269 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, 3602 sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
3270 ntop, sizeof(ntop), strport, sizeof(strport), 3603 strlcpy(ntop, "unix", sizeof(ntop));
3271 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 3604 strlcpy(strport, sunaddr->sun_path, sizeof(strport));
3272 error("connect_next: getnameinfo failed"); 3605 break;
3606 case AF_INET:
3607 case AF_INET6:
3608 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
3609 ntop, sizeof(ntop), strport, sizeof(strport),
3610 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
3611 error("connect_next: getnameinfo failed");
3612 continue;
3613 }
3614 break;
3615 default:
3273 continue; 3616 continue;
3274 } 3617 }
3275 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, 3618 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
@@ -3292,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
3292 errno = saved_errno; 3635 errno = saved_errno;
3293 continue; /* fail -- try next */ 3636 continue; /* fail -- try next */
3294 } 3637 }
3638 if (cctx->ai->ai_family != AF_UNIX)
3639 set_nodelay(sock);
3295 debug("connect_next: host %.100s ([%.100s]:%s) " 3640 debug("connect_next: host %.100s ([%.100s]:%s) "
3296 "in progress, fd=%d", cctx->host, ntop, strport, sock); 3641 "in progress, fd=%d", cctx->host, ntop, strport, sock);
3297 cctx->ai = cctx->ai->ai_next; 3642 cctx->ai = cctx->ai->ai_next;
3298 set_nodelay(sock);
3299 return sock; 3643 return sock;
3300 } 3644 }
3301 return -1; 3645 return -1;
@@ -3305,14 +3649,18 @@ static void
3305channel_connect_ctx_free(struct channel_connect *cctx) 3649channel_connect_ctx_free(struct channel_connect *cctx)
3306{ 3650{
3307 free(cctx->host); 3651 free(cctx->host);
3308 if (cctx->aitop) 3652 if (cctx->aitop) {
3309 freeaddrinfo(cctx->aitop); 3653 if (cctx->aitop->ai_family == AF_UNIX)
3654 free(cctx->aitop);
3655 else
3656 freeaddrinfo(cctx->aitop);
3657 }
3310 memset(cctx, 0, sizeof(*cctx)); 3658 memset(cctx, 0, sizeof(*cctx));
3311} 3659}
3312 3660
3313/* Return CONNECTING channel to remote host, port */ 3661/* Return CONNECTING channel to remote host:port or local socket path */
3314static Channel * 3662static Channel *
3315connect_to(const char *host, u_short port, char *ctype, char *rname) 3663connect_to(const char *name, int port, char *ctype, char *rname)
3316{ 3664{
3317 struct addrinfo hints; 3665 struct addrinfo hints;
3318 int gaierr; 3666 int gaierr;
@@ -3322,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
3322 Channel *c; 3670 Channel *c;
3323 3671
3324 memset(&cctx, 0, sizeof(cctx)); 3672 memset(&cctx, 0, sizeof(cctx));
3325 memset(&hints, 0, sizeof(hints)); 3673
3326 hints.ai_family = IPv4or6; 3674 if (port == PORT_STREAMLOCAL) {
3327 hints.ai_socktype = SOCK_STREAM; 3675 struct sockaddr_un *sunaddr;
3328 snprintf(strport, sizeof strport, "%d", port); 3676 struct addrinfo *ai;
3329 if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) { 3677
3330 error("connect_to %.100s: unknown host (%s)", host, 3678 if (strlen(name) > sizeof(sunaddr->sun_path)) {
3331 ssh_gai_strerror(gaierr)); 3679 error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
3332 return NULL; 3680 return (NULL);
3681 }
3682
3683 /*
3684 * Fake up a struct addrinfo for AF_UNIX connections.
3685 * channel_connect_ctx_free() must check ai_family
3686 * and use free() not freeaddirinfo() for AF_UNIX.
3687 */
3688 ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
3689 memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
3690 ai->ai_addr = (struct sockaddr *)(ai + 1);
3691 ai->ai_addrlen = sizeof(*sunaddr);
3692 ai->ai_family = AF_UNIX;
3693 ai->ai_socktype = SOCK_STREAM;
3694 ai->ai_protocol = PF_UNSPEC;
3695 sunaddr = (struct sockaddr_un *)ai->ai_addr;
3696 sunaddr->sun_family = AF_UNIX;
3697 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
3698 cctx.aitop = ai;
3699 } else {
3700 memset(&hints, 0, sizeof(hints));
3701 hints.ai_family = IPv4or6;
3702 hints.ai_socktype = SOCK_STREAM;
3703 snprintf(strport, sizeof strport, "%d", port);
3704 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
3705 error("connect_to %.100s: unknown host (%s)", name,
3706 ssh_gai_strerror(gaierr));
3707 return NULL;
3708 }
3333 } 3709 }
3334 3710
3335 cctx.host = xstrdup(host); 3711 cctx.host = xstrdup(name);
3336 cctx.port = port; 3712 cctx.port = port;
3337 cctx.ai = cctx.aitop; 3713 cctx.ai = cctx.aitop;
3338 3714
3339 if ((sock = connect_next(&cctx)) == -1) { 3715 if ((sock = connect_next(&cctx)) == -1) {
3340 error("connect to %.100s port %d failed: %s", 3716 error("connect to %.100s port %d failed: %s",
3341 host, port, strerror(errno)); 3717 name, port, strerror(errno));
3342 channel_connect_ctx_free(&cctx); 3718 channel_connect_ctx_free(&cctx);
3343 return NULL; 3719 return NULL;
3344 } 3720 }
@@ -3349,13 +3725,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
3349} 3725}
3350 3726
3351Channel * 3727Channel *
3352channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) 3728channel_connect_by_listen_address(const char *listen_host,
3729 u_short listen_port, char *ctype, char *rname)
3353{ 3730{
3354 int i; 3731 int i;
3355 3732
3356 for (i = 0; i < num_permitted_opens; i++) { 3733 for (i = 0; i < num_permitted_opens; i++) {
3357 if (permitted_opens[i].host_to_connect != NULL && 3734 if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
3358 port_match(permitted_opens[i].listen_port, listen_port)) { 3735 listen_port, 1)) {
3359 return connect_to( 3736 return connect_to(
3360 permitted_opens[i].host_to_connect, 3737 permitted_opens[i].host_to_connect,
3361 permitted_opens[i].port_to_connect, ctype, rname); 3738 permitted_opens[i].port_to_connect, ctype, rname);
@@ -3366,29 +3743,45 @@ channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
3366 return NULL; 3743 return NULL;
3367} 3744}
3368 3745
3746Channel *
3747channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
3748{
3749 int i;
3750
3751 for (i = 0; i < num_permitted_opens; i++) {
3752 if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
3753 return connect_to(
3754 permitted_opens[i].host_to_connect,
3755 permitted_opens[i].port_to_connect, ctype, rname);
3756 }
3757 }
3758 error("WARNING: Server requests forwarding for unknown path %.100s",
3759 path);
3760 return NULL;
3761}
3762
3369/* Check if connecting to that port is permitted and connect. */ 3763/* Check if connecting to that port is permitted and connect. */
3370Channel * 3764Channel *
3371channel_connect_to(const char *host, u_short port, char *ctype, char *rname) 3765channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
3372{ 3766{
3373 int i, permit, permit_adm = 1; 3767 int i, permit, permit_adm = 1;
3374 3768
3375 permit = all_opens_permitted; 3769 permit = all_opens_permitted;
3376 if (!permit) { 3770 if (!permit) {
3377 for (i = 0; i < num_permitted_opens; i++) 3771 for (i = 0; i < num_permitted_opens; i++)
3378 if (permitted_opens[i].host_to_connect != NULL && 3772 if (open_match(&permitted_opens[i], host, port)) {
3379 port_match(permitted_opens[i].port_to_connect, port) &&
3380 strcmp(permitted_opens[i].host_to_connect, host) == 0)
3381 permit = 1; 3773 permit = 1;
3774 break;
3775 }
3382 } 3776 }
3383 3777
3384 if (num_adm_permitted_opens > 0) { 3778 if (num_adm_permitted_opens > 0) {
3385 permit_adm = 0; 3779 permit_adm = 0;
3386 for (i = 0; i < num_adm_permitted_opens; i++) 3780 for (i = 0; i < num_adm_permitted_opens; i++)
3387 if (permitted_adm_opens[i].host_to_connect != NULL && 3781 if (open_match(&permitted_adm_opens[i], host, port)) {
3388 port_match(permitted_adm_opens[i].port_to_connect, port) &&
3389 strcmp(permitted_adm_opens[i].host_to_connect, host)
3390 == 0)
3391 permit_adm = 1; 3782 permit_adm = 1;
3783 break;
3784 }
3392 } 3785 }
3393 3786
3394 if (!permit || !permit_adm) { 3787 if (!permit || !permit_adm) {
@@ -3399,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
3399 return connect_to(host, port, ctype, rname); 3792 return connect_to(host, port, ctype, rname);
3400} 3793}
3401 3794
3795/* Check if connecting to that path is permitted and connect. */
3796Channel *
3797channel_connect_to_path(const char *path, char *ctype, char *rname)
3798{
3799 int i, permit, permit_adm = 1;
3800
3801 permit = all_opens_permitted;
3802 if (!permit) {
3803 for (i = 0; i < num_permitted_opens; i++)
3804 if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
3805 permit = 1;
3806 break;
3807 }
3808 }
3809
3810 if (num_adm_permitted_opens > 0) {
3811 permit_adm = 0;
3812 for (i = 0; i < num_adm_permitted_opens; i++)
3813 if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
3814 permit_adm = 1;
3815 break;
3816 }
3817 }
3818
3819 if (!permit || !permit_adm) {
3820 logit("Received request to connect to path %.100s, "
3821 "but the request was denied.", path);
3822 return NULL;
3823 }
3824 return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
3825}
3826
3402void 3827void
3403channel_send_window_changes(void) 3828channel_send_window_changes(void)
3404{ 3829{