summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c119
1 files changed, 100 insertions, 19 deletions
diff --git a/ssh.c b/ssh.c
index ee51823cd..15aee569e 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.507 2019/09/13 04:27:35 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.519 2020/02/07 03:54:44 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
@@ -65,6 +65,7 @@
65#include <stdio.h> 65#include <stdio.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <stdarg.h>
68#include <unistd.h> 69#include <unistd.h>
69#include <limits.h> 70#include <limits.h>
70#include <locale.h> 71#include <locale.h>
@@ -167,6 +168,12 @@ char *config = NULL;
167 */ 168 */
168char *host; 169char *host;
169 170
171/*
172 * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is
173 * not NULL, forward the socket at this path instead.
174 */
175char *forward_agent_sock_path = NULL;
176
170/* Various strings used to to percent_expand() arguments */ 177/* Various strings used to to percent_expand() arguments */
171static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 178static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
172static char uidstr[32], *host_arg, *conn_hash_hex; 179static char uidstr[32], *host_arg, *conn_hash_hex;
@@ -595,6 +602,7 @@ main(int ac, char **av)
595 struct addrinfo *addrs = NULL; 602 struct addrinfo *addrs = NULL;
596 struct ssh_digest_ctx *md; 603 struct ssh_digest_ctx *md;
597 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 604 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
605 size_t n, len;
598 606
599 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 607 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
600 sanitise_stdfd(); 608 sanitise_stdfd();
@@ -728,13 +736,16 @@ main(int ac, char **av)
728 break; 736 break;
729 case 'Q': 737 case 'Q':
730 cp = NULL; 738 cp = NULL;
731 if (strcmp(optarg, "cipher") == 0) 739 if (strcmp(optarg, "cipher") == 0 ||
740 strcasecmp(optarg, "Ciphers") == 0)
732 cp = cipher_alg_list('\n', 0); 741 cp = cipher_alg_list('\n', 0);
733 else if (strcmp(optarg, "cipher-auth") == 0) 742 else if (strcmp(optarg, "cipher-auth") == 0)
734 cp = cipher_alg_list('\n', 1); 743 cp = cipher_alg_list('\n', 1);
735 else if (strcmp(optarg, "mac") == 0) 744 else if (strcmp(optarg, "mac") == 0 ||
745 strcasecmp(optarg, "MACs") == 0)
736 cp = mac_alg_list('\n'); 746 cp = mac_alg_list('\n');
737 else if (strcmp(optarg, "kex") == 0) 747 else if (strcmp(optarg, "kex") == 0 ||
748 strcasecmp(optarg, "KexAlgorithms") == 0)
738 cp = kex_alg_list('\n'); 749 cp = kex_alg_list('\n');
739 else if (strcmp(optarg, "key") == 0) 750 else if (strcmp(optarg, "key") == 0)
740 cp = sshkey_alg_list(0, 0, 0, '\n'); 751 cp = sshkey_alg_list(0, 0, 0, '\n');
@@ -742,14 +753,26 @@ main(int ac, char **av)
742 cp = sshkey_alg_list(1, 0, 0, '\n'); 753 cp = sshkey_alg_list(1, 0, 0, '\n');
743 else if (strcmp(optarg, "key-plain") == 0) 754 else if (strcmp(optarg, "key-plain") == 0)
744 cp = sshkey_alg_list(0, 1, 0, '\n'); 755 cp = sshkey_alg_list(0, 1, 0, '\n');
756 else if (strcmp(optarg, "key-sig") == 0 ||
757 strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 ||
758 strcasecmp(optarg, "HostKeyAlgorithms") == 0 ||
759 strcasecmp(optarg, "HostbasedKeyTypes") == 0 ||
760 strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0)
761 cp = sshkey_alg_list(0, 0, 1, '\n');
745 else if (strcmp(optarg, "sig") == 0) 762 else if (strcmp(optarg, "sig") == 0)
746 cp = sshkey_alg_list(0, 1, 1, '\n'); 763 cp = sshkey_alg_list(0, 1, 1, '\n');
747 else if (strcmp(optarg, "protocol-version") == 0) 764 else if (strcmp(optarg, "protocol-version") == 0)
748 cp = xstrdup("2"); 765 cp = xstrdup("2");
749 else if (strcmp(optarg, "help") == 0) { 766 else if (strcmp(optarg, "compression") == 0) {
767 cp = xstrdup(compression_alg_list(0));
768 len = strlen(cp);
769 for (n = 0; n < len; n++)
770 if (cp[n] == ',')
771 cp[n] = '\n';
772 } else if (strcmp(optarg, "help") == 0) {
750 cp = xstrdup( 773 cp = xstrdup(
751 "cipher\ncipher-auth\nkex\nkey\n" 774 "cipher\ncipher-auth\ncompression\nkex\n"
752 "key-cert\nkey-plain\nmac\n" 775 "key\nkey-cert\nkey-plain\nkey-sig\nmac\n"
753 "protocol-version\nsig"); 776 "protocol-version\nsig");
754 } 777 }
755 if (cp == NULL) 778 if (cp == NULL)
@@ -952,7 +975,11 @@ main(int ac, char **av)
952 break; 975 break;
953 976
954 case 'C': 977 case 'C':
978#ifdef WITH_ZLIB
955 options.compression = 1; 979 options.compression = 1;
980#else
981 error("Compression not supported, disabling.");
982#endif
956 break; 983 break;
957 case 'N': 984 case 'N':
958 no_shell_flag = 1; 985 no_shell_flag = 1;
@@ -1230,11 +1257,21 @@ main(int ac, char **av)
1230 strcmp(options.proxy_command, "-") == 0 && 1257 strcmp(options.proxy_command, "-") == 0 &&
1231 options.proxy_use_fdpass) 1258 options.proxy_use_fdpass)
1232 fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); 1259 fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
1233 if (options.control_persist && 1260 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
1234 options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { 1261 if (options.control_persist && options.control_path != NULL) {
1235 debug("UpdateHostKeys=ask is incompatible with ControlPersist; " 1262 debug("UpdateHostKeys=ask is incompatible with "
1236 "disabling"); 1263 "ControlPersist; disabling");
1237 options.update_hostkeys = 0; 1264 options.update_hostkeys = 0;
1265 } else if (sshbuf_len(command) != 0 ||
1266 options.remote_command != NULL ||
1267 options.request_tty == REQUEST_TTY_NO) {
1268 debug("UpdateHostKeys=ask is incompatible with "
1269 "remote command execution; disabling");
1270 options.update_hostkeys = 0;
1271 } else if (options.log_level < SYSLOG_LEVEL_INFO) {
1272 /* no point logging anything; user won't see it */
1273 options.update_hostkeys = 0;
1274 }
1238 } 1275 }
1239 if (options.connection_attempts <= 0) 1276 if (options.connection_attempts <= 0)
1240 fatal("Invalid number of ConnectionAttempts"); 1277 fatal("Invalid number of ConnectionAttempts");
@@ -1344,6 +1381,22 @@ main(int ac, char **av)
1344 exit(0); 1381 exit(0);
1345 } 1382 }
1346 1383
1384 /* Expand SecurityKeyProvider if it refers to an environment variable */
1385 if (options.sk_provider != NULL && *options.sk_provider == '$' &&
1386 strlen(options.sk_provider) > 1) {
1387 if ((cp = getenv(options.sk_provider + 1)) == NULL) {
1388 debug("Authenticator provider %s did not resolve; "
1389 "disabling", options.sk_provider);
1390 free(options.sk_provider);
1391 options.sk_provider = NULL;
1392 } else {
1393 debug2("resolved SecurityKeyProvider %s => %s",
1394 options.sk_provider, cp);
1395 free(options.sk_provider);
1396 options.sk_provider = xstrdup(cp);
1397 }
1398 }
1399
1347 if (muxclient_command != 0 && options.control_path == NULL) 1400 if (muxclient_command != 0 && options.control_path == NULL)
1348 fatal("No ControlPath specified for \"-O\" command"); 1401 fatal("No ControlPath specified for \"-O\" command");
1349 if (options.control_path != NULL) { 1402 if (options.control_path != NULL) {
@@ -1369,7 +1422,7 @@ main(int ac, char **av)
1369 timeout_ms = options.connection_timeout * 1000; 1422 timeout_ms = options.connection_timeout * 1000;
1370 1423
1371 /* Open a connection to the remote host. */ 1424 /* Open a connection to the remote host. */
1372 if (ssh_connect(ssh, host_arg, host, addrs, &hostaddr, options.port, 1425 if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port,
1373 options.address_family, options.connection_attempts, 1426 options.address_family, options.connection_attempts,
1374 &timeout_ms, options.tcp_keep_alive) != 0) 1427 &timeout_ms, options.tcp_keep_alive) != 0)
1375 exit(255); 1428 exit(255);
@@ -1481,13 +1534,39 @@ main(int ac, char **av)
1481 } 1534 }
1482 } 1535 }
1483 1536
1537 if (options.forward_agent && (options.forward_agent_sock_path != NULL)) {
1538 p = tilde_expand_filename(options.forward_agent_sock_path, getuid());
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] == '$') {
1550 if (!valid_env_name(cp + 1)) {
1551 fatal("Invalid ForwardAgent environment variable name %s", cp);
1552 }
1553 if ((p = getenv(cp + 1)) != NULL)
1554 forward_agent_sock_path = p;
1555 else
1556 options.forward_agent = 0;
1557 free(cp);
1558 } else {
1559 forward_agent_sock_path = cp;
1560 }
1561 }
1562
1484 /* Expand ~ in known host file names. */ 1563 /* Expand ~ in known host file names. */
1485 tilde_expand_paths(options.system_hostfiles, 1564 tilde_expand_paths(options.system_hostfiles,
1486 options.num_system_hostfiles); 1565 options.num_system_hostfiles);
1487 tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); 1566 tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
1488 1567
1489 signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ 1568 ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
1490 signal(SIGCHLD, main_sigchld_handler); 1569 ssh_signal(SIGCHLD, main_sigchld_handler);
1491 1570
1492 /* Log into the remote system. Never returns if the login fails. */ 1571 /* Log into the remote system. Never returns if the login fails. */
1493 ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, 1572 ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
@@ -2012,7 +2091,8 @@ load_public_identity_files(struct passwd *pw)
2012 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; 2091 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
2013 int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; 2092 int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
2014#ifdef ENABLE_PKCS11 2093#ifdef ENABLE_PKCS11
2015 struct sshkey **keys; 2094 struct sshkey **keys = NULL;
2095 char **comments = NULL;
2016 int nkeys; 2096 int nkeys;
2017#endif /* PKCS11 */ 2097#endif /* PKCS11 */
2018 2098
@@ -2031,18 +2111,19 @@ load_public_identity_files(struct passwd *pw)
2031 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 2111 options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
2032 (pkcs11_init(!options.batch_mode) == 0) && 2112 (pkcs11_init(!options.batch_mode) == 0) &&
2033 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, 2113 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
2034 &keys)) > 0) { 2114 &keys, &comments)) > 0) {
2035 for (i = 0; i < nkeys; i++) { 2115 for (i = 0; i < nkeys; i++) {
2036 if (n_ids >= SSH_MAX_IDENTITY_FILES) { 2116 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
2037 sshkey_free(keys[i]); 2117 sshkey_free(keys[i]);
2118 free(comments[i]);
2038 continue; 2119 continue;
2039 } 2120 }
2040 identity_keys[n_ids] = keys[i]; 2121 identity_keys[n_ids] = keys[i];
2041 identity_files[n_ids] = 2122 identity_files[n_ids] = comments[i]; /* transferred */
2042 xstrdup(options.pkcs11_provider); /* XXX */
2043 n_ids++; 2123 n_ids++;
2044 } 2124 }
2045 free(keys); 2125 free(keys);
2126 free(comments);
2046 } 2127 }
2047#endif /* ENABLE_PKCS11 */ 2128#endif /* ENABLE_PKCS11 */
2048 for (i = 0; i < options.num_identity_files; i++) { 2129 for (i = 0; i < options.num_identity_files; i++) {