diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 235 |
1 files changed, 197 insertions, 38 deletions
diff --git a/readconf.c b/readconf.c index dc884c9b1..7948ce1cd 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 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); |
@@ -345,6 +358,7 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
345 | int userprovided) | 358 | int userprovided) |
346 | { | 359 | { |
347 | char *path; | 360 | char *path; |
361 | int i; | ||
348 | 362 | ||
349 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) | 363 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) |
350 | fatal("Too many identity files specified (max %d)", | 364 | fatal("Too many identity files specified (max %d)", |
@@ -355,6 +369,16 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
355 | else | 369 | else |
356 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); | 370 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); |
357 | 371 | ||
372 | /* Avoid registering duplicates */ | ||
373 | for (i = 0; i < options->num_identity_files; i++) { | ||
374 | if (options->identity_file_userprovided[i] == userprovided && | ||
375 | strcmp(options->identity_files[i], path) == 0) { | ||
376 | debug2("%s: ignoring duplicate key %s", __func__, path); | ||
377 | free(path); | ||
378 | return; | ||
379 | } | ||
380 | } | ||
381 | |||
358 | options->identity_file_userprovided[options->num_identity_files] = | 382 | options->identity_file_userprovided[options->num_identity_files] = |
359 | userprovided; | 383 | userprovided; |
360 | options->identity_files[options->num_identity_files++] = path; | 384 | options->identity_files[options->num_identity_files++] = path; |
@@ -704,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
704 | LogLevel *log_level_ptr; | 728 | LogLevel *log_level_ptr; |
705 | long long val64; | 729 | long long val64; |
706 | size_t len; | 730 | size_t len; |
707 | Forward fwd; | 731 | struct Forward fwd; |
708 | const struct multistate *multistate_ptr; | 732 | const struct multistate *multistate_ptr; |
709 | struct allowed_cname *cname; | 733 | struct allowed_cname *cname; |
710 | 734 | ||
@@ -794,7 +818,7 @@ parse_time: | |||
794 | goto parse_time; | 818 | goto parse_time; |
795 | 819 | ||
796 | case oGatewayPorts: | 820 | case oGatewayPorts: |
797 | intptr = &options->gateway_ports; | 821 | intptr = &options->fwd_opts.gateway_ports; |
798 | goto parse_flag; | 822 | goto parse_flag; |
799 | 823 | ||
800 | case oExitOnForwardFailure: | 824 | case oExitOnForwardFailure: |
@@ -1394,6 +1418,21 @@ parse_int: | |||
1394 | intptr = &options->canonicalize_fallback_local; | 1418 | intptr = &options->canonicalize_fallback_local; |
1395 | goto parse_flag; | 1419 | goto parse_flag; |
1396 | 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 | |||
1397 | case oDeprecated: | 1436 | case oDeprecated: |
1398 | debug("%s line %d: Deprecated option \"%s\"", | 1437 | debug("%s line %d: Deprecated option \"%s\"", |
1399 | filename, linenum, keyword); | 1438 | filename, linenum, keyword); |
@@ -1491,7 +1530,9 @@ initialize_options(Options * options) | |||
1491 | options->forward_x11_timeout = -1; | 1530 | options->forward_x11_timeout = -1; |
1492 | options->exit_on_forward_failure = -1; | 1531 | options->exit_on_forward_failure = -1; |
1493 | options->xauth_location = NULL; | 1532 | options->xauth_location = NULL; |
1494 | 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; | ||
1495 | options->use_privileged_port = -1; | 1536 | options->use_privileged_port = -1; |
1496 | options->rsa_authentication = -1; | 1537 | options->rsa_authentication = -1; |
1497 | options->pubkey_authentication = -1; | 1538 | options->pubkey_authentication = -1; |
@@ -1604,8 +1645,12 @@ fill_default_options(Options * options) | |||
1604 | options->exit_on_forward_failure = 0; | 1645 | options->exit_on_forward_failure = 0; |
1605 | if (options->xauth_location == NULL) | 1646 | if (options->xauth_location == NULL) |
1606 | options->xauth_location = _PATH_XAUTH; | 1647 | options->xauth_location = _PATH_XAUTH; |
1607 | if (options->gateway_ports == -1) | 1648 | if (options->fwd_opts.gateway_ports == -1) |
1608 | 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; | ||
1609 | if (options->use_privileged_port == -1) | 1654 | if (options->use_privileged_port == -1) |
1610 | options->use_privileged_port = 0; | 1655 | options->use_privileged_port = 0; |
1611 | if (options->rsa_authentication == -1) | 1656 | if (options->rsa_authentication == -1) |
@@ -1757,22 +1802,92 @@ fill_default_options(Options * options) | |||
1757 | /* options->preferred_authentications will be set in ssh */ | 1802 | /* options->preferred_authentications will be set in ssh */ |
1758 | } | 1803 | } |
1759 | 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 | |||
1760 | /* | 1872 | /* |
1761 | * parse_forward | 1873 | * parse_forward |
1762 | * parses a string containing a port forwarding specification of the form: | 1874 | * parses a string containing a port forwarding specification of the form: |
1763 | * dynamicfwd == 0 | 1875 | * dynamicfwd == 0 |
1764 | * [listenhost:]listenport:connecthost:connectport | 1876 | * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath |
1877 | * listenpath:connectpath | ||
1765 | * dynamicfwd == 1 | 1878 | * dynamicfwd == 1 |
1766 | * [listenhost:]listenport | 1879 | * [listenhost:]listenport |
1767 | * returns number of arguments parsed or zero on error | 1880 | * returns number of arguments parsed or zero on error |
1768 | */ | 1881 | */ |
1769 | int | 1882 | int |
1770 | parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | 1883 | parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) |
1771 | { | 1884 | { |
1885 | struct fwdarg fwdargs[4]; | ||
1886 | char *p, *cp; | ||
1772 | int i; | 1887 | int i; |
1773 | char *p, *cp, *fwdarg[4]; | ||
1774 | 1888 | ||
1775 | memset(fwd, '\0', sizeof(*fwd)); | 1889 | memset(fwd, 0, sizeof(*fwd)); |
1890 | memset(fwdargs, 0, sizeof(fwdargs)); | ||
1776 | 1891 | ||
1777 | cp = p = xstrdup(fwdspec); | 1892 | cp = p = xstrdup(fwdspec); |
1778 | 1893 | ||
@@ -1780,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1780 | while (isspace((u_char)*cp)) | 1895 | while (isspace((u_char)*cp)) |
1781 | cp++; | 1896 | cp++; |
1782 | 1897 | ||
1783 | for (i = 0; i < 4; ++i) | 1898 | for (i = 0; i < 4; ++i) { |
1784 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | 1899 | if (parse_fwd_field(&cp, &fwdargs[i]) != 0) |
1785 | break; | 1900 | break; |
1901 | } | ||
1786 | 1902 | ||
1787 | /* Check for trailing garbage */ | 1903 | /* Check for trailing garbage */ |
1788 | if (cp != NULL) | 1904 | if (cp != NULL && *cp != '\0') { |
1789 | i = 0; /* failure */ | 1905 | i = 0; /* failure */ |
1906 | } | ||
1790 | 1907 | ||
1791 | switch (i) { | 1908 | switch (i) { |
1792 | case 1: | 1909 | case 1: |
1793 | fwd->listen_host = NULL; | 1910 | if (fwdargs[0].ispath) { |
1794 | 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 | } | ||
1795 | fwd->connect_host = xstrdup("socks"); | 1917 | fwd->connect_host = xstrdup("socks"); |
1796 | break; | 1918 | break; |
1797 | 1919 | ||
1798 | case 2: | 1920 | case 2: |
1799 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1921 | if (fwdargs[0].ispath && fwdargs[1].ispath) { |
1800 | fwd->listen_port = a2port(fwdarg[1]); | 1922 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1801 | 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 | } | ||
1802 | break; | 1936 | break; |
1803 | 1937 | ||
1804 | case 3: | 1938 | case 3: |
1805 | fwd->listen_host = NULL; | 1939 | if (fwdargs[0].ispath) { |
1806 | fwd->listen_port = a2port(fwdarg[0]); | 1940 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1807 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | 1941 | fwd->listen_port = PORT_STREAMLOCAL; |
1808 | 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 | } | ||
1809 | break; | 1955 | break; |
1810 | 1956 | ||
1811 | case 4: | 1957 | case 4: |
1812 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1958 | fwd->listen_host = xstrdup(fwdargs[0].arg); |
1813 | fwd->listen_port = a2port(fwdarg[1]); | 1959 | fwd->listen_port = a2port(fwdargs[1].arg); |
1814 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | 1960 | fwd->connect_host = xstrdup(fwdargs[2].arg); |
1815 | fwd->connect_port = a2port(fwdarg[3]); | 1961 | fwd->connect_port = a2port(fwdargs[3].arg); |
1816 | break; | 1962 | break; |
1817 | default: | 1963 | default: |
1818 | i = 0; /* failure */ | 1964 | i = 0; /* failure */ |
@@ -1824,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1824 | if (!(i == 1 || i == 2)) | 1970 | if (!(i == 1 || i == 2)) |
1825 | goto fail_free; | 1971 | goto fail_free; |
1826 | } else { | 1972 | } else { |
1827 | if (!(i == 3 || i == 4)) | 1973 | if (!(i == 3 || i == 4)) { |
1828 | goto fail_free; | 1974 | if (fwd->connect_path == NULL && |
1829 | 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) | ||
1830 | goto fail_free; | 1979 | goto fail_free; |
1831 | } | 1980 | } |
1832 | 1981 | ||
1833 | 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)) | ||
1834 | goto fail_free; | 1984 | goto fail_free; |
1835 | |||
1836 | if (fwd->connect_host != NULL && | 1985 | if (fwd->connect_host != NULL && |
1837 | strlen(fwd->connect_host) >= NI_MAXHOST) | 1986 | strlen(fwd->connect_host) >= NI_MAXHOST) |
1838 | 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; | ||
1839 | if (fwd->listen_host != NULL && | 1992 | if (fwd->listen_host != NULL && |
1840 | strlen(fwd->listen_host) >= NI_MAXHOST) | 1993 | strlen(fwd->listen_host) >= NI_MAXHOST) |
1841 | goto fail_free; | 1994 | goto fail_free; |
1842 | 1995 | if (fwd->listen_path != NULL && | |
1996 | strlen(fwd->listen_path) >= PATH_MAX_SUN) | ||
1997 | goto fail_free; | ||
1843 | 1998 | ||
1844 | return (i); | 1999 | return (i); |
1845 | 2000 | ||
1846 | fail_free: | 2001 | fail_free: |
1847 | free(fwd->connect_host); | 2002 | free(fwd->connect_host); |
1848 | fwd->connect_host = NULL; | 2003 | fwd->connect_host = NULL; |
2004 | free(fwd->connect_path); | ||
2005 | fwd->connect_path = NULL; | ||
1849 | free(fwd->listen_host); | 2006 | free(fwd->listen_host); |
1850 | fwd->listen_host = NULL; | 2007 | fwd->listen_host = NULL; |
2008 | free(fwd->listen_path); | ||
2009 | fwd->listen_path = NULL; | ||
1851 | return (0); | 2010 | return (0); |
1852 | } | 2011 | } |