diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 266 |
1 files changed, 241 insertions, 25 deletions
diff --git a/readconf.c b/readconf.c index dc22360d1..5cd51f3e6 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.250 2016/02/08 23:40:12 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.259 2016/07/22 03:35:11 djm 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 |
@@ -39,8 +39,11 @@ | |||
39 | #include <stdio.h> | 39 | #include <stdio.h> |
40 | #include <string.h> | 40 | #include <string.h> |
41 | #include <unistd.h> | 41 | #include <unistd.h> |
42 | #include <pwd.h> | 42 | #ifdef USE_SYSTEM_GLOB |
43 | #include <grp.h> | 43 | # include <glob.h> |
44 | #else | ||
45 | # include "openbsd-compat/glob.h" | ||
46 | #endif | ||
44 | #ifdef HAVE_UTIL_H | 47 | #ifdef HAVE_UTIL_H |
45 | #include <util.h> | 48 | #include <util.h> |
46 | #endif | 49 | #endif |
@@ -127,17 +130,24 @@ | |||
127 | 130 | ||
128 | */ | 131 | */ |
129 | 132 | ||
133 | static int read_config_file_depth(const char *filename, struct passwd *pw, | ||
134 | const char *host, const char *original_host, Options *options, | ||
135 | int flags, int *activep, int depth); | ||
136 | static int process_config_line_depth(Options *options, struct passwd *pw, | ||
137 | const char *host, const char *original_host, char *line, | ||
138 | const char *filename, int linenum, int *activep, int flags, int depth); | ||
139 | |||
130 | /* Keyword tokens. */ | 140 | /* Keyword tokens. */ |
131 | 141 | ||
132 | typedef enum { | 142 | typedef enum { |
133 | oBadOption, | 143 | oBadOption, |
134 | oHost, oMatch, | 144 | oHost, oMatch, oInclude, |
135 | oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, | 145 | oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, |
136 | oGatewayPorts, oExitOnForwardFailure, | 146 | oGatewayPorts, oExitOnForwardFailure, |
137 | oPasswordAuthentication, oRSAAuthentication, | 147 | oPasswordAuthentication, oRSAAuthentication, |
138 | oChallengeResponseAuthentication, oXAuthLocation, | 148 | oChallengeResponseAuthentication, oXAuthLocation, |
139 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, | 149 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, |
140 | oCertificateFile, oAddKeysToAgent, | 150 | oCertificateFile, oAddKeysToAgent, oIdentityAgent, |
141 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, | 151 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, |
142 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, | 152 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, |
143 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, | 153 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, |
@@ -162,7 +172,7 @@ typedef enum { | |||
162 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 172 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
163 | oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, | 173 | oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, |
164 | oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, | 174 | oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, |
165 | oPubkeyAcceptedKeyTypes, | 175 | oPubkeyAcceptedKeyTypes, oProxyJump, |
166 | oProtocolKeepAlives, oSetupTimeOut, | 176 | oProtocolKeepAlives, oSetupTimeOut, |
167 | oIgnoredUnknownOption, oDeprecated, oUnsupported | 177 | oIgnoredUnknownOption, oDeprecated, oUnsupported |
168 | } OpCodes; | 178 | } OpCodes; |
@@ -220,6 +230,7 @@ static struct { | |||
220 | { "identitiesonly", oIdentitiesOnly }, | 230 | { "identitiesonly", oIdentitiesOnly }, |
221 | { "certificatefile", oCertificateFile }, | 231 | { "certificatefile", oCertificateFile }, |
222 | { "addkeystoagent", oAddKeysToAgent }, | 232 | { "addkeystoagent", oAddKeysToAgent }, |
233 | { "identityagent", oIdentityAgent }, | ||
223 | { "hostname", oHostName }, | 234 | { "hostname", oHostName }, |
224 | { "hostkeyalias", oHostKeyAlias }, | 235 | { "hostkeyalias", oHostKeyAlias }, |
225 | { "proxycommand", oProxyCommand }, | 236 | { "proxycommand", oProxyCommand }, |
@@ -273,6 +284,7 @@ static struct { | |||
273 | { "controlmaster", oControlMaster }, | 284 | { "controlmaster", oControlMaster }, |
274 | { "controlpersist", oControlPersist }, | 285 | { "controlpersist", oControlPersist }, |
275 | { "hashknownhosts", oHashKnownHosts }, | 286 | { "hashknownhosts", oHashKnownHosts }, |
287 | { "include", oInclude }, | ||
276 | { "tunnel", oTunnel }, | 288 | { "tunnel", oTunnel }, |
277 | { "tunneldevice", oTunnelDevice }, | 289 | { "tunneldevice", oTunnelDevice }, |
278 | { "localcommand", oLocalCommand }, | 290 | { "localcommand", oLocalCommand }, |
@@ -296,6 +308,7 @@ static struct { | |||
296 | { "hostbasedkeytypes", oHostbasedKeyTypes }, | 308 | { "hostbasedkeytypes", oHostbasedKeyTypes }, |
297 | { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, | 309 | { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, |
298 | { "ignoreunknown", oIgnoreUnknown }, | 310 | { "ignoreunknown", oIgnoreUnknown }, |
311 | { "proxyjump", oProxyJump }, | ||
299 | { "protocolkeepalives", oProtocolKeepAlives }, | 312 | { "protocolkeepalives", oProtocolKeepAlives }, |
300 | { "setuptimeout", oSetupTimeOut }, | 313 | { "setuptimeout", oSetupTimeOut }, |
301 | 314 | ||
@@ -311,12 +324,17 @@ void | |||
311 | add_local_forward(Options *options, const struct Forward *newfwd) | 324 | add_local_forward(Options *options, const struct Forward *newfwd) |
312 | { | 325 | { |
313 | struct Forward *fwd; | 326 | struct Forward *fwd; |
314 | #ifndef NO_IPPORT_RESERVED_CONCEPT | ||
315 | extern uid_t original_real_uid; | 327 | extern uid_t original_real_uid; |
328 | int i; | ||
329 | |||
316 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 && | 330 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 && |
317 | newfwd->listen_path == NULL) | 331 | newfwd->listen_path == NULL) |
318 | fatal("Privileged ports can only be forwarded by root."); | 332 | fatal("Privileged ports can only be forwarded by root."); |
319 | #endif | 333 | /* Don't add duplicates */ |
334 | for (i = 0; i < options->num_local_forwards; i++) { | ||
335 | if (forward_equals(newfwd, options->local_forwards + i)) | ||
336 | return; | ||
337 | } | ||
320 | options->local_forwards = xreallocarray(options->local_forwards, | 338 | options->local_forwards = xreallocarray(options->local_forwards, |
321 | options->num_local_forwards + 1, | 339 | options->num_local_forwards + 1, |
322 | sizeof(*options->local_forwards)); | 340 | sizeof(*options->local_forwards)); |
@@ -339,7 +357,13 @@ void | |||
339 | add_remote_forward(Options *options, const struct Forward *newfwd) | 357 | add_remote_forward(Options *options, const struct Forward *newfwd) |
340 | { | 358 | { |
341 | struct Forward *fwd; | 359 | struct Forward *fwd; |
360 | int i; | ||
342 | 361 | ||
362 | /* Don't add duplicates */ | ||
363 | for (i = 0; i < options->num_remote_forwards; i++) { | ||
364 | if (forward_equals(newfwd, options->remote_forwards + i)) | ||
365 | return; | ||
366 | } | ||
343 | options->remote_forwards = xreallocarray(options->remote_forwards, | 367 | options->remote_forwards = xreallocarray(options->remote_forwards, |
344 | options->num_remote_forwards + 1, | 368 | options->num_remote_forwards + 1, |
345 | sizeof(*options->remote_forwards)); | 369 | sizeof(*options->remote_forwards)); |
@@ -789,22 +813,32 @@ static const struct multistate multistate_canonicalizehostname[] = { | |||
789 | * Processes a single option line as used in the configuration files. This | 813 | * Processes a single option line as used in the configuration files. This |
790 | * only sets those values that have not already been set. | 814 | * only sets those values that have not already been set. |
791 | */ | 815 | */ |
792 | #define WHITESPACE " \t\r\n" | ||
793 | int | 816 | int |
794 | process_config_line(Options *options, struct passwd *pw, const char *host, | 817 | process_config_line(Options *options, struct passwd *pw, const char *host, |
795 | const char *original_host, char *line, const char *filename, | 818 | const char *original_host, char *line, const char *filename, |
796 | int linenum, int *activep, int flags) | 819 | int linenum, int *activep, int flags) |
797 | { | 820 | { |
821 | return process_config_line_depth(options, pw, host, original_host, | ||
822 | line, filename, linenum, activep, flags, 0); | ||
823 | } | ||
824 | |||
825 | #define WHITESPACE " \t\r\n" | ||
826 | static int | ||
827 | process_config_line_depth(Options *options, struct passwd *pw, const char *host, | ||
828 | const char *original_host, char *line, const char *filename, | ||
829 | int linenum, int *activep, int flags, int depth) | ||
830 | { | ||
798 | char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; | 831 | char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; |
799 | char **cpptr, fwdarg[256]; | 832 | char **cpptr, fwdarg[256]; |
800 | u_int i, *uintptr, max_entries = 0; | 833 | u_int i, *uintptr, max_entries = 0; |
801 | int negated, opcode, *intptr, value, value2, cmdline = 0; | 834 | int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; |
802 | LogLevel *log_level_ptr; | 835 | LogLevel *log_level_ptr; |
803 | long long val64; | 836 | long long val64; |
804 | size_t len; | 837 | size_t len; |
805 | struct Forward fwd; | 838 | struct Forward fwd; |
806 | const struct multistate *multistate_ptr; | 839 | const struct multistate *multistate_ptr; |
807 | struct allowed_cname *cname; | 840 | struct allowed_cname *cname; |
841 | glob_t gl; | ||
808 | 842 | ||
809 | if (activep == NULL) { /* We are processing a command line directive */ | 843 | if (activep == NULL) { /* We are processing a command line directive */ |
810 | cmdline = 1; | 844 | cmdline = 1; |
@@ -1123,6 +1157,9 @@ parse_char_array: | |||
1123 | 1157 | ||
1124 | case oProxyCommand: | 1158 | case oProxyCommand: |
1125 | charptr = &options->proxy_command; | 1159 | charptr = &options->proxy_command; |
1160 | /* Ignore ProxyCommand if ProxyJump already specified */ | ||
1161 | if (options->jump_host != NULL) | ||
1162 | charptr = &options->jump_host; /* Skip below */ | ||
1126 | parse_command: | 1163 | parse_command: |
1127 | if (s == NULL) | 1164 | if (s == NULL) |
1128 | fatal("%.200s line %d: Missing argument.", filename, linenum); | 1165 | fatal("%.200s line %d: Missing argument.", filename, linenum); |
@@ -1131,6 +1168,18 @@ parse_command: | |||
1131 | *charptr = xstrdup(s + len); | 1168 | *charptr = xstrdup(s + len); |
1132 | return 0; | 1169 | return 0; |
1133 | 1170 | ||
1171 | case oProxyJump: | ||
1172 | if (s == NULL) { | ||
1173 | fatal("%.200s line %d: Missing argument.", | ||
1174 | filename, linenum); | ||
1175 | } | ||
1176 | len = strspn(s, WHITESPACE "="); | ||
1177 | if (parse_jump(s + len, options, *activep) == -1) { | ||
1178 | fatal("%.200s line %d: Invalid ProxyJump \"%s\"", | ||
1179 | filename, linenum, s + len); | ||
1180 | } | ||
1181 | return 0; | ||
1182 | |||
1134 | case oPort: | 1183 | case oPort: |
1135 | intptr = &options->port; | 1184 | intptr = &options->port; |
1136 | parse_int: | 1185 | parse_int: |
@@ -1284,6 +1333,8 @@ parse_keytypes: | |||
1284 | *activep = 0; | 1333 | *activep = 0; |
1285 | arg2 = NULL; | 1334 | arg2 = NULL; |
1286 | while ((arg = strdelim(&s)) != NULL && *arg != '\0') { | 1335 | while ((arg = strdelim(&s)) != NULL && *arg != '\0') { |
1336 | if ((flags & SSHCONF_NEVERMATCH) != 0) | ||
1337 | break; | ||
1287 | negated = *arg == '!'; | 1338 | negated = *arg == '!'; |
1288 | if (negated) | 1339 | if (negated) |
1289 | arg++; | 1340 | arg++; |
@@ -1316,7 +1367,7 @@ parse_keytypes: | |||
1316 | if (value < 0) | 1367 | if (value < 0) |
1317 | fatal("%.200s line %d: Bad Match condition", filename, | 1368 | fatal("%.200s line %d: Bad Match condition", filename, |
1318 | linenum); | 1369 | linenum); |
1319 | *activep = value; | 1370 | *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; |
1320 | break; | 1371 | break; |
1321 | 1372 | ||
1322 | case oEscapeChar: | 1373 | case oEscapeChar: |
@@ -1446,6 +1497,63 @@ parse_keytypes: | |||
1446 | intptr = &options->visual_host_key; | 1497 | intptr = &options->visual_host_key; |
1447 | goto parse_flag; | 1498 | goto parse_flag; |
1448 | 1499 | ||
1500 | case oInclude: | ||
1501 | if (cmdline) | ||
1502 | fatal("Include directive not supported as a " | ||
1503 | "command-line option"); | ||
1504 | value = 0; | ||
1505 | while ((arg = strdelim(&s)) != NULL && *arg != '\0') { | ||
1506 | /* | ||
1507 | * Ensure all paths are anchored. User configuration | ||
1508 | * files may begin with '~/' but system configurations | ||
1509 | * must not. If the path is relative, then treat it | ||
1510 | * as living in ~/.ssh for user configurations or | ||
1511 | * /etc/ssh for system ones. | ||
1512 | */ | ||
1513 | if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) | ||
1514 | fatal("%.200s line %d: bad include path %s.", | ||
1515 | filename, linenum, arg); | ||
1516 | if (*arg != '/' && *arg != '~') { | ||
1517 | xasprintf(&arg2, "%s/%s", | ||
1518 | (flags & SSHCONF_USERCONF) ? | ||
1519 | "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); | ||
1520 | } else | ||
1521 | arg2 = xstrdup(arg); | ||
1522 | memset(&gl, 0, sizeof(gl)); | ||
1523 | r = glob(arg2, GLOB_TILDE, NULL, &gl); | ||
1524 | if (r == GLOB_NOMATCH) { | ||
1525 | debug("%.200s line %d: include %s matched no " | ||
1526 | "files",filename, linenum, arg2); | ||
1527 | continue; | ||
1528 | } else if (r != 0 || gl.gl_pathc < 0) | ||
1529 | fatal("%.200s line %d: glob failed for %s.", | ||
1530 | filename, linenum, arg2); | ||
1531 | free(arg2); | ||
1532 | oactive = *activep; | ||
1533 | for (i = 0; i < (u_int)gl.gl_pathc; i++) { | ||
1534 | debug3("%.200s line %d: Including file %s " | ||
1535 | "depth %d%s", filename, linenum, | ||
1536 | gl.gl_pathv[i], depth, | ||
1537 | oactive ? "" : " (parse only)"); | ||
1538 | r = read_config_file_depth(gl.gl_pathv[i], | ||
1539 | pw, host, original_host, options, | ||
1540 | flags | SSHCONF_CHECKPERM | | ||
1541 | (oactive ? 0 : SSHCONF_NEVERMATCH), | ||
1542 | activep, depth + 1); | ||
1543 | /* | ||
1544 | * don't let Match in includes clobber the | ||
1545 | * containing file's Match state. | ||
1546 | */ | ||
1547 | *activep = oactive; | ||
1548 | if (r != 1) | ||
1549 | value = -1; | ||
1550 | } | ||
1551 | globfree(&gl); | ||
1552 | } | ||
1553 | if (value != 0) | ||
1554 | return value; | ||
1555 | break; | ||
1556 | |||
1449 | case oIPQoS: | 1557 | case oIPQoS: |
1450 | arg = strdelim(&s); | 1558 | arg = strdelim(&s); |
1451 | if ((value = parse_ipqos(arg)) == -1) | 1559 | if ((value = parse_ipqos(arg)) == -1) |
@@ -1582,6 +1690,10 @@ parse_keytypes: | |||
1582 | multistate_ptr = multistate_yesnoaskconfirm; | 1690 | multistate_ptr = multistate_yesnoaskconfirm; |
1583 | goto parse_multistate; | 1691 | goto parse_multistate; |
1584 | 1692 | ||
1693 | case oIdentityAgent: | ||
1694 | charptr = &options->identity_agent; | ||
1695 | goto parse_string; | ||
1696 | |||
1585 | case oDeprecated: | 1697 | case oDeprecated: |
1586 | debug("%s line %d: Deprecated option \"%s\"", | 1698 | debug("%s line %d: Deprecated option \"%s\"", |
1587 | filename, linenum, keyword); | 1699 | filename, linenum, keyword); |
@@ -1604,22 +1716,35 @@ parse_keytypes: | |||
1604 | return 0; | 1716 | return 0; |
1605 | } | 1717 | } |
1606 | 1718 | ||
1607 | |||
1608 | /* | 1719 | /* |
1609 | * Reads the config file and modifies the options accordingly. Options | 1720 | * Reads the config file and modifies the options accordingly. Options |
1610 | * should already be initialized before this call. This never returns if | 1721 | * should already be initialized before this call. This never returns if |
1611 | * there is an error. If the file does not exist, this returns 0. | 1722 | * there is an error. If the file does not exist, this returns 0. |
1612 | */ | 1723 | */ |
1613 | |||
1614 | int | 1724 | int |
1615 | read_config_file(const char *filename, struct passwd *pw, const char *host, | 1725 | read_config_file(const char *filename, struct passwd *pw, const char *host, |
1616 | const char *original_host, Options *options, int flags) | 1726 | const char *original_host, Options *options, int flags) |
1617 | { | 1727 | { |
1728 | int active = 1; | ||
1729 | |||
1730 | return read_config_file_depth(filename, pw, host, original_host, | ||
1731 | options, flags, &active, 0); | ||
1732 | } | ||
1733 | |||
1734 | #define READCONF_MAX_DEPTH 16 | ||
1735 | static int | ||
1736 | read_config_file_depth(const char *filename, struct passwd *pw, | ||
1737 | const char *host, const char *original_host, Options *options, | ||
1738 | int flags, int *activep, int depth) | ||
1739 | { | ||
1618 | FILE *f; | 1740 | FILE *f; |
1619 | char line[1024]; | 1741 | char line[1024]; |
1620 | int active, linenum; | 1742 | int linenum; |
1621 | int bad_options = 0; | 1743 | int bad_options = 0; |
1622 | 1744 | ||
1745 | if (depth < 0 || depth > READCONF_MAX_DEPTH) | ||
1746 | fatal("Too many recursive configuration includes"); | ||
1747 | |||
1623 | if ((f = fopen(filename, "r")) == NULL) | 1748 | if ((f = fopen(filename, "r")) == NULL) |
1624 | return 0; | 1749 | return 0; |
1625 | 1750 | ||
@@ -1638,13 +1763,12 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, | |||
1638 | * Mark that we are now processing the options. This flag is turned | 1763 | * Mark that we are now processing the options. This flag is turned |
1639 | * on/off by Host specifications. | 1764 | * on/off by Host specifications. |
1640 | */ | 1765 | */ |
1641 | active = 1; | ||
1642 | linenum = 0; | 1766 | linenum = 0; |
1643 | while (fgets(line, sizeof(line), f)) { | 1767 | while (fgets(line, sizeof(line), f)) { |
1644 | /* Update line number counter. */ | 1768 | /* Update line number counter. */ |
1645 | linenum++; | 1769 | linenum++; |
1646 | if (process_config_line(options, pw, host, original_host, | 1770 | if (process_config_line_depth(options, pw, host, original_host, |
1647 | line, filename, linenum, &active, flags) != 0) | 1771 | line, filename, linenum, activep, flags, depth) != 0) |
1648 | bad_options++; | 1772 | bad_options++; |
1649 | } | 1773 | } |
1650 | fclose(f); | 1774 | fclose(f); |
@@ -1676,6 +1800,9 @@ initialize_options(Options * options) | |||
1676 | options->forward_x11 = -1; | 1800 | options->forward_x11 = -1; |
1677 | options->forward_x11_trusted = -1; | 1801 | options->forward_x11_trusted = -1; |
1678 | options->forward_x11_timeout = -1; | 1802 | options->forward_x11_timeout = -1; |
1803 | options->stdio_forward_host = NULL; | ||
1804 | options->stdio_forward_port = 0; | ||
1805 | options->clear_forwardings = -1; | ||
1679 | options->exit_on_forward_failure = -1; | 1806 | options->exit_on_forward_failure = -1; |
1680 | options->xauth_location = NULL; | 1807 | options->xauth_location = NULL; |
1681 | options->fwd_opts.gateway_ports = -1; | 1808 | options->fwd_opts.gateway_ports = -1; |
@@ -1719,6 +1846,10 @@ initialize_options(Options * options) | |||
1719 | options->hostname = NULL; | 1846 | options->hostname = NULL; |
1720 | options->host_key_alias = NULL; | 1847 | options->host_key_alias = NULL; |
1721 | options->proxy_command = NULL; | 1848 | options->proxy_command = NULL; |
1849 | options->jump_user = NULL; | ||
1850 | options->jump_host = NULL; | ||
1851 | options->jump_port = -1; | ||
1852 | options->jump_extra = NULL; | ||
1722 | options->user = NULL; | 1853 | options->user = NULL; |
1723 | options->escape_char = -1; | 1854 | options->escape_char = -1; |
1724 | options->num_system_hostfiles = 0; | 1855 | options->num_system_hostfiles = 0; |
@@ -1727,7 +1858,6 @@ initialize_options(Options * options) | |||
1727 | options->num_local_forwards = 0; | 1858 | options->num_local_forwards = 0; |
1728 | options->remote_forwards = NULL; | 1859 | options->remote_forwards = NULL; |
1729 | options->num_remote_forwards = 0; | 1860 | options->num_remote_forwards = 0; |
1730 | options->clear_forwardings = -1; | ||
1731 | options->log_level = SYSLOG_LEVEL_NOT_SET; | 1861 | options->log_level = SYSLOG_LEVEL_NOT_SET; |
1732 | options->preferred_authentications = NULL; | 1862 | options->preferred_authentications = NULL; |
1733 | options->bind_address = NULL; | 1863 | options->bind_address = NULL; |
@@ -1752,6 +1882,7 @@ initialize_options(Options * options) | |||
1752 | options->local_command = NULL; | 1882 | options->local_command = NULL; |
1753 | options->permit_local_command = -1; | 1883 | options->permit_local_command = -1; |
1754 | options->add_keys_to_agent = -1; | 1884 | options->add_keys_to_agent = -1; |
1885 | options->identity_agent = NULL; | ||
1755 | options->visual_host_key = -1; | 1886 | options->visual_host_key = -1; |
1756 | options->ip_qos_interactive = -1; | 1887 | options->ip_qos_interactive = -1; |
1757 | options->ip_qos_bulk = -1; | 1888 | options->ip_qos_bulk = -1; |
@@ -1800,8 +1931,19 @@ fill_default_options(Options * options) | |||
1800 | options->forward_x11_trusted = 1; | 1931 | options->forward_x11_trusted = 1; |
1801 | if (options->forward_x11_timeout == -1) | 1932 | if (options->forward_x11_timeout == -1) |
1802 | options->forward_x11_timeout = 1200; | 1933 | options->forward_x11_timeout = 1200; |
1934 | /* | ||
1935 | * stdio forwarding (-W) changes the default for these but we defer | ||
1936 | * setting the values so they can be overridden. | ||
1937 | */ | ||
1803 | if (options->exit_on_forward_failure == -1) | 1938 | if (options->exit_on_forward_failure == -1) |
1804 | options->exit_on_forward_failure = 0; | 1939 | options->exit_on_forward_failure = |
1940 | options->stdio_forward_host != NULL ? 1 : 0; | ||
1941 | if (options->clear_forwardings == -1) | ||
1942 | options->clear_forwardings = | ||
1943 | options->stdio_forward_host != NULL ? 1 : 0; | ||
1944 | if (options->clear_forwardings == 1) | ||
1945 | clear_forwardings(options); | ||
1946 | |||
1805 | if (options->xauth_location == NULL) | 1947 | if (options->xauth_location == NULL) |
1806 | options->xauth_location = _PATH_XAUTH; | 1948 | options->xauth_location = _PATH_XAUTH; |
1807 | if (options->fwd_opts.gateway_ports == -1) | 1949 | if (options->fwd_opts.gateway_ports == -1) |
@@ -1898,8 +2040,6 @@ fill_default_options(Options * options) | |||
1898 | } | 2040 | } |
1899 | if (options->log_level == SYSLOG_LEVEL_NOT_SET) | 2041 | if (options->log_level == SYSLOG_LEVEL_NOT_SET) |
1900 | options->log_level = SYSLOG_LEVEL_INFO; | 2042 | options->log_level = SYSLOG_LEVEL_INFO; |
1901 | if (options->clear_forwardings == 1) | ||
1902 | clear_forwardings(options); | ||
1903 | if (options->no_host_authentication_for_localhost == - 1) | 2043 | if (options->no_host_authentication_for_localhost == - 1) |
1904 | options->no_host_authentication_for_localhost = 0; | 2044 | options->no_host_authentication_for_localhost = 0; |
1905 | if (options->identities_only == -1) | 2045 | if (options->identities_only == -1) |
@@ -1977,6 +2117,7 @@ fill_default_options(Options * options) | |||
1977 | CLEAR_ON_NONE(options->proxy_command); | 2117 | CLEAR_ON_NONE(options->proxy_command); |
1978 | CLEAR_ON_NONE(options->control_path); | 2118 | CLEAR_ON_NONE(options->control_path); |
1979 | CLEAR_ON_NONE(options->revoked_host_keys); | 2119 | CLEAR_ON_NONE(options->revoked_host_keys); |
2120 | /* options->identity_agent distinguishes NULL from 'none' */ | ||
1980 | /* options->user will be set in the main program if appropriate */ | 2121 | /* options->user will be set in the main program if appropriate */ |
1981 | /* options->hostname will be set in the main program if appropriate */ | 2122 | /* options->hostname will be set in the main program if appropriate */ |
1982 | /* options->host_key_alias should not be set by default */ | 2123 | /* options->host_key_alias should not be set by default */ |
@@ -2192,6 +2333,54 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo | |||
2192 | return (0); | 2333 | return (0); |
2193 | } | 2334 | } |
2194 | 2335 | ||
2336 | int | ||
2337 | parse_jump(const char *s, Options *o, int active) | ||
2338 | { | ||
2339 | char *orig, *sdup, *cp; | ||
2340 | char *host = NULL, *user = NULL; | ||
2341 | int ret = -1, port = -1, first; | ||
2342 | |||
2343 | active &= o->proxy_command == NULL && o->jump_host == NULL; | ||
2344 | |||
2345 | orig = sdup = xstrdup(s); | ||
2346 | first = active; | ||
2347 | do { | ||
2348 | if ((cp = strrchr(sdup, ',')) == NULL) | ||
2349 | cp = sdup; /* last */ | ||
2350 | else | ||
2351 | *cp++ = '\0'; | ||
2352 | |||
2353 | if (first) { | ||
2354 | /* First argument and configuration is active */ | ||
2355 | if (parse_user_host_port(cp, &user, &host, &port) != 0) | ||
2356 | goto out; | ||
2357 | } else { | ||
2358 | /* Subsequent argument or inactive configuration */ | ||
2359 | if (parse_user_host_port(cp, NULL, NULL, NULL) != 0) | ||
2360 | goto out; | ||
2361 | } | ||
2362 | first = 0; /* only check syntax for subsequent hosts */ | ||
2363 | } while (cp != sdup); | ||
2364 | /* success */ | ||
2365 | if (active) { | ||
2366 | o->jump_user = user; | ||
2367 | o->jump_host = host; | ||
2368 | o->jump_port = port; | ||
2369 | o->proxy_command = xstrdup("none"); | ||
2370 | user = host = NULL; | ||
2371 | if ((cp = strrchr(s, ',')) != NULL && cp != s) { | ||
2372 | o->jump_extra = xstrdup(s); | ||
2373 | o->jump_extra[cp - s] = '\0'; | ||
2374 | } | ||
2375 | } | ||
2376 | ret = 0; | ||
2377 | out: | ||
2378 | free(orig); | ||
2379 | free(user); | ||
2380 | free(host); | ||
2381 | return ret; | ||
2382 | } | ||
2383 | |||
2195 | /* XXX the following is a near-vebatim copy from servconf.c; refactor */ | 2384 | /* XXX the following is a near-vebatim copy from servconf.c; refactor */ |
2196 | static const char * | 2385 | static const char * |
2197 | fmt_multistate_int(int val, const struct multistate *m) | 2386 | fmt_multistate_int(int val, const struct multistate *m) |
@@ -2343,7 +2532,7 @@ void | |||
2343 | dump_client_config(Options *o, const char *host) | 2532 | dump_client_config(Options *o, const char *host) |
2344 | { | 2533 | { |
2345 | int i; | 2534 | int i; |
2346 | char vbuf[5]; | 2535 | char buf[8]; |
2347 | 2536 | ||
2348 | /* This is normally prepared in ssh_kex2 */ | 2537 | /* This is normally prepared in ssh_kex2 */ |
2349 | if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) | 2538 | if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) |
@@ -2364,6 +2553,7 @@ dump_client_config(Options *o, const char *host) | |||
2364 | dump_cfg_fmtint(oCompression, o->compression); | 2553 | dump_cfg_fmtint(oCompression, o->compression); |
2365 | dump_cfg_fmtint(oControlMaster, o->control_master); | 2554 | dump_cfg_fmtint(oControlMaster, o->control_master); |
2366 | dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); | 2555 | dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); |
2556 | dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); | ||
2367 | dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); | 2557 | dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); |
2368 | dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); | 2558 | dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); |
2369 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); | 2559 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); |
@@ -2412,6 +2602,7 @@ dump_client_config(Options *o, const char *host) | |||
2412 | dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); | 2602 | dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); |
2413 | dump_cfg_string(oHostKeyAlias, o->host_key_alias); | 2603 | dump_cfg_string(oHostKeyAlias, o->host_key_alias); |
2414 | dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); | 2604 | dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); |
2605 | dump_cfg_string(oIdentityAgent, o->identity_agent); | ||
2415 | dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); | 2606 | dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); |
2416 | dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); | 2607 | dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); |
2417 | dump_cfg_string(oLocalCommand, o->local_command); | 2608 | dump_cfg_string(oLocalCommand, o->local_command); |
@@ -2419,7 +2610,6 @@ dump_client_config(Options *o, const char *host) | |||
2419 | dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); | 2610 | dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); |
2420 | dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); | 2611 | dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); |
2421 | dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); | 2612 | dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); |
2422 | dump_cfg_string(oProxyCommand, o->proxy_command); | ||
2423 | dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); | 2613 | dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); |
2424 | dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); | 2614 | dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); |
2425 | dump_cfg_string(oXAuthLocation, o->xauth_location); | 2615 | dump_cfg_string(oXAuthLocation, o->xauth_location); |
@@ -2480,8 +2670,8 @@ dump_client_config(Options *o, const char *host) | |||
2480 | if (o->escape_char == SSH_ESCAPECHAR_NONE) | 2670 | if (o->escape_char == SSH_ESCAPECHAR_NONE) |
2481 | printf("escapechar none\n"); | 2671 | printf("escapechar none\n"); |
2482 | else { | 2672 | else { |
2483 | vis(vbuf, o->escape_char, VIS_WHITE, 0); | 2673 | vis(buf, o->escape_char, VIS_WHITE, 0); |
2484 | printf("escapechar %s\n", vbuf); | 2674 | printf("escapechar %s\n", buf); |
2485 | } | 2675 | } |
2486 | 2676 | ||
2487 | /* oIPQoS */ | 2677 | /* oIPQoS */ |
@@ -2495,4 +2685,30 @@ dump_client_config(Options *o, const char *host) | |||
2495 | /* oStreamLocalBindMask */ | 2685 | /* oStreamLocalBindMask */ |
2496 | printf("streamlocalbindmask 0%o\n", | 2686 | printf("streamlocalbindmask 0%o\n", |
2497 | o->fwd_opts.streamlocal_bind_mask); | 2687 | o->fwd_opts.streamlocal_bind_mask); |
2688 | |||
2689 | /* oProxyCommand / oProxyJump */ | ||
2690 | if (o->jump_host == NULL) | ||
2691 | dump_cfg_string(oProxyCommand, o->proxy_command); | ||
2692 | else { | ||
2693 | /* Check for numeric addresses */ | ||
2694 | i = strchr(o->jump_host, ':') != NULL || | ||
2695 | strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); | ||
2696 | snprintf(buf, sizeof(buf), "%d", o->jump_port); | ||
2697 | printf("proxyjump %s%s%s%s%s%s%s%s%s\n", | ||
2698 | /* optional additional jump spec */ | ||
2699 | o->jump_extra == NULL ? "" : o->jump_extra, | ||
2700 | o->jump_extra == NULL ? "" : ",", | ||
2701 | /* optional user */ | ||
2702 | o->jump_user == NULL ? "" : o->jump_user, | ||
2703 | o->jump_user == NULL ? "" : "@", | ||
2704 | /* opening [ if hostname is numeric */ | ||
2705 | i ? "[" : "", | ||
2706 | /* mandatory hostname */ | ||
2707 | o->jump_host, | ||
2708 | /* closing ] if hostname is numeric */ | ||
2709 | i ? "]" : "", | ||
2710 | /* optional port number */ | ||
2711 | o->jump_port <= 0 ? "" : ":", | ||
2712 | o->jump_port <= 0 ? "" : buf); | ||
2713 | } | ||
2498 | } | 2714 | } |