summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2014-10-07 13:33:15 +0100
committerColin Watson <cjwatson@debian.org>2014-10-07 14:27:30 +0100
commitf0b009aea83e9ff3a50be30f51012099a5143c16 (patch)
tree3825e6f7e3b7ea4481d06ed89aba9a7a95150df5 /channels.c
parent47f0bad4330b16ec3bad870fcf9839c196e42c12 (diff)
parent762c062828f5a8f6ed189ed6e44ad38fd92f8b36 (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 '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{