From patchwork Tue Oct 20 08:12:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 270936 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1AE0BC433E7 for ; Tue, 20 Oct 2020 08:15:27 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4E4A32225F for ; Tue, 20 Oct 2020 08:15:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="X0RyLtSY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4E4A32225F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40938 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmnl-0007rA-7y for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:15:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41010) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmlq-0006N9-Dt for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:28 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:36692) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmlk-0001Ze-9a for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181599; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oC06nz2LgSApPVAE0UdU3X/ockXF5+7JzZSINGGlJo8=; b=X0RyLtSYMi1CvQFUETfM/0vMpUvi8mRA9e4wQAvbT3xcrHkccSdwcBABU0zyNDfnI/IOKM p1n/WFBSffo8jaZGySc+mytY4ogYDNqISUuSiw+qZmMPgpaNrtLZnYsmEZLK7dtRqEw050 sHTcWpSQGpe7nmufj07VwvR11zazrig= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-449-lonXw_QhNQG4qyFloTPW_w-1; Tue, 20 Oct 2020 04:13:14 -0400 X-MC-Unique: lonXw_QhNQG4qyFloTPW_w-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C3E40108E1A9; Tue, 20 Oct 2020 08:13:13 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id BE7A827CD1; Tue, 20 Oct 2020 08:13:09 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 1/7] glib-compat: add g_unix_get_passwd_entry_qemu() Date: Tue, 20 Oct 2020 12:12:51 +0400 Message-Id: <20201020081257.2054548-2-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:16:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau The glib function was introduced in 2.64. It's a safer version of getpwnam, and also simpler to use than getpwnam_r. Currently, it's only use by the next patch in qemu-ga, which doesn't (well well...) need the thread safety guarantees. Since the fallback version is still unsafe, I would rather keep the _qemu postfix, to make sure it's not being misused by mistake. When/if necessary, we can implement a safer fallback and drop the _qemu suffix. Signed-off-by: Marc-André Lureau Reviewed-by: Michal Privoznik --- include/glib-compat.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/glib-compat.h b/include/glib-compat.h index 0b0ec76299..64e68aa730 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -30,6 +30,11 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #include +#if defined(G_OS_UNIX) +#include +#include +#include +#endif /* * Note that because of the GLIB_VERSION_MAX_ALLOWED constant above, allowing @@ -72,6 +77,27 @@ gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); #endif +#if defined(G_OS_UNIX) +/* Note: The fallback implementation is not MT-safe, and it returns a copy of + * the libc passwd (must be g_free() after use) but not the content. Because of + * these important differences the caller must be aware of, it's not #define for + * GLib API substitution. */ +static inline struct passwd * +g_unix_get_passwd_entry_qemu(const gchar *user_name, GError **error) +{ +#if GLIB_CHECK_VERSION(2, 64, 0) + return g_unix_get_passwd_entry(user_name, error); +#else + struct passwd *p = getpwnam(user_name); + if (!p) { + g_set_error_literal(error, G_UNIX_ERROR, 0, g_strerror(errno)); + return NULL; + } + return (struct passwd *)g_memdup(p, sizeof(*p)); +#endif +} +#endif /* G_OS_UNIX */ + #pragma GCC diagnostic pop #endif From patchwork Tue Oct 20 08:12:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 302538 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 407B5C433E7 for ; Tue, 20 Oct 2020 08:15:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5BB9D222C8 for ; Tue, 20 Oct 2020 08:15:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Fzb+A2Du" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5BB9D222C8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40858 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmnl-0007p7-9n for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:15:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41052) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmlu-0006Rd-JJ for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:49009) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmls-0001ap-0n for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181606; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+GI2x4W7Qqtk1Ev4mtnewpzyfihXVNC+Z9qJme/SdlI=; b=Fzb+A2Du1txnocxgQmZjTs8Y0zUlU/7vCEQZ8QBSuZWCLHb+TqhA/3aOoCzlaqDqVckVs/ 3GkhQ5e0qdbsY6XXFHpD68xdyRPW581N7dWqy+8ghKrs4IwR6RECuEsHzT5fC3FcT1IlZa dIgyWpXQGLCb48uDmG0sK9ePKxIIyJA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-497-nGEiLfpJOUWiyUOyJrpGSw-1; Tue, 20 Oct 2020 04:13:24 -0400 X-MC-Unique: nGEiLfpJOUWiyUOyJrpGSw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1A3BAEDBC0; Tue, 20 Oct 2020 08:13:23 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3BA971002388; Tue, 20 Oct 2020 08:13:17 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 2/7] qga: add ssh-{add,remove}-authorized-keys Date: Tue, 20 Oct 2020 12:12:52 +0400 Message-Id: <20201020081257.2054548-3-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:16:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Add new commands to add and remove SSH public keys from ~/.ssh/authorized_keys. I took a different approach for testing, including the unit tests right with the code. I wanted to overwrite the function to get the user details, I couldn't easily do that over QMP. Furthermore, I prefer having unit tests very close to the code, and unit files that are domain specific (commands-posix is too crowded already). FWIW, that coding/testing style is Rust-style (where tests can or should even be part of the documentation!). Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1885332 Signed-off-by: Marc-André Lureau Reviewed-by: Michal Privoznik Reviewed-by: Daniel P. Berrangé --- qga/commands-posix-ssh.c | 400 +++++++++++++++++++++++++++++++++++++++ qga/commands-win32.c | 12 ++ qga/meson.build | 20 +- qga/qapi-schema.json | 33 ++++ 4 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 qga/commands-posix-ssh.c diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c new file mode 100644 index 0000000000..d41c114c3c --- /dev/null +++ b/qga/commands-posix-ssh.c @@ -0,0 +1,400 @@ + /* + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" + +#include +#include +#include +#include + +#include "qapi/error.h" +#include "qga-qapi-commands.h" + +#ifdef QGA_BUILD_UNIT_TEST +static struct passwd * +test_get_passwd_entry(const gchar *user_name, GError **error) +{ + struct passwd *p; + int ret; + + if (!user_name || g_strcmp0(user_name, g_get_user_name())) { + g_set_error(error, G_UNIX_ERROR, 0, "Invalid user name"); + return NULL; + } + + p = g_new0(struct passwd, 1); + p->pw_dir = (char *)g_get_home_dir(); + p->pw_uid = geteuid(); + p->pw_gid = getegid(); + + ret = g_mkdir_with_parents(p->pw_dir, 0700); + g_assert_cmpint(ret, ==, 0); + + return p; +} + +#define g_unix_get_passwd_entry_qemu(username, err) \ + test_get_passwd_entry(username, err) +#endif + +static struct passwd * +get_passwd_entry(const char *username, Error **errp) +{ + g_autoptr(GError) err = NULL; + struct passwd *p; + + ERRP_GUARD(); + + p = g_unix_get_passwd_entry_qemu(username, &err); + if (p == NULL) { + error_setg(errp, "failed to lookup user '%s': %s", + username, err->message); + return NULL; + } + + return p; +} + +static bool +mkdir_for_user(const char *path, const struct passwd *p, + mode_t mode, Error **errp) +{ + ERRP_GUARD(); + + if (g_mkdir(path, mode) == -1) { + error_setg(errp, "failed to create directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + if (chown(path, p->pw_uid, p->pw_gid) == -1) { + error_setg(errp, "failed to set ownership of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + if (chmod(path, mode) == -1) { + error_setg(errp, "failed to set permissions of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + return true; +} + +static bool +check_openssh_pub_key(const char *key, Error **errp) +{ + ERRP_GUARD(); + + /* simple sanity-check, we may want more? */ + if (!key || key[0] == '#' || strchr(key, '\n')) { + error_setg(errp, "invalid OpenSSH public key: '%s'", key); + return false; + } + + return true; +} + +static bool +check_openssh_pub_keys(strList *keys, size_t *nkeys, Error **errp) +{ + size_t n = 0; + strList *k; + + ERRP_GUARD(); + + for (k = keys; k != NULL; k = k->next) { + if (!check_openssh_pub_key(k->value, errp)) { + return false; + } + n++; + } + + if (nkeys) { + *nkeys = n; + } + return true; +} + +static bool +write_authkeys(const char *path, const GStrv keys, Error **errp) +{ + g_autofree char *contents = NULL; + g_autoptr(GError) err = NULL; + + ERRP_GUARD(); + + contents = g_strjoinv("\n", keys); + if (!g_file_set_contents(path, contents, -1, &err)) { + error_setg(errp, "failed to write to '%s': %s", path, err->message); + return false; + } + + if (chmod(path, 0600) == -1) { + error_setg(errp, "failed to set permissions of '%s': %s", + path, g_strerror(errno)); + return false; + } + + return true; +} + +static GStrv +read_authkeys(const char *path, Error **errp) +{ + g_autoptr(GError) err = NULL; + g_autofree char *contents = NULL; + + ERRP_GUARD(); + + if (!g_file_get_contents(path, &contents, NULL, &err)) { + error_setg(errp, "failed to read '%s': %s", path, err->message); + return NULL; + } + + return g_strsplit(contents, "\n", -1); + +} + +void +qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, + Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *ssh_path = NULL; + g_autofree char *authkeys_path = NULL; + g_auto(GStrv) authkeys = NULL; + strList *k; + size_t nkeys, nauthkeys; + + ERRP_GUARD(); + + if (!check_openssh_pub_keys(keys, &nkeys, errp)) { + return; + } + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return; + } + + ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL); + authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL); + + authkeys = read_authkeys(authkeys_path, NULL); + if (authkeys == NULL) { + if (!g_file_test(ssh_path, G_FILE_TEST_IS_DIR) && + !mkdir_for_user(ssh_path, p, 0700, errp)) { + return; + } + } + + nauthkeys = authkeys ? g_strv_length(authkeys) : 0; + authkeys = g_realloc_n(authkeys, nauthkeys + nkeys + 1, sizeof(char *)); + memset(authkeys + nauthkeys, 0, (nkeys + 1) * sizeof(char *)); + + for (k = keys; k != NULL; k = k->next) { + if (g_strv_contains((const gchar * const *)authkeys, k->value)) { + continue; + } + authkeys[nauthkeys++] = g_strdup(k->value); + } + + write_authkeys(authkeys_path, authkeys, errp); +} + +void +qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, + Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *authkeys_path = NULL; + g_autofree GStrv new_keys = NULL; /* do not own the strings */ + g_auto(GStrv) authkeys = NULL; + GStrv a; + size_t nkeys = 0; + + ERRP_GUARD(); + + if (!check_openssh_pub_keys(keys, NULL, errp)) { + return; + } + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return; + } + + authkeys_path = g_build_filename(p->pw_dir, ".ssh", + "authorized_keys", NULL); + if (!g_file_test(authkeys_path, G_FILE_TEST_EXISTS)) { + return; + } + authkeys = read_authkeys(authkeys_path, errp); + if (authkeys == NULL) { + return; + } + + new_keys = g_new0(char *, g_strv_length(authkeys) + 1); + for (a = authkeys; *a != NULL; a++) { + strList *k; + + for (k = keys; k != NULL; k = k->next) { + if (g_str_equal(k->value, *a)) { + break; + } + } + if (k != NULL) { + continue; + } + + new_keys[nkeys++] = *a; + } + + write_authkeys(authkeys_path, new_keys, errp); +} + + +#ifdef QGA_BUILD_UNIT_TEST +#if GLIB_CHECK_VERSION(2, 60, 0) +static const strList test_key2 = { + .value = (char *)"algo key2 comments" +}; + +static const strList test_key1_2 = { + .value = (char *)"algo key1 comments", + .next = (strList *)&test_key2, +}; + +static char * +test_get_authorized_keys_path(void) +{ + return g_build_filename(g_get_home_dir(), ".ssh", "authorized_keys", NULL); +} + +static void +test_authorized_keys_set(const char *contents) +{ + g_autoptr(GError) err = NULL; + g_autofree char *path = NULL; + int ret; + + path = g_build_filename(g_get_home_dir(), ".ssh", NULL); + ret = g_mkdir_with_parents(path, 0700); + g_assert_cmpint(ret, ==, 0); + g_free(path); + + path = test_get_authorized_keys_path(); + g_file_set_contents(path, contents, -1, &err); + g_assert_no_error(err); +} + +static void +test_authorized_keys_equal(const char *expected) +{ + g_autoptr(GError) err = NULL; + g_autofree char *path = NULL; + g_autofree char *contents = NULL; + + path = test_get_authorized_keys_path(); + g_file_get_contents(path, &contents, NULL, &err); + g_assert_no_error(err); + + g_assert_cmpstr(contents, ==, expected); +} + +static void +test_invalid_user(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys("", NULL, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys("", NULL, &err); + error_free_or_abort(&err); +} + +static void +test_invalid_key(void) +{ + strList key = { + .value = (char *)"not a valid\nkey" + }; + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), &key, &err); + error_free_or_abort(&err); +} + +static void +test_add_keys(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key2, &err); + g_assert_null(err); + + test_authorized_keys_equal("algo key2 comments"); + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, &err); + g_assert_null(err); + + /* key2 came first, and should'nt be duplicated */ + test_authorized_keys_equal("algo key2 comments\n" + "algo key1 comments"); +} + +static void +test_remove_keys(void) +{ + Error *err = NULL; + static const char *authkeys = + "algo key1 comments\n" + /* originally duplicated */ + "algo key1 comments\n" + "# a commented line\n" + "algo some-key another\n"; + + test_authorized_keys_set(authkeys); + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), + (strList *)&test_key2, &err); + g_assert_null(err); + test_authorized_keys_equal(authkeys); + + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, &err); + g_assert_null(err); + test_authorized_keys_equal("# a commented line\n" + "algo some-key another\n"); +} + +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); + + g_test_add_func("/qga/ssh/invalid_user", test_invalid_user); + g_test_add_func("/qga/ssh/invalid_key", test_invalid_key); + g_test_add_func("/qga/ssh/add_keys", test_add_keys); + g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); + + return g_test_run(); +} +#else +int main(int argc, char *argv[]) +{ + g_test_message("test skipped, needs glib >= 2.60"); + return 0; +} +#endif /* GLIB_2_60 */ +#endif /* BUILD_UNIT_TEST */ diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 0c3c05484f..1e188b03d3 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2457,3 +2457,15 @@ GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) } return head; } + +void qmp_guest_ssh_add_authorized_keys(const char *username, + strList *keys, Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); +} + +void qmp_guest_ssh_remove_authorized_keys(const char *username, + strList *keys, Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); +} diff --git a/qga/meson.build b/qga/meson.build index cd08bd953a..6315bb357e 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -35,7 +35,9 @@ qga_ss.add(files( )) qga_ss.add(when: 'CONFIG_POSIX', if_true: files( 'channel-posix.c', - 'commands-posix.c')) + 'commands-posix.c', + 'commands-posix-ssh.c', +)) qga_ss.add(when: 'CONFIG_WIN32', if_true: files( 'channel-win32.c', 'commands-win32.c', @@ -87,3 +89,19 @@ else endif alias_target('qemu-ga', all_qga) + +test_env = environment() +test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) +test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) + +if 'CONFIG_POSIX' in config_host + qga_ssh_test = executable('qga-ssh-test', + files('commands-posix-ssh.c'), + dependencies: [qemuutil], + c_args: ['-DQGA_BUILD_UNIT_TEST']) + + test('qga-ssh-test', + qga_ssh_test, + env: test_env, + suite: ['unit', 'qga']) +endif diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index cec98c7e06..361883f870 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1306,3 +1306,36 @@ ## { 'command': 'guest-get-devices', 'returns': ['GuestDeviceInfo'] } + +## +# @guest-ssh-add-authorized-keys: +# +# @username: the user account to add the authorized keys +# @keys: the public keys to add (in OpenSSH/sshd(8) authorized_keys format) +# +# Append public keys to user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). +# +# Returns: Nothing on success. +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-add-authorized-keys', + 'data': { 'username': 'str', 'keys': ['str'] } } + +## +# @guest-ssh-remove-authorized-keys: +# +# @username: the user account to remove the authorized keys +# @keys: the public keys to remove (in OpenSSH/sshd(8) authorized_keys format) +# +# Remove public keys from the user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). It's not an error if the key is already +# missing. +# +# Returns: Nothing on success. +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-remove-authorized-keys', + 'data': { 'username': 'str', 'keys': ['str'] } } From patchwork Tue Oct 20 08:12:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 302537 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5858C433DF for ; Tue, 20 Oct 2020 08:17:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DF13D206D5 for ; Tue, 20 Oct 2020 08:17:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="X6+9Emf5" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DF13D206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47266 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmq5-0002GD-St for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:17:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41090) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmm3-0006Yq-HM for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:28247) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmlz-0001d9-TR for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181614; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JMk0al0zeovsGmlIhx/ed/Qyn+bVEIP38hbp992ehZs=; b=X6+9Emf5fud9iAKFkm87xb5QKnnVRS/Pc7Ws32dTdLCr2qZ1FODbgPDaP6EKgT2xMaf3Uo dBC820AN/xLdiXAr4VVtbJqpdNIUQZkovrsJku8zaSt6dQKEssea3CME1OLiWDd50h6dWE 1xQODid9XdEmdQ+GidnuZvRh9c/cCFE= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-541-hWUqgWYtOF6XFiJ8pBzXjw-1; Tue, 20 Oct 2020 04:13:32 -0400 X-MC-Unique: hWUqgWYtOF6XFiJ8pBzXjw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7484D108E1A2; Tue, 20 Oct 2020 08:13:31 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id 472C85C1C2; Tue, 20 Oct 2020 08:13:26 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 3/7] fixup! qga: add ssh-{add,remove}-authorized-keys Date: Tue, 20 Oct 2020 12:12:53 +0400 Message-Id: <20201020081257.2054548-4-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:16:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau I forgot to reset the file ownership after it is written. --- qga/commands-posix-ssh.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c index d41c114c3c..a7bc9a1c24 100644 --- a/qga/commands-posix-ssh.c +++ b/qga/commands-posix-ssh.c @@ -120,7 +120,8 @@ check_openssh_pub_keys(strList *keys, size_t *nkeys, Error **errp) } static bool -write_authkeys(const char *path, const GStrv keys, Error **errp) +write_authkeys(const char *path, const GStrv keys, + const struct passwd *p, Error **errp) { g_autofree char *contents = NULL; g_autoptr(GError) err = NULL; @@ -133,6 +134,12 @@ write_authkeys(const char *path, const GStrv keys, Error **errp) return false; } + if (chown(path, p->pw_uid, p->pw_gid) == -1) { + error_setg(errp, "failed to set ownership of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + if (chmod(path, 0600) == -1) { error_setg(errp, "failed to set permissions of '%s': %s", path, g_strerror(errno)); @@ -203,7 +210,7 @@ qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, authkeys[nauthkeys++] = g_strdup(k->value); } - write_authkeys(authkeys_path, authkeys, errp); + write_authkeys(authkeys_path, authkeys, p, errp); } void @@ -254,7 +261,7 @@ qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, new_keys[nkeys++] = *a; } - write_authkeys(authkeys_path, new_keys, errp); + write_authkeys(authkeys_path, new_keys, p, errp); } From patchwork Tue Oct 20 08:12:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 270935 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 983B0C433DF for ; Tue, 20 Oct 2020 08:17:44 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DC148206D5 for ; Tue, 20 Oct 2020 08:17:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BmdhRYBf" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DC148206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:46594 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmpy-0001y6-Ne for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:17:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41168) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmmC-0006g3-BC for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:23915) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmmA-0001gC-OF for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181625; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9kY52Pk7M04KQoU/rKrPNfI3H3mP/dsppHZkYxLjjcA=; b=BmdhRYBfawHc+WfvIFOYZ/5K4sL6LogRArnUM69vrr5p/sRcwXRdD9bhuIIpoHh1Zjq1W0 0og8U9LQg2mOZ0Fk+velTUIDT5aRotPBEkAn7ARSqjGyVWRM+B5F+uY3Q+CL2/vtG2r28P fB3o7++Hd9iHvy+GYbf1o+qltqyy9XY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-474-JXawvBeFOJmYmR-OEHFiLw-1; Tue, 20 Oct 2020 04:13:41 -0400 X-MC-Unique: JXawvBeFOJmYmR-OEHFiLw-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 10A7C18C9F40; Tue, 20 Oct 2020 08:13:40 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4452E55763; Tue, 20 Oct 2020 08:13:35 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 4/7] fixup! qga: add ssh-{add,remove}-authorized-keys Date: Tue, 20 Oct 2020 12:12:54 +0400 Message-Id: <20201020081257.2054548-5-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:15:43 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Use 'if' condition, as suggested by E. Blake. --- qga/commands-win32.c | 12 ------------ qga/qapi-schema.json | 6 ++++-- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 1e188b03d3..0c3c05484f 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2457,15 +2457,3 @@ GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) } return head; } - -void qmp_guest_ssh_add_authorized_keys(const char *username, - strList *keys, Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); -} - -void qmp_guest_ssh_remove_authorized_keys(const char *username, - strList *keys, Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); -} diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 361883f870..90615f95d4 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1321,7 +1321,8 @@ # Since: 5.2 ## { 'command': 'guest-ssh-add-authorized-keys', - 'data': { 'username': 'str', 'keys': ['str'] } } + 'data': { 'username': 'str', 'keys': ['str'] }, + 'if': 'defined(CONFIG_POSIX)' } ## # @guest-ssh-remove-authorized-keys: @@ -1338,4 +1339,5 @@ # Since: 5.2 ## { 'command': 'guest-ssh-remove-authorized-keys', - 'data': { 'username': 'str', 'keys': ['str'] } } + 'data': { 'username': 'str', 'keys': ['str'] }, + 'if': 'defined(CONFIG_POSIX)' } From patchwork Tue Oct 20 08:12:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 270933 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8ABCBC433E7 for ; Tue, 20 Oct 2020 08:19:22 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D11B9206D5 for ; Tue, 20 Oct 2020 08:19:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="SW+oNiYH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D11B9206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:53552 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmrY-0004sR-S1 for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:19:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41200) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmmJ-0006i7-OC for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:57 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:43204) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmmH-0001ic-8X for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:13:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181632; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4HegxmTuUwmkrYCTtISK3mquAYj5KpbIrtQxrdaR1lE=; b=SW+oNiYHBQQKu745BvkEwUra3airmjDGuAQ6+RNenjRTt+GWjT1jSrVP/tJdMMA/RTvECV Z5YjwyuYuflwKU8/F5fibMR3Spb+xheTzWenHN3kRSxT6oj+4xWtXkoMDmJj9vMkO8N941 yhAhd3Hi/nwe4owXpW3jp06JYdN3Tq4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-384-lgN6xWmUNLK2kMsrqAoomA-1; Tue, 20 Oct 2020 04:13:50 -0400 X-MC-Unique: lgN6xWmUNLK2kMsrqAoomA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 283D78049D5; Tue, 20 Oct 2020 08:13:49 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id E157B1992D; Tue, 20 Oct 2020 08:13:44 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 5/7] qga: add *reset argument to ssh-add-authorized-keys Date: Tue, 20 Oct 2020 12:12:55 +0400 Message-Id: <20201020081257.2054548-6-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:15:43 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau I prefer 'reset' over 'clear', since 'clear' and keys may have some other relations or meaning. Signed-off-by: Marc-André Lureau --- qga/commands-posix-ssh.c | 53 ++++++++++++++++++++++++++++++++++++---- qga/qapi-schema.json | 3 ++- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c index a7bc9a1c24..f974bc4b64 100644 --- a/qga/commands-posix-ssh.c +++ b/qga/commands-posix-ssh.c @@ -168,6 +168,7 @@ read_authkeys(const char *path, Error **errp) void qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, + bool has_reset, bool reset, Error **errp) { g_autofree struct passwd *p = NULL; @@ -178,6 +179,7 @@ qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, size_t nkeys, nauthkeys; ERRP_GUARD(); + reset = has_reset && reset; if (!check_openssh_pub_keys(keys, &nkeys, errp)) { return; @@ -191,7 +193,9 @@ qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL); authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL); - authkeys = read_authkeys(authkeys_path, NULL); + if (!reset) { + authkeys = read_authkeys(authkeys_path, NULL); + } if (authkeys == NULL) { if (!g_file_test(ssh_path, G_FILE_TEST_IS_DIR) && !mkdir_for_user(ssh_path, p, 0700, errp)) { @@ -318,7 +322,7 @@ test_invalid_user(void) { Error *err = NULL; - qmp_guest_ssh_add_authorized_keys("", NULL, &err); + qmp_guest_ssh_add_authorized_keys("", NULL, FALSE, FALSE, &err); error_free_or_abort(&err); qmp_guest_ssh_remove_authorized_keys("", NULL, &err); @@ -333,7 +337,8 @@ test_invalid_key(void) }; Error *err = NULL; - qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, &err); + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, + FALSE, FALSE, &err); error_free_or_abort(&err); qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), &key, &err); @@ -346,13 +351,17 @@ test_add_keys(void) Error *err = NULL; qmp_guest_ssh_add_authorized_keys(g_get_user_name(), - (strList *)&test_key2, &err); + (strList *)&test_key2, + FALSE, FALSE, + &err); g_assert_null(err); test_authorized_keys_equal("algo key2 comments"); qmp_guest_ssh_add_authorized_keys(g_get_user_name(), - (strList *)&test_key1_2, &err); + (strList *)&test_key1_2, + FALSE, FALSE, + &err); g_assert_null(err); /* key2 came first, and should'nt be duplicated */ @@ -360,6 +369,39 @@ test_add_keys(void) "algo key1 comments"); } +static void +test_add_reset_keys(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, + FALSE, FALSE, + &err); + g_assert_null(err); + + /* reset with key2 only */ + test_authorized_keys_equal("algo key1 comments\n" + "algo key2 comments"); + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key2, + TRUE, TRUE, + &err); + g_assert_null(err); + + test_authorized_keys_equal("algo key2 comments"); + + /* empty should clear file */ + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)NULL, + TRUE, TRUE, + &err); + g_assert_null(err); + + test_authorized_keys_equal(""); +} + static void test_remove_keys(void) { @@ -393,6 +435,7 @@ int main(int argc, char *argv[]) g_test_add_func("/qga/ssh/invalid_user", test_invalid_user); g_test_add_func("/qga/ssh/invalid_key", test_invalid_key); g_test_add_func("/qga/ssh/add_keys", test_add_keys); + g_test_add_func("/qga/ssh/add_reset_keys", test_add_reset_keys); g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); return g_test_run(); diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 90615f95d4..6b7cb86dee 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1312,6 +1312,7 @@ # # @username: the user account to add the authorized keys # @keys: the public keys to add (in OpenSSH/sshd(8) authorized_keys format) +# @reset: ignore the existing content, set it with the given keys only # # Append public keys to user .ssh/authorized_keys on Unix systems (not # implemented for other systems). @@ -1321,7 +1322,7 @@ # Since: 5.2 ## { 'command': 'guest-ssh-add-authorized-keys', - 'data': { 'username': 'str', 'keys': ['str'] }, + 'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' }, 'if': 'defined(CONFIG_POSIX)' } ## From patchwork Tue Oct 20 08:12:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 302536 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E44D7C433E7 for ; Tue, 20 Oct 2020 08:19:17 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 471FB206D5 for ; Tue, 20 Oct 2020 08:19:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EwvsuKOj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 471FB206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:53150 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmrU-0004iS-6s for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:19:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41230) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmmR-0006kc-7x for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:14:03 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:59405) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmmN-0001kD-4t for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:14:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181637; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wyqyNvcpwklgle2vcLDz7KiAMPo1Fql7UvmvwberulA=; b=EwvsuKOj4qkQsWxDpd7WjzWdoHg3MFsQLxTVdCewzIziIw9/MxjvVbsFnwjrDU+oliRjos aaEhXqYvypZvxSqjNJ/Fj/KY9Ty5YAWlcJc/qvTcOPZpTINrxKePfkb1/jHmE8uX8IAB4E ozIZDyA/vy/ATvy/PnAXNMQPvbRblmo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-28-GMhO8zupP2KKs6nisdHrSg-1; Tue, 20 Oct 2020 04:13:55 -0400 X-MC-Unique: GMhO8zupP2KKs6nisdHrSg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5FB8E803F47; Tue, 20 Oct 2020 08:13:54 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6487555785; Tue, 20 Oct 2020 08:13:53 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 6/7] meson: minor simplification Date: Tue, 20 Oct 2020 12:12:56 +0400 Message-Id: <20201020081257.2054548-7-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:15:43 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Signed-off-by: Marc-André Lureau --- qga/meson.build | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/qga/meson.build b/qga/meson.build index 6315bb357e..8340892139 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -22,12 +22,7 @@ qga_qapi_files = custom_target('QGA QAPI files', depend_files: qapi_gen_depends) qga_ss = ss.source_set() -i = 0 -foreach output: qga_qapi_outputs - qga_ss.add(qga_qapi_files[i]) - i = i + 1 -endforeach - +qga_ss.add(qga_qapi_files.to_list()) qga_ss.add(files( 'commands.c', 'guest-agent-command-state.c', From patchwork Tue Oct 20 08:12:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 302535 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 982BAC433E7 for ; Tue, 20 Oct 2020 08:20:50 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CB3BE206D5 for ; Tue, 20 Oct 2020 08:20:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OIGFHtC6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CB3BE206D5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56622 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kUmsy-00069c-QN for qemu-devel@archiver.kernel.org; Tue, 20 Oct 2020 04:20:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41258) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kUmmW-0006pB-97 for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:14:08 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:23870) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kUmmS-0001mi-Q2 for qemu-devel@nongnu.org; Tue, 20 Oct 2020 04:14:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603181643; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a5SDg3P76a+sbXL0s7Nt+dkyVY87caCOtIVPNNwrOjg=; b=OIGFHtC6INKsYMPcYgX6e12Zqp81T07hX6ADxY6U9P62ikRw7VoVnW6G0wAdrn74lTHTt0 MR+OMcDqaiocIb+U3t7O/gLL8dZrX7Lbt2xuAT+oRToMgCFn/fQJzFGZu0qZQKYdYsvIfT RiYouuo9wHKxM7fr5qVqhbM7B99GZ54= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-520-co-509pbPR-ScqIri0ijEg-1; Tue, 20 Oct 2020 04:14:00 -0400 X-MC-Unique: co-509pbPR-ScqIri0ijEg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 73748803F47; Tue, 20 Oct 2020 08:13:59 +0000 (UTC) Received: from localhost (unknown [10.36.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTP id 198B31992D; Tue, 20 Oct 2020 08:13:57 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PATCH v3 7/7] qga: add ssh-get-authorized-keys Date: Tue, 20 Oct 2020 12:12:57 +0400 Message-Id: <20201020081257.2054548-8-marcandre.lureau@redhat.com> In-Reply-To: <20201020081257.2054548-1-marcandre.lureau@redhat.com> References: <20201020081257.2054548-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/20 01:15:43 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, Michael Roth , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Signed-off-by: Marc-André Lureau --- qga/commands-posix-ssh.c | 66 ++++++++++++++++++++++++++++++++++++++++ qga/meson.build | 11 +++++-- qga/qapi-schema.json | 31 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c index f974bc4b64..4d75cb0113 100644 --- a/qga/commands-posix-ssh.c +++ b/qga/commands-posix-ssh.c @@ -268,6 +268,46 @@ qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, write_authkeys(authkeys_path, new_keys, p, errp); } +GuestAuthorizedKeys * +qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *authkeys_path = NULL; + g_auto(GStrv) authkeys = NULL; + g_autoptr(GuestAuthorizedKeys) ret = NULL; + int i; + + ERRP_GUARD(); + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return NULL; + } + + authkeys_path = g_build_filename(p->pw_dir, ".ssh", + "authorized_keys", NULL); + authkeys = read_authkeys(authkeys_path, errp); + if (authkeys == NULL) { + return NULL; + } + + ret = g_new0(GuestAuthorizedKeys, 1); + for (i = 0; authkeys[i] != NULL; i++) { + strList *new; + + g_strstrip(authkeys[i]); + if (!authkeys[i][0] || authkeys[i][0] == '#') { + continue; + } + + new = g_new0(strList, 1); + new->value = g_strdup(authkeys[i]); + new->next = ret->keys; + ret->keys = new; + } + + return g_steal_pointer (&ret); +} #ifdef QGA_BUILD_UNIT_TEST #if GLIB_CHECK_VERSION(2, 60, 0) @@ -426,6 +466,31 @@ test_remove_keys(void) "algo some-key another\n"); } +static void +test_get_keys(void) +{ + Error *err = NULL; + static const char *authkeys = + "algo key1 comments\n" + "# a commented line\n" + "algo some-key another\n"; + g_autoptr(GuestAuthorizedKeys) ret = NULL; + strList *k; + size_t len = 0; + + test_authorized_keys_set(authkeys); + + ret = qmp_guest_ssh_get_authorized_keys(g_get_user_name(), &err); + g_assert_null(err); + + for (len = 0, k = ret->keys; k != NULL; k = k->next) { + g_assert(g_str_has_prefix(k->value, "algo ")); + len++; + } + + g_assert_cmpint(len, ==, 2); +} + int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); @@ -437,6 +502,7 @@ int main(int argc, char *argv[]) g_test_add_func("/qga/ssh/add_keys", test_add_keys); g_test_add_func("/qga/ssh/add_reset_keys", test_add_reset_keys); g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); + g_test_add_func("/qga/ssh/get_keys", test_get_keys); return g_test_run(); } diff --git a/qga/meson.build b/qga/meson.build index 8340892139..80e7487f32 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -90,8 +90,15 @@ test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) if 'CONFIG_POSIX' in config_host - qga_ssh_test = executable('qga-ssh-test', - files('commands-posix-ssh.c'), + srcs = [files('commands-posix-ssh.c')] + i = 0 + foreach output: qga_qapi_outputs + if output.startswith('qga-qapi-types') or output.startswith('qga-qapi-visit') + srcs += qga_qapi_files[i] + endif + i = i + 1 + endforeach + qga_ssh_test = executable('qga-ssh-test', srcs, dependencies: [qemuutil], c_args: ['-DQGA_BUILD_UNIT_TEST']) diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 6b7cb86dee..4702bc7d72 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1307,6 +1307,37 @@ { 'command': 'guest-get-devices', 'returns': ['GuestDeviceInfo'] } +## +# @GuestAuthorizedKeys: +# +# @keys: public keys (in OpenSSH/sshd(8) authorized_keys format) +# +# Since: 5.2 +## +{ 'struct': 'GuestAuthorizedKeys', + 'data': { + 'keys': ['str'] + }, + 'if': 'defined(CONFIG_POSIX)' } + + +## +# @guest-ssh-get-authorized-keys: +# +# @username: the user account to add the authorized keys +# +# Return the public keys from user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). +# +# Returns: @GuestAuthorizedKeys +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-get-authorized-keys', + 'data': { 'username': 'str' }, + 'returns': 'GuestAuthorizedKeys', + 'if': 'defined(CONFIG_POSIX)' } + ## # @guest-ssh-add-authorized-keys: #