diff mbox

[2/2] guest-set-user-password - added ability to create new user

Message ID 1452081699-11894-3-git-send-email-den@openvz.org
State New
Headers show

Commit Message

Denis V. Lunev Jan. 6, 2016, 12:01 p.m. UTC
From: Yuriy Pudgorodskiy <yur@virtuozzo.com>

Added optional 'create' flag to guest-set-user-password command.
When it is specified, a new user will be created if it does not
exist yet.

The option to the existing command is added as password for newly created
user should be set as specified.

This code is made specifically for Linux/Windows and is inside proper
ifdef braces.

Signed-off-by: Yuri Pudgorodskiy <yur@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Eric Blake <eblake@redhat.com>
CC: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 qga/commands-posix.c | 20 ++++++++++++++++++++
 qga/commands-win32.c | 25 ++++++++++++++++++++++++-
 qga/qapi-schema.json |  5 ++++-
 3 files changed, 48 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 53e8d3b..2cd10df 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2089,6 +2089,8 @@  out:
 void qmp_guest_set_user_password(const char *username,
                                  const char *password,
                                  bool crypted,
+                                 bool has_create,
+                                 bool create,
                                  Error **errp)
 {
     char *passwd_path = NULL;
@@ -2125,6 +2127,24 @@  void qmp_guest_set_user_password(const char *username,
 
     chpasswd_argv[0] = passwd_path;
 
+    /* create new user if requested */
+    if (has_create && create) {
+        char *str = g_shell_quote(username);
+        char *cmd = g_strdup_printf(
+                /* we want output only from useradd command */
+                "id -u %s >/dev/null 2>&1 || useradd -m %s",
+                str, str);
+        const char *argv[] = {
+            "/bin/sh", "-c", cmd, NULL
+        };
+        ga_run_program(argv, NULL, "add new user", errp);
+        g_free(str);
+        g_free(cmd);
+        if (*errp) {
+            goto out;
+        }
+    }
+
     /* set password for existed user */
     if (!crypted) {
         /* wipe -e option */
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 61ffbdf..83fbf17 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -1285,6 +1285,8 @@  get_net_error_message(gint error)
 void qmp_guest_set_user_password(const char *username,
                                  const char *password,
                                  bool crypted,
+                                 bool has_create,
+                                 bool create,
                                  Error **errp)
 {
     NET_API_STATUS nas;
@@ -1308,6 +1310,27 @@  void qmp_guest_set_user_password(const char *username,
     user = g_utf8_to_utf16(username, -1, NULL, NULL, NULL);
     wpass = g_utf8_to_utf16(rawpasswddata, -1, NULL, NULL, NULL);
 
+    if (has_create && create) {
+        USER_INFO_1 ui = { 0 };
+
+        ui.usri1_name = user;
+        ui.usri1_password = wpass;
+        ui.usri1_priv = USER_PRIV_USER;
+        ui.usri1_flags = UF_SCRIPT|UF_DONT_EXPIRE_PASSWD;
+        nas = NetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);
+
+        if (nas == NERR_Success) {
+            goto out;
+        }
+
+        if (nas != NERR_UserExists) {
+            gchar *msg = get_net_error_message(nas);
+            error_setg(errp, "failed to add user: %s", msg);
+            g_free(msg);
+            goto out;
+        }
+    }
+
     pi1003.usri1003_password = wpass;
     nas = NetUserSetInfo(NULL, user,
                          1003, (LPBYTE)&pi1003,
@@ -1318,7 +1341,7 @@  void qmp_guest_set_user_password(const char *username,
         error_setg(errp, "failed to set password: %s", msg);
         g_free(msg);
     }
-
+out:
     g_free(user);
     g_free(wpass);
     g_free(rawpasswddata);
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 01c9ee4..53a9f6a 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -787,6 +787,8 @@ 
 # @username: the user account whose password to change
 # @password: the new password entry string, base64 encoded
 # @crypted: true if password is already crypt()d, false if raw
+# @create: #optinal user will be created if it does not exist yet (since 2.6).
+#          The default value is false.
 #
 # If the @crypted flag is true, it is the caller's responsibility
 # to ensure the correct crypt() encryption scheme is used. This
@@ -806,7 +808,8 @@ 
 # Since 2.3
 ##
 { 'command': 'guest-set-user-password',
-  'data': { 'username': 'str', 'password': 'str', 'crypted': 'bool' } }
+  'data': { 'username': 'str', 'password': 'str', 'crypted': 'bool',
+  '*create': 'bool' } }
 
 # @GuestMemoryBlock:
 #