mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 02:56:17 +00:00
Set all SSH hostkey preferences that are available
This commit is contained in:
committed by
Edward Thomson
parent
870f69c34c
commit
b7352a7058
@@ -467,28 +467,26 @@ out:
|
||||
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) {
|
||||
case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
|
||||
return "ssh-rsa";
|
||||
case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
|
||||
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
|
||||
}
|
||||
struct libssh2_knownhost *host = NULL;
|
||||
const char key = '\0';
|
||||
int mask = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | type;
|
||||
int error;
|
||||
|
||||
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)
|
||||
* look it up with a nonsense key and using that mismatch to figure out what key
|
||||
* we do have stored for the host.
|
||||
*
|
||||
* Returns the string to pass to libssh2_session_method_pref or NULL if we were
|
||||
* unable to find anything or an error happened.
|
||||
* Populates prefs with the string to pass to libssh2_session_method_pref.
|
||||
*/
|
||||
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 returned host's information as it means that an entry was found
|
||||
* but our nonsense key obviously didn't match.
|
||||
* The order here is important as it indicates the priority of what will
|
||||
* be preferred.
|
||||
*/
|
||||
error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, type, &host);
|
||||
if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH)
|
||||
return hostkey_type_to_string(host->typemask & LIBSSH2_KNOWNHOST_KEY_MASK);
|
||||
|
||||
return NULL;
|
||||
#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
|
||||
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ED25519, "ssh-ed25519");
|
||||
#endif
|
||||
#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
|
||||
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(
|
||||
@@ -526,11 +524,11 @@ static int _git_ssh_session_create(
|
||||
int port,
|
||||
git_stream *io)
|
||||
{
|
||||
int rc = 0;
|
||||
git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
|
||||
LIBSSH2_SESSION *s;
|
||||
LIBSSH2_KNOWNHOSTS *known_hosts;
|
||||
git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
|
||||
const char *keytype = NULL;
|
||||
git_str prefs = GIT_STR_INIT;
|
||||
int rc = 0;
|
||||
|
||||
GIT_ASSERT_ARG(session);
|
||||
GIT_ASSERT_ARG(hosts);
|
||||
@@ -547,16 +545,17 @@ static int _git_ssh_session_create(
|
||||
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 {
|
||||
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);
|
||||
if (rc != LIBSSH2_ERROR_NONE) {
|
||||
ssh_error(s, "failed to set hostkey preference");
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
git_str_dispose(&prefs);
|
||||
|
||||
do {
|
||||
rc = libssh2_session_handshake(s, socket->s);
|
||||
|
||||
Reference in New Issue
Block a user