diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 139 |
1 files changed, 79 insertions, 60 deletions
diff --git a/channels.c b/channels.c index bb872dc94..941556ace 100644 --- a/channels.c +++ b/channels.c | |||
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: channels.c,v 1.98 2001/03/04 17:42:28 millert Exp $"); | 43 | RCSID("$OpenBSD: channels.c,v 1.99 2001/03/16 19:06:29 markus Exp $"); |
44 | 44 | ||
45 | #include <openssl/rsa.h> | 45 | #include <openssl/rsa.h> |
46 | #include <openssl/dsa.h> | 46 | #include <openssl/dsa.h> |
@@ -141,18 +141,6 @@ channel_set_options(int hostname_in_open) | |||
141 | have_hostname_in_open = hostname_in_open; | 141 | have_hostname_in_open = hostname_in_open; |
142 | } | 142 | } |
143 | 143 | ||
144 | /* | ||
145 | * Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually | ||
146 | * called by the server, because the user could connect to any port anyway, | ||
147 | * and the server has no way to know but to trust the client anyway. | ||
148 | */ | ||
149 | |||
150 | void | ||
151 | channel_permit_all_opens() | ||
152 | { | ||
153 | all_opens_permitted = 1; | ||
154 | } | ||
155 | |||
156 | /* lookup channel by id */ | 144 | /* lookup channel by id */ |
157 | 145 | ||
158 | Channel * | 146 | Channel * |
@@ -1791,9 +1779,47 @@ channel_input_port_forward_request(int is_root, int gateway_ports) | |||
1791 | xfree(hostname); | 1779 | xfree(hostname); |
1792 | } | 1780 | } |
1793 | 1781 | ||
1794 | /* XXX move to aux.c */ | 1782 | /* |
1783 | * Permits opening to any host/port if permitted_opens[] is empty. This is | ||
1784 | * usually called by the server, because the user could connect to any port | ||
1785 | * anyway, and the server has no way to know but to trust the client anyway. | ||
1786 | */ | ||
1787 | void | ||
1788 | channel_permit_all_opens() | ||
1789 | { | ||
1790 | if (num_permitted_opens == 0) | ||
1791 | all_opens_permitted = 1; | ||
1792 | } | ||
1793 | |||
1794 | void | ||
1795 | channel_add_permitted_opens(char *host, int port) | ||
1796 | { | ||
1797 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) | ||
1798 | fatal("channel_request_remote_forwarding: too many forwards"); | ||
1799 | debug("allow port forwarding to host %s port %d", host, port); | ||
1800 | |||
1801 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); | ||
1802 | permitted_opens[num_permitted_opens].port_to_connect = port; | ||
1803 | num_permitted_opens++; | ||
1804 | |||
1805 | all_opens_permitted = 0; | ||
1806 | } | ||
1807 | |||
1808 | void | ||
1809 | channel_clear_permitted_opens(void) | ||
1810 | { | ||
1811 | int i; | ||
1812 | |||
1813 | for (i = 0; i < num_permitted_opens; i++) | ||
1814 | xfree(permitted_opens[i].host_to_connect); | ||
1815 | num_permitted_opens = 0; | ||
1816 | |||
1817 | } | ||
1818 | |||
1819 | |||
1820 | /* return socket to remote host, port */ | ||
1795 | int | 1821 | int |
1796 | channel_connect_to(const char *host, u_short host_port) | 1822 | connect_to(const char *host, u_short port) |
1797 | { | 1823 | { |
1798 | struct addrinfo hints, *ai, *aitop; | 1824 | struct addrinfo hints, *ai, *aitop; |
1799 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 1825 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
@@ -1803,9 +1829,10 @@ channel_connect_to(const char *host, u_short host_port) | |||
1803 | memset(&hints, 0, sizeof(hints)); | 1829 | memset(&hints, 0, sizeof(hints)); |
1804 | hints.ai_family = IPv4or6; | 1830 | hints.ai_family = IPv4or6; |
1805 | hints.ai_socktype = SOCK_STREAM; | 1831 | hints.ai_socktype = SOCK_STREAM; |
1806 | snprintf(strport, sizeof strport, "%d", host_port); | 1832 | snprintf(strport, sizeof strport, "%d", port); |
1807 | if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { | 1833 | if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { |
1808 | error("%.100s: unknown host (%s)", host, gai_strerror(gaierr)); | 1834 | error("connect_to %.100s: unknown host (%s)", host, |
1835 | gai_strerror(gaierr)); | ||
1809 | return -1; | 1836 | return -1; |
1810 | } | 1837 | } |
1811 | for (ai = aitop; ai; ai = ai->ai_next) { | 1838 | for (ai = aitop; ai; ai = ai->ai_next) { |
@@ -1813,10 +1840,9 @@ channel_connect_to(const char *host, u_short host_port) | |||
1813 | continue; | 1840 | continue; |
1814 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 1841 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
1815 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 1842 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
1816 | error("channel_connect_to: getnameinfo failed"); | 1843 | error("connect_to: getnameinfo failed"); |
1817 | continue; | 1844 | continue; |
1818 | } | 1845 | } |
1819 | /* Create the socket. */ | ||
1820 | sock = socket(ai->ai_family, SOCK_STREAM, 0); | 1846 | sock = socket(ai->ai_family, SOCK_STREAM, 0); |
1821 | if (sock < 0) { | 1847 | if (sock < 0) { |
1822 | error("socket: %.100s", strerror(errno)); | 1848 | error("socket: %.100s", strerror(errno)); |
@@ -1824,10 +1850,9 @@ channel_connect_to(const char *host, u_short host_port) | |||
1824 | } | 1850 | } |
1825 | if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) | 1851 | if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) |
1826 | fatal("connect_to: F_SETFL: %s", strerror(errno)); | 1852 | fatal("connect_to: F_SETFL: %s", strerror(errno)); |
1827 | /* Connect to the host/port. */ | ||
1828 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && | 1853 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && |
1829 | errno != EINPROGRESS) { | 1854 | errno != EINPROGRESS) { |
1830 | error("connect %.100s port %s: %.100s", ntop, strport, | 1855 | error("connect_to %.100s port %s: %.100s", ntop, strport, |
1831 | strerror(errno)); | 1856 | strerror(errno)); |
1832 | close(sock); | 1857 | close(sock); |
1833 | continue; /* fail -- try next */ | 1858 | continue; /* fail -- try next */ |
@@ -1837,19 +1862,21 @@ channel_connect_to(const char *host, u_short host_port) | |||
1837 | } | 1862 | } |
1838 | freeaddrinfo(aitop); | 1863 | freeaddrinfo(aitop); |
1839 | if (!ai) { | 1864 | if (!ai) { |
1840 | error("connect %.100s port %d: failed.", host, host_port); | 1865 | error("connect_to %.100s port %d: failed.", host, port); |
1841 | return -1; | 1866 | return -1; |
1842 | } | 1867 | } |
1843 | /* success */ | 1868 | /* success */ |
1844 | return sock; | 1869 | return sock; |
1845 | } | 1870 | } |
1871 | |||
1846 | int | 1872 | int |
1847 | channel_connect_by_listen_adress(u_short listen_port) | 1873 | channel_connect_by_listen_adress(u_short listen_port) |
1848 | { | 1874 | { |
1849 | int i; | 1875 | int i; |
1876 | |||
1850 | for (i = 0; i < num_permitted_opens; i++) | 1877 | for (i = 0; i < num_permitted_opens; i++) |
1851 | if (permitted_opens[i].listen_port == listen_port) | 1878 | if (permitted_opens[i].listen_port == listen_port) |
1852 | return channel_connect_to( | 1879 | return connect_to( |
1853 | permitted_opens[i].host_to_connect, | 1880 | permitted_opens[i].host_to_connect, |
1854 | permitted_opens[i].port_to_connect); | 1881 | permitted_opens[i].port_to_connect); |
1855 | error("WARNING: Server requests forwarding for unknown listen_port %d", | 1882 | error("WARNING: Server requests forwarding for unknown listen_port %d", |
@@ -1857,6 +1884,28 @@ channel_connect_by_listen_adress(u_short listen_port) | |||
1857 | return -1; | 1884 | return -1; |
1858 | } | 1885 | } |
1859 | 1886 | ||
1887 | /* Check if connecting to that port is permitted and connect. */ | ||
1888 | int | ||
1889 | channel_connect_to(const char *host, u_short port) | ||
1890 | { | ||
1891 | int i, permit; | ||
1892 | |||
1893 | permit = all_opens_permitted; | ||
1894 | if (!permit) { | ||
1895 | for (i = 0; i < num_permitted_opens; i++) | ||
1896 | if (permitted_opens[i].port_to_connect == port && | ||
1897 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | ||
1898 | permit = 1; | ||
1899 | |||
1900 | } | ||
1901 | if (!permit) { | ||
1902 | log("Received request to connect to host %.100s port %d, " | ||
1903 | "but the request was denied.", host, port); | ||
1904 | return -1; | ||
1905 | } | ||
1906 | return connect_to(host, port); | ||
1907 | } | ||
1908 | |||
1860 | /* | 1909 | /* |
1861 | * This is called after receiving PORT_OPEN message. This attempts to | 1910 | * This is called after receiving PORT_OPEN message. This attempts to |
1862 | * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION | 1911 | * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION |
@@ -1868,55 +1917,25 @@ channel_input_port_open(int type, int plen, void *ctxt) | |||
1868 | { | 1917 | { |
1869 | u_short host_port; | 1918 | u_short host_port; |
1870 | char *host, *originator_string; | 1919 | char *host, *originator_string; |
1871 | int remote_channel, sock = -1, newch, i, denied; | 1920 | int remote_channel, sock = -1, newch; |
1872 | u_int host_len, originator_len; | ||
1873 | 1921 | ||
1874 | /* Get remote channel number. */ | ||
1875 | remote_channel = packet_get_int(); | 1922 | remote_channel = packet_get_int(); |
1876 | 1923 | host = packet_get_string(NULL); | |
1877 | /* Get host name to connect to. */ | ||
1878 | host = packet_get_string(&host_len); | ||
1879 | |||
1880 | /* Get port to connect to. */ | ||
1881 | host_port = packet_get_int(); | 1924 | host_port = packet_get_int(); |
1882 | 1925 | ||
1883 | /* Get remote originator name. */ | ||
1884 | if (have_hostname_in_open) { | 1926 | if (have_hostname_in_open) { |
1885 | originator_string = packet_get_string(&originator_len); | 1927 | originator_string = packet_get_string(NULL); |
1886 | originator_len += 4; /* size of packet_int */ | ||
1887 | } else { | 1928 | } else { |
1888 | originator_string = xstrdup("unknown (remote did not supply name)"); | 1929 | originator_string = xstrdup("unknown (remote did not supply name)"); |
1889 | originator_len = 0; /* no originator supplied */ | ||
1890 | } | ||
1891 | |||
1892 | packet_integrity_check(plen, | ||
1893 | 4 + 4 + host_len + 4 + originator_len, SSH_MSG_PORT_OPEN); | ||
1894 | |||
1895 | /* Check if opening that port is permitted. */ | ||
1896 | denied = 0; | ||
1897 | if (!all_opens_permitted) { | ||
1898 | /* Go trough all permitted ports. */ | ||
1899 | for (i = 0; i < num_permitted_opens; i++) | ||
1900 | if (permitted_opens[i].port_to_connect == host_port && | ||
1901 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | ||
1902 | break; | ||
1903 | |||
1904 | /* Check if we found the requested port among those permitted. */ | ||
1905 | if (i >= num_permitted_opens) { | ||
1906 | /* The port is not permitted. */ | ||
1907 | log("Received request to connect to %.100s:%d, but the request was denied.", | ||
1908 | host, host_port); | ||
1909 | denied = 1; | ||
1910 | } | ||
1911 | } | 1930 | } |
1912 | sock = denied ? -1 : channel_connect_to(host, host_port); | 1931 | packet_done(); |
1913 | if (sock > 0) { | 1932 | sock = channel_connect_to(host, host_port); |
1914 | /* Allocate a channel for this connection. */ | 1933 | if (sock != -1) { |
1915 | newch = channel_allocate(SSH_CHANNEL_CONNECTING, | 1934 | newch = channel_allocate(SSH_CHANNEL_CONNECTING, |
1916 | sock, originator_string); | 1935 | sock, originator_string); |
1917 | /*XXX delay answer? */ | ||
1918 | channels[newch].remote_id = remote_channel; | 1936 | channels[newch].remote_id = remote_channel; |
1919 | 1937 | ||
1938 | /*XXX delay answer? */ | ||
1920 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | 1939 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); |
1921 | packet_put_int(remote_channel); | 1940 | packet_put_int(remote_channel); |
1922 | packet_put_int(newch); | 1941 | packet_put_int(newch); |