Commit 1dfdf4b8 by Eric Huss Committed by Edward Thomson

Set all SSH hostkey preferences that are available

parent bef34cb2
...@@ -467,28 +467,26 @@ out: ...@@ -467,28 +467,26 @@ out:
return error; return error;
} }
static const char *hostkey_type_to_string(int type) static void add_hostkey_pref_if_avail(
LIBSSH2_KNOWNHOSTS *known_hosts,
const char *hostname,
int port,
git_str *prefs,
int type,
const char *type_name)
{ {
switch (type) { struct libssh2_knownhost *host = NULL;
case LIBSSH2_KNOWNHOST_KEY_SSHRSA: const char key = '\0';
return "ssh-rsa"; int mask = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | type;
case LIBSSH2_KNOWNHOST_KEY_SSHDSS: int error;
return "ssh-dss";
#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
return "ecdsa-sha2-nistp256";
case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
return "ecdsa-sha2-nistp384";
case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
return "ecdsa-sha2-nistp521";
#endif
#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
case LIBSSH2_KNOWNHOST_KEY_ED25519:
return "ssh-ed25519";
#endif
}
return NULL; error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, mask, &host);
if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
if (git_str_len(prefs) > 0) {
git_str_putc(prefs, ',');
}
git_str_puts(prefs, type_name);
}
} }
/* /*
...@@ -496,27 +494,27 @@ static const char *hostkey_type_to_string(int type) ...@@ -496,27 +494,27 @@ static const char *hostkey_type_to_string(int type)
* look it up with a nonsense key and using that mismatch to figure out what key * look it up with a nonsense key and using that mismatch to figure out what key
* we do have stored for the host. * we do have stored for the host.
* *
* Returns the string to pass to libssh2_session_method_pref or NULL if we were * Populates prefs with the string to pass to libssh2_session_method_pref.
* unable to find anything or an error happened.
*/ */
static const char *find_hostkey_preference(LIBSSH2_KNOWNHOSTS *known_hosts, const char *hostname, int port) static void find_hostkey_preference(
LIBSSH2_KNOWNHOSTS *known_hosts,
const char *hostname,
int port,
git_str *prefs)
{ {
struct libssh2_knownhost *host = NULL;
/* Specify no key type so we don't filter on that */
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW;
const char key = '\0';
int error;
/* /*
* In case of mismatch, we can find the type of key from known_hosts in * The order here is important as it indicates the priority of what will
* the returned host's information as it means that an entry was found * be preferred.
* but our nonsense key obviously didn't match.
*/ */
error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, type, &host); #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ED25519, "ssh-ed25519");
return hostkey_type_to_string(host->typemask & LIBSSH2_KNOWNHOST_KEY_MASK); #endif
#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
return NULL; add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_256, "ecdsa-sha2-nistp256");
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_384, "ecdsa-sha2-nistp384");
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_521, "ecdsa-sha2-nistp521");
#endif
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_SSHRSA, "ssh-rsa");
} }
static int _git_ssh_session_create( static int _git_ssh_session_create(
...@@ -526,11 +524,11 @@ static int _git_ssh_session_create( ...@@ -526,11 +524,11 @@ static int _git_ssh_session_create(
int port, int port,
git_stream *io) git_stream *io)
{ {
int rc = 0; git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
LIBSSH2_SESSION *s; LIBSSH2_SESSION *s;
LIBSSH2_KNOWNHOSTS *known_hosts; LIBSSH2_KNOWNHOSTS *known_hosts;
git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent); git_str prefs = GIT_STR_INIT;
const char *keytype = NULL; int rc = 0;
GIT_ASSERT_ARG(session); GIT_ASSERT_ARG(session);
GIT_ASSERT_ARG(hosts); GIT_ASSERT_ARG(hosts);
...@@ -547,16 +545,17 @@ static int _git_ssh_session_create( ...@@ -547,16 +545,17 @@ static int _git_ssh_session_create(
return -1; return -1;
} }
if ((keytype = find_hostkey_preference(known_hosts, hostname, port)) != NULL) { find_hostkey_preference(known_hosts, hostname, port, &prefs);
if (git_str_len(&prefs) > 0) {
do { do {
rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, keytype); rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, git_str_cstr(&prefs));
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
if (rc != LIBSSH2_ERROR_NONE) { if (rc != LIBSSH2_ERROR_NONE) {
ssh_error(s, "failed to set hostkey preference"); ssh_error(s, "failed to set hostkey preference");
goto on_error; goto on_error;
} }
} }
git_str_dispose(&prefs);
do { do {
rc = libssh2_session_handshake(s, socket->s); rc = libssh2_session_handshake(s, socket->s);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment