external/openssh: update to 6.8p1.
In preparation for some updates to external/openssh to make it work with
BoringSSL, this change updates the code to a recent version. The current
version (5.9p1) is coming up on four years old now.
* Confirmed that f5c67b478bef9992de9e9ec91ce10af4f6205e0d matches
OpenSSH 5.9p1 exactly (save for the removal of the scard
subdirectory).
* Downloaded openssh-6.8p1.tar.gz (SHA256:
3ff64ce73ee124480b5bf767b9830d7d3c03bbcb6abe716b78f0192c37ce160e)
and verified with PGP signature. (I've verified Damien's key in
person previously.)
* Applied changes between f5c67b478bef9992de9e9ec91ce10af4f6205e0d and
OpenSSH 5.9p1 to 6.8p1 and updated the build as best I can. The
ugliest change is probably the duplication of umac.c to umac128.c
because Android conditionally compiles that file twice. See the
comment in those files.
Change-Id: I63cb07a8118afb5a377f116087a0882914cea486
diff --git a/sshconnect.c b/sshconnect.c
index 0ee7266..9e51506 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.259 2015/01/28 22:36:00 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -15,6 +15,7 @@
#include "includes.h"
+#include <sys/param.h> /* roundup */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
@@ -54,16 +55,20 @@
#include "sshconnect.h"
#include "hostfile.h"
#include "log.h"
+#include "misc.h"
#include "readconf.h"
#include "atomicio.h"
-#include "misc.h"
#include "dns.h"
#include "roaming.h"
+#include "monitor_fdpass.h"
#include "ssh2.h"
#include "version.h"
+#include "authfile.h"
+#include "ssherr.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
+Key *previous_host_key = NULL;
static int matching_host_key_dns = 0;
@@ -78,40 +83,122 @@
static int show_other_keys(struct hostkeys *, Key *);
static void warn_changed_key(Key *);
+/* Expand a proxy command */
+static char *
+expand_proxy_command(const char *proxy_command, const char *user,
+ const char *host, int port)
+{
+ char *tmp, *ret, strport[NI_MAXSERV];
+
+ snprintf(strport, sizeof strport, "%d", port);
+ xasprintf(&tmp, "exec %s", proxy_command);
+ ret = percent_expand(tmp, "h", host, "p", strport,
+ "r", options.user, (char *)NULL);
+ free(tmp);
+ return ret;
+}
+
+/*
+ * Connect to the given ssh server using a proxy command that passes a
+ * a connected fd back to us.
+ */
+static int
+ssh_proxy_fdpass_connect(const char *host, u_short port,
+ const char *proxy_command)
+{
+ char *command_string;
+ int sp[2], sock;
+ pid_t pid;
+ char *shell;
+
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = _PATH_BSHELL;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0)
+ fatal("Could not create socketpair to communicate with "
+ "proxy dialer: %.100s", strerror(errno));
+
+ command_string = expand_proxy_command(proxy_command, options.user,
+ host, port);
+ debug("Executing proxy dialer command: %.500s", command_string);
+
+ /* Fork and execute the proxy command. */
+ if ((pid = fork()) == 0) {
+ char *argv[10];
+
+ /* Child. Permanently give up superuser privileges. */
+ permanently_drop_suid(original_real_uid);
+
+ close(sp[1]);
+ /* Redirect stdin and stdout. */
+ if (sp[0] != 0) {
+ if (dup2(sp[0], 0) < 0)
+ perror("dup2 stdin");
+ }
+ if (sp[0] != 1) {
+ if (dup2(sp[0], 1) < 0)
+ perror("dup2 stdout");
+ }
+ if (sp[0] >= 2)
+ close(sp[0]);
+
+ /*
+ * Stderr is left as it is so that error messages get
+ * printed on the user's terminal.
+ */
+ argv[0] = shell;
+ argv[1] = "-c";
+ argv[2] = command_string;
+ argv[3] = NULL;
+
+ /*
+ * Execute the proxy command.
+ * Note that we gave up any extra privileges above.
+ */
+ execv(argv[0], argv);
+ perror(argv[0]);
+ exit(1);
+ }
+ /* Parent. */
+ if (pid < 0)
+ fatal("fork failed: %.100s", strerror(errno));
+ close(sp[0]);
+ free(command_string);
+
+ if ((sock = mm_receive_fd(sp[1])) == -1)
+ fatal("proxy dialer did not pass back a connection");
+
+ while (waitpid(pid, NULL, 0) == -1)
+ if (errno != EINTR)
+ fatal("Couldn't wait for child: %s", strerror(errno));
+
+ /* Set the connection file descriptors. */
+ packet_set_connection(sock, sock);
+
+ return 0;
+}
+
/*
* Connect to the given ssh server using a proxy command.
*/
static int
ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
{
- char *command_string, *tmp;
+ char *command_string;
int pin[2], pout[2];
pid_t pid;
- char *shell, strport[NI_MAXSERV];
+ char *shell;
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
- /* Convert the port number into a string. */
- snprintf(strport, sizeof strport, "%hu", port);
-
- /*
- * Build the final command string in the buffer by making the
- * appropriate substitutions to the given proxy command.
- *
- * Use "exec" to avoid "sh -c" processes on some platforms
- * (e.g. Solaris)
- */
- xasprintf(&tmp, "exec %s", proxy_command);
- command_string = percent_expand(tmp, "h", host, "p", strport,
- "r", options.user, (char *)NULL);
- xfree(tmp);
-
/* Create pipes for communicating with the proxy. */
if (pipe(pin) < 0 || pipe(pout) < 0)
fatal("Could not create pipes to communicate with the proxy: %.100s",
strerror(errno));
+ command_string = expand_proxy_command(proxy_command, options.user,
+ host, port);
debug("Executing proxy command: %.500s", command_string);
/* Fork and execute the proxy command. */
@@ -159,12 +246,10 @@
close(pout[1]);
/* Free the command name. */
- xfree(command_string);
+ free(command_string);
/* Set the connection file descriptors. */
packet_set_connection(pout[0], pin[1]);
- packet_set_timeout(options.server_alive_interval,
- options.server_alive_count_max);
/* Indicate OK return */
return 0;
@@ -187,55 +272,59 @@
static int
ssh_create_socket(int privileged, struct addrinfo *ai)
{
- int sock, gaierr;
- struct addrinfo hints, *res;
+ int sock, r, gaierr;
+ struct addrinfo hints, *res = NULL;
- /*
- * If we are running as root and want to connect to a privileged
- * port, bind our own socket to a privileged port.
- */
- if (privileged) {
- int p = IPPORT_RESERVED - 1;
- PRIV_START;
- sock = rresvport_af(&p, ai->ai_family);
- PRIV_END;
- if (sock < 0)
- error("rresvport: af=%d %.100s", ai->ai_family,
- strerror(errno));
- else
- debug("Allocated local port %d.", p);
- return sock;
- }
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0) {
- error("socket: %.100s", strerror(errno));
+ error("socket: %s", strerror(errno));
return -1;
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
/* Bind the socket to an alternative local IP address */
- if (options.bind_address == NULL)
+ if (options.bind_address == NULL && !privileged)
return sock;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = ai->ai_family;
- hints.ai_socktype = ai->ai_socktype;
- hints.ai_protocol = ai->ai_protocol;
- hints.ai_flags = AI_PASSIVE;
- gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
- if (gaierr) {
- error("getaddrinfo: %s: %s", options.bind_address,
- ssh_gai_strerror(gaierr));
- close(sock);
- return -1;
+ if (options.bind_address) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = ai->ai_family;
+ hints.ai_socktype = ai->ai_socktype;
+ hints.ai_protocol = ai->ai_protocol;
+ hints.ai_flags = AI_PASSIVE;
+ gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
+ if (gaierr) {
+ error("getaddrinfo: %s: %s", options.bind_address,
+ ssh_gai_strerror(gaierr));
+ close(sock);
+ return -1;
+ }
}
- if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
- error("bind: %s: %s", options.bind_address, strerror(errno));
- close(sock);
+ /*
+ * If we are running as root and want to connect to a privileged
+ * port, bind our own socket to a privileged port.
+ */
+ if (privileged) {
+ PRIV_START;
+ r = bindresvport_sa(sock, res ? res->ai_addr : NULL);
+ PRIV_END;
+ if (r < 0) {
+ error("bindresvport_sa: af=%d %s", ai->ai_family,
+ strerror(errno));
+ goto fail;
+ }
+ } else {
+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
+ error("bind: %s: %s", options.bind_address,
+ strerror(errno));
+ fail:
+ close(sock);
+ freeaddrinfo(res);
+ return -1;
+ }
+ }
+ if (res != NULL)
freeaddrinfo(res);
- return -1;
- }
- freeaddrinfo(res);
return sock;
}
@@ -308,7 +397,7 @@
fatal("Bogus return (%d) from select()", rc);
}
- xfree(fdset);
+ free(fdset);
done:
if (result == 0 && *timeoutp > 0) {
@@ -333,33 +422,18 @@
* and %p substituted for host and port, respectively) to use to contact
* the daemon.
*/
-int
-ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
- u_short port, int family, int connection_attempts, int *timeout_ms,
- int want_keepalive, int needpriv, const char *proxy_command)
+static int
+ssh_connect_direct(const char *host, struct addrinfo *aitop,
+ struct sockaddr_storage *hostaddr, u_short port, int family,
+ int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
{
- int gaierr;
int on = 1;
int sock = -1, attempt;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
- struct addrinfo hints, *ai, *aitop;
+ struct addrinfo *ai;
debug2("ssh_connect: needpriv %d", needpriv);
- /* If a proxy command is given, connect using it. */
- if (proxy_command != NULL)
- return ssh_proxy_connect(host, port, proxy_command);
-
- /* No proxy command. */
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%u", port);
- if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
- fatal("%s: Could not resolve hostname %.100s: %s", __progname,
- host, ssh_gai_strerror(gaierr));
-
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0) {
/* Sleep a moment before retrying. */
@@ -371,7 +445,8 @@
* sequence until the connection succeeds.
*/
for (ai = aitop; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+ if (ai->ai_family != AF_INET &&
+ ai->ai_family != AF_INET6)
continue;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
@@ -404,8 +479,6 @@
break; /* Successful connection. */
}
- freeaddrinfo(aitop);
-
/* Return failure if we didn't get a successful connection. */
if (sock == -1) {
error("ssh: connect to host %s port %s: %s",
@@ -423,12 +496,46 @@
/* Set the connection. */
packet_set_connection(sock, sock);
- packet_set_timeout(options.server_alive_interval,
- options.server_alive_count_max);
return 0;
}
+int
+ssh_connect(const char *host, struct addrinfo *addrs,
+ struct sockaddr_storage *hostaddr, u_short port, int family,
+ int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
+{
+ if (options.proxy_command == NULL) {
+ return ssh_connect_direct(host, addrs, hostaddr, port, family,
+ connection_attempts, timeout_ms, want_keepalive, needpriv);
+ } else if (strcmp(options.proxy_command, "-") == 0) {
+ packet_set_connection(STDIN_FILENO, STDOUT_FILENO);
+ return 0; /* Always succeeds */
+ } else if (options.proxy_use_fdpass) {
+ return ssh_proxy_fdpass_connect(host, port,
+ options.proxy_command);
+ }
+ return ssh_proxy_connect(host, port, options.proxy_command);
+}
+
+static void
+send_client_banner(int connection_out, int minor1)
+{
+ /* Send our own protocol version identification. */
+ if (compat20) {
+ xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
+ } else {
+ xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n",
+ PROTOCOL_MAJOR_1, minor1, SSH_VERSION);
+ }
+ if (roaming_atomicio(vwrite, connection_out, client_version_string,
+ strlen(client_version_string)) != strlen(client_version_string))
+ fatal("write: %.100s", strerror(errno));
+ chop(client_version_string);
+ debug("Local version string %.100s", client_version_string);
+}
+
/*
* Waits for the server identification string, and sends our own
* identification string.
@@ -440,7 +547,7 @@
int remote_major, remote_minor, mismatch;
int connection_in = packet_get_connection_in();
int connection_out = packet_get_connection_out();
- int minor1 = PROTOCOL_MINOR_1;
+ int minor1 = PROTOCOL_MINOR_1, client_banner_sent = 0;
u_int i, n;
size_t len;
int fdsetsz, remaining, rc;
@@ -450,6 +557,16 @@
fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
fdset = xcalloc(1, fdsetsz);
+ /*
+ * If we are SSH2-only then we can send the banner immediately and
+ * save a round-trip.
+ */
+ if (options.protocol == SSH_PROTO_2) {
+ enable_compat20();
+ send_client_banner(connection_out, 0);
+ client_banner_sent = 1;
+ }
+
/* Read other side's version identification. */
remaining = timeout_ms;
for (n = 0;;) {
@@ -499,7 +616,7 @@
debug("ssh_exchange_identification: %s", buf);
}
server_version_string = xstrdup(buf);
- xfree(fdset);
+ free(fdset);
/*
* Check that the versions match. In future this might accept
@@ -511,7 +628,7 @@
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
- compat_datafellows(remote_version);
+ active_state->compat = compat_datafellows(remote_version);
mismatch = 0;
switch (remote_major) {
@@ -552,18 +669,15 @@
fatal("Protocol major versions differ: %d vs. %d",
(options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
remote_major);
- /* Send our own protocol version identification. */
- snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
- compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
- compat20 ? PROTOCOL_MINOR_2 : minor1,
- SSH_VERSION, compat20 ? "\r\n" : "\n");
- if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
- != strlen(buf))
- fatal("write: %.100s", strerror(errno));
- client_version_string = xstrdup(buf);
- chop(client_version_string);
+ if ((datafellows & SSH_BUG_DERIVEKEY) != 0)
+ fatal("Server version \"%.100s\" uses unsafe key agreement; "
+ "refusing connection", remote_version);
+ if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
+ logit("Server version \"%.100s\" uses unsafe RSA signature "
+ "scheme; disabling use of RSA keys", remote_version);
+ if (!client_banner_sent)
+ send_client_banner(connection_out, minor1);
chop(server_version_string);
- debug("Local version string %.100s", client_version_string);
}
/* defaults to 'no' */
@@ -584,8 +698,7 @@
ret = 0;
if (p && strncasecmp(p, "yes", 3) == 0)
ret = 1;
- if (p)
- xfree(p);
+ free(p);
if (ret != -1)
return ret;
}
@@ -600,7 +713,7 @@
error("%s", reason);
return 0;
}
- if (buffer_len(&host_key->cert->critical) != 0) {
+ if (buffer_len(host_key->cert->critical) != 0) {
error("Certificate for %s contains unsupported "
"critical options(s)", host);
return 0;
@@ -657,7 +770,7 @@
if (options.proxy_command == NULL) {
if (getnameinfo(hostaddr, addrlen,
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
- fatal("check_host_key: getnameinfo failed");
+ fatal("%s: getnameinfo failed", __func__);
*hostfile_ipaddr = put_host_port(ntop, port);
} else {
*hostfile_ipaddr = xstrdup("<no hostip for proxy "
@@ -705,6 +818,7 @@
int len, cancelled_forwarding = 0;
int local = sockaddr_is_local(hostaddr);
int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
+ int hostkey_trusted = 0; /* Known or explicitly accepted by user */
struct hostkeys *host_hostkeys, *ip_hostkeys;
u_int i;
@@ -805,13 +919,17 @@
"key for IP address '%.128s' to the list "
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
- SSH_FP_RANDOMART);
+ fp = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
+ if (fp == NULL || ra == NULL)
+ fatal("%s: sshkey_fingerprint fail", __func__);
logit("Host key fingerprint is %s\n%s\n", fp, ra);
- xfree(ra);
- xfree(fp);
+ free(ra);
+ free(fp);
}
+ hostkey_trusted = 1;
break;
case HOST_NEW:
if (options.host_key_alias == NULL && port != 0 &&
@@ -846,9 +964,12 @@
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
- SSH_FP_RANDOMART);
+ fp = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
+ if (fp == NULL || ra == NULL)
+ fatal("%s: sshkey_fingerprint fail", __func__);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -870,10 +991,11 @@
options.visual_host_key ? "\n" : "",
options.visual_host_key ? ra : "",
msg2);
- xfree(ra);
- xfree(fp);
+ free(ra);
+ free(fp);
if (!confirm(msg))
goto fail;
+ hostkey_trusted = 1; /* user explicitly confirmed */
}
/*
* If not in strict mode, add the key automatically to the
@@ -1072,8 +1194,14 @@
}
}
- xfree(ip);
- xfree(host);
+ if (!hostkey_trusted && options.update_hostkeys) {
+ debug("%s: hostkey not known or explicitly trusted: "
+ "disabling UpdateHostkeys", __func__);
+ options.update_hostkeys = 0;
+ }
+
+ free(ip);
+ free(host);
if (host_hostkeys != NULL)
free_hostkeys(host_hostkeys);
if (ip_hostkeys != NULL)
@@ -1095,8 +1223,8 @@
}
if (raw_key != NULL)
key_free(raw_key);
- xfree(ip);
- xfree(host);
+ free(ip);
+ free(host);
if (host_hostkeys != NULL)
free_hostkeys(host_hostkeys);
if (ip_hostkeys != NULL)
@@ -1108,36 +1236,89 @@
int
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
- int flags = 0;
- char *fp;
+ int r = -1, flags = 0;
+ char *fp = NULL;
+ struct sshkey *plain = NULL;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- debug("Server host key: %s %s", key_type(host_key), fp);
- xfree(fp);
+ if ((fp = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ error("%s: fingerprint host key: %s", __func__, ssh_err(r));
+ r = -1;
+ goto out;
+ }
- /* XXX certs are not yet supported for DNS */
- if (!key_is_cert(host_key) && options.verify_host_key_dns &&
- verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
- if (flags & DNS_VERIFY_FOUND) {
+ debug("Server host key: %s %s",
+ compat20 ? sshkey_ssh_name(host_key) : sshkey_type(host_key), fp);
- if (options.verify_host_key_dns == 1 &&
- flags & DNS_VERIFY_MATCH &&
- flags & DNS_VERIFY_SECURE)
- return 0;
+ if (sshkey_equal(previous_host_key, host_key)) {
+ debug2("%s: server host key %s %s matches cached key",
+ __func__, sshkey_type(host_key), fp);
+ r = 0;
+ goto out;
+ }
- if (flags & DNS_VERIFY_MATCH) {
- matching_host_key_dns = 1;
- } else {
- warn_changed_key(host_key);
- error("Update the SSHFP RR in DNS with the new "
- "host key to get rid of this message.");
- }
+ /* Check in RevokedHostKeys file if specified */
+ if (options.revoked_host_keys != NULL) {
+ r = sshkey_check_revoked(host_key, options.revoked_host_keys);
+ switch (r) {
+ case 0:
+ break; /* not revoked */
+ case SSH_ERR_KEY_REVOKED:
+ error("Host key %s %s revoked by file %s",
+ sshkey_type(host_key), fp,
+ options.revoked_host_keys);
+ r = -1;
+ goto out;
+ default:
+ error("Error checking host key %s %s in "
+ "revoked keys file %s: %s", sshkey_type(host_key),
+ fp, options.revoked_host_keys, ssh_err(r));
+ r = -1;
+ goto out;
}
}
- return check_host_key(host, hostaddr, options.port, host_key, RDRW,
+ if (options.verify_host_key_dns) {
+ /*
+ * XXX certs are not yet supported for DNS, so downgrade
+ * them and try the plain key.
+ */
+ if ((r = sshkey_from_private(host_key, &plain)) != 0)
+ goto out;
+ if (sshkey_is_cert(plain))
+ sshkey_drop_cert(plain);
+ if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
+ if (flags & DNS_VERIFY_FOUND) {
+ if (options.verify_host_key_dns == 1 &&
+ flags & DNS_VERIFY_MATCH &&
+ flags & DNS_VERIFY_SECURE) {
+ r = 0;
+ goto out;
+ }
+ if (flags & DNS_VERIFY_MATCH) {
+ matching_host_key_dns = 1;
+ } else {
+ warn_changed_key(plain);
+ error("Update the SSHFP RR in DNS "
+ "with the new host key to get rid "
+ "of this message.");
+ }
+ }
+ }
+ }
+ r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
options.user_hostfiles, options.num_user_hostfiles,
options.system_hostfiles, options.num_system_hostfiles);
+
+out:
+ sshkey_free(plain);
+ free(fp);
+ if (r == 0 && host_key != NULL) {
+ key_free(previous_host_key);
+ previous_host_key = key_from_private(host_key);
+ }
+
+ return r;
}
/*
@@ -1151,7 +1332,7 @@
ssh_login(Sensitive *sensitive, const char *orighost,
struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
{
- char *host, *cp;
+ char *host;
char *server_user, *local_user;
local_user = xstrdup(pw->pw_name);
@@ -1159,9 +1340,7 @@
/* Convert the user-supplied hostname into all lowercase. */
host = xstrdup(orighost);
- for (cp = host; *cp; cp++)
- if (isupper(*cp))
- *cp = (char)tolower(*cp);
+ lowercase(host);
/* Exchange protocol version identification strings with the server. */
ssh_exchange_identification(timeout_ms);
@@ -1175,10 +1354,14 @@
ssh_kex2(host, hostaddr, port);
ssh_userauth2(local_user, server_user, host, sensitive);
} else {
+#ifdef WITH_SSH1
ssh_kex(host, hostaddr);
ssh_userauth1(local_user, server_user, host, sensitive);
+#else
+ fatal("ssh1 is not unsupported");
+#endif
}
- xfree(local_user);
+ free(local_user);
}
void
@@ -1195,15 +1378,22 @@
padded = xcalloc(1, size);
strlcpy(padded, password, size);
packet_put_string(padded, size);
- memset(padded, 0, size);
- xfree(padded);
+ explicit_bzero(padded, size);
+ free(padded);
}
/* print all known host keys for a given host, but skip keys of given type */
static int
show_other_keys(struct hostkeys *hostkeys, Key *key)
{
- int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
+ int type[] = {
+ KEY_RSA1,
+ KEY_RSA,
+ KEY_DSA,
+ KEY_ECDSA,
+ KEY_ED25519,
+ -1
+ };
int i, ret = 0;
char *fp, *ra;
const struct hostkey_entry *found;
@@ -1213,8 +1403,12 @@
continue;
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
continue;
- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
+ fp = sshkey_fingerprint(found->key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = sshkey_fingerprint(found->key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
+ if (fp == NULL || ra == NULL)
+ fatal("%s: sshkey_fingerprint fail", __func__);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
@@ -1223,8 +1417,8 @@
key_type(found->key), fp);
if (options.visual_host_key)
logit("%s", ra);
- xfree(ra);
- xfree(fp);
+ free(ra);
+ free(fp);
ret = 1;
}
return ret;
@@ -1235,7 +1429,10 @@
{
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
+ if (fp == NULL)
+ fatal("%s: sshkey_fingerprint fail", __func__);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
@@ -1247,7 +1444,7 @@
key_type(host_key), fp);
error("Please contact your system administrator.");
- xfree(fp);
+ free(fp);
}
/*