summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c128
1 files changed, 88 insertions, 40 deletions
diff --git a/ssh.c b/ssh.c
index 7879d4f4d..aa15b8a1f 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker Exp $ */ 1/* $OpenBSD: ssh.c,v 1.536 2020/09/21 07:29:09 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
@@ -16,7 +16,7 @@
16 * Copyright (c) 1999 Niels Provos. All rights reserved. 16 * Copyright (c) 1999 Niels Provos. All rights reserved.
17 * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved. 17 * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved.
18 * 18 *
19 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> 19 * Modified to work with SSLeay by Niels Provos <provos@citi.umich.edu>
20 * in Canada (German citizen). 20 * in Canada (German citizen).
21 * 21 *
22 * Redistribution and use in source and binary forms, with or without 22 * Redistribution and use in source and binary forms, with or without
@@ -137,11 +137,11 @@ int stdin_null_flag = 0;
137 137
138/* 138/*
139 * Flag indicating that the current process should be backgrounded and 139 * Flag indicating that the current process should be backgrounded and
140 * a new slave launched in the foreground for ControlPersist. 140 * a new mux-client launched in the foreground for ControlPersist.
141 */ 141 */
142int need_controlpersist_detach = 0; 142int need_controlpersist_detach = 0;
143 143
144/* Copies of flags for ControlPersist foreground slave */ 144/* Copies of flags for ControlPersist foreground mux-client */
145int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty; 145int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
146 146
147/* 147/*
@@ -176,6 +176,7 @@ char *forward_agent_sock_path = NULL;
176/* Various strings used to to percent_expand() arguments */ 176/* Various strings used to to percent_expand() arguments */
177static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 177static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
178static char uidstr[32], *host_arg, *conn_hash_hex; 178static char uidstr[32], *host_arg, *conn_hash_hex;
179static const char *keyalias;
179 180
180/* socket address the host resolves to */ 181/* socket address the host resolves to */
181struct sockaddr_storage hostaddr; 182struct sockaddr_storage hostaddr;
@@ -235,6 +236,7 @@ tilde_expand_paths(char **paths, u_int num_paths)
235 "C", conn_hash_hex, \ 236 "C", conn_hash_hex, \
236 "L", shorthost, \ 237 "L", shorthost, \
237 "i", uidstr, \ 238 "i", uidstr, \
239 "k", keyalias, \
238 "l", thishost, \ 240 "l", thishost, \
239 "n", host_arg, \ 241 "n", host_arg, \
240 "p", portstr 242 "p", portstr
@@ -260,6 +262,31 @@ default_client_percent_expand(const char *str, const char *homedir,
260} 262}
261 263
262/* 264/*
265 * Expands the set of percent_expand options used by the majority of keywords
266 * AND perform environment variable substitution.
267 * Caller must free returned string.
268 */
269static char *
270default_client_percent_dollar_expand(const char *str, const char *homedir,
271 const char *remhost, const char *remuser, const char *locuser)
272{
273 char *ret;
274
275 ret = percent_dollar_expand(str,
276 /* values from statics above */
277 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
278 /* values from arguments */
279 "d", homedir,
280 "h", remhost,
281 "r", remuser,
282 "u", locuser,
283 (char *)NULL);
284 if (ret == NULL)
285 fatal("invalid environment variable expansion");
286 return ret;
287}
288
289/*
263 * Attempt to resolve a host name / port to a set of addresses and 290 * Attempt to resolve a host name / port to a set of addresses and
264 * optionally return any CNAMEs encountered along the way. 291 * optionally return any CNAMEs encountered along the way.
265 * Returns NULL on failure. 292 * Returns NULL on failure.
@@ -620,7 +647,7 @@ main(int ac, char **av)
620 struct ssh *ssh = NULL; 647 struct ssh *ssh = NULL;
621 int i, r, opt, exit_status, use_syslog, direct, timeout_ms; 648 int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
622 int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; 649 int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
623 char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; 650 char *p, *cp, *line, *argv0, *logfile;
624 char cname[NI_MAXHOST]; 651 char cname[NI_MAXHOST];
625 struct stat st; 652 struct stat st;
626 struct passwd *pw; 653 struct passwd *pw;
@@ -629,6 +656,7 @@ main(int ac, char **av)
629 struct Forward fwd; 656 struct Forward fwd;
630 struct addrinfo *addrs = NULL; 657 struct addrinfo *addrs = NULL;
631 size_t n, len; 658 size_t n, len;
659 u_int j;
632 660
633 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 661 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
634 sanitise_stdfd(); 662 sanitise_stdfd();
@@ -1230,19 +1258,25 @@ main(int ac, char **av)
1230 /* Fill configuration defaults. */ 1258 /* Fill configuration defaults. */
1231 fill_default_options(&options); 1259 fill_default_options(&options);
1232 1260
1261 if (options.user == NULL)
1262 options.user = xstrdup(pw->pw_name);
1263
1233 /* 1264 /*
1234 * If ProxyJump option specified, then construct a ProxyCommand now. 1265 * If ProxyJump option specified, then construct a ProxyCommand now.
1235 */ 1266 */
1236 if (options.jump_host != NULL) { 1267 if (options.jump_host != NULL) {
1237 char port_s[8]; 1268 char port_s[8];
1238 const char *sshbin = argv0; 1269 const char *jumpuser = options.jump_user, *sshbin = argv0;
1239 int port = options.port, jumpport = options.jump_port; 1270 int port = options.port, jumpport = options.jump_port;
1240 1271
1241 if (port <= 0) 1272 if (port <= 0)
1242 port = default_ssh_port(); 1273 port = default_ssh_port();
1243 if (jumpport <= 0) 1274 if (jumpport <= 0)
1244 jumpport = default_ssh_port(); 1275 jumpport = default_ssh_port();
1245 if (strcmp(options.jump_host, host) == 0 && port == jumpport) 1276 if (jumpuser == NULL)
1277 jumpuser = options.user;
1278 if (strcmp(options.jump_host, host) == 0 && port == jumpport &&
1279 strcmp(options.user, jumpuser) == 0)
1246 fatal("jumphost loop via %s", options.jump_host); 1280 fatal("jumphost loop via %s", options.jump_host);
1247 1281
1248 /* 1282 /*
@@ -1345,9 +1379,6 @@ main(int ac, char **av)
1345 tty_flag = 0; 1379 tty_flag = 0;
1346 } 1380 }
1347 1381
1348 if (options.user == NULL)
1349 options.user = xstrdup(pw->pw_name);
1350
1351 /* Set up strings used to percent_expand() arguments */ 1382 /* Set up strings used to percent_expand() arguments */
1352 if (gethostname(thishost, sizeof(thishost)) == -1) 1383 if (gethostname(thishost, sizeof(thishost)) == -1)
1353 fatal("gethostname: %s", strerror(errno)); 1384 fatal("gethostname: %s", strerror(errno));
@@ -1356,6 +1387,7 @@ main(int ac, char **av)
1356 snprintf(portstr, sizeof(portstr), "%d", options.port); 1387 snprintf(portstr, sizeof(portstr), "%d", options.port);
1357 snprintf(uidstr, sizeof(uidstr), "%llu", 1388 snprintf(uidstr, sizeof(uidstr), "%llu",
1358 (unsigned long long)pw->pw_uid); 1389 (unsigned long long)pw->pw_uid);
1390 keyalias = options.host_key_alias ? options.host_key_alias : host_arg;
1359 1391
1360 conn_hash_hex = ssh_connection_hash(thishost, host, portstr, 1392 conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
1361 options.user); 1393 options.user);
@@ -1380,14 +1412,14 @@ main(int ac, char **av)
1380 if (options.control_path != NULL) { 1412 if (options.control_path != NULL) {
1381 cp = tilde_expand_filename(options.control_path, getuid()); 1413 cp = tilde_expand_filename(options.control_path, getuid());
1382 free(options.control_path); 1414 free(options.control_path);
1383 options.control_path = default_client_percent_expand(cp, 1415 options.control_path = default_client_percent_dollar_expand(cp,
1384 pw->pw_dir, host, options.user, pw->pw_name); 1416 pw->pw_dir, host, options.user, pw->pw_name);
1385 free(cp); 1417 free(cp);
1386 } 1418 }
1387 1419
1388 if (options.identity_agent != NULL) { 1420 if (options.identity_agent != NULL) {
1389 p = tilde_expand_filename(options.identity_agent, getuid()); 1421 p = tilde_expand_filename(options.identity_agent, getuid());
1390 cp = default_client_percent_expand(p, 1422 cp = default_client_percent_dollar_expand(p,
1391 pw->pw_dir, host, options.user, pw->pw_name); 1423 pw->pw_dir, host, options.user, pw->pw_name);
1392 free(p); 1424 free(p);
1393 free(options.identity_agent); 1425 free(options.identity_agent);
@@ -1397,13 +1429,28 @@ main(int ac, char **av)
1397 if (options.forward_agent_sock_path != NULL) { 1429 if (options.forward_agent_sock_path != NULL) {
1398 p = tilde_expand_filename(options.forward_agent_sock_path, 1430 p = tilde_expand_filename(options.forward_agent_sock_path,
1399 getuid()); 1431 getuid());
1400 cp = default_client_percent_expand(p, 1432 cp = default_client_percent_dollar_expand(p,
1401 pw->pw_dir, host, options.user, pw->pw_name); 1433 pw->pw_dir, host, options.user, pw->pw_name);
1402 free(p); 1434 free(p);
1403 free(options.forward_agent_sock_path); 1435 free(options.forward_agent_sock_path);
1404 options.forward_agent_sock_path = cp; 1436 options.forward_agent_sock_path = cp;
1405 } 1437 }
1406 1438
1439 for (j = 0; j < options.num_user_hostfiles; j++) {
1440 if (options.user_hostfiles[j] != NULL) {
1441 cp = tilde_expand_filename(options.user_hostfiles[j],
1442 getuid());
1443 p = default_client_percent_dollar_expand(cp,
1444 pw->pw_dir, host, options.user, pw->pw_name);
1445 if (strcmp(options.user_hostfiles[j], p) != 0)
1446 debug3("expanded UserKnownHostsFile '%s' -> "
1447 "'%s'", options.user_hostfiles[j], p);
1448 free(options.user_hostfiles[j]);
1449 free(cp);
1450 options.user_hostfiles[j] = p;
1451 }
1452 }
1453
1407 for (i = 0; i < options.num_local_forwards; i++) { 1454 for (i = 0; i < options.num_local_forwards; i++) {
1408 if (options.local_forwards[i].listen_path != NULL) { 1455 if (options.local_forwards[i].listen_path != NULL) {
1409 cp = options.local_forwards[i].listen_path; 1456 cp = options.local_forwards[i].listen_path;
@@ -1549,22 +1596,6 @@ main(int ac, char **av)
1549 } 1596 }
1550 } 1597 }
1551 1598
1552 /* Create ~/.ssh * directory if it doesn't already exist. */
1553 if (config == NULL) {
1554 r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
1555 strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
1556 if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) {
1557#ifdef WITH_SELINUX
1558 ssh_selinux_setfscreatecon(buf);
1559#endif
1560 if (mkdir(buf, 0700) < 0)
1561 error("Could not create directory '%.200s'.",
1562 buf);
1563#ifdef WITH_SELINUX
1564 ssh_selinux_setfscreatecon(NULL);
1565#endif
1566 }
1567 }
1568 /* load options.identity_files */ 1599 /* load options.identity_files */
1569 load_public_identity_files(pw); 1600 load_public_identity_files(pw);
1570 1601
@@ -1575,7 +1606,8 @@ main(int ac, char **av)
1575 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1606 unsetenv(SSH_AUTHSOCKET_ENV_NAME);
1576 } else { 1607 } else {
1577 cp = options.identity_agent; 1608 cp = options.identity_agent;
1578 if (cp[0] == '$') { 1609 /* legacy (limited) format */
1610 if (cp[0] == '$' && cp[1] != '{') {
1579 if (!valid_env_name(cp + 1)) { 1611 if (!valid_env_name(cp + 1)) {
1580 fatal("Invalid IdentityAgent " 1612 fatal("Invalid IdentityAgent "
1581 "environment variable name %s", cp); 1613 "environment variable name %s", cp);
@@ -1683,7 +1715,7 @@ control_persist_detach(void)
1683 /* Child: master process continues mainloop */ 1715 /* Child: master process continues mainloop */
1684 break; 1716 break;
1685 default: 1717 default:
1686 /* Parent: set up mux slave to connect to backgrounded master */ 1718 /* Parent: set up mux client to connect to backgrounded master */
1687 debug2("%s: background process is %ld", __func__, (long)pid); 1719 debug2("%s: background process is %ld", __func__, (long)pid);
1688 stdin_null_flag = ostdin_null_flag; 1720 stdin_null_flag = ostdin_null_flag;
1689 options.request_tty = orequest_tty; 1721 options.request_tty = orequest_tty;
@@ -1715,12 +1747,26 @@ control_persist_detach(void)
1715static void 1747static void
1716fork_postauth(void) 1748fork_postauth(void)
1717{ 1749{
1750 int devnull, keep_stderr;
1751
1718 if (need_controlpersist_detach) 1752 if (need_controlpersist_detach)
1719 control_persist_detach(); 1753 control_persist_detach();
1720 debug("forking to background"); 1754 debug("forking to background");
1721 fork_after_authentication_flag = 0; 1755 fork_after_authentication_flag = 0;
1722 if (daemon(1, 1) == -1) 1756 if (daemon(1, 1) == -1)
1723 fatal("daemon() failed: %.200s", strerror(errno)); 1757 fatal("daemon() failed: %.200s", strerror(errno));
1758 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
1759 error("%s: open %s: %s", __func__,
1760 _PATH_DEVNULL, strerror(errno));
1761 else {
1762 keep_stderr = log_is_on_stderr() && debug_flag;
1763 if (dup2(devnull, STDIN_FILENO) == -1 ||
1764 dup2(devnull, STDOUT_FILENO) == -1 ||
1765 (!keep_stderr && dup2(devnull, STDOUT_FILENO) == -1))
1766 fatal("%s: dup2() stdio failed", __func__);
1767 if (devnull > STDERR_FILENO)
1768 close(devnull);
1769 }
1724} 1770}
1725 1771
1726static void 1772static void
@@ -2062,9 +2108,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
2062 /* 2108 /*
2063 * If we are in control persist mode and have a working mux listen 2109 * If we are in control persist mode and have a working mux listen
2064 * socket, then prepare to background ourselves and have a foreground 2110 * socket, then prepare to background ourselves and have a foreground
2065 * client attach as a control slave. 2111 * client attach as a control client.
2066 * NB. we must save copies of the flags that we override for 2112 * NB. we must save copies of the flags that we override for
2067 * the backgrounding, since we defer attachment of the slave until 2113 * the backgrounding, since we defer attachment of the client until
2068 * after the connection is fully established (in particular, 2114 * after the connection is fully established (in particular,
2069 * async rfwd replies have been received for ExitOnForwardFailure). 2115 * async rfwd replies have been received for ExitOnForwardFailure).
2070 */ 2116 */
@@ -2119,13 +2165,15 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
2119 * as it may want to write to stdout. 2165 * as it may want to write to stdout.
2120 */ 2166 */
2121 if (!need_controlpersist_detach) { 2167 if (!need_controlpersist_detach) {
2122 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) 2168 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
2123 error("%s: open %s: %s", __func__, 2169 error("%s: open %s: %s", __func__,
2124 _PATH_DEVNULL, strerror(errno)); 2170 _PATH_DEVNULL, strerror(errno));
2125 if (dup2(devnull, STDOUT_FILENO) == -1) 2171 } else {
2126 fatal("%s: dup2() stdout failed", __func__); 2172 if (dup2(devnull, STDOUT_FILENO) == -1)
2127 if (devnull > STDERR_FILENO) 2173 fatal("%s: dup2() stdout failed", __func__);
2128 close(devnull); 2174 if (devnull > STDERR_FILENO)
2175 close(devnull);
2176 }
2129 } 2177 }
2130 2178
2131 /* 2179 /*
@@ -2203,7 +2251,7 @@ load_public_identity_files(struct passwd *pw)
2203 continue; 2251 continue;
2204 } 2252 }
2205 cp = tilde_expand_filename(options.identity_files[i], getuid()); 2253 cp = tilde_expand_filename(options.identity_files[i], getuid());
2206 filename = default_client_percent_expand(cp, 2254 filename = default_client_percent_dollar_expand(cp,
2207 pw->pw_dir, host, options.user, pw->pw_name); 2255 pw->pw_dir, host, options.user, pw->pw_name);
2208 free(cp); 2256 free(cp);
2209 check_load(sshkey_load_public(filename, &public, NULL), 2257 check_load(sshkey_load_public(filename, &public, NULL),
@@ -2253,7 +2301,7 @@ load_public_identity_files(struct passwd *pw)
2253 for (i = 0; i < options.num_certificate_files; i++) { 2301 for (i = 0; i < options.num_certificate_files; i++) {
2254 cp = tilde_expand_filename(options.certificate_files[i], 2302 cp = tilde_expand_filename(options.certificate_files[i],
2255 getuid()); 2303 getuid());
2256 filename = default_client_percent_expand(cp, 2304 filename = default_client_percent_dollar_expand(cp,
2257 pw->pw_dir, host, options.user, pw->pw_name); 2305 pw->pw_dir, host, options.user, pw->pw_name);
2258 free(cp); 2306 free(cp);
2259 2307