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 6138fd4d3..7879d4f4d 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 */
@@ -1210,6 +1236,14 @@ main(int ac, char **av)
1210 if (options.jump_host != NULL) { 1236 if (options.jump_host != NULL) {
1211 char port_s[8]; 1237 char port_s[8];
1212 const char *sshbin = argv0; 1238 const char *sshbin = argv0;
1239 int port = options.port, jumpport = options.jump_port;
1240
1241 if (port <= 0)
1242 port = default_ssh_port();
1243 if (jumpport <= 0)
1244 jumpport = default_ssh_port();
1245 if (strcmp(options.jump_host, host) == 0 && port == jumpport)
1246 fatal("jumphost loop via %s", options.jump_host);
1213 1247
1214 /* 1248 /*
1215 * Try to use SSH indicated by argv[0], but fall back to 1249 * Try to use SSH indicated by argv[0], but fall back to
@@ -1323,15 +1357,8 @@ main(int ac, char **av)
1323 snprintf(uidstr, sizeof(uidstr), "%llu", 1357 snprintf(uidstr, sizeof(uidstr), "%llu",
1324 (unsigned long long)pw->pw_uid); 1358 (unsigned long long)pw->pw_uid);
1325 1359
1326 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || 1360 conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
1327 ssh_digest_update(md, thishost, strlen(thishost)) < 0 || 1361 options.user);
1328 ssh_digest_update(md, host, strlen(host)) < 0 ||
1329 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
1330 ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
1331 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
1332 fatal("%s: mux digest failed", __func__);
1333 ssh_digest_free(md);
1334 conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
1335 1362
1336 /* 1363 /*
1337 * Expand tokens in arguments. NB. LocalCommand is expanded later, 1364 * Expand tokens in arguments. NB. LocalCommand is expanded later,
@@ -1341,18 +1368,8 @@ main(int ac, char **av)
1341 if (options.remote_command != NULL) { 1368 if (options.remote_command != NULL) {
1342 debug3("expanding RemoteCommand: %s", options.remote_command); 1369 debug3("expanding RemoteCommand: %s", options.remote_command);
1343 cp = options.remote_command; 1370 cp = options.remote_command;
1344 options.remote_command = percent_expand(cp, 1371 options.remote_command = default_client_percent_expand(cp,
1345 "C", conn_hash_hex, 1372 pw->pw_dir, host, options.user, pw->pw_name);
1346 "L", shorthost,
1347 "d", pw->pw_dir,
1348 "h", host,
1349 "i", uidstr,
1350 "l", thishost,
1351 "n", host_arg,
1352 "p", portstr,
1353 "r", options.user,
1354 "u", pw->pw_name,
1355 (char *)NULL);
1356 debug3("expanded RemoteCommand: %s", options.remote_command); 1373 debug3("expanded RemoteCommand: %s", options.remote_command);
1357 free(cp); 1374 free(cp);
1358 if ((r = sshbuf_put(command, options.remote_command, 1375 if ((r = sshbuf_put(command, options.remote_command,
@@ -1363,21 +1380,76 @@ main(int ac, char **av)
1363 if (options.control_path != NULL) { 1380 if (options.control_path != NULL) {
1364 cp = tilde_expand_filename(options.control_path, getuid()); 1381 cp = tilde_expand_filename(options.control_path, getuid());
1365 free(options.control_path); 1382 free(options.control_path);
1366 options.control_path = percent_expand(cp, 1383 options.control_path = default_client_percent_expand(cp,
1367 "C", conn_hash_hex, 1384 pw->pw_dir, host, options.user, pw->pw_name);
1368 "L", shorthost,
1369 "h", host,
1370 "i", uidstr,
1371 "l", thishost,
1372 "n", host_arg,
1373 "p", portstr,
1374 "r", options.user,
1375 "u", pw->pw_name,
1376 "i", uidstr,
1377 (char *)NULL);
1378 free(cp); 1385 free(cp);
1379 } 1386 }
1380 1387
1388 if (options.identity_agent != NULL) {
1389 p = tilde_expand_filename(options.identity_agent, getuid());
1390 cp = default_client_percent_expand(p,
1391 pw->pw_dir, host, options.user, pw->pw_name);
1392 free(p);
1393 free(options.identity_agent);
1394 options.identity_agent = cp;
1395 }
1396
1397 if (options.forward_agent_sock_path != NULL) {
1398 p = tilde_expand_filename(options.forward_agent_sock_path,
1399 getuid());
1400 cp = default_client_percent_expand(p,
1401 pw->pw_dir, host, options.user, pw->pw_name);
1402 free(p);
1403 free(options.forward_agent_sock_path);
1404 options.forward_agent_sock_path = cp;
1405 }
1406
1407 for (i = 0; i < options.num_local_forwards; i++) {
1408 if (options.local_forwards[i].listen_path != NULL) {
1409 cp = options.local_forwards[i].listen_path;
1410 p = options.local_forwards[i].listen_path =
1411 default_client_percent_expand(cp,
1412 pw->pw_dir, host, options.user, pw->pw_name);
1413 if (strcmp(cp, p) != 0)
1414 debug3("expanded LocalForward listen path "
1415 "'%s' -> '%s'", cp, p);
1416 free(cp);
1417 }
1418 if (options.local_forwards[i].connect_path != NULL) {
1419 cp = options.local_forwards[i].connect_path;
1420 p = options.local_forwards[i].connect_path =
1421 default_client_percent_expand(cp,
1422 pw->pw_dir, host, options.user, pw->pw_name);
1423 if (strcmp(cp, p) != 0)
1424 debug3("expanded LocalForward connect path "
1425 "'%s' -> '%s'", cp, p);
1426 free(cp);
1427 }
1428 }
1429
1430 for (i = 0; i < options.num_remote_forwards; i++) {
1431 if (options.remote_forwards[i].listen_path != NULL) {
1432 cp = options.remote_forwards[i].listen_path;
1433 p = options.remote_forwards[i].listen_path =
1434 default_client_percent_expand(cp,
1435 pw->pw_dir, host, options.user, pw->pw_name);
1436 if (strcmp(cp, p) != 0)
1437 debug3("expanded RemoteForward listen path "
1438 "'%s' -> '%s'", cp, p);
1439 free(cp);
1440 }
1441 if (options.remote_forwards[i].connect_path != NULL) {
1442 cp = options.remote_forwards[i].connect_path;
1443 p = options.remote_forwards[i].connect_path =
1444 default_client_percent_expand(cp,
1445 pw->pw_dir, host, options.user, pw->pw_name);
1446 if (strcmp(cp, p) != 0)
1447 debug3("expanded RemoteForward connect path "
1448 "'%s' -> '%s'", cp, p);
1449 free(cp);
1450 }
1451 }
1452
1381 if (config_test) { 1453 if (config_test) {
1382 dump_client_config(&options, host); 1454 dump_client_config(&options, host);
1383 exit(0); 1455 exit(0);
@@ -1502,23 +1574,7 @@ main(int ac, char **av)
1502 if (strcmp(options.identity_agent, "none") == 0) { 1574 if (strcmp(options.identity_agent, "none") == 0) {
1503 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1575 unsetenv(SSH_AUTHSOCKET_ENV_NAME);
1504 } else { 1576 } else {
1505 p = tilde_expand_filename(options.identity_agent, 1577 cp = options.identity_agent;
1506 getuid());
1507 cp = percent_expand(p,
1508 "d", pw->pw_dir,
1509 "h", host,
1510 "i", uidstr,
1511 "l", thishost,
1512 "r", options.user,
1513 "u", pw->pw_name,
1514 (char *)NULL);
1515 free(p);
1516 /*
1517 * If identity_agent represents an environment variable
1518 * then recheck that it is valid (since processing with
1519 * percent_expand() may have changed it) and substitute
1520 * its value.
1521 */
1522 if (cp[0] == '$') { 1578 if (cp[0] == '$') {
1523 if (!valid_env_name(cp + 1)) { 1579 if (!valid_env_name(cp + 1)) {
1524 fatal("Invalid IdentityAgent " 1580 fatal("Invalid IdentityAgent "
@@ -1532,22 +1588,11 @@ main(int ac, char **av)
1532 /* identity_agent specifies a path directly */ 1588 /* identity_agent specifies a path directly */
1533 setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); 1589 setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
1534 } 1590 }
1535 free(cp);
1536 } 1591 }
1537 } 1592 }
1538 1593
1539 if (options.forward_agent && (options.forward_agent_sock_path != NULL)) { 1594 if (options.forward_agent && options.forward_agent_sock_path != NULL) {
1540 p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); 1595 cp = options.forward_agent_sock_path;
1541 cp = percent_expand(p,
1542 "d", pw->pw_dir,
1543 "h", host,
1544 "i", uidstr,
1545 "l", thishost,
1546 "r", options.user,
1547 "u", pw->pw_name,
1548 (char *)NULL);
1549 free(p);
1550
1551 if (cp[0] == '$') { 1596 if (cp[0] == '$') {
1552 if (!valid_env_name(cp + 1)) { 1597 if (!valid_env_name(cp + 1)) {
1553 fatal("Invalid ForwardAgent environment variable name %s", cp); 1598 fatal("Invalid ForwardAgent environment variable name %s", cp);
@@ -1678,6 +1723,21 @@ fork_postauth(void)
1678 fatal("daemon() failed: %.200s", strerror(errno)); 1723 fatal("daemon() failed: %.200s", strerror(errno));
1679} 1724}
1680 1725
1726static void
1727forwarding_success(void)
1728{
1729 if (forward_confirms_pending == -1)
1730 return;
1731 if (--forward_confirms_pending == 0) {
1732 debug("%s: all expected forwarding replies received", __func__);
1733 if (fork_after_authentication_flag)
1734 fork_postauth();
1735 } else {
1736 debug2("%s: %d expected forwarding replies remaining",
1737 __func__, forward_confirms_pending);
1738 }
1739}
1740
1681/* Callback for remote forward global requests */ 1741/* Callback for remote forward global requests */
1682static void 1742static void
1683ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) 1743ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
@@ -1737,11 +1797,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
1737 "for listen port %d", rfwd->listen_port); 1797 "for listen port %d", rfwd->listen_port);
1738 } 1798 }
1739 } 1799 }
1740 if (++remote_forward_confirms_received == options.num_remote_forwards) { 1800 forwarding_success();
1741 debug("All remote forwarding requests processed");
1742 if (fork_after_authentication_flag)
1743 fork_postauth();
1744 }
1745} 1801}
1746 1802
1747static void 1803static void
@@ -1759,6 +1815,19 @@ ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
1759} 1815}
1760 1816
1761static void 1817static void
1818ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg)
1819{
1820 if (!success) {
1821 error("Tunnel forwarding failed");
1822 if (options.exit_on_forward_failure)
1823 cleanup_exit(255);
1824 }
1825
1826 debug("%s: tunnel forward established, id=%d", __func__, id);
1827 forwarding_success();
1828}
1829
1830static void
1762ssh_init_stdio_forwarding(struct ssh *ssh) 1831ssh_init_stdio_forwarding(struct ssh *ssh)
1763{ 1832{
1764 Channel *c; 1833 Channel *c;
@@ -1786,6 +1855,8 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
1786 int success = 0; 1855 int success = 0;
1787 int i; 1856 int i;
1788 1857
1858 if (options.exit_on_forward_failure)
1859 forward_confirms_pending = 0; /* track pending requests */
1789 /* Initiate local TCP/IP port forwardings. */ 1860 /* Initiate local TCP/IP port forwardings. */
1790 for (i = 0; i < options.num_local_forwards; i++) { 1861 for (i = 0; i < options.num_local_forwards; i++) {
1791 debug("Local connections to %.200s:%d forwarded to remote " 1862 debug("Local connections to %.200s:%d forwarded to remote "
@@ -1821,32 +1892,33 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
1821 options.remote_forwards[i].connect_path : 1892 options.remote_forwards[i].connect_path :
1822 options.remote_forwards[i].connect_host, 1893 options.remote_forwards[i].connect_host,
1823 options.remote_forwards[i].connect_port); 1894 options.remote_forwards[i].connect_port);
1824 options.remote_forwards[i].handle = 1895 if ((options.remote_forwards[i].handle =
1825 channel_request_remote_forwarding(ssh, 1896 channel_request_remote_forwarding(ssh,
1826 &options.remote_forwards[i]); 1897 &options.remote_forwards[i])) >= 0) {
1827 if (options.remote_forwards[i].handle < 0) {
1828 if (options.exit_on_forward_failure)
1829 fatal("Could not request remote forwarding.");
1830 else
1831 logit("Warning: Could not request remote "
1832 "forwarding.");
1833 } else {
1834 client_register_global_confirm( 1898 client_register_global_confirm(
1835 ssh_confirm_remote_forward, 1899 ssh_confirm_remote_forward,
1836 &options.remote_forwards[i]); 1900 &options.remote_forwards[i]);
1837 } 1901 forward_confirms_pending++;
1902 } else if (options.exit_on_forward_failure)
1903 fatal("Could not request remote forwarding.");
1904 else
1905 logit("Warning: Could not request remote forwarding.");
1838 } 1906 }
1839 1907
1840 /* Initiate tunnel forwarding. */ 1908 /* Initiate tunnel forwarding. */
1841 if (options.tun_open != SSH_TUNMODE_NO) { 1909 if (options.tun_open != SSH_TUNMODE_NO) {
1842 if ((*ifname = client_request_tun_fwd(ssh, 1910 if ((*ifname = client_request_tun_fwd(ssh,
1843 options.tun_open, options.tun_local, 1911 options.tun_open, options.tun_local,
1844 options.tun_remote)) == NULL) { 1912 options.tun_remote, ssh_tun_confirm, NULL)) != NULL)
1845 if (options.exit_on_forward_failure) 1913 forward_confirms_pending++;
1846 fatal("Could not request tunnel forwarding."); 1914 else if (options.exit_on_forward_failure)
1847 else 1915 fatal("Could not request tunnel forwarding.");
1848 error("Could not request tunnel forwarding."); 1916 else
1849 } 1917 error("Could not request tunnel forwarding.");
1918 }
1919 if (forward_confirms_pending > 0) {
1920 debug("%s: expecting replies for %d forwards", __func__,
1921 forward_confirms_pending);
1850 } 1922 }
1851} 1923}
1852 1924
@@ -1972,14 +2044,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
1972 debug3("expanding LocalCommand: %s", options.local_command); 2044 debug3("expanding LocalCommand: %s", options.local_command);
1973 cp = options.local_command; 2045 cp = options.local_command;
1974 options.local_command = percent_expand(cp, 2046 options.local_command = percent_expand(cp,
1975 "C", conn_hash_hex, 2047 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
1976 "L", shorthost,
1977 "d", pw->pw_dir, 2048 "d", pw->pw_dir,
1978 "h", host, 2049 "h", host,
1979 "i", uidstr,
1980 "l", thishost,
1981 "n", host_arg,
1982 "p", portstr,
1983 "r", options.user, 2050 "r", options.user,
1984 "u", pw->pw_name, 2051 "u", pw->pw_name,
1985 "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, 2052 "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
@@ -2136,9 +2203,8 @@ load_public_identity_files(struct passwd *pw)
2136 continue; 2203 continue;
2137 } 2204 }
2138 cp = tilde_expand_filename(options.identity_files[i], getuid()); 2205 cp = tilde_expand_filename(options.identity_files[i], getuid());
2139 filename = percent_expand(cp, "d", pw->pw_dir, 2206 filename = default_client_percent_expand(cp,
2140 "u", pw->pw_name, "l", thishost, "h", host, 2207 pw->pw_dir, host, options.user, pw->pw_name);
2141 "r", options.user, (char *)NULL);
2142 free(cp); 2208 free(cp);
2143 check_load(sshkey_load_public(filename, &public, NULL), 2209 check_load(sshkey_load_public(filename, &public, NULL),
2144 filename, "pubkey"); 2210 filename, "pubkey");
@@ -2187,14 +2253,8 @@ load_public_identity_files(struct passwd *pw)
2187 for (i = 0; i < options.num_certificate_files; i++) { 2253 for (i = 0; i < options.num_certificate_files; i++) {
2188 cp = tilde_expand_filename(options.certificate_files[i], 2254 cp = tilde_expand_filename(options.certificate_files[i],
2189 getuid()); 2255 getuid());
2190 filename = percent_expand(cp, 2256 filename = default_client_percent_expand(cp,
2191 "d", pw->pw_dir, 2257 pw->pw_dir, host, options.user, pw->pw_name);
2192 "h", host,
2193 "i", uidstr,
2194 "l", thishost,
2195 "r", options.user,
2196 "u", pw->pw_name,
2197 (char *)NULL);
2198 free(cp); 2258 free(cp);
2199 2259
2200 check_load(sshkey_load_public(filename, &public, NULL), 2260 check_load(sshkey_load_public(filename, &public, NULL),