diff options
author | Damien Miller <djm@mindrot.org> | 2014-07-18 14:11:24 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-07-18 14:11:24 +1000 |
commit | 7acefbbcbeab725420ea07397ae35992f505f702 (patch) | |
tree | bfb07917715d425438dab987a47ccd7a8d7f118b /readconf.c | |
parent | 6262d760e00714523633bd989d62e273a3dca99a (diff) |
- millert@cvs.openbsd.org 2014/07/15 15:54:14
[PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
[auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
[auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
[clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
[readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
[ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
[sshd_config.5 sshlogin.c]
Add support for Unix domain socket forwarding. A remote TCP port
may be forwarded to a local Unix domain socket and vice versa or
both ends may be a Unix domain socket. This is a reimplementation
of the streamlocal patches by William Ahern from:
http://www.25thandclement.com/~william/projects/streamlocal.html
OK djm@ markus@
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 224 |
1 files changed, 186 insertions, 38 deletions
diff --git a/readconf.c b/readconf.c index a4ecf7a0b..7948ce1cd 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.219 2014/04/23 12:42:34 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.220 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 |
@@ -18,6 +18,7 @@ | |||
18 | #include <sys/stat.h> | 18 | #include <sys/stat.h> |
19 | #include <sys/socket.h> | 19 | #include <sys/socket.h> |
20 | #include <sys/wait.h> | 20 | #include <sys/wait.h> |
21 | #include <sys/un.h> | ||
21 | 22 | ||
22 | #include <netinet/in.h> | 23 | #include <netinet/in.h> |
23 | #include <netinet/in_systm.h> | 24 | #include <netinet/in_systm.h> |
@@ -48,9 +49,9 @@ | |||
48 | #include "pathnames.h" | 49 | #include "pathnames.h" |
49 | #include "log.h" | 50 | #include "log.h" |
50 | #include "key.h" | 51 | #include "key.h" |
52 | #include "misc.h" | ||
51 | #include "readconf.h" | 53 | #include "readconf.h" |
52 | #include "match.h" | 54 | #include "match.h" |
53 | #include "misc.h" | ||
54 | #include "buffer.h" | 55 | #include "buffer.h" |
55 | #include "kex.h" | 56 | #include "kex.h" |
56 | #include "mac.h" | 57 | #include "mac.h" |
@@ -149,6 +150,7 @@ typedef enum { | |||
149 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, | 150 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
150 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, | 151 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
151 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 152 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
153 | oStreamLocalBindMask, oStreamLocalBindUnlink, | ||
152 | oIgnoredUnknownOption, oDeprecated, oUnsupported | 154 | oIgnoredUnknownOption, oDeprecated, oUnsupported |
153 | } OpCodes; | 155 | } OpCodes; |
154 | 156 | ||
@@ -261,6 +263,8 @@ static struct { | |||
261 | { "canonicalizehostname", oCanonicalizeHostname }, | 263 | { "canonicalizehostname", oCanonicalizeHostname }, |
262 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, | 264 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, |
263 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, | 265 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, |
266 | { "streamlocalbindmask", oStreamLocalBindMask }, | ||
267 | { "streamlocalbindunlink", oStreamLocalBindUnlink }, | ||
264 | { "ignoreunknown", oIgnoreUnknown }, | 268 | { "ignoreunknown", oIgnoreUnknown }, |
265 | 269 | ||
266 | { NULL, oBadOption } | 270 | { NULL, oBadOption } |
@@ -272,12 +276,13 @@ static struct { | |||
272 | */ | 276 | */ |
273 | 277 | ||
274 | void | 278 | void |
275 | add_local_forward(Options *options, const Forward *newfwd) | 279 | add_local_forward(Options *options, const struct Forward *newfwd) |
276 | { | 280 | { |
277 | Forward *fwd; | 281 | struct Forward *fwd; |
278 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 282 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
279 | extern uid_t original_real_uid; | 283 | extern uid_t original_real_uid; |
280 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) | 284 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 && |
285 | newfwd->listen_path == NULL) | ||
281 | fatal("Privileged ports can only be forwarded by root."); | 286 | fatal("Privileged ports can only be forwarded by root."); |
282 | #endif | 287 | #endif |
283 | options->local_forwards = xrealloc(options->local_forwards, | 288 | options->local_forwards = xrealloc(options->local_forwards, |
@@ -287,8 +292,10 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
287 | 292 | ||
288 | fwd->listen_host = newfwd->listen_host; | 293 | fwd->listen_host = newfwd->listen_host; |
289 | fwd->listen_port = newfwd->listen_port; | 294 | fwd->listen_port = newfwd->listen_port; |
295 | fwd->listen_path = newfwd->listen_path; | ||
290 | fwd->connect_host = newfwd->connect_host; | 296 | fwd->connect_host = newfwd->connect_host; |
291 | fwd->connect_port = newfwd->connect_port; | 297 | fwd->connect_port = newfwd->connect_port; |
298 | fwd->connect_path = newfwd->connect_path; | ||
292 | } | 299 | } |
293 | 300 | ||
294 | /* | 301 | /* |
@@ -297,9 +304,9 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
297 | */ | 304 | */ |
298 | 305 | ||
299 | void | 306 | void |
300 | add_remote_forward(Options *options, const Forward *newfwd) | 307 | add_remote_forward(Options *options, const struct Forward *newfwd) |
301 | { | 308 | { |
302 | Forward *fwd; | 309 | struct Forward *fwd; |
303 | 310 | ||
304 | options->remote_forwards = xrealloc(options->remote_forwards, | 311 | options->remote_forwards = xrealloc(options->remote_forwards, |
305 | options->num_remote_forwards + 1, | 312 | options->num_remote_forwards + 1, |
@@ -308,8 +315,10 @@ add_remote_forward(Options *options, const Forward *newfwd) | |||
308 | 315 | ||
309 | fwd->listen_host = newfwd->listen_host; | 316 | fwd->listen_host = newfwd->listen_host; |
310 | fwd->listen_port = newfwd->listen_port; | 317 | fwd->listen_port = newfwd->listen_port; |
318 | fwd->listen_path = newfwd->listen_path; | ||
311 | fwd->connect_host = newfwd->connect_host; | 319 | fwd->connect_host = newfwd->connect_host; |
312 | fwd->connect_port = newfwd->connect_port; | 320 | fwd->connect_port = newfwd->connect_port; |
321 | fwd->connect_path = newfwd->connect_path; | ||
313 | fwd->handle = newfwd->handle; | 322 | fwd->handle = newfwd->handle; |
314 | fwd->allocated_port = 0; | 323 | fwd->allocated_port = 0; |
315 | } | 324 | } |
@@ -321,7 +330,9 @@ clear_forwardings(Options *options) | |||
321 | 330 | ||
322 | for (i = 0; i < options->num_local_forwards; i++) { | 331 | for (i = 0; i < options->num_local_forwards; i++) { |
323 | free(options->local_forwards[i].listen_host); | 332 | free(options->local_forwards[i].listen_host); |
333 | free(options->local_forwards[i].listen_path); | ||
324 | free(options->local_forwards[i].connect_host); | 334 | free(options->local_forwards[i].connect_host); |
335 | free(options->local_forwards[i].connect_path); | ||
325 | } | 336 | } |
326 | if (options->num_local_forwards > 0) { | 337 | if (options->num_local_forwards > 0) { |
327 | free(options->local_forwards); | 338 | free(options->local_forwards); |
@@ -330,7 +341,9 @@ clear_forwardings(Options *options) | |||
330 | options->num_local_forwards = 0; | 341 | options->num_local_forwards = 0; |
331 | for (i = 0; i < options->num_remote_forwards; i++) { | 342 | for (i = 0; i < options->num_remote_forwards; i++) { |
332 | free(options->remote_forwards[i].listen_host); | 343 | free(options->remote_forwards[i].listen_host); |
344 | free(options->remote_forwards[i].listen_path); | ||
333 | free(options->remote_forwards[i].connect_host); | 345 | free(options->remote_forwards[i].connect_host); |
346 | free(options->remote_forwards[i].connect_path); | ||
334 | } | 347 | } |
335 | if (options->num_remote_forwards > 0) { | 348 | if (options->num_remote_forwards > 0) { |
336 | free(options->remote_forwards); | 349 | free(options->remote_forwards); |
@@ -715,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
715 | LogLevel *log_level_ptr; | 728 | LogLevel *log_level_ptr; |
716 | long long val64; | 729 | long long val64; |
717 | size_t len; | 730 | size_t len; |
718 | Forward fwd; | 731 | struct Forward fwd; |
719 | const struct multistate *multistate_ptr; | 732 | const struct multistate *multistate_ptr; |
720 | struct allowed_cname *cname; | 733 | struct allowed_cname *cname; |
721 | 734 | ||
@@ -805,7 +818,7 @@ parse_time: | |||
805 | goto parse_time; | 818 | goto parse_time; |
806 | 819 | ||
807 | case oGatewayPorts: | 820 | case oGatewayPorts: |
808 | intptr = &options->gateway_ports; | 821 | intptr = &options->fwd_opts.gateway_ports; |
809 | goto parse_flag; | 822 | goto parse_flag; |
810 | 823 | ||
811 | case oExitOnForwardFailure: | 824 | case oExitOnForwardFailure: |
@@ -1405,6 +1418,21 @@ parse_int: | |||
1405 | intptr = &options->canonicalize_fallback_local; | 1418 | intptr = &options->canonicalize_fallback_local; |
1406 | goto parse_flag; | 1419 | goto parse_flag; |
1407 | 1420 | ||
1421 | case oStreamLocalBindMask: | ||
1422 | arg = strdelim(&s); | ||
1423 | if (!arg || *arg == '\0') | ||
1424 | fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); | ||
1425 | /* Parse mode in octal format */ | ||
1426 | value = strtol(arg, &endofnumber, 8); | ||
1427 | if (arg == endofnumber || value < 0 || value > 0777) | ||
1428 | fatal("%.200s line %d: Bad mask.", filename, linenum); | ||
1429 | options->fwd_opts.streamlocal_bind_mask = (mode_t)value; | ||
1430 | break; | ||
1431 | |||
1432 | case oStreamLocalBindUnlink: | ||
1433 | intptr = &options->fwd_opts.streamlocal_bind_unlink; | ||
1434 | goto parse_flag; | ||
1435 | |||
1408 | case oDeprecated: | 1436 | case oDeprecated: |
1409 | debug("%s line %d: Deprecated option \"%s\"", | 1437 | debug("%s line %d: Deprecated option \"%s\"", |
1410 | filename, linenum, keyword); | 1438 | filename, linenum, keyword); |
@@ -1502,7 +1530,9 @@ initialize_options(Options * options) | |||
1502 | options->forward_x11_timeout = -1; | 1530 | options->forward_x11_timeout = -1; |
1503 | options->exit_on_forward_failure = -1; | 1531 | options->exit_on_forward_failure = -1; |
1504 | options->xauth_location = NULL; | 1532 | options->xauth_location = NULL; |
1505 | options->gateway_ports = -1; | 1533 | options->fwd_opts.gateway_ports = -1; |
1534 | options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; | ||
1535 | options->fwd_opts.streamlocal_bind_unlink = -1; | ||
1506 | options->use_privileged_port = -1; | 1536 | options->use_privileged_port = -1; |
1507 | options->rsa_authentication = -1; | 1537 | options->rsa_authentication = -1; |
1508 | options->pubkey_authentication = -1; | 1538 | options->pubkey_authentication = -1; |
@@ -1615,8 +1645,12 @@ fill_default_options(Options * options) | |||
1615 | options->exit_on_forward_failure = 0; | 1645 | options->exit_on_forward_failure = 0; |
1616 | if (options->xauth_location == NULL) | 1646 | if (options->xauth_location == NULL) |
1617 | options->xauth_location = _PATH_XAUTH; | 1647 | options->xauth_location = _PATH_XAUTH; |
1618 | if (options->gateway_ports == -1) | 1648 | if (options->fwd_opts.gateway_ports == -1) |
1619 | options->gateway_ports = 0; | 1649 | options->fwd_opts.gateway_ports = 0; |
1650 | if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) | ||
1651 | options->fwd_opts.streamlocal_bind_mask = 0177; | ||
1652 | if (options->fwd_opts.streamlocal_bind_unlink == -1) | ||
1653 | options->fwd_opts.streamlocal_bind_unlink = 0; | ||
1620 | if (options->use_privileged_port == -1) | 1654 | if (options->use_privileged_port == -1) |
1621 | options->use_privileged_port = 0; | 1655 | options->use_privileged_port = 0; |
1622 | if (options->rsa_authentication == -1) | 1656 | if (options->rsa_authentication == -1) |
@@ -1768,22 +1802,92 @@ fill_default_options(Options * options) | |||
1768 | /* options->preferred_authentications will be set in ssh */ | 1802 | /* options->preferred_authentications will be set in ssh */ |
1769 | } | 1803 | } |
1770 | 1804 | ||
1805 | struct fwdarg { | ||
1806 | char *arg; | ||
1807 | int ispath; | ||
1808 | }; | ||
1809 | |||
1810 | /* | ||
1811 | * parse_fwd_field | ||
1812 | * parses the next field in a port forwarding specification. | ||
1813 | * sets fwd to the parsed field and advances p past the colon | ||
1814 | * or sets it to NULL at end of string. | ||
1815 | * returns 0 on success, else non-zero. | ||
1816 | */ | ||
1817 | static int | ||
1818 | parse_fwd_field(char **p, struct fwdarg *fwd) | ||
1819 | { | ||
1820 | char *ep, *cp = *p; | ||
1821 | int ispath = 0; | ||
1822 | |||
1823 | if (*cp == '\0') { | ||
1824 | *p = NULL; | ||
1825 | return -1; /* end of string */ | ||
1826 | } | ||
1827 | |||
1828 | /* | ||
1829 | * A field escaped with square brackets is used literally. | ||
1830 | * XXX - allow ']' to be escaped via backslash? | ||
1831 | */ | ||
1832 | if (*cp == '[') { | ||
1833 | /* find matching ']' */ | ||
1834 | for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { | ||
1835 | if (*ep == '/') | ||
1836 | ispath = 1; | ||
1837 | } | ||
1838 | /* no matching ']' or not at end of field. */ | ||
1839 | if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) | ||
1840 | return -1; | ||
1841 | /* NUL terminate the field and advance p past the colon */ | ||
1842 | *ep++ = '\0'; | ||
1843 | if (*ep != '\0') | ||
1844 | *ep++ = '\0'; | ||
1845 | fwd->arg = cp + 1; | ||
1846 | fwd->ispath = ispath; | ||
1847 | *p = ep; | ||
1848 | return 0; | ||
1849 | } | ||
1850 | |||
1851 | for (cp = *p; *cp != '\0'; cp++) { | ||
1852 | switch (*cp) { | ||
1853 | case '\\': | ||
1854 | memmove(cp, cp + 1, strlen(cp + 1) + 1); | ||
1855 | cp++; | ||
1856 | break; | ||
1857 | case '/': | ||
1858 | ispath = 1; | ||
1859 | break; | ||
1860 | case ':': | ||
1861 | *cp++ = '\0'; | ||
1862 | goto done; | ||
1863 | } | ||
1864 | } | ||
1865 | done: | ||
1866 | fwd->arg = *p; | ||
1867 | fwd->ispath = ispath; | ||
1868 | *p = cp; | ||
1869 | return 0; | ||
1870 | } | ||
1871 | |||
1771 | /* | 1872 | /* |
1772 | * parse_forward | 1873 | * parse_forward |
1773 | * parses a string containing a port forwarding specification of the form: | 1874 | * parses a string containing a port forwarding specification of the form: |
1774 | * dynamicfwd == 0 | 1875 | * dynamicfwd == 0 |
1775 | * [listenhost:]listenport:connecthost:connectport | 1876 | * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath |
1877 | * listenpath:connectpath | ||
1776 | * dynamicfwd == 1 | 1878 | * dynamicfwd == 1 |
1777 | * [listenhost:]listenport | 1879 | * [listenhost:]listenport |
1778 | * returns number of arguments parsed or zero on error | 1880 | * returns number of arguments parsed or zero on error |
1779 | */ | 1881 | */ |
1780 | int | 1882 | int |
1781 | parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | 1883 | parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) |
1782 | { | 1884 | { |
1885 | struct fwdarg fwdargs[4]; | ||
1886 | char *p, *cp; | ||
1783 | int i; | 1887 | int i; |
1784 | char *p, *cp, *fwdarg[4]; | ||
1785 | 1888 | ||
1786 | memset(fwd, '\0', sizeof(*fwd)); | 1889 | memset(fwd, 0, sizeof(*fwd)); |
1890 | memset(fwdargs, 0, sizeof(fwdargs)); | ||
1787 | 1891 | ||
1788 | cp = p = xstrdup(fwdspec); | 1892 | cp = p = xstrdup(fwdspec); |
1789 | 1893 | ||
@@ -1791,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1791 | while (isspace((u_char)*cp)) | 1895 | while (isspace((u_char)*cp)) |
1792 | cp++; | 1896 | cp++; |
1793 | 1897 | ||
1794 | for (i = 0; i < 4; ++i) | 1898 | for (i = 0; i < 4; ++i) { |
1795 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | 1899 | if (parse_fwd_field(&cp, &fwdargs[i]) != 0) |
1796 | break; | 1900 | break; |
1901 | } | ||
1797 | 1902 | ||
1798 | /* Check for trailing garbage */ | 1903 | /* Check for trailing garbage */ |
1799 | if (cp != NULL) | 1904 | if (cp != NULL && *cp != '\0') { |
1800 | i = 0; /* failure */ | 1905 | i = 0; /* failure */ |
1906 | } | ||
1801 | 1907 | ||
1802 | switch (i) { | 1908 | switch (i) { |
1803 | case 1: | 1909 | case 1: |
1804 | fwd->listen_host = NULL; | 1910 | if (fwdargs[0].ispath) { |
1805 | fwd->listen_port = a2port(fwdarg[0]); | 1911 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1912 | fwd->listen_port = PORT_STREAMLOCAL; | ||
1913 | } else { | ||
1914 | fwd->listen_host = NULL; | ||
1915 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1916 | } | ||
1806 | fwd->connect_host = xstrdup("socks"); | 1917 | fwd->connect_host = xstrdup("socks"); |
1807 | break; | 1918 | break; |
1808 | 1919 | ||
1809 | case 2: | 1920 | case 2: |
1810 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1921 | if (fwdargs[0].ispath && fwdargs[1].ispath) { |
1811 | fwd->listen_port = a2port(fwdarg[1]); | 1922 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1812 | fwd->connect_host = xstrdup("socks"); | 1923 | fwd->listen_port = PORT_STREAMLOCAL; |
1924 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1925 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1926 | } else if (fwdargs[1].ispath) { | ||
1927 | fwd->listen_host = NULL; | ||
1928 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1929 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1930 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1931 | } else { | ||
1932 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
1933 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
1934 | fwd->connect_host = xstrdup("socks"); | ||
1935 | } | ||
1813 | break; | 1936 | break; |
1814 | 1937 | ||
1815 | case 3: | 1938 | case 3: |
1816 | fwd->listen_host = NULL; | 1939 | if (fwdargs[0].ispath) { |
1817 | fwd->listen_port = a2port(fwdarg[0]); | 1940 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1818 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | 1941 | fwd->listen_port = PORT_STREAMLOCAL; |
1819 | fwd->connect_port = a2port(fwdarg[2]); | 1942 | fwd->connect_host = xstrdup(fwdargs[1].arg); |
1943 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
1944 | } else if (fwdargs[2].ispath) { | ||
1945 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
1946 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
1947 | fwd->connect_path = xstrdup(fwdargs[2].arg); | ||
1948 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1949 | } else { | ||
1950 | fwd->listen_host = NULL; | ||
1951 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1952 | fwd->connect_host = xstrdup(fwdargs[1].arg); | ||
1953 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
1954 | } | ||
1820 | break; | 1955 | break; |
1821 | 1956 | ||
1822 | case 4: | 1957 | case 4: |
1823 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1958 | fwd->listen_host = xstrdup(fwdargs[0].arg); |
1824 | fwd->listen_port = a2port(fwdarg[1]); | 1959 | fwd->listen_port = a2port(fwdargs[1].arg); |
1825 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | 1960 | fwd->connect_host = xstrdup(fwdargs[2].arg); |
1826 | fwd->connect_port = a2port(fwdarg[3]); | 1961 | fwd->connect_port = a2port(fwdargs[3].arg); |
1827 | break; | 1962 | break; |
1828 | default: | 1963 | default: |
1829 | i = 0; /* failure */ | 1964 | i = 0; /* failure */ |
@@ -1835,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1835 | if (!(i == 1 || i == 2)) | 1970 | if (!(i == 1 || i == 2)) |
1836 | goto fail_free; | 1971 | goto fail_free; |
1837 | } else { | 1972 | } else { |
1838 | if (!(i == 3 || i == 4)) | 1973 | if (!(i == 3 || i == 4)) { |
1839 | goto fail_free; | 1974 | if (fwd->connect_path == NULL && |
1840 | if (fwd->connect_port <= 0) | 1975 | fwd->listen_path == NULL) |
1976 | goto fail_free; | ||
1977 | } | ||
1978 | if (fwd->connect_port <= 0 && fwd->connect_path == NULL) | ||
1841 | goto fail_free; | 1979 | goto fail_free; |
1842 | } | 1980 | } |
1843 | 1981 | ||
1844 | if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) | 1982 | if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || |
1983 | (!remotefwd && fwd->listen_port == 0)) | ||
1845 | goto fail_free; | 1984 | goto fail_free; |
1846 | |||
1847 | if (fwd->connect_host != NULL && | 1985 | if (fwd->connect_host != NULL && |
1848 | strlen(fwd->connect_host) >= NI_MAXHOST) | 1986 | strlen(fwd->connect_host) >= NI_MAXHOST) |
1849 | goto fail_free; | 1987 | goto fail_free; |
1988 | /* XXX - if connecting to a remote socket, max sun len may not match this host */ | ||
1989 | if (fwd->connect_path != NULL && | ||
1990 | strlen(fwd->connect_path) >= PATH_MAX_SUN) | ||
1991 | goto fail_free; | ||
1850 | if (fwd->listen_host != NULL && | 1992 | if (fwd->listen_host != NULL && |
1851 | strlen(fwd->listen_host) >= NI_MAXHOST) | 1993 | strlen(fwd->listen_host) >= NI_MAXHOST) |
1852 | goto fail_free; | 1994 | goto fail_free; |
1853 | 1995 | if (fwd->listen_path != NULL && | |
1996 | strlen(fwd->listen_path) >= PATH_MAX_SUN) | ||
1997 | goto fail_free; | ||
1854 | 1998 | ||
1855 | return (i); | 1999 | return (i); |
1856 | 2000 | ||
1857 | fail_free: | 2001 | fail_free: |
1858 | free(fwd->connect_host); | 2002 | free(fwd->connect_host); |
1859 | fwd->connect_host = NULL; | 2003 | fwd->connect_host = NULL; |
2004 | free(fwd->connect_path); | ||
2005 | fwd->connect_path = NULL; | ||
1860 | free(fwd->listen_host); | 2006 | free(fwd->listen_host); |
1861 | fwd->listen_host = NULL; | 2007 | fwd->listen_host = NULL; |
2008 | free(fwd->listen_path); | ||
2009 | fwd->listen_path = NULL; | ||
1862 | return (0); | 2010 | return (0); |
1863 | } | 2011 | } |