All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, mreitz@redhat.com, pkrempa@redhat.com,
	eblake@redhat.com, jcody@redhat.com, jdurgin@redhat.com,
	mitake.hitoshi@lab.ntt.co.jp, namei.unix@gmail.com,
	qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 21/27] ssh: QAPIfy host-key-check option
Date: Thu,  8 Feb 2018 20:23:22 +0100	[thread overview]
Message-ID: <20180208192328.16550-22-kwolf@redhat.com> (raw)
In-Reply-To: <20180208192328.16550-1-kwolf@redhat.com>

This makes the host-key-check option available in blockdev-add.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json | 63 +++++++++++++++++++++++++++++++++++--
 block/ssh.c          | 88 +++++++++++++++++++++++++++++++++-------------------
 2 files changed, 117 insertions(+), 34 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 08217e3e38..7ad25ce372 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2533,6 +2533,63 @@
             '*encrypt': 'BlockdevQcow2Encryption' } }
 
 ##
+# @SshHostKeyCheckMode:
+#
+# @none             Don't check the host key at all
+# @hash             Compare the host key with a given hash
+# @known_hosts      Check the host key against the known_hosts file
+#
+# Since: 2.12
+##
+{ 'enum': 'SshHostKeyCheckMode',
+  'data': [ 'none', 'hash', 'known_hosts' ] }
+
+##
+# @SshHostKeyCheckHashType:
+#
+# @md5              The given hash is an md5 hash
+# @sha1             The given hash is an sha1 hash
+#
+# Since: 2.12
+##
+{ 'enum': 'SshHostKeyCheckHashType',
+  'data': [ 'md5', 'sha1' ] }
+
+##
+# @SshHostKeyHash:
+#
+# @type             The hash algorithm used for the hash
+# @hash             The expected hash value
+#
+# Since: 2.12
+##
+{ 'struct': 'SshHostKeyHash',
+  'data': { 'type': 'SshHostKeyCheckHashType',
+            'hash': 'str' }}
+
+##
+# @SshHostKeyDummy:
+#
+# For those union branches that don't need additional fields.
+#
+# Since: 2.12
+##
+{ 'struct': 'SshHostKeyDummy',
+  'data': {} }
+
+##
+# @SshHostKeyCheck:
+#
+# Since: 2.12
+##
+{ 'union': 'SshHostKeyCheck',
+  'base': { 'mode': 'SshHostKeyCheckMode' },
+  'discriminator': 'mode',
+  'data': { 'none': 'SshHostKeyDummy',
+            'hash': 'SshHostKeyHash',
+            'known_hosts': 'SshHostKeyDummy' } }
+
+##
 # @BlockdevOptionsSsh:
 #
 # @server:              host address
@@ -2542,14 +2599,16 @@
 # @user:                user as which to connect, defaults to current
 #                       local user name
 #
-# TODO: Expose the host_key_check option in QMP
+# @host-key-check:      Defines how and what to check the host key against
+#                       (default: known_hosts)
 #
 # Since: 2.9
 ##
 { 'struct': 'BlockdevOptionsSsh',
   'data': { 'server': 'InetSocketAddress',
             'path': 'str',
-            '*user': 'str' } }
+            '*user': 'str',
+            '*host-key-check': 'SshHostKeyCheck' } }
 
 
 ##
diff --git a/block/ssh.c b/block/ssh.c
index 691080b560..d565d876d3 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -428,31 +428,35 @@ check_host_key_hash(BDRVSSHState *s, const char *hash,
 }
 
 static int check_host_key(BDRVSSHState *s, const char *host, int port,
-                          const char *host_key_check, Error **errp)
+                          SshHostKeyCheck *hkc, Error **errp)
 {
-    /* host_key_check=no */
-    if (strcmp(host_key_check, "no") == 0) {
-        return 0;
-    }
+    SshHostKeyCheckMode mode;
 
-    /* host_key_check=md5:xx:yy:zz:... */
-    if (strncmp(host_key_check, "md5:", 4) == 0) {
-        return check_host_key_hash(s, &host_key_check[4],
-                                   LIBSSH2_HOSTKEY_HASH_MD5, 16, errp);
-    }
-
-    /* host_key_check=sha1:xx:yy:zz:... */
-    if (strncmp(host_key_check, "sha1:", 5) == 0) {
-        return check_host_key_hash(s, &host_key_check[5],
-                                   LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp);
+    if (hkc) {
+        mode = hkc->mode;
+    } else {
+        mode = SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS;
     }
 
-    /* host_key_check=yes */
-    if (strcmp(host_key_check, "yes") == 0) {
+    switch (mode) {
+    case SSH_HOST_KEY_CHECK_MODE_NONE:
+        return 0;
+    case SSH_HOST_KEY_CHECK_MODE_HASH:
+        if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_MD5) {
+            return check_host_key_hash(s, hkc->u.hash.hash,
+                                       LIBSSH2_HOSTKEY_HASH_MD5, 16, errp);
+        } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA1) {
+            return check_host_key_hash(s, hkc->u.hash.hash,
+                                       LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp);
+        }
+        g_assert_not_reached();
+        break;
+    case SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS:
         return check_host_key_knownhosts(s, host, port, errp);
+    default:
+        g_assert_not_reached();
     }
 
-    error_setg(errp, "unknown host_key_check setting (%s)", host_key_check);
     return -EINVAL;
 }
 
@@ -541,15 +545,21 @@ static QemuOptsList ssh_runtime_opts = {
             .type = QEMU_OPT_NUMBER,
             .help = "Port to connect to",
         },
+        {
+            .name = "host_key_check",
+            .type = QEMU_OPT_STRING,
+            .help = "Defines how and what to check the host key against",
+        },
     },
 };
 
-static bool ssh_process_legacy_socket_options(QDict *output_opts,
-                                              QemuOpts *legacy_opts,
-                                              Error **errp)
+static bool ssh_process_legacy_options(QDict *output_opts,
+                                       QemuOpts *legacy_opts,
+                                       Error **errp)
 {
     const char *host = qemu_opt_get(legacy_opts, "host");
     const char *port = qemu_opt_get(legacy_opts, "port");
+    const char *host_key_check = qemu_opt_get(legacy_opts, "host_key_check");
 
     if (!host && port) {
         error_setg(errp, "port may not be used without host");
@@ -561,6 +571,28 @@ static bool ssh_process_legacy_socket_options(QDict *output_opts,
         qdict_put_str(output_opts, "server.port", port ?: stringify(22));
     }
 
+    if (host_key_check) {
+        if (strcmp(host_key_check, "no") == 0) {
+            qdict_put_str(output_opts, "host-key-check.mode", "none");
+        } else if (strncmp(host_key_check, "md5:", 4) == 0) {
+            qdict_put_str(output_opts, "host-key-check.mode", "hash");
+            qdict_put_str(output_opts, "host-key-check.type", "md5");
+            qdict_put_str(output_opts, "host-key-check.hash",
+                          &host_key_check[4]);
+        } else if (strncmp(host_key_check, "sha1:", 5) == 0) {
+            qdict_put_str(output_opts, "host-key-check.mode", "hash");
+            qdict_put_str(output_opts, "host-key-check.type", "sha1");
+            qdict_put_str(output_opts, "host-key-check.hash",
+                          &host_key_check[5]);
+        } else if (strcmp(host_key_check, "yes") == 0) {
+            qdict_put_str(output_opts, "host-key-check.mode", "known_hosts");
+        } else {
+            error_setg(errp, "unknown host_key_check setting (%s)",
+                       host_key_check);
+            return false;
+        }
+    }
+
     return true;
 }
 
@@ -581,7 +613,7 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp)
         goto fail;
     }
 
-    if (!ssh_process_legacy_socket_options(options, opts, errp)) {
+    if (!ssh_process_legacy_options(options, opts, errp)) {
         goto fail;
     }
 
@@ -625,16 +657,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
 {
     BlockdevOptionsSsh *opts;
     int r, ret;
-    const char *user, *host_key_check;
+    const char *user;
     long port = 0;
 
-    host_key_check = qdict_get_try_str(options, "host_key_check");
-    if (!host_key_check) {
-        host_key_check = "yes";
-    } else {
-        qdict_del(options, "host_key_check");
-    }
-
     opts = ssh_parse_options(options, errp);
     if (opts == NULL) {
         return -EINVAL;
@@ -688,8 +713,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
     }
 
     /* Check the remote host's key against known_hosts. */
-    ret = check_host_key(s, s->inet->host, port, host_key_check,
-                         errp);
+    ret = check_host_key(s, s->inet->host, port, opts->host_key_check, errp);
     if (ret < 0) {
         goto err;
     }
-- 
2.13.6

  parent reply	other threads:[~2018-02-08 19:25 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-08 19:23 [Qemu-devel] [PATCH 00/27] x-blockdev-create for protocols and qcow2 Kevin Wolf
2018-02-08 19:23 ` [Qemu-devel] [PATCH 01/27] block/qapi: Introduce BlockdevCreateOptions Kevin Wolf
2018-02-08 22:48   ` Eric Blake
2018-02-09 13:19   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 02/27] block/qapi: Add qcow2 create options to schema Kevin Wolf
2018-02-08 23:14   ` Eric Blake
2018-02-09 13:36   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 03/27] qcow2: Let qcow2_create() handle protocol layer Kevin Wolf
2018-02-09 13:57   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 04/27] qcow2: Pass BlockdevCreateOptions to qcow2_create2() Kevin Wolf
2018-02-08 23:29   ` Eric Blake
2018-02-09 14:00     ` Kevin Wolf
2018-02-09 14:12   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 05/27] qcow2: Use BlockdevRef in qcow2_create2() Kevin Wolf
2018-02-09 13:57   ` Eric Blake
2018-02-09 14:31   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 06/27] qcow2: Use QCryptoBlockCreateOptions " Kevin Wolf
2018-02-09 14:13   ` Eric Blake
2018-02-09 18:01   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 07/27] qcow2: Handle full/falloc preallocation " Kevin Wolf
2018-02-09 18:04   ` Max Reitz
2018-02-12 14:19   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 08/27] util: Add qemu_opts_to_qdict_filtered() Kevin Wolf
2018-02-09 18:07   ` Max Reitz
2018-02-15 19:33   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 09/27] qdict: Introduce qdict_rename_keys() Kevin Wolf
2018-02-09 18:18   ` Max Reitz
2018-02-09 18:19     ` Max Reitz
2018-02-15 19:39   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 10/27] qcow2: Use visitor for options in qcow2_create() Kevin Wolf
2018-02-09 18:43   ` Max Reitz
2018-02-15 19:51   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 11/27] block: x-blockdev-create QMP command Kevin Wolf
2018-02-12 13:48   ` Max Reitz
2018-02-15 19:58   ` Eric Blake
2018-02-21 10:29     ` Kevin Wolf
2018-02-21 16:21       ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 12/27] file-posix: Support .bdrv_co_create Kevin Wolf
2018-02-12 13:55   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 13/27] file-win32: " Kevin Wolf
2018-02-12 13:57   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 14/27] gluster: " Kevin Wolf
2018-02-12 14:28   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 15/27] rbd: " Kevin Wolf
2018-02-12 15:16   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 16/27] nfs: Use QAPI options in nfs_client_open() Kevin Wolf
2018-02-12 15:36   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 17/27] nfs: Support .bdrv_co_create Kevin Wolf
2018-02-12 15:45   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 18/27] sheepdog: QAPIfy "redundacy" create option Kevin Wolf
2018-02-12 16:03   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 19/27] sheepdog: Support .bdrv_co_create Kevin Wolf
2018-02-12 16:43   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 20/27] ssh: Use QAPI BlockdevOptionsSsh object Kevin Wolf
2018-02-12 17:17   ` Max Reitz
2018-02-08 19:23 ` Kevin Wolf [this message]
2018-02-12 17:29   ` [Qemu-devel] [PATCH 21/27] ssh: QAPIfy host-key-check option Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 22/27] ssh: Pass BlockdevOptionsSsh to connect_to_ssh() Kevin Wolf
2018-02-12 17:35   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 23/27] ssh: Support .bdrv_co_create Kevin Wolf
2018-02-12 17:40   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 24/27] file-posix: Fix no-op bdrv_truncate() with falloc preallocation Kevin Wolf
2018-02-12 17:41   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 25/27] block: Fail bdrv_truncate() with negative size Kevin Wolf
2018-02-12 17:42   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 26/27] qemu-iotests: Test qcow2 over file image creation with QMP Kevin Wolf
2018-02-12 17:50   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 27/27] qemu-iotests: Test ssh image creation over QMP Kevin Wolf
2018-02-12 17:56   ` Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180208192328.16550-22-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=eblake@redhat.com \
    --cc=jcody@redhat.com \
    --cc=jdurgin@redhat.com \
    --cc=mitake.hitoshi@lab.ntt.co.jp \
    --cc=mreitz@redhat.com \
    --cc=namei.unix@gmail.com \
    --cc=pkrempa@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.