[libvirt] [PATCH 1/3] rpc: libssh: allow a NULL known_hosts file

Make sure that virNetLibsshSessionSetHostKeyVerification accepts a NULL value for the path to the known_hosts file: - call ssh_options_set(SSH_OPTIONS_KNOWNHOSTS) anyway, using /dev/null, otherwise libssh will use its default path - do not call ssh_write_knownhost when no known hosts file was set Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1406457 --- src/rpc/virnetlibsshsession.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/rpc/virnetlibsshsession.c b/src/rpc/virnetlibsshsession.c index 5de6629..25f93ce 100644 --- a/src/rpc/virnetlibsshsession.c +++ b/src/rpc/virnetlibsshsession.c @@ -382,14 +382,16 @@ virNetLibsshCheckHostKey(virNetLibsshSessionPtr sess) VIR_FREE(askKey.result); } - /* write the host key file */ - if (ssh_write_knownhost(sess->session) < 0) { - errmsg = ssh_get_error(sess->session); - virReportError(VIR_ERR_LIBSSH, - _("failed to write known_host file '%s': %s"), - sess->knownHostsFile, - errmsg); - return -1; + /* write the host key file, if specified */ + if (sess->knownHostsFile) { + if (ssh_write_knownhost(sess->session) < 0) { + errmsg = ssh_get_error(sess->session); + virReportError(VIR_ERR_LIBSSH, + _("failed to write known_host file '%s': %s"), + sess->knownHostsFile, + errmsg); + return -1; + } } /* key was accepted and added */ return 0; @@ -1172,13 +1174,20 @@ virNetLibsshSessionSetHostKeyVerification(virNetLibsshSessionPtr sess, goto error; } - /* set the known hosts file */ - if (ssh_options_set(sess->session, SSH_OPTIONS_KNOWNHOSTS, hostsfile) < 0) - goto error; + /* set the known hosts file, if specified */ + if (hostsfile) { + if (ssh_options_set(sess->session, SSH_OPTIONS_KNOWNHOSTS, hostsfile) < 0) + goto error; - VIR_FREE(sess->knownHostsFile); - if (VIR_STRDUP(sess->knownHostsFile, hostsfile) < 0) - goto error; + VIR_FREE(sess->knownHostsFile); + if (VIR_STRDUP(sess->knownHostsFile, hostsfile) < 0) + goto error; + } else { + /* libssh does not support trying no known_host file at all: + * hence use /dev/null here, without storing it as file */ + if (ssh_options_set(sess->session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null") < 0) + goto error; + } virObjectUnlock(sess); return 0; -- 2.7.4

If any of them is specified for the libssh and libssh2 drivers, there is no need to depend on chec ks based on other paths: in particular, a specified path for known_hosts was ignored if the local config directory could not be determined, and the path for keyfile was ignored if the home could not be determined. Instead, lazily determine and use these two paths only in case they are needed. --- src/rpc/virnetclient.c | 52 +++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 34475d9..9c781e3 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -450,32 +450,34 @@ virNetClientPtr virNetClientNewLibSSH2(const char *host, char *nc = NULL; char *command = NULL; - char *homedir = virGetUserDirectory(); - char *confdir = virGetUserConfigDirectory(); + char *homedir = NULL; + char *confdir = NULL; char *knownhosts = NULL; char *privkey = NULL; /* Use default paths for known hosts an public keys if not provided */ - if (confdir) { - if (!knownHostsPath) { + if (knownHostsPath) { + if (VIR_STRDUP(knownhosts, knownHostsPath) < 0) + goto cleanup; + } else { + confdir = virGetUserConfigDirectory(); + if (confdir) { if (virFileExists(confdir)) { virBufferAsprintf(&buf, "%s/known_hosts", confdir); if (!(knownhosts = virBufferContentAndReset(&buf))) goto no_memory; } - } else { - if (VIR_STRDUP(knownhosts, knownHostsPath) < 0) - goto cleanup; } } - if (homedir) { - if (!privkeyPath) { + if (privkeyPath) { + if (VIR_STRDUP(privkey, privkeyPath) < 0) + goto cleanup; + } else { + homedir = virGetUserDirectory(); + if (homedir) { if (virNetClientFindDefaultSshKey(homedir, &privkey) < 0) goto no_memory; - } else { - if (VIR_STRDUP(privkey, privkeyPath) < 0) - goto cleanup; } } @@ -559,31 +561,33 @@ virNetClientPtr virNetClientNewLibssh(const char *host, char *nc = NULL; char *command = NULL; - char *homedir = virGetUserDirectory(); - char *confdir = virGetUserConfigDirectory(); + char *homedir = NULL; + char *confdir = NULL; char *knownhosts = NULL; char *privkey = NULL; /* Use default paths for known hosts an public keys if not provided */ - if (confdir) { - if (!knownHostsPath) { + if (knownHostsPath) { + if (VIR_STRDUP(knownhosts, knownHostsPath) < 0) + goto cleanup; + } else { + confdir = virGetUserConfigDirectory(); + if (confdir) { if (virFileExists(confdir)) { if (virAsprintf(&knownhosts, "%s/known_hosts", confdir) < 0) goto cleanup; } - } else { - if (VIR_STRDUP(knownhosts, knownHostsPath) < 0) - goto cleanup; } } - if (homedir) { - if (!privkeyPath) { + if (privkeyPath) { + if (VIR_STRDUP(privkey, privkeyPath) < 0) + goto cleanup; + } else { + homedir = virGetUserDirectory(); + if (homedir) { if (virNetClientFindDefaultSshKey(homedir, &privkey) < 0) goto no_memory; - } else { - if (VIR_STRDUP(privkey, privkeyPath) < 0) - goto cleanup; } } -- 2.7.4

On Tue, Jan 10, 2017 at 19:43:19 +0100, Pino Toscano wrote:
If any of them is specified for the libssh and libssh2 drivers, there is no need to depend on chec ks based on other paths: in particular, a
s/chec ks/checks/
specified path for known_hosts was ignored if the local config directory could not be determined, and the path for keyfile was ignored if the home could not be determined.
Instead, lazily determine and use these two paths only in case they are needed. --- src/rpc/virnetclient.c | 52 +++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 24 deletions(-)
ACK

When composing the path to the default known_hosts file (for the libssh and libssh2 drivers), do not check whether the configuration directory (determined by virGetUserConfigDirectory()) exists: both the drivers can handle non-existing files, and are able to create them (and their directories) in that case. This adds a small behaviour change: before, the key for an unknown host, and manually accepted, was saved only if the configuration directory existed -- a bit incoherent behaviour though. --- src/rpc/virnetclient.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 9c781e3..5174614 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -462,11 +462,9 @@ virNetClientPtr virNetClientNewLibSSH2(const char *host, } else { confdir = virGetUserConfigDirectory(); if (confdir) { - if (virFileExists(confdir)) { - virBufferAsprintf(&buf, "%s/known_hosts", confdir); - if (!(knownhosts = virBufferContentAndReset(&buf))) - goto no_memory; - } + virBufferAsprintf(&buf, "%s/known_hosts", confdir); + if (!(knownhosts = virBufferContentAndReset(&buf))) + goto no_memory; } } @@ -573,10 +571,8 @@ virNetClientPtr virNetClientNewLibssh(const char *host, } else { confdir = virGetUserConfigDirectory(); if (confdir) { - if (virFileExists(confdir)) { - if (virAsprintf(&knownhosts, "%s/known_hosts", confdir) < 0) - goto cleanup; - } + if (virAsprintf(&knownhosts, "%s/known_hosts", confdir) < 0) + goto cleanup; } } -- 2.7.4

On Tue, Jan 10, 2017 at 19:43:20 +0100, Pino Toscano wrote:
When composing the path to the default known_hosts file (for the libssh and libssh2 drivers), do not check whether the configuration directory (determined by virGetUserConfigDirectory()) exists: both the drivers can handle non-existing files, and are able to create them (and their directories) in that case.
This adds a small behaviour change: before, the key for an unknown host, and manually accepted, was saved only if the configuration directory existed -- a bit incoherent behaviour though. ---
ACK

On Tue, Jan 10, 2017 at 19:43:18 +0100, Pino Toscano wrote:
Make sure that virNetLibsshSessionSetHostKeyVerification accepts a NULL value for the path to the known_hosts file: - call ssh_options_set(SSH_OPTIONS_KNOWNHOSTS) anyway, using /dev/null, otherwise libssh will use its default path - do not call ssh_write_knownhost when no known hosts file was set
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1406457 --- src/rpc/virnetlibsshsession.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-)
ACK
participants (2)
-
Peter Krempa
-
Pino Toscano