From patchwork Tue Jan 10 15:08:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pino Toscano X-Patchwork-Id: 90716 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp1058758obz; Tue, 10 Jan 2017 07:11:38 -0800 (PST) X-Received: by 10.28.181.145 with SMTP id e139mr646132wmf.103.1484061097930; Tue, 10 Jan 2017 07:11:37 -0800 (PST) Return-Path: Received: from mx3-phx2.redhat.com (mx3-phx2.redhat.com. [209.132.183.24]) by mx.google.com with ESMTPS id r6si1709488wrr.237.2017.01.10.07.11.37 (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 10 Jan 2017 07:11:37 -0800 (PST) Received-SPF: pass (google.com: domain of libvir-list-bounces@redhat.com designates 209.132.183.24 as permitted sender) client-ip=209.132.183.24; Authentication-Results: mx.google.com; spf=pass (google.com: domain of libvir-list-bounces@redhat.com designates 209.132.183.24 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx3-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v0AF8IAs007279; Tue, 10 Jan 2017 10:08:19 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v0AF8HRF017427 for ; Tue, 10 Jan 2017 10:08:17 -0500 Received: from thyrus.usersys.redhat.com (dhcp129-231.brq.redhat.com [10.34.129.231]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v0AF8Gms005745 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 10 Jan 2017 10:08:17 -0500 From: Pino Toscano To: libvir-list@redhat.com Date: Tue, 10 Jan 2017 16:08:03 +0100 Message-ID: <6062162.CBVnNAEPkv@thyrus.usersys.redhat.com> Organization: Red Hat User-Agent: KMail/5.3.3 (Linux/4.8.15-200.fc24.x86_64; KDE/5.29.0; x86_64; ; ) In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: Re: [libvirt] [PATCH] rpc: libssh: don't crash when known_hosts file path is not provided X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com On Monday, 9 January 2017 15:16:46 CET Peter Krempa wrote: > When connecting as root, the "hostsfile" variable would be NULL due to > the code leading to this point. This would result into a crash when > attempting to set the known hosts file path. Almost: the issue happens generally when known_hosts does not exist. Considering the following code in src/rpc/virnetclient.c (both virNetClientNewLibSSH2 and virNetClientNewLibssh have it): if (confdir) { if (!knownHostsPath) { 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; } } knownHostsPath is left NULL if known_hosts is not passed as parameter, and either one of: a) confdir is NULL: reading virGetUserConfigDirectory (actually, virGetXDGDirectory) this happens only when XDG_CONFIG_HOME is not set, and neither is HOME b) confdir is not NULL, but it does not exist Regarding (a), there is no other "fix" doable within virNetClient itself, since all the ways to determine the user home failed (and thus no path can be determined). Regarding (b), IMHO virNetClient could drop the virFileExists check, letting the libssh and libssh2 drivers to handle: - libssh seems to handle a non-existing file fine, creating its directories and the file itself on its own when saving - the libssh2 already checks whether the file exists, using it only in that case > To avoid deviating from the approach taken in the libssh2 driver set the > file to /dev/null so that all entries are discarded unless explicitly > specified. While this works (ssh_write_knownhost should handle /dev as existing already), IMHO it's better to make the libssh driver behave more close to the libssh2, i.e. setting knownHostsFile only when considered valid. What about the attached patch instead? -- Pino Toscano -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From=20a97d1baeefd32990730f4ec32501bf5fdb7b675b Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Tue, 10 Jan 2017 16:04:03 +0100 Subject: [PATCH] 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 | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/rpc/virnetlibsshsession.c b/src/rpc/virnetlibsshsession.c index 5de6629..3ffe158 100644 --- a/src/rpc/virnetlibsshsession.c +++ b/src/rpc/virnetlibsshsession.c @@ -303,6 +303,10 @@ virNetLibsshCheckHostKey(virNetLibsshSessionPtr sess) if (!keyhashstr) return -1; + /* If a key mismatch happens, then surely there was an existing + * known_host file (with the different key). */ + sa_assert(sess->knownHostsFile); + /* host key verification failed */ virReportError(VIR_ERR_AUTH_FAILED, _("!!! SSH HOST KEY VERIFICATION FAILED !!!: " @@ -382,14 +386,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 +1178,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