From patchwork Mon Dec 15 12:47:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= X-Patchwork-Id: 421155 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B53D21400B7 for ; Mon, 15 Dec 2014 23:48:27 +1100 (AEDT) Received: from localhost ([::1]:39282 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0V4c-0000XQ-0g for incoming@patchwork.ozlabs.org; Mon, 15 Dec 2014 07:48:26 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32943) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0V4D-0000Eg-CG for qemu-devel@nongnu.org; Mon, 15 Dec 2014 07:48:07 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y0V46-0006Ij-T2 for qemu-devel@nongnu.org; Mon, 15 Dec 2014 07:48:01 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56651) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0V46-0006Id-LW for qemu-devel@nongnu.org; Mon, 15 Dec 2014 07:47:54 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sBFClphk021639 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 15 Dec 2014 07:47:51 -0500 Received: from localhost.localdomain.com (vpn1-5-155.ams2.redhat.com [10.36.5.155]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sBFClooU020780; Mon, 15 Dec 2014 07:47:50 -0500 From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Mon, 15 Dec 2014 12:47:46 +0000 Message-Id: <1418647666-18771-1-git-send-email-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Michael Roth Subject: [Qemu-devel] [PATCH] qga: add guest-set-admin-password command X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add a new 'guest-set-admin-password' command for changing the root/administrator password. This command is needed to allow OpenStack to support its API for changing the admin password on a running guest. Accepts either the raw password string: $ virsh -c qemu:///system qemu-agent-command f21x86_64 \ '{ "execute": "guest-set-admin-password", "arguments": { "crypted": false, "password": "12345678" } }' {"return":{}} Or a pre-encrypted string (recommended) $ virsh -c qemu:///system qemu-agent-command f21x86_64 \ '{ "execute": "guest-set-admin-password", "arguments": { "crypted": true, "password": "$6$T9O/j/aGPrE...snip....rQoRN4F0.GG0MPjNUNyml." } }' NB windows support is desirable, but not implemented in this patch. Signed-off-by: Daniel P. Berrange --- qga/commands-posix.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ qga/commands-win32.c | 6 ++++ qga/qapi-schema.json | 13 ++++++++ 3 files changed, 108 insertions(+) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index f6f3e3c..3c3998a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -1875,6 +1875,89 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) return processed; } +void qmp_guest_set_admin_password(bool crypted, const char *password, + Error **errp) +{ + Error *local_err = NULL; + char *passwd_path = NULL; + pid_t pid; + int status; + int datafd[2] = { -1, -1 }; + char *acctpw = g_strdup_printf("root:%s\n", password); + + if (strchr(password, '\n')) { + error_setg(errp, "forbidden characters in new password"); + goto out; + } + + passwd_path = g_find_program_in_path("chpasswd"); + + if (!passwd_path) { + error_setg(errp, "cannot find 'passwd' program in PATH"); + goto out; + } + + if (pipe(datafd) < 0) { + error_setg(errp, "cannot create pipe FDs"); + goto out; + } + + pid = fork(); + if (pid == 0) { + close(datafd[1]); + /* child */ + setsid(); + dup2(datafd[0], 0); + reopen_fd_to_null(1); + reopen_fd_to_null(2); + + if (crypted) { + execle(passwd_path, "chpasswd", "-e", NULL, environ); + } else { + execle(passwd_path, "chpasswd", NULL, environ); + } + _exit(EXIT_FAILURE); + } else if (pid < 0) { + error_setg_errno(errp, errno, "failed to create child process"); + goto out; + } + close(datafd[0]); + datafd[0] = -1; + + if (write(datafd[1], acctpw, strlen(acctpw)) != strlen(acctpw)) { + error_setg(errp, "cannot write new account password"); + goto out; + } + close(datafd[1]); + datafd[1] = -1; + + ga_wait_child(pid, &status, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + + if (!WIFEXITED(status)) { + error_setg(errp, "child process has terminated abnormally"); + goto out; + } + + if (WEXITSTATUS(status)) { + error_setg(errp, "child process has failed to suspend"); + goto out; + } + +out: + g_free(acctpw); + g_free(passwd_path); + if (datafd[0] != -1) { + close(datafd[0]); + } + if (datafd[1] != -1) { + close(datafd[1]); + } +} + #else /* defined(__linux__) */ void qmp_guest_suspend_disk(Error **errp) @@ -1910,6 +1993,12 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) return -1; } +void qmp_guest_set_admin_password(bool crypted, const char *password, + Error **errp) +{ + error_set(errp, QERR_UNSUPPORTED); +} + #endif #if !defined(CONFIG_FSFREEZE) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3bcbeae..56854d5 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -446,6 +446,12 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) return -1; } +void qmp_guest_set_admin_password(bool crypted, const char *password, + Error **errp) +{ + error_set(errp, QERR_UNSUPPORTED); +} + /* add unsupported commands to the blacklist */ GList *ga_command_blacklist_init(GList *blacklist) { diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 376e79f..202d3be 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -738,3 +738,16 @@ ## { 'command': 'guest-get-fsinfo', 'returns': ['GuestFilesystemInfo'] } + +## +# @guest-set-admin-password +# +# @crypted: true if password is already crypt()d, false if raw +# @password: the new password entry +# +# Returns: Nothing on success. +# +# Since 2.3 +## +{ 'command': 'guest-set-admin-password', + 'data': { 'crypted': 'bool', 'password': 'str' } }