diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | auth-options.c | 62 | ||||
-rw-r--r-- | channels.c | 139 | ||||
-rw-r--r-- | channels.h | 16 | ||||
-rw-r--r-- | serverloop.c | 8 | ||||
-rw-r--r-- | session.c | 11 |
6 files changed, 159 insertions, 83 deletions
@@ -18,6 +18,10 @@ | |||
18 | - markus@cvs.openbsd.org 2001/03/16 13:44:24 | 18 | - markus@cvs.openbsd.org 2001/03/16 13:44:24 |
19 | [sftp-int.c] | 19 | [sftp-int.c] |
20 | discourage strcat/strcpy | 20 | discourage strcat/strcpy |
21 | - markus@cvs.openbsd.org 2001/03/16 19:06:30 | ||
22 | [auth-options.c channels.c channels.h serverloop.c session.c] | ||
23 | implement "permitopen" key option, restricts -L style forwarding to | ||
24 | to specified host:port pairs. based on work by harlan@genua.de | ||
21 | 25 | ||
22 | 20010315 | 26 | 20010315 |
23 | - OpenBSD CVS Sync | 27 | - OpenBSD CVS Sync |
@@ -4580,4 +4584,4 @@ | |||
4580 | - Wrote replacements for strlcpy and mkdtemp | 4584 | - Wrote replacements for strlcpy and mkdtemp |
4581 | - Released 1.0pre1 | 4585 | - Released 1.0pre1 |
4582 | 4586 | ||
4583 | $Id: ChangeLog,v 1.966 2001/03/17 00:37:31 mouring Exp $ | 4587 | $Id: ChangeLog,v 1.967 2001/03/17 00:47:54 mouring Exp $ |
diff --git a/auth-options.c b/auth-options.c index bfb1af86b..7ce1e4b0c 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -10,13 +10,14 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "includes.h" | 12 | #include "includes.h" |
13 | RCSID("$OpenBSD: auth-options.c,v 1.14 2001/03/13 17:34:42 markus Exp $"); | 13 | RCSID("$OpenBSD: auth-options.c,v 1.15 2001/03/16 19:06:28 markus Exp $"); |
14 | 14 | ||
15 | #include "packet.h" | 15 | #include "packet.h" |
16 | #include "xmalloc.h" | 16 | #include "xmalloc.h" |
17 | #include "match.h" | 17 | #include "match.h" |
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "canohost.h" | 19 | #include "canohost.h" |
20 | #include "channels.h" | ||
20 | #include "auth-options.h" | 21 | #include "auth-options.h" |
21 | #include "servconf.h" | 22 | #include "servconf.h" |
22 | 23 | ||
@@ -51,6 +52,7 @@ auth_clear_options(void) | |||
51 | xfree(forced_command); | 52 | xfree(forced_command); |
52 | forced_command = NULL; | 53 | forced_command = NULL; |
53 | } | 54 | } |
55 | channel_clear_permitted_opens(); | ||
54 | } | 56 | } |
55 | 57 | ||
56 | /* | 58 | /* |
@@ -61,6 +63,7 @@ int | |||
61 | auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | 63 | auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) |
62 | { | 64 | { |
63 | const char *cp; | 65 | const char *cp; |
66 | int i; | ||
64 | 67 | ||
65 | /* reset options */ | 68 | /* reset options */ |
66 | auth_clear_options(); | 69 | auth_clear_options(); |
@@ -99,7 +102,6 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
99 | } | 102 | } |
100 | cp = "command=\""; | 103 | cp = "command=\""; |
101 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { | 104 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
102 | int i; | ||
103 | opts += strlen(cp); | 105 | opts += strlen(cp); |
104 | forced_command = xmalloc(strlen(opts) + 1); | 106 | forced_command = xmalloc(strlen(opts) + 1); |
105 | i = 0; | 107 | i = 0; |
@@ -129,9 +131,9 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
129 | } | 131 | } |
130 | cp = "environment=\""; | 132 | cp = "environment=\""; |
131 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { | 133 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
132 | int i; | ||
133 | char *s; | 134 | char *s; |
134 | struct envstring *new_envstring; | 135 | struct envstring *new_envstring; |
136 | |||
135 | opts += strlen(cp); | 137 | opts += strlen(cp); |
136 | s = xmalloc(strlen(opts) + 1); | 138 | s = xmalloc(strlen(opts) + 1); |
137 | i = 0; | 139 | i = 0; |
@@ -170,7 +172,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
170 | const char *remote_host = get_canonical_hostname( | 172 | const char *remote_host = get_canonical_hostname( |
171 | options.reverse_mapping_check); | 173 | options.reverse_mapping_check); |
172 | char *patterns = xmalloc(strlen(opts) + 1); | 174 | char *patterns = xmalloc(strlen(opts) + 1); |
173 | int i; | 175 | |
174 | opts += strlen(cp); | 176 | opts += strlen(cp); |
175 | i = 0; | 177 | i = 0; |
176 | while (*opts) { | 178 | while (*opts) { |
@@ -218,6 +220,58 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
218 | /* Host name matches. */ | 220 | /* Host name matches. */ |
219 | goto next_option; | 221 | goto next_option; |
220 | } | 222 | } |
223 | cp = "permitopen=\""; | ||
224 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { | ||
225 | u_short port; | ||
226 | char *c, *ep; | ||
227 | char *patterns = xmalloc(strlen(opts) + 1); | ||
228 | |||
229 | opts += strlen(cp); | ||
230 | i = 0; | ||
231 | while (*opts) { | ||
232 | if (*opts == '"') | ||
233 | break; | ||
234 | if (*opts == '\\' && opts[1] == '"') { | ||
235 | opts += 2; | ||
236 | patterns[i++] = '"'; | ||
237 | continue; | ||
238 | } | ||
239 | patterns[i++] = *opts++; | ||
240 | } | ||
241 | if (!*opts) { | ||
242 | debug("%.100s, line %lu: missing end quote", | ||
243 | file, linenum); | ||
244 | packet_send_debug("%.100s, line %lu: missing end quote", | ||
245 | file, linenum); | ||
246 | xfree(patterns); | ||
247 | goto bad_option; | ||
248 | } | ||
249 | patterns[i] = 0; | ||
250 | opts++; | ||
251 | c = strchr(patterns, ':'); | ||
252 | if (c == NULL) { | ||
253 | debug("%.100s, line %lu: permitopen: missing colon <%.100s>", | ||
254 | file, linenum, patterns); | ||
255 | packet_send_debug("%.100s, line %lu: missing colon", | ||
256 | file, linenum); | ||
257 | xfree(patterns); | ||
258 | goto bad_option; | ||
259 | } | ||
260 | *c = 0; | ||
261 | c++; | ||
262 | port = strtol(c, &ep, 0); | ||
263 | if (c == ep) { | ||
264 | debug("%.100s, line %lu: permitopen: missing port <%.100s>", | ||
265 | file, linenum, patterns); | ||
266 | packet_send_debug("%.100s, line %lu: missing port", | ||
267 | file, linenum); | ||
268 | xfree(patterns); | ||
269 | goto bad_option; | ||
270 | } | ||
271 | channel_add_permitted_opens(patterns, port); | ||
272 | xfree(patterns); | ||
273 | goto next_option; | ||
274 | } | ||
221 | next_option: | 275 | next_option: |
222 | /* | 276 | /* |
223 | * Skip the comma, and move to the next option | 277 | * Skip the comma, and move to the next option |
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); |
diff --git a/channels.h b/channels.h index f57029a14..493b04aa2 100644 --- a/channels.h +++ b/channels.h | |||
@@ -32,11 +32,13 @@ | |||
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | 34 | */ |
35 | /* RCSID("$OpenBSD: channels.h,v 1.27 2001/02/15 23:19:59 markus Exp $"); */ | 35 | /* RCSID("$OpenBSD: channels.h,v 1.28 2001/03/16 19:06:29 markus Exp $"); */ |
36 | 36 | ||
37 | #ifndef CHANNELS_H | 37 | #ifndef CHANNELS_H |
38 | #define CHANNELS_H | 38 | #define CHANNELS_H |
39 | 39 | ||
40 | #include "buffer.h" | ||
41 | |||
40 | /* Definitions for channel types. */ | 42 | /* Definitions for channel types. */ |
41 | #define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */ | 43 | #define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */ |
42 | #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ | 44 | #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ |
@@ -226,12 +228,18 @@ channel_request_remote_forwarding(u_short port, const char *host, | |||
226 | u_short remote_port); | 228 | u_short remote_port); |
227 | 229 | ||
228 | /* | 230 | /* |
229 | * Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually | 231 | * Permits opening to any host/port if permitted_opens[] is empty. This is |
230 | * called by the server, because the user could connect to any port anyway, | 232 | * usually called by the server, because the user could connect to any port |
231 | * and the server has no way to know but to trust the client anyway. | 233 | * anyway, and the server has no way to know but to trust the client anyway. |
232 | */ | 234 | */ |
233 | void channel_permit_all_opens(void); | 235 | void channel_permit_all_opens(void); |
234 | 236 | ||
237 | /* Add host/port to list of allowed targets for port forwarding */ | ||
238 | void channel_add_permitted_opens(char *host, int port); | ||
239 | |||
240 | /* Flush list */ | ||
241 | void channel_clear_permitted_opens(void); | ||
242 | |||
235 | /* | 243 | /* |
236 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates | 244 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates |
237 | * listening for the port, and sends back a success reply (or disconnect | 245 | * listening for the port, and sends back a success reply (or disconnect |
diff --git a/serverloop.c b/serverloop.c index 8b1ee9919..66bc52573 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.54 2001/03/04 01:46:30 djm Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.55 2001/03/16 19:06:29 markus Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "packet.h" | 41 | #include "packet.h" |
@@ -756,11 +756,6 @@ server_request_direct_tcpip(char *ctype) | |||
756 | originator, originator_port, target, target_port); | 756 | originator, originator_port, target, target_port); |
757 | 757 | ||
758 | /* XXX check permission */ | 758 | /* XXX check permission */ |
759 | if (no_port_forwarding_flag || !options.allow_tcp_forwarding) { | ||
760 | xfree(target); | ||
761 | xfree(originator); | ||
762 | return NULL; | ||
763 | } | ||
764 | sock = channel_connect_to(target, target_port); | 759 | sock = channel_connect_to(target, target_port); |
765 | xfree(target); | 760 | xfree(target); |
766 | xfree(originator); | 761 | xfree(originator); |
@@ -858,6 +853,7 @@ server_input_global_request(int type, int plen, void *ctxt) | |||
858 | want_reply = packet_get_char(); | 853 | want_reply = packet_get_char(); |
859 | debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); | 854 | debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); |
860 | 855 | ||
856 | /* -R style forwarding */ | ||
861 | if (strcmp(rtype, "tcpip-forward") == 0) { | 857 | if (strcmp(rtype, "tcpip-forward") == 0) { |
862 | struct passwd *pw; | 858 | struct passwd *pw; |
863 | char *listen_address; | 859 | char *listen_address; |
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "includes.h" | 35 | #include "includes.h" |
36 | RCSID("$OpenBSD: session.c,v 1.60 2001/03/15 22:07:08 markus Exp $"); | 36 | RCSID("$OpenBSD: session.c,v 1.61 2001/03/16 19:06:30 markus Exp $"); |
37 | 37 | ||
38 | #include "ssh.h" | 38 | #include "ssh.h" |
39 | #include "ssh1.h" | 39 | #include "ssh1.h" |
@@ -228,13 +228,6 @@ do_authenticated(struct passwd * pw) | |||
228 | startup_pipe = -1; | 228 | startup_pipe = -1; |
229 | } | 229 | } |
230 | 230 | ||
231 | /* | ||
232 | * Inform the channel mechanism that we are the server side and that | ||
233 | * the client may request to connect to any port at all. (The user | ||
234 | * could do it anyway, and we wouldn\'t know what is permitted except | ||
235 | * by the client telling us, so we can equally well trust the client | ||
236 | * not to request anything bogus.) | ||
237 | */ | ||
238 | if (!no_port_forwarding_flag && options.allow_tcp_forwarding) | 231 | if (!no_port_forwarding_flag && options.allow_tcp_forwarding) |
239 | channel_permit_all_opens(); | 232 | channel_permit_all_opens(); |
240 | 233 | ||
@@ -2037,6 +2030,8 @@ do_authenticated2(Authctxt *authctxt) | |||
2037 | close(startup_pipe); | 2030 | close(startup_pipe); |
2038 | startup_pipe = -1; | 2031 | startup_pipe = -1; |
2039 | } | 2032 | } |
2033 | if (!no_port_forwarding_flag && options.allow_tcp_forwarding) | ||
2034 | channel_permit_all_opens(); | ||
2040 | #if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) | 2035 | #if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) |
2041 | if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { | 2036 | if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { |
2042 | error("unable to get login class"); | 2037 | error("unable to get login class"); |