summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c137
1 files changed, 99 insertions, 38 deletions
diff --git a/clientloop.c b/clientloop.c
index b5a1f7038..ebd0dbca1 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.327 2019/07/24 08:57:00 mestre Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.340 2020/02/02 09:45:34 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
@@ -77,10 +77,10 @@
77#include <paths.h> 77#include <paths.h>
78#endif 78#endif
79#include <signal.h> 79#include <signal.h>
80#include <stdarg.h>
81#include <stdio.h> 80#include <stdio.h>
82#include <stdlib.h> 81#include <stdlib.h>
83#include <string.h> 82#include <string.h>
83#include <stdarg.h>
84#include <termios.h> 84#include <termios.h>
85#include <pwd.h> 85#include <pwd.h>
86#include <unistd.h> 86#include <unistd.h>
@@ -135,6 +135,12 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
135extern char *host; 135extern char *host;
136 136
137/* 137/*
138 * If this field is not NULL, the ForwardAgent socket is this path and different
139 * instead of SSH_AUTH_SOCK.
140 */
141extern char *forward_agent_sock_path;
142
143/*
138 * Flag to indicate that we have received a window change signal which has 144 * Flag to indicate that we have received a window change signal which has
139 * not yet been processed. This will cause a message indicating the new 145 * not yet been processed. This will cause a message indicating the new
140 * window size to be sent to the server a little later. This is volatile 146 * window size to be sent to the server a little later. This is volatile
@@ -779,7 +785,7 @@ process_cmdline(struct ssh *ssh)
779 memset(&fwd, 0, sizeof(fwd)); 785 memset(&fwd, 0, sizeof(fwd));
780 786
781 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 787 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
782 handler = signal(SIGINT, SIG_IGN); 788 handler = ssh_signal(SIGINT, SIG_IGN);
783 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); 789 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
784 if (s == NULL) 790 if (s == NULL)
785 goto out; 791 goto out;
@@ -877,7 +883,7 @@ process_cmdline(struct ssh *ssh)
877 } 883 }
878 884
879out: 885out:
880 signal(SIGINT, handler); 886 ssh_signal(SIGINT, handler);
881 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 887 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
882 free(cmd); 888 free(cmd);
883 free(fwd.listen_host); 889 free(fwd.listen_host);
@@ -1300,15 +1306,15 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1300 * Set signal handlers, (e.g. to restore non-blocking mode) 1306 * Set signal handlers, (e.g. to restore non-blocking mode)
1301 * but don't overwrite SIG_IGN, matches behaviour from rsh(1) 1307 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1302 */ 1308 */
1303 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 1309 if (ssh_signal(SIGHUP, SIG_IGN) != SIG_IGN)
1304 signal(SIGHUP, signal_handler); 1310 ssh_signal(SIGHUP, signal_handler);
1305 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1311 if (ssh_signal(SIGINT, SIG_IGN) != SIG_IGN)
1306 signal(SIGINT, signal_handler); 1312 ssh_signal(SIGINT, signal_handler);
1307 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 1313 if (ssh_signal(SIGQUIT, SIG_IGN) != SIG_IGN)
1308 signal(SIGQUIT, signal_handler); 1314 ssh_signal(SIGQUIT, signal_handler);
1309 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 1315 if (ssh_signal(SIGTERM, SIG_IGN) != SIG_IGN)
1310 signal(SIGTERM, signal_handler); 1316 ssh_signal(SIGTERM, signal_handler);
1311 signal(SIGWINCH, window_change_handler); 1317 ssh_signal(SIGWINCH, window_change_handler);
1312 1318
1313 if (have_pty) 1319 if (have_pty)
1314 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 1320 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
@@ -1386,8 +1392,12 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1386 * Send as much buffered packet data as possible to the 1392 * Send as much buffered packet data as possible to the
1387 * sender. 1393 * sender.
1388 */ 1394 */
1389 if (FD_ISSET(connection_out, writeset)) 1395 if (FD_ISSET(connection_out, writeset)) {
1390 ssh_packet_write_poll(ssh); 1396 if ((r = ssh_packet_write_poll(ssh)) != 0) {
1397 sshpkt_fatal(ssh, r,
1398 "%s: ssh_packet_write_poll", __func__);
1399 }
1400 }
1391 1401
1392 /* 1402 /*
1393 * If we are a backgrounded control master, and the 1403 * If we are a backgrounded control master, and the
@@ -1407,7 +1417,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1407 /* Terminate the session. */ 1417 /* Terminate the session. */
1408 1418
1409 /* Stop watching for window change. */ 1419 /* Stop watching for window change. */
1410 signal(SIGWINCH, SIG_DFL); 1420 ssh_signal(SIGWINCH, SIG_DFL);
1411 1421
1412 if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || 1422 if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
1413 (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 || 1423 (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 ||
@@ -1618,7 +1628,12 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
1618 "malicious server."); 1628 "malicious server.");
1619 return NULL; 1629 return NULL;
1620 } 1630 }
1621 if ((r = ssh_get_authentication_socket(&sock)) != 0) { 1631 if (forward_agent_sock_path == NULL) {
1632 r = ssh_get_authentication_socket(&sock);
1633 } else {
1634 r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock);
1635 }
1636 if (r != 0) {
1622 if (r != SSH_ERR_AGENT_NOT_PRESENT) 1637 if (r != SSH_ERR_AGENT_NOT_PRESENT)
1623 debug("%s: ssh_get_authentication_socket: %s", 1638 debug("%s: ssh_get_authentication_socket: %s",
1624 __func__, ssh_err(r)); 1639 __func__, ssh_err(r));
@@ -1877,13 +1892,22 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
1877} 1892}
1878 1893
1879static void 1894static void
1895hostkey_change_preamble(LogLevel loglevel)
1896{
1897 do_log2(loglevel, "The server has updated its host keys.");
1898 do_log2(loglevel, "These changes were verified by the server's "
1899 "existing trusted key.");
1900}
1901
1902static void
1880update_known_hosts(struct hostkeys_update_ctx *ctx) 1903update_known_hosts(struct hostkeys_update_ctx *ctx)
1881{ 1904{
1882 int r, was_raw = 0; 1905 int r, was_raw = 0, first = 1;
1883 LogLevel loglevel = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK ? 1906 int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK;
1884 SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; 1907 LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
1885 char *fp, *response; 1908 char *fp, *response;
1886 size_t i; 1909 size_t i;
1910 struct stat sb;
1887 1911
1888 for (i = 0; i < ctx->nkeys; i++) { 1912 for (i = 0; i < ctx->nkeys; i++) {
1889 if (ctx->keys_seen[i] != 2) 1913 if (ctx->keys_seen[i] != 2)
@@ -1891,16 +1915,22 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
1891 if ((fp = sshkey_fingerprint(ctx->keys[i], 1915 if ((fp = sshkey_fingerprint(ctx->keys[i],
1892 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 1916 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
1893 fatal("%s: sshkey_fingerprint failed", __func__); 1917 fatal("%s: sshkey_fingerprint failed", __func__);
1918 if (first && asking)
1919 hostkey_change_preamble(loglevel);
1894 do_log2(loglevel, "Learned new hostkey: %s %s", 1920 do_log2(loglevel, "Learned new hostkey: %s %s",
1895 sshkey_type(ctx->keys[i]), fp); 1921 sshkey_type(ctx->keys[i]), fp);
1922 first = 0;
1896 free(fp); 1923 free(fp);
1897 } 1924 }
1898 for (i = 0; i < ctx->nold; i++) { 1925 for (i = 0; i < ctx->nold; i++) {
1899 if ((fp = sshkey_fingerprint(ctx->old_keys[i], 1926 if ((fp = sshkey_fingerprint(ctx->old_keys[i],
1900 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 1927 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
1901 fatal("%s: sshkey_fingerprint failed", __func__); 1928 fatal("%s: sshkey_fingerprint failed", __func__);
1929 if (first && asking)
1930 hostkey_change_preamble(loglevel);
1902 do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", 1931 do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",
1903 sshkey_type(ctx->old_keys[i]), fp); 1932 sshkey_type(ctx->old_keys[i]), fp);
1933 first = 0;
1904 free(fp); 1934 free(fp);
1905 } 1935 }
1906 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { 1936 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
@@ -1930,19 +1960,37 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
1930 if (was_raw) 1960 if (was_raw)
1931 enter_raw_mode(1); 1961 enter_raw_mode(1);
1932 } 1962 }
1933 1963 if (options.update_hostkeys == 0)
1964 return;
1934 /* 1965 /*
1935 * Now that all the keys are verified, we can go ahead and replace 1966 * Now that all the keys are verified, we can go ahead and replace
1936 * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't 1967 * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
1937 * cancel the operation). 1968 * cancel the operation).
1938 */ 1969 */
1939 if (options.update_hostkeys != 0 && 1970 for (i = 0; i < options.num_user_hostfiles; i++) {
1940 (r = hostfile_replace_entries(options.user_hostfiles[0], 1971 /*
1941 ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys, 1972 * NB. keys are only added to hostfiles[0], for the rest we
1942 options.hash_known_hosts, 0, 1973 * just delete the hostname entries.
1943 options.fingerprint_hash)) != 0) 1974 */
1944 error("%s: hostfile_replace_entries failed: %s", 1975 if (stat(options.user_hostfiles[i], &sb) != 0) {
1945 __func__, ssh_err(r)); 1976 if (errno == ENOENT) {
1977 debug("%s: known hosts file %s does not exist",
1978 __func__, strerror(errno));
1979 } else {
1980 error("%s: known hosts file %s inaccessible",
1981 __func__, strerror(errno));
1982 }
1983 continue;
1984 }
1985 if ((r = hostfile_replace_entries(options.user_hostfiles[i],
1986 ctx->host_str, ctx->ip_str,
1987 i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0,
1988 options.hash_known_hosts, 0,
1989 options.fingerprint_hash)) != 0) {
1990 error("%s: hostfile_replace_entries failed for %s: %s",
1991 __func__, options.user_hostfiles[i], ssh_err(r));
1992 }
1993 }
1946} 1994}
1947 1995
1948static void 1996static void
@@ -2003,7 +2051,8 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
2003 sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA; 2051 sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
2004 if ((r = sshkey_verify(ctx->keys[i], sig, siglen, 2052 if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
2005 sshbuf_ptr(signdata), sshbuf_len(signdata), 2053 sshbuf_ptr(signdata), sshbuf_len(signdata),
2006 use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0) { 2054 use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
2055 NULL)) != 0) {
2007 error("%s: server gave bad signature for %s key %zu", 2056 error("%s: server gave bad signature for %s key %zu",
2008 __func__, sshkey_type(ctx->keys[i]), i); 2057 __func__, sshkey_type(ctx->keys[i]), i);
2009 goto out; 2058 goto out;
@@ -2034,8 +2083,7 @@ static int
2034key_accepted_by_hostkeyalgs(const struct sshkey *key) 2083key_accepted_by_hostkeyalgs(const struct sshkey *key)
2035{ 2084{
2036 const char *ktype = sshkey_ssh_name(key); 2085 const char *ktype = sshkey_ssh_name(key);
2037 const char *hostkeyalgs = options.hostkeyalgorithms != NULL ? 2086 const char *hostkeyalgs = options.hostkeyalgorithms;
2038 options.hostkeyalgorithms : KEX_DEFAULT_PK_ALG;
2039 2087
2040 if (key == NULL || key->type == KEY_UNSPEC) 2088 if (key == NULL || key->type == KEY_UNSPEC)
2041 return 0; 2089 return 0;
@@ -2082,8 +2130,10 @@ client_input_hostkeys(struct ssh *ssh)
2082 goto out; 2130 goto out;
2083 } 2131 }
2084 if ((r = sshkey_from_blob(blob, len, &key)) != 0) { 2132 if ((r = sshkey_from_blob(blob, len, &key)) != 0) {
2085 error("%s: parse key: %s", __func__, ssh_err(r)); 2133 do_log2(r == SSH_ERR_KEY_TYPE_UNKNOWN ?
2086 goto out; 2134 SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR,
2135 "%s: parse key: %s", __func__, ssh_err(r));
2136 continue;
2087 } 2137 }
2088 fp = sshkey_fingerprint(key, options.fingerprint_hash, 2138 fp = sshkey_fingerprint(key, options.fingerprint_hash,
2089 SSH_FP_DEFAULT); 2139 SSH_FP_DEFAULT);
@@ -2135,11 +2185,22 @@ client_input_hostkeys(struct ssh *ssh)
2135 options.check_host_ip ? &ctx->ip_str : NULL); 2185 options.check_host_ip ? &ctx->ip_str : NULL);
2136 2186
2137 /* Find which keys we already know about. */ 2187 /* Find which keys we already know about. */
2138 if ((r = hostkeys_foreach(options.user_hostfiles[0], hostkeys_find, 2188 for (i = 0; i < options.num_user_hostfiles; i++) {
2139 ctx, ctx->host_str, ctx->ip_str, 2189 debug("%s: searching %s for %s / %s", __func__,
2140 HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) { 2190 options.user_hostfiles[i], ctx->host_str,
2141 error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); 2191 ctx->ip_str ? ctx->ip_str : "(none)");
2142 goto out; 2192 if ((r = hostkeys_foreach(options.user_hostfiles[i],
2193 hostkeys_find, ctx, ctx->host_str, ctx->ip_str,
2194 HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
2195 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
2196 debug("%s: hostkeys file %s does not exist",
2197 __func__, options.user_hostfiles[i]);
2198 continue;
2199 }
2200 error("%s: hostkeys_foreach failed for %s: %s",
2201 __func__, options.user_hostfiles[i], ssh_err(r));
2202 goto out;
2203 }
2143 } 2204 }
2144 2205
2145 /* Figure out if we have any new keys to add */ 2206 /* Figure out if we have any new keys to add */