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 98b6ce788..f34ca0d71 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();
@@ -1228,19 +1256,25 @@ main(int ac, char **av)
1228 /* Fill configuration defaults. */ 1256 /* Fill configuration defaults. */
1229 fill_default_options(&options); 1257 fill_default_options(&options);
1230 1258
1259 if (options.user == NULL)
1260 options.user = xstrdup(pw->pw_name);
1261
1231 /* 1262 /*
1232 * If ProxyJump option specified, then construct a ProxyCommand now. 1263 * If ProxyJump option specified, then construct a ProxyCommand now.
1233 */ 1264 */
1234 if (options.jump_host != NULL) { 1265 if (options.jump_host != NULL) {
1235 char port_s[8]; 1266 char port_s[8];
1236 const char *sshbin = argv0; 1267 const char *jumpuser = options.jump_user, *sshbin = argv0;
1237 int port = options.port, jumpport = options.jump_port; 1268 int port = options.port, jumpport = options.jump_port;
1238 1269
1239 if (port <= 0) 1270 if (port <= 0)
1240 port = default_ssh_port(); 1271 port = default_ssh_port();
1241 if (jumpport <= 0) 1272 if (jumpport <= 0)
1242 jumpport = default_ssh_port(); 1273 jumpport = default_ssh_port();
1243 if (strcmp(options.jump_host, host) == 0 && port == jumpport) 1274 if (jumpuser == NULL)
1275 jumpuser = options.user;
1276 if (strcmp(options.jump_host, host) == 0 && port == jumpport &&
1277 strcmp(options.user, jumpuser) == 0)
1244 fatal("jumphost loop via %s", options.jump_host); 1278 fatal("jumphost loop via %s", options.jump_host);
1245 1279
1246 /* 1280 /*
@@ -1343,9 +1377,6 @@ main(int ac, char **av)
1343 tty_flag = 0; 1377 tty_flag = 0;
1344 } 1378 }
1345 1379
1346 if (options.user == NULL)
1347 options.user = xstrdup(pw->pw_name);
1348
1349 /* Set up strings used to percent_expand() arguments */ 1380 /* Set up strings used to percent_expand() arguments */
1350 if (gethostname(thishost, sizeof(thishost)) == -1) 1381 if (gethostname(thishost, sizeof(thishost)) == -1)
1351 fatal("gethostname: %s", strerror(errno)); 1382 fatal("gethostname: %s", strerror(errno));
@@ -1354,6 +1385,7 @@ main(int ac, char **av)
1354 snprintf(portstr, sizeof(portstr), "%d", options.port); 1385 snprintf(portstr, sizeof(portstr), "%d", options.port);
1355 snprintf(uidstr, sizeof(uidstr), "%llu", 1386 snprintf(uidstr, sizeof(uidstr), "%llu",
1356 (unsigned long long)pw->pw_uid); 1387 (unsigned long long)pw->pw_uid);
1388 keyalias = options.host_key_alias ? options.host_key_alias : host_arg;
1357 1389
1358 conn_hash_hex = ssh_connection_hash(thishost, host, portstr, 1390 conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
1359 options.user); 1391 options.user);
@@ -1378,14 +1410,14 @@ main(int ac, char **av)
1378 if (options.control_path != NULL) { 1410 if (options.control_path != NULL) {
1379 cp = tilde_expand_filename(options.control_path, getuid()); 1411 cp = tilde_expand_filename(options.control_path, getuid());
1380 free(options.control_path); 1412 free(options.control_path);
1381 options.control_path = default_client_percent_expand(cp, 1413 options.control_path = default_client_percent_dollar_expand(cp,
1382 pw->pw_dir, host, options.user, pw->pw_name); 1414 pw->pw_dir, host, options.user, pw->pw_name);
1383 free(cp); 1415 free(cp);
1384 } 1416 }
1385 1417
1386 if (options.identity_agent != NULL) { 1418 if (options.identity_agent != NULL) {
1387 p = tilde_expand_filename(options.identity_agent, getuid()); 1419 p = tilde_expand_filename(options.identity_agent, getuid());
1388 cp = default_client_percent_expand(p, 1420 cp = default_client_percent_dollar_expand(p,
1389 pw->pw_dir, host, options.user, pw->pw_name); 1421 pw->pw_dir, host, options.user, pw->pw_name);
1390 free(p); 1422 free(p);
1391 free(options.identity_agent); 1423 free(options.identity_agent);
@@ -1395,13 +1427,28 @@ main(int ac, char **av)
1395 if (options.forward_agent_sock_path != NULL) { 1427 if (options.forward_agent_sock_path != NULL) {
1396 p = tilde_expand_filename(options.forward_agent_sock_path, 1428 p = tilde_expand_filename(options.forward_agent_sock_path,
1397 getuid()); 1429 getuid());
1398 cp = default_client_percent_expand(p, 1430 cp = default_client_percent_dollar_expand(p,
1399 pw->pw_dir, host, options.user, pw->pw_name); 1431 pw->pw_dir, host, options.user, pw->pw_name);
1400 free(p); 1432 free(p);
1401 free(options.forward_agent_sock_path); 1433 free(options.forward_agent_sock_path);
1402 options.forward_agent_sock_path = cp; 1434 options.forward_agent_sock_path = cp;
1403 } 1435 }
1404 1436
1437 for (j = 0; j < options.num_user_hostfiles; j++) {
1438 if (options.user_hostfiles[j] != NULL) {
1439 cp = tilde_expand_filename(options.user_hostfiles[j],
1440 getuid());
1441 p = default_client_percent_dollar_expand(cp,
1442 pw->pw_dir, host, options.user, pw->pw_name);
1443 if (strcmp(options.user_hostfiles[j], p) != 0)
1444 debug3("expanded UserKnownHostsFile '%s' -> "
1445 "'%s'", options.user_hostfiles[j], p);
1446 free(options.user_hostfiles[j]);
1447 free(cp);
1448 options.user_hostfiles[j] = p;
1449 }
1450 }
1451
1405 for (i = 0; i < options.num_local_forwards; i++) { 1452 for (i = 0; i < options.num_local_forwards; i++) {
1406 if (options.local_forwards[i].listen_path != NULL) { 1453 if (options.local_forwards[i].listen_path != NULL) {
1407 cp = options.local_forwards[i].listen_path; 1454 cp = options.local_forwards[i].listen_path;
@@ -1547,22 +1594,6 @@ main(int ac, char **av)
1547 } 1594 }
1548 } 1595 }
1549 1596
1550 /* Create ~/.ssh * directory if it doesn't already exist. */
1551 if (config == NULL) {
1552 r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
1553 strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
1554 if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) {
1555#ifdef WITH_SELINUX
1556 ssh_selinux_setfscreatecon(buf);
1557#endif
1558 if (mkdir(buf, 0700) < 0)
1559 error("Could not create directory '%.200s'.",
1560 buf);
1561#ifdef WITH_SELINUX
1562 ssh_selinux_setfscreatecon(NULL);
1563#endif
1564 }
1565 }
1566 /* load options.identity_files */ 1597 /* load options.identity_files */
1567 load_public_identity_files(pw); 1598 load_public_identity_files(pw);
1568 1599
@@ -1573,7 +1604,8 @@ main(int ac, char **av)
1573 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1604 unsetenv(SSH_AUTHSOCKET_ENV_NAME);
1574 } else { 1605 } else {
1575 cp = options.identity_agent; 1606 cp = options.identity_agent;
1576 if (cp[0] == '$') { 1607 /* legacy (limited) format */
1608 if (cp[0] == '$' && cp[1] != '{') {
1577 if (!valid_env_name(cp + 1)) { 1609 if (!valid_env_name(cp + 1)) {
1578 fatal("Invalid IdentityAgent " 1610 fatal("Invalid IdentityAgent "
1579 "environment variable name %s", cp); 1611 "environment variable name %s", cp);
@@ -1681,7 +1713,7 @@ control_persist_detach(void)
1681 /* Child: master process continues mainloop */ 1713 /* Child: master process continues mainloop */
1682 break; 1714 break;
1683 default: 1715 default:
1684 /* Parent: set up mux slave to connect to backgrounded master */ 1716 /* Parent: set up mux client to connect to backgrounded master */
1685 debug2("%s: background process is %ld", __func__, (long)pid); 1717 debug2("%s: background process is %ld", __func__, (long)pid);
1686 stdin_null_flag = ostdin_null_flag; 1718 stdin_null_flag = ostdin_null_flag;
1687 options.request_tty = orequest_tty; 1719 options.request_tty = orequest_tty;
@@ -1713,12 +1745,26 @@ control_persist_detach(void)
1713static void 1745static void
1714fork_postauth(void) 1746fork_postauth(void)
1715{ 1747{
1748 int devnull, keep_stderr;
1749
1716 if (need_controlpersist_detach) 1750 if (need_controlpersist_detach)
1717 control_persist_detach(); 1751 control_persist_detach();
1718 debug("forking to background"); 1752 debug("forking to background");
1719 fork_after_authentication_flag = 0; 1753 fork_after_authentication_flag = 0;
1720 if (daemon(1, 1) == -1) 1754 if (daemon(1, 1) == -1)
1721 fatal("daemon() failed: %.200s", strerror(errno)); 1755 fatal("daemon() failed: %.200s", strerror(errno));
1756 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
1757 error("%s: open %s: %s", __func__,
1758 _PATH_DEVNULL, strerror(errno));
1759 else {
1760 keep_stderr = log_is_on_stderr() && debug_flag;
1761 if (dup2(devnull, STDIN_FILENO) == -1 ||
1762 dup2(devnull, STDOUT_FILENO) == -1 ||
1763 (!keep_stderr && dup2(devnull, STDOUT_FILENO) == -1))
1764 fatal("%s: dup2() stdio failed", __func__);
1765 if (devnull > STDERR_FILENO)
1766 close(devnull);
1767 }
1722} 1768}
1723 1769
1724static void 1770static void
@@ -2060,9 +2106,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
2060 /* 2106 /*
2061 * If we are in control persist mode and have a working mux listen 2107 * If we are in control persist mode and have a working mux listen
2062 * socket, then prepare to background ourselves and have a foreground 2108 * socket, then prepare to background ourselves and have a foreground
2063 * client attach as a control slave. 2109 * client attach as a control client.
2064 * NB. we must save copies of the flags that we override for 2110 * NB. we must save copies of the flags that we override for
2065 * the backgrounding, since we defer attachment of the slave until 2111 * the backgrounding, since we defer attachment of the client until
2066 * after the connection is fully established (in particular, 2112 * after the connection is fully established (in particular,
2067 * async rfwd replies have been received for ExitOnForwardFailure). 2113 * async rfwd replies have been received for ExitOnForwardFailure).
2068 */ 2114 */
@@ -2117,13 +2163,15 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
2117 * as it may want to write to stdout. 2163 * as it may want to write to stdout.
2118 */ 2164 */
2119 if (!need_controlpersist_detach) { 2165 if (!need_controlpersist_detach) {
2120 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) 2166 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
2121 error("%s: open %s: %s", __func__, 2167 error("%s: open %s: %s", __func__,
2122 _PATH_DEVNULL, strerror(errno)); 2168 _PATH_DEVNULL, strerror(errno));
2123 if (dup2(devnull, STDOUT_FILENO) == -1) 2169 } else {
2124 fatal("%s: dup2() stdout failed", __func__); 2170 if (dup2(devnull, STDOUT_FILENO) == -1)
2125 if (devnull > STDERR_FILENO) 2171 fatal("%s: dup2() stdout failed", __func__);
2126 close(devnull); 2172 if (devnull > STDERR_FILENO)
2173 close(devnull);
2174 }
2127 } 2175 }
2128 2176
2129 /* 2177 /*
@@ -2201,7 +2249,7 @@ load_public_identity_files(struct passwd *pw)
2201 continue; 2249 continue;
2202 } 2250 }
2203 cp = tilde_expand_filename(options.identity_files[i], getuid()); 2251 cp = tilde_expand_filename(options.identity_files[i], getuid());
2204 filename = default_client_percent_expand(cp, 2252 filename = default_client_percent_dollar_expand(cp,
2205 pw->pw_dir, host, options.user, pw->pw_name); 2253 pw->pw_dir, host, options.user, pw->pw_name);
2206 free(cp); 2254 free(cp);
2207 check_load(sshkey_load_public(filename, &public, NULL), 2255 check_load(sshkey_load_public(filename, &public, NULL),
@@ -2251,7 +2299,7 @@ load_public_identity_files(struct passwd *pw)
2251 for (i = 0; i < options.num_certificate_files; i++) { 2299 for (i = 0; i < options.num_certificate_files; i++) {
2252 cp = tilde_expand_filename(options.certificate_files[i], 2300 cp = tilde_expand_filename(options.certificate_files[i],
2253 getuid()); 2301 getuid());
2254 filename = default_client_percent_expand(cp, 2302 filename = default_client_percent_dollar_expand(cp,
2255 pw->pw_dir, host, options.user, pw->pw_name); 2303 pw->pw_dir, host, options.user, pw->pw_name);
2256 free(cp); 2304 free(cp);
2257 2305