diff options
author | dtucker@openbsd.org <dtucker@openbsd.org> | 2020-04-03 02:27:12 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-04-03 13:33:37 +1100 |
commit | ed833da176611a39d3376d62154eb88eb440d31c (patch) | |
tree | f9fe72b08478c0ad599538f9dbfb94e582e93a93 /ssh.c | |
parent | 6ec7457171468da2bbd908b8cd63d298b0e049ea (diff) |
upstream: Make with config keywords support which
percent_expansions more consistent. - %C is moved into its own function and
added to Match Exec. - move the common (global) options into a macro. This
is ugly but it's the least-ugly way I could come up with. - move
IdentityAgent and ForwardAgent percent expansion to before the config dump
to make it regression-testable. - document all of the above
ok jmc@ for man page bits, "makes things less terrible" djm@ for the rest.
OpenBSD-Commit-ID: 4b65664bd6d8ae2a9afaf1a2438ddd1b614b1d75
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 120 |
1 files changed, 53 insertions, 67 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.521 2020/03/06 18:20:02 markus Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.522 2020/04/03 02:27:12 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" |
@@ -177,6 +176,13 @@ char *forward_agent_sock_path = NULL; | |||
177 | /* Various strings used to to percent_expand() arguments */ | 176 | /* Various strings used to to percent_expand() arguments */ |
178 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; | 177 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
179 | static char uidstr[32], *host_arg, *conn_hash_hex; | 178 | static char uidstr[32], *host_arg, *conn_hash_hex; |
179 | #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \ | ||
180 | "C", conn_hash_hex, \ | ||
181 | "L", shorthost, \ | ||
182 | "i", uidstr, \ | ||
183 | "l", thishost, \ | ||
184 | "n", host_arg, \ | ||
185 | "p", portstr | ||
180 | 186 | ||
181 | /* socket address the host resolves to */ | 187 | /* socket address the host resolves to */ |
182 | struct sockaddr_storage hostaddr; | 188 | struct sockaddr_storage hostaddr; |
@@ -601,8 +607,6 @@ main(int ac, char **av) | |||
601 | extern char *optarg; | 607 | extern char *optarg; |
602 | struct Forward fwd; | 608 | struct Forward fwd; |
603 | struct addrinfo *addrs = NULL; | 609 | struct addrinfo *addrs = NULL; |
604 | struct ssh_digest_ctx *md; | ||
605 | u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; | ||
606 | size_t n, len; | 610 | size_t n, len; |
607 | 611 | ||
608 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 612 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
@@ -1330,15 +1334,8 @@ main(int ac, char **av) | |||
1330 | snprintf(uidstr, sizeof(uidstr), "%llu", | 1334 | snprintf(uidstr, sizeof(uidstr), "%llu", |
1331 | (unsigned long long)pw->pw_uid); | 1335 | (unsigned long long)pw->pw_uid); |
1332 | 1336 | ||
1333 | if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || | 1337 | conn_hash_hex = ssh_connection_hash(thishost, host, portstr, |
1334 | ssh_digest_update(md, thishost, strlen(thishost)) < 0 || | 1338 | options.user); |
1335 | ssh_digest_update(md, host, strlen(host)) < 0 || | ||
1336 | ssh_digest_update(md, portstr, strlen(portstr)) < 0 || | ||
1337 | ssh_digest_update(md, options.user, strlen(options.user)) < 0 || | ||
1338 | ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) | ||
1339 | fatal("%s: mux digest failed", __func__); | ||
1340 | ssh_digest_free(md); | ||
1341 | conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); | ||
1342 | 1339 | ||
1343 | /* | 1340 | /* |
1344 | * Expand tokens in arguments. NB. LocalCommand is expanded later, | 1341 | * Expand tokens in arguments. NB. LocalCommand is expanded later, |
@@ -1349,14 +1346,9 @@ main(int ac, char **av) | |||
1349 | debug3("expanding RemoteCommand: %s", options.remote_command); | 1346 | debug3("expanding RemoteCommand: %s", options.remote_command); |
1350 | cp = options.remote_command; | 1347 | cp = options.remote_command; |
1351 | options.remote_command = percent_expand(cp, | 1348 | options.remote_command = percent_expand(cp, |
1352 | "C", conn_hash_hex, | 1349 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, |
1353 | "L", shorthost, | ||
1354 | "d", pw->pw_dir, | 1350 | "d", pw->pw_dir, |
1355 | "h", host, | 1351 | "h", host, |
1356 | "i", uidstr, | ||
1357 | "l", thishost, | ||
1358 | "n", host_arg, | ||
1359 | "p", portstr, | ||
1360 | "r", options.user, | 1352 | "r", options.user, |
1361 | "u", pw->pw_name, | 1353 | "u", pw->pw_name, |
1362 | (char *)NULL); | 1354 | (char *)NULL); |
@@ -1371,20 +1363,44 @@ main(int ac, char **av) | |||
1371 | cp = tilde_expand_filename(options.control_path, getuid()); | 1363 | cp = tilde_expand_filename(options.control_path, getuid()); |
1372 | free(options.control_path); | 1364 | free(options.control_path); |
1373 | options.control_path = percent_expand(cp, | 1365 | options.control_path = percent_expand(cp, |
1374 | "C", conn_hash_hex, | 1366 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, |
1375 | "L", shorthost, | 1367 | "d", pw->pw_dir, |
1376 | "h", host, | 1368 | "h", host, |
1377 | "i", uidstr, | ||
1378 | "l", thishost, | ||
1379 | "n", host_arg, | ||
1380 | "p", portstr, | ||
1381 | "r", options.user, | 1369 | "r", options.user, |
1382 | "u", pw->pw_name, | 1370 | "u", pw->pw_name, |
1383 | "i", uidstr, | ||
1384 | (char *)NULL); | 1371 | (char *)NULL); |
1385 | free(cp); | 1372 | free(cp); |
1386 | } | 1373 | } |
1387 | 1374 | ||
1375 | if (options.identity_agent != NULL) { | ||
1376 | p = tilde_expand_filename(options.identity_agent, getuid()); | ||
1377 | cp = percent_expand(p, | ||
1378 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | ||
1379 | "d", pw->pw_dir, | ||
1380 | "h", host, | ||
1381 | "r", options.user, | ||
1382 | "u", pw->pw_name, | ||
1383 | (char *)NULL); | ||
1384 | free(p); | ||
1385 | free(options.identity_agent); | ||
1386 | options.identity_agent = cp; | ||
1387 | } | ||
1388 | |||
1389 | if (options.forward_agent_sock_path != NULL) { | ||
1390 | p = tilde_expand_filename(options.forward_agent_sock_path, | ||
1391 | getuid()); | ||
1392 | cp = percent_expand(p, | ||
1393 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | ||
1394 | "d", pw->pw_dir, | ||
1395 | "h", host, | ||
1396 | "r", options.user, | ||
1397 | "u", pw->pw_name, | ||
1398 | (char *)NULL); | ||
1399 | free(p); | ||
1400 | free(options.forward_agent_sock_path); | ||
1401 | options.forward_agent_sock_path = cp; | ||
1402 | } | ||
1403 | |||
1388 | if (config_test) { | 1404 | if (config_test) { |
1389 | dump_client_config(&options, host); | 1405 | dump_client_config(&options, host); |
1390 | exit(0); | 1406 | exit(0); |
@@ -1509,23 +1525,7 @@ main(int ac, char **av) | |||
1509 | if (strcmp(options.identity_agent, "none") == 0) { | 1525 | if (strcmp(options.identity_agent, "none") == 0) { |
1510 | unsetenv(SSH_AUTHSOCKET_ENV_NAME); | 1526 | unsetenv(SSH_AUTHSOCKET_ENV_NAME); |
1511 | } else { | 1527 | } else { |
1512 | p = tilde_expand_filename(options.identity_agent, | 1528 | cp = options.identity_agent; |
1513 | getuid()); | ||
1514 | cp = percent_expand(p, | ||
1515 | "d", pw->pw_dir, | ||
1516 | "h", host, | ||
1517 | "i", uidstr, | ||
1518 | "l", thishost, | ||
1519 | "r", options.user, | ||
1520 | "u", pw->pw_name, | ||
1521 | (char *)NULL); | ||
1522 | free(p); | ||
1523 | /* | ||
1524 | * If identity_agent represents an environment variable | ||
1525 | * then recheck that it is valid (since processing with | ||
1526 | * percent_expand() may have changed it) and substitute | ||
1527 | * its value. | ||
1528 | */ | ||
1529 | if (cp[0] == '$') { | 1529 | if (cp[0] == '$') { |
1530 | if (!valid_env_name(cp + 1)) { | 1530 | if (!valid_env_name(cp + 1)) { |
1531 | fatal("Invalid IdentityAgent " | 1531 | fatal("Invalid IdentityAgent " |
@@ -1539,22 +1539,10 @@ main(int ac, char **av) | |||
1539 | /* identity_agent specifies a path directly */ | 1539 | /* identity_agent specifies a path directly */ |
1540 | setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); | 1540 | setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); |
1541 | } | 1541 | } |
1542 | free(cp); | ||
1543 | } | 1542 | } |
1544 | } | 1543 | } |
1545 | 1544 | ||
1546 | if (options.forward_agent && (options.forward_agent_sock_path != NULL)) { | 1545 | if (options.forward_agent && options.forward_agent_sock_path != NULL) { |
1547 | p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); | ||
1548 | cp = percent_expand(p, | ||
1549 | "d", pw->pw_dir, | ||
1550 | "h", host, | ||
1551 | "i", uidstr, | ||
1552 | "l", thishost, | ||
1553 | "r", options.user, | ||
1554 | "u", pw->pw_name, | ||
1555 | (char *)NULL); | ||
1556 | free(p); | ||
1557 | |||
1558 | if (cp[0] == '$') { | 1546 | if (cp[0] == '$') { |
1559 | if (!valid_env_name(cp + 1)) { | 1547 | if (!valid_env_name(cp + 1)) { |
1560 | fatal("Invalid ForwardAgent environment variable name %s", cp); | 1548 | fatal("Invalid ForwardAgent environment variable name %s", cp); |
@@ -1979,14 +1967,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) | |||
1979 | debug3("expanding LocalCommand: %s", options.local_command); | 1967 | debug3("expanding LocalCommand: %s", options.local_command); |
1980 | cp = options.local_command; | 1968 | cp = options.local_command; |
1981 | options.local_command = percent_expand(cp, | 1969 | options.local_command = percent_expand(cp, |
1982 | "C", conn_hash_hex, | 1970 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, |
1983 | "L", shorthost, | ||
1984 | "d", pw->pw_dir, | 1971 | "d", pw->pw_dir, |
1985 | "h", host, | 1972 | "h", host, |
1986 | "i", uidstr, | ||
1987 | "l", thishost, | ||
1988 | "n", host_arg, | ||
1989 | "p", portstr, | ||
1990 | "r", options.user, | 1973 | "r", options.user, |
1991 | "u", pw->pw_name, | 1974 | "u", pw->pw_name, |
1992 | "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, | 1975 | "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, |
@@ -2143,9 +2126,13 @@ load_public_identity_files(struct passwd *pw) | |||
2143 | continue; | 2126 | continue; |
2144 | } | 2127 | } |
2145 | cp = tilde_expand_filename(options.identity_files[i], getuid()); | 2128 | cp = tilde_expand_filename(options.identity_files[i], getuid()); |
2146 | filename = percent_expand(cp, "d", pw->pw_dir, | 2129 | filename = percent_expand(cp, |
2147 | "u", pw->pw_name, "l", thishost, "h", host, | 2130 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, |
2148 | "r", options.user, (char *)NULL); | 2131 | "d", pw->pw_dir, |
2132 | "h", host, | ||
2133 | "r", options.user, | ||
2134 | "u", pw->pw_name, | ||
2135 | (char *)NULL); | ||
2149 | free(cp); | 2136 | free(cp); |
2150 | check_load(sshkey_load_public(filename, &public, NULL), | 2137 | check_load(sshkey_load_public(filename, &public, NULL), |
2151 | filename, "pubkey"); | 2138 | filename, "pubkey"); |
@@ -2195,10 +2182,9 @@ load_public_identity_files(struct passwd *pw) | |||
2195 | cp = tilde_expand_filename(options.certificate_files[i], | 2182 | cp = tilde_expand_filename(options.certificate_files[i], |
2196 | getuid()); | 2183 | getuid()); |
2197 | filename = percent_expand(cp, | 2184 | filename = percent_expand(cp, |
2185 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | ||
2198 | "d", pw->pw_dir, | 2186 | "d", pw->pw_dir, |
2199 | "h", host, | 2187 | "h", host, |
2200 | "i", uidstr, | ||
2201 | "l", thishost, | ||
2202 | "r", options.user, | 2188 | "r", options.user, |
2203 | "u", pw->pw_name, | 2189 | "u", pw->pw_name, |
2204 | (char *)NULL); | 2190 | (char *)NULL); |