summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c274
1 files changed, 167 insertions, 107 deletions
diff --git a/ssh.c b/ssh.c
index 15aee569e..98b6ce788 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.519 2020/02/07 03:54:44 dtucker Exp $ */ 1/* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker 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
@@ -86,7 +86,6 @@
86#include "canohost.h" 86#include "canohost.h"
87#include "compat.h" 87#include "compat.h"
88#include "cipher.h" 88#include "cipher.h"
89#include "digest.h"
90#include "packet.h" 89#include "packet.h"
91#include "sshbuf.h" 90#include "sshbuf.h"
92#include "channels.h" 91#include "channels.h"
@@ -191,7 +190,7 @@ struct sshbuf *command;
191int subsystem_flag = 0; 190int subsystem_flag = 0;
192 191
193/* # of replies received for global requests */ 192/* # of replies received for global requests */
194static int remote_forward_confirms_received = 0; 193static int forward_confirms_pending = -1;
195 194
196/* mux.c */ 195/* mux.c */
197extern int muxserver_sock; 196extern int muxserver_sock;
@@ -232,6 +231,34 @@ tilde_expand_paths(char **paths, u_int num_paths)
232 } 231 }
233} 232}
234 233
234#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \
235 "C", conn_hash_hex, \
236 "L", shorthost, \
237 "i", uidstr, \
238 "l", thishost, \
239 "n", host_arg, \
240 "p", portstr
241
242/*
243 * Expands the set of percent_expand options used by the majority of keywords
244 * in the client that support percent expansion.
245 * Caller must free returned string.
246 */
247static char *
248default_client_percent_expand(const char *str, const char *homedir,
249 const char *remhost, const char *remuser, const char *locuser)
250{
251 return percent_expand(str,
252 /* values from statics above */
253 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
254 /* values from arguments */
255 "d", homedir,
256 "h", remhost,
257 "r", remuser,
258 "u", locuser,
259 (char *)NULL);
260}
261
235/* 262/*
236 * Attempt to resolve a host name / port to a set of addresses and 263 * Attempt to resolve a host name / port to a set of addresses and
237 * optionally return any CNAMEs encountered along the way. 264 * optionally return any CNAMEs encountered along the way.
@@ -248,6 +275,8 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
248 275
249 if (port <= 0) 276 if (port <= 0)
250 port = default_ssh_port(); 277 port = default_ssh_port();
278 if (cname != NULL)
279 *cname = '\0';
251 280
252 snprintf(strport, sizeof strport, "%d", port); 281 snprintf(strport, sizeof strport, "%d", port);
253 memset(&hints, 0, sizeof(hints)); 282 memset(&hints, 0, sizeof(hints));
@@ -477,7 +506,6 @@ resolve_canonicalize(char **hostp, int port)
477 } 506 }
478 /* Attempt each supplied suffix */ 507 /* Attempt each supplied suffix */
479 for (i = 0; i < options.num_canonical_domains; i++) { 508 for (i = 0; i < options.num_canonical_domains; i++) {
480 *newname = '\0';
481 xasprintf(&fullhost, "%s.%s.", *hostp, 509 xasprintf(&fullhost, "%s.%s.", *hostp,
482 options.canonical_domains[i]); 510 options.canonical_domains[i]);
483 debug3("%s: attempting \"%s\" => \"%s\"", __func__, 511 debug3("%s: attempting \"%s\" => \"%s\"", __func__,
@@ -600,8 +628,6 @@ main(int ac, char **av)
600 extern char *optarg; 628 extern char *optarg;
601 struct Forward fwd; 629 struct Forward fwd;
602 struct addrinfo *addrs = NULL; 630 struct addrinfo *addrs = NULL;
603 struct ssh_digest_ctx *md;
604 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
605 size_t n, len; 631 size_t n, len;
606 632
607 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 633 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
@@ -1208,6 +1234,14 @@ main(int ac, char **av)
1208 if (options.jump_host != NULL) { 1234 if (options.jump_host != NULL) {
1209 char port_s[8]; 1235 char port_s[8];
1210 const char *sshbin = argv0; 1236 const char *sshbin = argv0;
1237 int port = options.port, jumpport = options.jump_port;
1238
1239 if (port <= 0)
1240 port = default_ssh_port();
1241 if (jumpport <= 0)
1242 jumpport = default_ssh_port();
1243 if (strcmp(options.jump_host, host) == 0 && port == jumpport)
1244 fatal("jumphost loop via %s", options.jump_host);
1211 1245
1212 /* 1246 /*
1213 * Try to use SSH indicated by argv[0], but fall back to 1247 * Try to use SSH indicated by argv[0], but fall back to
@@ -1321,15 +1355,8 @@ main(int ac, char **av)
1321 snprintf(uidstr, sizeof(uidstr), "%llu", 1355 snprintf(uidstr, sizeof(uidstr), "%llu",
1322 (unsigned long long)pw->pw_uid); 1356 (unsigned long long)pw->pw_uid);
1323 1357
1324 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 1358 conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
1325 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 1359 options.user);
1326 ssh_digest_update(md, host, strlen(host)) < 0 ||
1327 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
1328 ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
1329 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
1330 fatal("%s: mux digest failed", __func__);
1331 ssh_digest_free(md);
1332 conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
1333 1360
1334 /* 1361 /*
1335 * Expand tokens in arguments. NB. LocalCommand is expanded later, 1362 * Expand tokens in arguments. NB. LocalCommand is expanded later,
@@ -1339,18 +1366,8 @@ main(int ac, char **av)
1339 if (options.remote_command != NULL) { 1366 if (options.remote_command != NULL) {
1340 debug3("expanding RemoteCommand: %s", options.remote_command); 1367 debug3("expanding RemoteCommand: %s", options.remote_command);
1341 cp = options.remote_command; 1368 cp = options.remote_command;
1342 options.remote_command = percent_expand(cp, 1369 options.remote_command = default_client_percent_expand(cp,
1343 "C", conn_hash_hex, 1370 pw->pw_dir, host, options.user, pw->pw_name);
1344 "L", shorthost,
1345 "d", pw->pw_dir,
1346 "h", host,
1347 "i", uidstr,
1348 "l", thishost,
1349 "n", host_arg,
1350 "p", portstr,
1351 "r", options.user,
1352 "u", pw->pw_name,
1353 (char *)NULL);
1354 debug3("expanded RemoteCommand: %s", options.remote_command); 1371 debug3("expanded RemoteCommand: %s", options.remote_command);
1355 free(cp); 1372 free(cp);
1356 if ((r = sshbuf_put(command, options.remote_command, 1373 if ((r = sshbuf_put(command, options.remote_command,
@@ -1361,21 +1378,76 @@ main(int ac, char **av)
1361 if (options.control_path != NULL) { 1378 if (options.control_path != NULL) {
1362 cp = tilde_expand_filename(options.control_path, getuid()); 1379 cp = tilde_expand_filename(options.control_path, getuid());
1363 free(options.control_path); 1380 free(options.control_path);
1364 options.control_path = percent_expand(cp, 1381 options.control_path = default_client_percent_expand(cp,
1365 "C", conn_hash_hex, 1382 pw->pw_dir, host, options.user, pw->pw_name);
1366 "L", shorthost,
1367 "h", host,
1368 "i", uidstr,
1369 "l", thishost,
1370 "n", host_arg,
1371 "p", portstr,
1372 "r", options.user,
1373 "u", pw->pw_name,
1374 "i", uidstr,
1375 (char *)NULL);
1376 free(cp); 1383 free(cp);
1377 } 1384 }
1378 1385
1386 if (options.identity_agent != NULL) {
1387 p = tilde_expand_filename(options.identity_agent, getuid());
1388 cp = default_client_percent_expand(p,
1389 pw->pw_dir, host, options.user, pw->pw_name);
1390 free(p);
1391 free(options.identity_agent);
1392 options.identity_agent = cp;
1393 }
1394
1395 if (options.forward_agent_sock_path != NULL) {
1396 p = tilde_expand_filename(options.forward_agent_sock_path,
1397 getuid());
1398 cp = default_client_percent_expand(p,
1399 pw->pw_dir, host, options.user, pw->pw_name);
1400 free(p);
1401 free(options.forward_agent_sock_path);
1402 options.forward_agent_sock_path = cp;
1403 }
1404
1405 for (i = 0; i < options.num_local_forwards; i++) {
1406 if (options.local_forwards[i].listen_path != NULL) {
1407 cp = options.local_forwards[i].listen_path;
1408 p = options.local_forwards[i].listen_path =
1409 default_client_percent_expand(cp,
1410 pw->pw_dir, host, options.user, pw->pw_name);
1411 if (strcmp(cp, p) != 0)
1412 debug3("expanded LocalForward listen path "
1413 "'%s' -> '%s'", cp, p);
1414 free(cp);
1415 }
1416 if (options.local_forwards[i].connect_path != NULL) {
1417 cp = options.local_forwards[i].connect_path;
1418 p = options.local_forwards[i].connect_path =
1419 default_client_percent_expand(cp,
1420 pw->pw_dir, host, options.user, pw->pw_name);
1421 if (strcmp(cp, p) != 0)
1422 debug3("expanded LocalForward connect path "
1423 "'%s' -> '%s'", cp, p);
1424 free(cp);
1425 }
1426 }
1427
1428 for (i = 0; i < options.num_remote_forwards; i++) {
1429 if (options.remote_forwards[i].listen_path != NULL) {
1430 cp = options.remote_forwards[i].listen_path;
1431 p = options.remote_forwards[i].listen_path =
1432 default_client_percent_expand(cp,
1433 pw->pw_dir, host, options.user, pw->pw_name);
1434 if (strcmp(cp, p) != 0)
1435 debug3("expanded RemoteForward listen path "
1436 "'%s' -> '%s'", cp, p);
1437 free(cp);
1438 }
1439 if (options.remote_forwards[i].connect_path != NULL) {
1440 cp = options.remote_forwards[i].connect_path;
1441 p = options.remote_forwards[i].connect_path =
1442 default_client_percent_expand(cp,
1443 pw->pw_dir, host, options.user, pw->pw_name);
1444 if (strcmp(cp, p) != 0)
1445 debug3("expanded RemoteForward connect path "
1446 "'%s' -> '%s'", cp, p);
1447 free(cp);
1448 }
1449 }
1450
1379 if (config_test) { 1451 if (config_test) {
1380 dump_client_config(&options, host); 1452 dump_client_config(&options, host);
1381 exit(0); 1453 exit(0);
@@ -1500,23 +1572,7 @@ main(int ac, char **av)
1500 if (strcmp(options.identity_agent, "none") == 0) { 1572 if (strcmp(options.identity_agent, "none") == 0) {
1501 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1573 unsetenv(SSH_AUTHSOCKET_ENV_NAME);
1502 } else { 1574 } else {
1503 p = tilde_expand_filename(options.identity_agent, 1575 cp = options.identity_agent;
1504 getuid());
1505 cp = percent_expand(p,
1506 "d", pw->pw_dir,
1507 "h", host,
1508 "i", uidstr,
1509 "l", thishost,
1510 "r", options.user,
1511 "u", pw->pw_name,
1512 (char *)NULL);
1513 free(p);
1514 /*
1515 * If identity_agent represents an environment variable
1516 * then recheck that it is valid (since processing with
1517 * percent_expand() may have changed it) and substitute
1518 * its value.
1519 */
1520 if (cp[0] == '$') { 1576 if (cp[0] == '$') {
1521 if (!valid_env_name(cp + 1)) { 1577 if (!valid_env_name(cp + 1)) {
1522 fatal("Invalid IdentityAgent " 1578 fatal("Invalid IdentityAgent "
@@ -1530,22 +1586,11 @@ main(int ac, char **av)
1530 /* identity_agent specifies a path directly */ 1586 /* identity_agent specifies a path directly */
1531 setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); 1587 setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
1532 } 1588 }
1533 free(cp);
1534 } 1589 }
1535 } 1590 }
1536 1591
1537 if (options.forward_agent && (options.forward_agent_sock_path != NULL)) { 1592 if (options.forward_agent && options.forward_agent_sock_path != NULL) {
1538 p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); 1593 cp = options.forward_agent_sock_path;
1539 cp = percent_expand(p,
1540 "d", pw->pw_dir,
1541 "h", host,
1542 "i", uidstr,
1543 "l", thishost,
1544 "r", options.user,
1545 "u", pw->pw_name,
1546 (char *)NULL);
1547 free(p);
1548
1549 if (cp[0] == '$') { 1594 if (cp[0] == '$') {
1550 if (!valid_env_name(cp + 1)) { 1595 if (!valid_env_name(cp + 1)) {
1551 fatal("Invalid ForwardAgent environment variable name %s", cp); 1596 fatal("Invalid ForwardAgent environment variable name %s", cp);
@@ -1676,6 +1721,21 @@ fork_postauth(void)
1676 fatal("daemon() failed: %.200s", strerror(errno)); 1721 fatal("daemon() failed: %.200s", strerror(errno));
1677} 1722}
1678 1723
1724static void
1725forwarding_success(void)
1726{
1727 if (forward_confirms_pending == -1)
1728 return;
1729 if (--forward_confirms_pending == 0) {
1730 debug("%s: all expected forwarding replies received", __func__);
1731 if (fork_after_authentication_flag)
1732 fork_postauth();
1733 } else {
1734 debug2("%s: %d expected forwarding replies remaining",
1735 __func__, forward_confirms_pending);
1736 }
1737}
1738
1679/* Callback for remote forward global requests */ 1739/* Callback for remote forward global requests */
1680static void 1740static void
1681ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) 1741ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
@@ -1735,11 +1795,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
1735 "for listen port %d", rfwd->listen_port); 1795 "for listen port %d", rfwd->listen_port);
1736 } 1796 }
1737 } 1797 }
1738 if (++remote_forward_confirms_received == options.num_remote_forwards) { 1798 forwarding_success();
1739 debug("All remote forwarding requests processed");
1740 if (fork_after_authentication_flag)
1741 fork_postauth();
1742 }
1743} 1799}
1744 1800
1745static void 1801static void
@@ -1757,6 +1813,19 @@ ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
1757} 1813}
1758 1814
1759static void 1815static void
1816ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg)
1817{
1818 if (!success) {
1819 error("Tunnel forwarding failed");
1820 if (options.exit_on_forward_failure)
1821 cleanup_exit(255);
1822 }
1823
1824 debug("%s: tunnel forward established, id=%d", __func__, id);
1825 forwarding_success();
1826}
1827
1828static void
1760ssh_init_stdio_forwarding(struct ssh *ssh) 1829ssh_init_stdio_forwarding(struct ssh *ssh)
1761{ 1830{
1762 Channel *c; 1831 Channel *c;
@@ -1784,6 +1853,8 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
1784 int success = 0; 1853 int success = 0;
1785 int i; 1854 int i;
1786 1855
1856 if (options.exit_on_forward_failure)
1857 forward_confirms_pending = 0; /* track pending requests */
1787 /* Initiate local TCP/IP port forwardings. */ 1858 /* Initiate local TCP/IP port forwardings. */
1788 for (i = 0; i < options.num_local_forwards; i++) { 1859 for (i = 0; i < options.num_local_forwards; i++) {
1789 debug("Local connections to %.200s:%d forwarded to remote " 1860 debug("Local connections to %.200s:%d forwarded to remote "
@@ -1819,32 +1890,33 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
1819 options.remote_forwards[i].connect_path : 1890 options.remote_forwards[i].connect_path :
1820 options.remote_forwards[i].connect_host, 1891 options.remote_forwards[i].connect_host,
1821 options.remote_forwards[i].connect_port); 1892 options.remote_forwards[i].connect_port);
1822 options.remote_forwards[i].handle = 1893 if ((options.remote_forwards[i].handle =
1823 channel_request_remote_forwarding(ssh, 1894 channel_request_remote_forwarding(ssh,
1824 &options.remote_forwards[i]); 1895 &options.remote_forwards[i])) >= 0) {
1825 if (options.remote_forwards[i].handle < 0) {
1826 if (options.exit_on_forward_failure)
1827 fatal("Could not request remote forwarding.");
1828 else
1829 logit("Warning: Could not request remote "
1830 "forwarding.");
1831 } else {
1832 client_register_global_confirm( 1896 client_register_global_confirm(
1833 ssh_confirm_remote_forward, 1897 ssh_confirm_remote_forward,
1834 &options.remote_forwards[i]); 1898 &options.remote_forwards[i]);
1835 } 1899 forward_confirms_pending++;
1900 } else if (options.exit_on_forward_failure)
1901 fatal("Could not request remote forwarding.");
1902 else
1903 logit("Warning: Could not request remote forwarding.");
1836 } 1904 }
1837 1905
1838 /* Initiate tunnel forwarding. */ 1906 /* Initiate tunnel forwarding. */
1839 if (options.tun_open != SSH_TUNMODE_NO) { 1907 if (options.tun_open != SSH_TUNMODE_NO) {
1840 if ((*ifname = client_request_tun_fwd(ssh, 1908 if ((*ifname = client_request_tun_fwd(ssh,
1841 options.tun_open, options.tun_local, 1909 options.tun_open, options.tun_local,
1842 options.tun_remote)) == NULL) { 1910 options.tun_remote, ssh_tun_confirm, NULL)) != NULL)
1843 if (options.exit_on_forward_failure) 1911 forward_confirms_pending++;
1844 fatal("Could not request tunnel forwarding."); 1912 else if (options.exit_on_forward_failure)
1845 else 1913 fatal("Could not request tunnel forwarding.");
1846 error("Could not request tunnel forwarding."); 1914 else
1847 } 1915 error("Could not request tunnel forwarding.");
1916 }
1917 if (forward_confirms_pending > 0) {
1918 debug("%s: expecting replies for %d forwards", __func__,
1919 forward_confirms_pending);
1848 } 1920 }
1849} 1921}
1850 1922
@@ -1970,14 +2042,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
1970 debug3("expanding LocalCommand: %s", options.local_command); 2042 debug3("expanding LocalCommand: %s", options.local_command);
1971 cp = options.local_command; 2043 cp = options.local_command;
1972 options.local_command = percent_expand(cp, 2044 options.local_command = percent_expand(cp,
1973 "C", conn_hash_hex, 2045 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
1974 "L", shorthost,
1975 "d", pw->pw_dir, 2046 "d", pw->pw_dir,
1976 "h", host, 2047 "h", host,
1977 "i", uidstr,
1978 "l", thishost,
1979 "n", host_arg,
1980 "p", portstr,
1981 "r", options.user, 2048 "r", options.user,
1982 "u", pw->pw_name, 2049 "u", pw->pw_name,
1983 "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, 2050 "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
@@ -2134,9 +2201,8 @@ load_public_identity_files(struct passwd *pw)
2134 continue; 2201 continue;
2135 } 2202 }
2136 cp = tilde_expand_filename(options.identity_files[i], getuid()); 2203 cp = tilde_expand_filename(options.identity_files[i], getuid());
2137 filename = percent_expand(cp, "d", pw->pw_dir, 2204 filename = default_client_percent_expand(cp,
2138 "u", pw->pw_name, "l", thishost, "h", host, 2205 pw->pw_dir, host, options.user, pw->pw_name);
2139 "r", options.user, (char *)NULL);
2140 free(cp); 2206 free(cp);
2141 check_load(sshkey_load_public(filename, &public, NULL), 2207 check_load(sshkey_load_public(filename, &public, NULL),
2142 filename, "pubkey"); 2208 filename, "pubkey");
@@ -2185,14 +2251,8 @@ load_public_identity_files(struct passwd *pw)
2185 for (i = 0; i < options.num_certificate_files; i++) { 2251 for (i = 0; i < options.num_certificate_files; i++) {
2186 cp = tilde_expand_filename(options.certificate_files[i], 2252 cp = tilde_expand_filename(options.certificate_files[i],
2187 getuid()); 2253 getuid());
2188 filename = percent_expand(cp, 2254 filename = default_client_percent_expand(cp,
2189 "d", pw->pw_dir, 2255 pw->pw_dir, host, options.user, pw->pw_name);
2190 "h", host,
2191 "i", uidstr,
2192 "l", thishost,
2193 "r", options.user,
2194 "u", pw->pw_name,
2195 (char *)NULL);
2196 free(cp); 2256 free(cp);
2197 2257
2198 check_load(sshkey_load_public(filename, &public, NULL), 2258 check_load(sshkey_load_public(filename, &public, NULL),