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 5429fc2ad..29338b619 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> |
@@ -50,9 +51,9 @@ | |||
50 | #include "pathnames.h" | 51 | #include "pathnames.h" |
51 | #include "log.h" | 52 | #include "log.h" |
52 | #include "key.h" | 53 | #include "key.h" |
54 | #include "misc.h" | ||
53 | #include "readconf.h" | 55 | #include "readconf.h" |
54 | #include "match.h" | 56 | #include "match.h" |
55 | #include "misc.h" | ||
56 | #include "buffer.h" | 57 | #include "buffer.h" |
57 | #include "kex.h" | 58 | #include "kex.h" |
58 | #include "mac.h" | 59 | #include "mac.h" |
@@ -153,6 +154,7 @@ typedef enum { | |||
153 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, | 154 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
154 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, | 155 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
155 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 156 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
157 | oStreamLocalBindMask, oStreamLocalBindUnlink, | ||
156 | oProtocolKeepAlives, oSetupTimeOut, | 158 | oProtocolKeepAlives, oSetupTimeOut, |
157 | oIgnoredUnknownOption, oDeprecated, oUnsupported | 159 | oIgnoredUnknownOption, oDeprecated, oUnsupported |
158 | } OpCodes; | 160 | } OpCodes; |
@@ -276,6 +278,8 @@ static struct { | |||
276 | { "canonicalizehostname", oCanonicalizeHostname }, | 278 | { "canonicalizehostname", oCanonicalizeHostname }, |
277 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, | 279 | { "canonicalizemaxdots", oCanonicalizeMaxDots }, |
278 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, | 280 | { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, |
281 | { "streamlocalbindmask", oStreamLocalBindMask }, | ||
282 | { "streamlocalbindunlink", oStreamLocalBindUnlink }, | ||
279 | { "ignoreunknown", oIgnoreUnknown }, | 283 | { "ignoreunknown", oIgnoreUnknown }, |
280 | { "protocolkeepalives", oProtocolKeepAlives }, | 284 | { "protocolkeepalives", oProtocolKeepAlives }, |
281 | { "setuptimeout", oSetupTimeOut }, | 285 | { "setuptimeout", oSetupTimeOut }, |
@@ -289,12 +293,13 @@ static struct { | |||
289 | */ | 293 | */ |
290 | 294 | ||
291 | void | 295 | void |
292 | add_local_forward(Options *options, const Forward *newfwd) | 296 | add_local_forward(Options *options, const struct Forward *newfwd) |
293 | { | 297 | { |
294 | Forward *fwd; | 298 | struct Forward *fwd; |
295 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 299 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
296 | extern uid_t original_real_uid; | 300 | extern uid_t original_real_uid; |
297 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) | 301 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 && |
302 | newfwd->listen_path == NULL) | ||
298 | fatal("Privileged ports can only be forwarded by root."); | 303 | fatal("Privileged ports can only be forwarded by root."); |
299 | #endif | 304 | #endif |
300 | options->local_forwards = xrealloc(options->local_forwards, | 305 | options->local_forwards = xrealloc(options->local_forwards, |
@@ -304,8 +309,10 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
304 | 309 | ||
305 | fwd->listen_host = newfwd->listen_host; | 310 | fwd->listen_host = newfwd->listen_host; |
306 | fwd->listen_port = newfwd->listen_port; | 311 | fwd->listen_port = newfwd->listen_port; |
312 | fwd->listen_path = newfwd->listen_path; | ||
307 | fwd->connect_host = newfwd->connect_host; | 313 | fwd->connect_host = newfwd->connect_host; |
308 | fwd->connect_port = newfwd->connect_port; | 314 | fwd->connect_port = newfwd->connect_port; |
315 | fwd->connect_path = newfwd->connect_path; | ||
309 | } | 316 | } |
310 | 317 | ||
311 | /* | 318 | /* |
@@ -314,9 +321,9 @@ add_local_forward(Options *options, const Forward *newfwd) | |||
314 | */ | 321 | */ |
315 | 322 | ||
316 | void | 323 | void |
317 | add_remote_forward(Options *options, const Forward *newfwd) | 324 | add_remote_forward(Options *options, const struct Forward *newfwd) |
318 | { | 325 | { |
319 | Forward *fwd; | 326 | struct Forward *fwd; |
320 | 327 | ||
321 | options->remote_forwards = xrealloc(options->remote_forwards, | 328 | options->remote_forwards = xrealloc(options->remote_forwards, |
322 | options->num_remote_forwards + 1, | 329 | options->num_remote_forwards + 1, |
@@ -325,8 +332,10 @@ add_remote_forward(Options *options, const Forward *newfwd) | |||
325 | 332 | ||
326 | fwd->listen_host = newfwd->listen_host; | 333 | fwd->listen_host = newfwd->listen_host; |
327 | fwd->listen_port = newfwd->listen_port; | 334 | fwd->listen_port = newfwd->listen_port; |
335 | fwd->listen_path = newfwd->listen_path; | ||
328 | fwd->connect_host = newfwd->connect_host; | 336 | fwd->connect_host = newfwd->connect_host; |
329 | fwd->connect_port = newfwd->connect_port; | 337 | fwd->connect_port = newfwd->connect_port; |
338 | fwd->connect_path = newfwd->connect_path; | ||
330 | fwd->handle = newfwd->handle; | 339 | fwd->handle = newfwd->handle; |
331 | fwd->allocated_port = 0; | 340 | fwd->allocated_port = 0; |
332 | } | 341 | } |
@@ -338,7 +347,9 @@ clear_forwardings(Options *options) | |||
338 | 347 | ||
339 | for (i = 0; i < options->num_local_forwards; i++) { | 348 | for (i = 0; i < options->num_local_forwards; i++) { |
340 | free(options->local_forwards[i].listen_host); | 349 | free(options->local_forwards[i].listen_host); |
350 | free(options->local_forwards[i].listen_path); | ||
341 | free(options->local_forwards[i].connect_host); | 351 | free(options->local_forwards[i].connect_host); |
352 | free(options->local_forwards[i].connect_path); | ||
342 | } | 353 | } |
343 | if (options->num_local_forwards > 0) { | 354 | if (options->num_local_forwards > 0) { |
344 | free(options->local_forwards); | 355 | free(options->local_forwards); |
@@ -347,7 +358,9 @@ clear_forwardings(Options *options) | |||
347 | options->num_local_forwards = 0; | 358 | options->num_local_forwards = 0; |
348 | for (i = 0; i < options->num_remote_forwards; i++) { | 359 | for (i = 0; i < options->num_remote_forwards; i++) { |
349 | free(options->remote_forwards[i].listen_host); | 360 | free(options->remote_forwards[i].listen_host); |
361 | free(options->remote_forwards[i].listen_path); | ||
350 | free(options->remote_forwards[i].connect_host); | 362 | free(options->remote_forwards[i].connect_host); |
363 | free(options->remote_forwards[i].connect_path); | ||
351 | } | 364 | } |
352 | if (options->num_remote_forwards > 0) { | 365 | if (options->num_remote_forwards > 0) { |
353 | free(options->remote_forwards); | 366 | free(options->remote_forwards); |
@@ -362,6 +375,7 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
362 | int userprovided) | 375 | int userprovided) |
363 | { | 376 | { |
364 | char *path; | 377 | char *path; |
378 | int i; | ||
365 | 379 | ||
366 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) | 380 | if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) |
367 | fatal("Too many identity files specified (max %d)", | 381 | fatal("Too many identity files specified (max %d)", |
@@ -372,6 +386,16 @@ add_identity_file(Options *options, const char *dir, const char *filename, | |||
372 | else | 386 | else |
373 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); | 387 | (void)xasprintf(&path, "%.100s%.100s", dir, filename); |
374 | 388 | ||
389 | /* Avoid registering duplicates */ | ||
390 | for (i = 0; i < options->num_identity_files; i++) { | ||
391 | if (options->identity_file_userprovided[i] == userprovided && | ||
392 | strcmp(options->identity_files[i], path) == 0) { | ||
393 | debug2("%s: ignoring duplicate key %s", __func__, path); | ||
394 | free(path); | ||
395 | return; | ||
396 | } | ||
397 | } | ||
398 | |||
375 | options->identity_file_userprovided[options->num_identity_files] = | 399 | options->identity_file_userprovided[options->num_identity_files] = |
376 | userprovided; | 400 | userprovided; |
377 | options->identity_files[options->num_identity_files++] = path; | 401 | options->identity_files[options->num_identity_files++] = path; |
@@ -721,7 +745,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
721 | LogLevel *log_level_ptr; | 745 | LogLevel *log_level_ptr; |
722 | long long val64; | 746 | long long val64; |
723 | size_t len; | 747 | size_t len; |
724 | Forward fwd; | 748 | struct Forward fwd; |
725 | const struct multistate *multistate_ptr; | 749 | const struct multistate *multistate_ptr; |
726 | struct allowed_cname *cname; | 750 | struct allowed_cname *cname; |
727 | 751 | ||
@@ -811,7 +835,7 @@ parse_time: | |||
811 | goto parse_time; | 835 | goto parse_time; |
812 | 836 | ||
813 | case oGatewayPorts: | 837 | case oGatewayPorts: |
814 | intptr = &options->gateway_ports; | 838 | intptr = &options->fwd_opts.gateway_ports; |
815 | goto parse_flag; | 839 | goto parse_flag; |
816 | 840 | ||
817 | case oExitOnForwardFailure: | 841 | case oExitOnForwardFailure: |
@@ -1433,6 +1457,21 @@ parse_int: | |||
1433 | intptr = &options->canonicalize_fallback_local; | 1457 | intptr = &options->canonicalize_fallback_local; |
1434 | goto parse_flag; | 1458 | goto parse_flag; |
1435 | 1459 | ||
1460 | case oStreamLocalBindMask: | ||
1461 | arg = strdelim(&s); | ||
1462 | if (!arg || *arg == '\0') | ||
1463 | fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); | ||
1464 | /* Parse mode in octal format */ | ||
1465 | value = strtol(arg, &endofnumber, 8); | ||
1466 | if (arg == endofnumber || value < 0 || value > 0777) | ||
1467 | fatal("%.200s line %d: Bad mask.", filename, linenum); | ||
1468 | options->fwd_opts.streamlocal_bind_mask = (mode_t)value; | ||
1469 | break; | ||
1470 | |||
1471 | case oStreamLocalBindUnlink: | ||
1472 | intptr = &options->fwd_opts.streamlocal_bind_unlink; | ||
1473 | goto parse_flag; | ||
1474 | |||
1436 | case oDeprecated: | 1475 | case oDeprecated: |
1437 | debug("%s line %d: Deprecated option \"%s\"", | 1476 | debug("%s line %d: Deprecated option \"%s\"", |
1438 | filename, linenum, keyword); | 1477 | filename, linenum, keyword); |
@@ -1529,7 +1568,9 @@ initialize_options(Options * options) | |||
1529 | options->forward_x11_timeout = -1; | 1568 | options->forward_x11_timeout = -1; |
1530 | options->exit_on_forward_failure = -1; | 1569 | options->exit_on_forward_failure = -1; |
1531 | options->xauth_location = NULL; | 1570 | options->xauth_location = NULL; |
1532 | options->gateway_ports = -1; | 1571 | options->fwd_opts.gateway_ports = -1; |
1572 | options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; | ||
1573 | options->fwd_opts.streamlocal_bind_unlink = -1; | ||
1533 | options->use_privileged_port = -1; | 1574 | options->use_privileged_port = -1; |
1534 | options->rsa_authentication = -1; | 1575 | options->rsa_authentication = -1; |
1535 | options->pubkey_authentication = -1; | 1576 | options->pubkey_authentication = -1; |
@@ -1647,8 +1688,12 @@ fill_default_options(Options * options) | |||
1647 | options->exit_on_forward_failure = 0; | 1688 | options->exit_on_forward_failure = 0; |
1648 | if (options->xauth_location == NULL) | 1689 | if (options->xauth_location == NULL) |
1649 | options->xauth_location = _PATH_XAUTH; | 1690 | options->xauth_location = _PATH_XAUTH; |
1650 | if (options->gateway_ports == -1) | 1691 | if (options->fwd_opts.gateway_ports == -1) |
1651 | options->gateway_ports = 0; | 1692 | options->fwd_opts.gateway_ports = 0; |
1693 | if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) | ||
1694 | options->fwd_opts.streamlocal_bind_mask = 0177; | ||
1695 | if (options->fwd_opts.streamlocal_bind_unlink == -1) | ||
1696 | options->fwd_opts.streamlocal_bind_unlink = 0; | ||
1652 | if (options->use_privileged_port == -1) | 1697 | if (options->use_privileged_port == -1) |
1653 | options->use_privileged_port = 0; | 1698 | options->use_privileged_port = 0; |
1654 | if (options->rsa_authentication == -1) | 1699 | if (options->rsa_authentication == -1) |
@@ -1811,22 +1856,92 @@ fill_default_options(Options * options) | |||
1811 | /* options->preferred_authentications will be set in ssh */ | 1856 | /* options->preferred_authentications will be set in ssh */ |
1812 | } | 1857 | } |
1813 | 1858 | ||
1859 | struct fwdarg { | ||
1860 | char *arg; | ||
1861 | int ispath; | ||
1862 | }; | ||
1863 | |||
1864 | /* | ||
1865 | * parse_fwd_field | ||
1866 | * parses the next field in a port forwarding specification. | ||
1867 | * sets fwd to the parsed field and advances p past the colon | ||
1868 | * or sets it to NULL at end of string. | ||
1869 | * returns 0 on success, else non-zero. | ||
1870 | */ | ||
1871 | static int | ||
1872 | parse_fwd_field(char **p, struct fwdarg *fwd) | ||
1873 | { | ||
1874 | char *ep, *cp = *p; | ||
1875 | int ispath = 0; | ||
1876 | |||
1877 | if (*cp == '\0') { | ||
1878 | *p = NULL; | ||
1879 | return -1; /* end of string */ | ||
1880 | } | ||
1881 | |||
1882 | /* | ||
1883 | * A field escaped with square brackets is used literally. | ||
1884 | * XXX - allow ']' to be escaped via backslash? | ||
1885 | */ | ||
1886 | if (*cp == '[') { | ||
1887 | /* find matching ']' */ | ||
1888 | for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { | ||
1889 | if (*ep == '/') | ||
1890 | ispath = 1; | ||
1891 | } | ||
1892 | /* no matching ']' or not at end of field. */ | ||
1893 | if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) | ||
1894 | return -1; | ||
1895 | /* NUL terminate the field and advance p past the colon */ | ||
1896 | *ep++ = '\0'; | ||
1897 | if (*ep != '\0') | ||
1898 | *ep++ = '\0'; | ||
1899 | fwd->arg = cp + 1; | ||
1900 | fwd->ispath = ispath; | ||
1901 | *p = ep; | ||
1902 | return 0; | ||
1903 | } | ||
1904 | |||
1905 | for (cp = *p; *cp != '\0'; cp++) { | ||
1906 | switch (*cp) { | ||
1907 | case '\\': | ||
1908 | memmove(cp, cp + 1, strlen(cp + 1) + 1); | ||
1909 | cp++; | ||
1910 | break; | ||
1911 | case '/': | ||
1912 | ispath = 1; | ||
1913 | break; | ||
1914 | case ':': | ||
1915 | *cp++ = '\0'; | ||
1916 | goto done; | ||
1917 | } | ||
1918 | } | ||
1919 | done: | ||
1920 | fwd->arg = *p; | ||
1921 | fwd->ispath = ispath; | ||
1922 | *p = cp; | ||
1923 | return 0; | ||
1924 | } | ||
1925 | |||
1814 | /* | 1926 | /* |
1815 | * parse_forward | 1927 | * parse_forward |
1816 | * parses a string containing a port forwarding specification of the form: | 1928 | * parses a string containing a port forwarding specification of the form: |
1817 | * dynamicfwd == 0 | 1929 | * dynamicfwd == 0 |
1818 | * [listenhost:]listenport:connecthost:connectport | 1930 | * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath |
1931 | * listenpath:connectpath | ||
1819 | * dynamicfwd == 1 | 1932 | * dynamicfwd == 1 |
1820 | * [listenhost:]listenport | 1933 | * [listenhost:]listenport |
1821 | * returns number of arguments parsed or zero on error | 1934 | * returns number of arguments parsed or zero on error |
1822 | */ | 1935 | */ |
1823 | int | 1936 | int |
1824 | parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | 1937 | parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) |
1825 | { | 1938 | { |
1939 | struct fwdarg fwdargs[4]; | ||
1940 | char *p, *cp; | ||
1826 | int i; | 1941 | int i; |
1827 | char *p, *cp, *fwdarg[4]; | ||
1828 | 1942 | ||
1829 | memset(fwd, '\0', sizeof(*fwd)); | 1943 | memset(fwd, 0, sizeof(*fwd)); |
1944 | memset(fwdargs, 0, sizeof(fwdargs)); | ||
1830 | 1945 | ||
1831 | cp = p = xstrdup(fwdspec); | 1946 | cp = p = xstrdup(fwdspec); |
1832 | 1947 | ||
@@ -1834,39 +1949,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1834 | while (isspace((u_char)*cp)) | 1949 | while (isspace((u_char)*cp)) |
1835 | cp++; | 1950 | cp++; |
1836 | 1951 | ||
1837 | for (i = 0; i < 4; ++i) | 1952 | for (i = 0; i < 4; ++i) { |
1838 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | 1953 | if (parse_fwd_field(&cp, &fwdargs[i]) != 0) |
1839 | break; | 1954 | break; |
1955 | } | ||
1840 | 1956 | ||
1841 | /* Check for trailing garbage */ | 1957 | /* Check for trailing garbage */ |
1842 | if (cp != NULL) | 1958 | if (cp != NULL && *cp != '\0') { |
1843 | i = 0; /* failure */ | 1959 | i = 0; /* failure */ |
1960 | } | ||
1844 | 1961 | ||
1845 | switch (i) { | 1962 | switch (i) { |
1846 | case 1: | 1963 | case 1: |
1847 | fwd->listen_host = NULL; | 1964 | if (fwdargs[0].ispath) { |
1848 | fwd->listen_port = a2port(fwdarg[0]); | 1965 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1966 | fwd->listen_port = PORT_STREAMLOCAL; | ||
1967 | } else { | ||
1968 | fwd->listen_host = NULL; | ||
1969 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1970 | } | ||
1849 | fwd->connect_host = xstrdup("socks"); | 1971 | fwd->connect_host = xstrdup("socks"); |
1850 | break; | 1972 | break; |
1851 | 1973 | ||
1852 | case 2: | 1974 | case 2: |
1853 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 1975 | if (fwdargs[0].ispath && fwdargs[1].ispath) { |
1854 | fwd->listen_port = a2port(fwdarg[1]); | 1976 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1855 | fwd->connect_host = xstrdup("socks"); | 1977 | fwd->listen_port = PORT_STREAMLOCAL; |
1978 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1979 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1980 | } else if (fwdargs[1].ispath) { | ||
1981 | fwd->listen_host = NULL; | ||
1982 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
1983 | fwd->connect_path = xstrdup(fwdargs[1].arg); | ||
1984 | fwd->connect_port = PORT_STREAMLOCAL; | ||
1985 | } else { | ||
1986 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
1987 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
1988 | fwd->connect_host = xstrdup("socks"); | ||
1989 | } | ||
1856 | break; | 1990 | break; |
1857 | 1991 | ||
1858 | case 3: | 1992 | case 3: |
1859 | fwd->listen_host = NULL; | 1993 | if (fwdargs[0].ispath) { |
1860 | fwd->listen_port = a2port(fwdarg[0]); | 1994 | fwd->listen_path = xstrdup(fwdargs[0].arg); |
1861 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | 1995 | fwd->listen_port = PORT_STREAMLOCAL; |
1862 | fwd->connect_port = a2port(fwdarg[2]); | 1996 | fwd->connect_host = xstrdup(fwdargs[1].arg); |
1997 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
1998 | } else if (fwdargs[2].ispath) { | ||
1999 | fwd->listen_host = xstrdup(fwdargs[0].arg); | ||
2000 | fwd->listen_port = a2port(fwdargs[1].arg); | ||
2001 | fwd->connect_path = xstrdup(fwdargs[2].arg); | ||
2002 | fwd->connect_port = PORT_STREAMLOCAL; | ||
2003 | } else { | ||
2004 | fwd->listen_host = NULL; | ||
2005 | fwd->listen_port = a2port(fwdargs[0].arg); | ||
2006 | fwd->connect_host = xstrdup(fwdargs[1].arg); | ||
2007 | fwd->connect_port = a2port(fwdargs[2].arg); | ||
2008 | } | ||
1863 | break; | 2009 | break; |
1864 | 2010 | ||
1865 | case 4: | 2011 | case 4: |
1866 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | 2012 | fwd->listen_host = xstrdup(fwdargs[0].arg); |
1867 | fwd->listen_port = a2port(fwdarg[1]); | 2013 | fwd->listen_port = a2port(fwdargs[1].arg); |
1868 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | 2014 | fwd->connect_host = xstrdup(fwdargs[2].arg); |
1869 | fwd->connect_port = a2port(fwdarg[3]); | 2015 | fwd->connect_port = a2port(fwdargs[3].arg); |
1870 | break; | 2016 | break; |
1871 | default: | 2017 | default: |
1872 | i = 0; /* failure */ | 2018 | i = 0; /* failure */ |
@@ -1878,29 +2024,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) | |||
1878 | if (!(i == 1 || i == 2)) | 2024 | if (!(i == 1 || i == 2)) |
1879 | goto fail_free; | 2025 | goto fail_free; |
1880 | } else { | 2026 | } else { |
1881 | if (!(i == 3 || i == 4)) | 2027 | if (!(i == 3 || i == 4)) { |
1882 | goto fail_free; | 2028 | if (fwd->connect_path == NULL && |
1883 | if (fwd->connect_port <= 0) | 2029 | fwd->listen_path == NULL) |
2030 | goto fail_free; | ||
2031 | } | ||
2032 | if (fwd->connect_port <= 0 && fwd->connect_path == NULL) | ||
1884 | goto fail_free; | 2033 | goto fail_free; |
1885 | } | 2034 | } |
1886 | 2035 | ||
1887 | if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) | 2036 | if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || |
2037 | (!remotefwd && fwd->listen_port == 0)) | ||
1888 | goto fail_free; | 2038 | goto fail_free; |
1889 | |||
1890 | if (fwd->connect_host != NULL && | 2039 | if (fwd->connect_host != NULL && |
1891 | strlen(fwd->connect_host) >= NI_MAXHOST) | 2040 | strlen(fwd->connect_host) >= NI_MAXHOST) |
1892 | goto fail_free; | 2041 | goto fail_free; |
2042 | /* XXX - if connecting to a remote socket, max sun len may not match this host */ | ||
2043 | if (fwd->connect_path != NULL && | ||
2044 | strlen(fwd->connect_path) >= PATH_MAX_SUN) | ||
2045 | goto fail_free; | ||
1893 | if (fwd->listen_host != NULL && | 2046 | if (fwd->listen_host != NULL && |
1894 | strlen(fwd->listen_host) >= NI_MAXHOST) | 2047 | strlen(fwd->listen_host) >= NI_MAXHOST) |
1895 | goto fail_free; | 2048 | goto fail_free; |
1896 | 2049 | if (fwd->listen_path != NULL && | |
2050 | strlen(fwd->listen_path) >= PATH_MAX_SUN) | ||
2051 | goto fail_free; | ||
1897 | 2052 | ||
1898 | return (i); | 2053 | return (i); |
1899 | 2054 | ||
1900 | fail_free: | 2055 | fail_free: |
1901 | free(fwd->connect_host); | 2056 | free(fwd->connect_host); |
1902 | fwd->connect_host = NULL; | 2057 | fwd->connect_host = NULL; |
2058 | free(fwd->connect_path); | ||
2059 | fwd->connect_path = NULL; | ||
1903 | free(fwd->listen_host); | 2060 | free(fwd->listen_host); |
1904 | fwd->listen_host = NULL; | 2061 | fwd->listen_host = NULL; |
2062 | free(fwd->listen_path); | ||
2063 | fwd->listen_path = NULL; | ||
1905 | return (0); | 2064 | return (0); |
1906 | } | 2065 | } |