@@ -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 */
@@ -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);
@@ -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:
#