diff --git a/src/manage.h b/src/manage.h index 38ff958d6..cd3ffcf52 100644 --- a/src/manage.h +++ b/src/manage.h @@ -3214,11 +3214,6 @@ copy_user (const char*, const char*, const char*, user_t*); gchar * keyfile_to_auth_conf_settings_xml (const gchar *); -int -create_user (const gchar *, const gchar *, const gchar *, const gchar *, - int, const array_t *, array_t *, gchar **, - array_t *, gchar **, gchar **, user_t *, int); - int delete_user (const char *, const char *, int, const char*, const char*); diff --git a/src/manage_sql.c b/src/manage_sql.c index bd60f22bf..a8922de8d 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -208,9 +208,6 @@ static int cache_report_counts (report_t, int, int, severity_data_t*); static char* task_owner_uuid (task_t); -gchar* -clean_hosts (const char *, int*); - static int user_ensure_in_db (const gchar *, const gchar *); @@ -413,7 +410,7 @@ resource_with_name_exists (const char *name, const char *type, * * @return Whether resource with name exists. */ -static gboolean +gboolean resource_with_name_exists_global (const char *name, const char *type, resource_t resource) { @@ -21141,7 +21138,7 @@ manage_max_hosts () * * @param[in] new_max New max_hosts value. */ -static void +void manage_set_max_hosts (int new_max) { max_hosts = new_max; @@ -38160,289 +38157,6 @@ manage_set_password (GSList *log_config, const db_conn_info_t *database, return -1; } -/** - * @brief Adds a new user to the GVM installation. - * - * @todo Adding users authenticating with certificates is not yet implemented. - * - * @param[in] name The name of the new user. - * @param[in] password The password of the new user. - * @param[in] comment Comment for the new user or NULL. - * @param[in] hosts The host the user is allowed/forbidden to scan. - * @param[in] hosts_allow Whether hosts is allow or forbid. - * @param[in] allowed_methods Allowed login methods. - * @param[in] groups Groups. - * @param[out] group_id_return ID of group on "failed to find" error. - * @param[in] roles Roles. - * @param[out] role_id_return ID of role on "failed to find" error. - * @param[out] r_errdesc If not NULL the address of a variable to receive - * a malloced string with the error description. Will - * always be set to NULL on success. - * @param[out] new_user Created user. - * @param[in] forbid_super_admin Whether to forbid creation of Super Admin. - * - * @return 0 if the user has been added successfully, 1 failed to find group, - * 2 failed to find role, 3 syntax error in hosts, 99 permission denied, - * -1 on error, -2 if user exists already, -3 if wrong number of methods, - * -4 error in method. - */ -int -create_user (const gchar * name, const gchar * password, const gchar *comment, - const gchar * hosts, int hosts_allow, - const array_t * allowed_methods, array_t *groups, - gchar **group_id_return, array_t *roles, gchar **role_id_return, - gchar **r_errdesc, user_t *new_user, int forbid_super_admin) -{ - char *errstr, *uuid; - gchar *quoted_hosts, *quoted_method, *quoted_name, *hash; - gchar *quoted_comment, *clean, *generated; - int index, max, ret; - user_t user; - GArray *cache_users; - - assert (name); - assert (password); - - if (r_errdesc) - *r_errdesc = NULL; - - /* allowed_methods is a NULL terminated array. */ - if (allowed_methods && (allowed_methods->len > 2)) - return -3; - - if (allowed_methods && (allowed_methods->len <= 1)) - allowed_methods = NULL; - - if (allowed_methods - && (auth_method_name_valid (g_ptr_array_index (allowed_methods, 0)) - == 0)) - return -4; - - if (validate_username (name) != 0) - { - g_warning ("Invalid characters in user name!"); - if (r_errdesc) - *r_errdesc = g_strdup ("Invalid characters in user name"); - return -1; - } - - if (allowed_methods && - (!strcmp (g_ptr_array_index (allowed_methods, 0), "ldap_connect") - || !strcmp (g_ptr_array_index (allowed_methods, 0), "radius_connect"))) - password = generated = gvm_uuid_make (); - else - generated = NULL; - - if ((errstr = gvm_validate_password (password, name))) - { - g_warning ("new password for '%s' rejected: %s", name, errstr); - if (r_errdesc) - *r_errdesc = errstr; - else - g_free (errstr); - g_free (generated); - return -1; - } - - sql_begin_immediate (); - - if (acl_user_may ("create_user") == 0) - { - sql_rollback (); - g_free (generated); - return 99; - } - - /* Check if user exists already. */ - - if (resource_with_name_exists_global (name, "user", 0)) - { - sql_rollback (); - g_free (generated); - return -2; - } - quoted_name = sql_quote (name); - - /* Check hosts. */ - - max = manage_max_hosts (); - manage_set_max_hosts (MANAGE_USER_MAX_HOSTS); - if (hosts && (manage_count_hosts (hosts, NULL) < 0)) - { - manage_set_max_hosts (max); - sql_rollback (); - g_free (generated); - return 3; - } - manage_set_max_hosts (max); - - /* Get the password hashes. */ - - hash = manage_authentication_hash (password); - - /* Get the quoted comment */ - - if (comment) - quoted_comment = sql_quote (comment); - else - quoted_comment = g_strdup (""); - - /* Add the user to the database. */ - - clean = clean_hosts (hosts ? hosts : "", &max); - quoted_hosts = sql_quote (clean); - g_free (clean); - quoted_method = sql_quote (allowed_methods - ? g_ptr_array_index (allowed_methods, 0) - : "file"); - - ret - = sql_error ("INSERT INTO users" - " (uuid, owner, name, password, comment, hosts, hosts_allow," - " method, creation_time, modification_time)" - " VALUES" - " (make_uuid ()," - " (SELECT id FROM users WHERE uuid = '%s')," - " '%s', '%s', '%s', '%s', %i," - " '%s', m_now (), m_now ());", - current_credentials.uuid, - quoted_name, - hash, - quoted_comment, - quoted_hosts, - hosts_allow, - quoted_method); - g_free (generated); - g_free (hash); - g_free (quoted_comment); - g_free (quoted_hosts); - g_free (quoted_method); - g_free (quoted_name); - - if (ret == 3) - { - sql_rollback (); - return -2; - } - else if (ret) - { - sql_rollback (); - return -1; - } - - user = sql_last_insert_id (); - - /* Add the user to any given groups. */ - - index = 0; - while (groups && (index < groups->len)) - { - gchar *group_id; - group_t group; - - group_id = (gchar*) g_ptr_array_index (groups, index); - if (strcmp (group_id, "0") == 0) - { - index++; - continue; - } - - if (find_group_with_permission (group_id, &group, "modify_group")) - { - sql_rollback (); - return -1; - } - - if (group == 0) - { - sql_rollback (); - if (group_id_return) *group_id_return = group_id; - return 1; - } - - sql ("INSERT INTO group_users (\"group\", \"user\") VALUES (%llu, %llu);", - group, - user); - - index++; - } - - /* Add the user to any given roles. */ - - index = 0; - while (roles && (index < roles->len)) - { - gchar *role_id; - role_t role; - - role_id = (gchar*) g_ptr_array_index (roles, index); - if (strcmp (role_id, "0") == 0) - { - index++; - continue; - } - - if (forbid_super_admin && acl_role_can_super_everyone (role_id)) - { - sql_rollback (); - return 99; - } - - if (find_role_with_permission (role_id, &role, "get_roles")) - { - sql_rollback (); - return -1; - } - - if (role == 0) - { - sql_rollback (); - if (role_id_return) *role_id_return = role_id; - return 2; - } - - sql ("INSERT INTO role_users (role, \"user\") VALUES (%llu, %llu);", - role, - user); - - index++; - } - - if (new_user) - *new_user = user; - - /* Ensure the user can see themself. */ - - uuid = user_uuid (user); - if (uuid == NULL) - { - g_warning ("%s: Failed to allocate UUID", __func__); - sql_rollback (); - return -1; - } - - create_permission_internal (1, - "GET_USERS", - "Automatically created when adding user", - NULL, - uuid, - "user", - uuid, - NULL); - - free (uuid); - - /* Cache permissions. */ - - cache_users = g_array_new (TRUE, TRUE, sizeof (user_t)); - g_array_append_val (cache_users, user); - cache_all_permissions_for_users (cache_users); - g_free (g_array_free (cache_users, TRUE)); - - sql_commit (); - return 0; -} - /** * @brief Create a user from an existing user. * diff --git a/src/manage_sql.h b/src/manage_sql.h index 0110a1874..273f920e4 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -497,6 +497,9 @@ copy_resource (const char *, const char *, const char *, const char *, gboolean resource_with_name_exists (const char *, const char *, resource_t); +gboolean +resource_with_name_exists_global (const char *, const char *, resource_t); + int create_permission_internal (int, const char *, const char *, const char *, const char *, const char *, const char *, @@ -610,4 +613,10 @@ ldap_auth_enabled (); int radius_auth_enabled (); +void +manage_set_max_hosts (int); + +gchar* +clean_hosts (const char *, int *); + #endif /* not _GVMD_MANAGE_SQL_H */ diff --git a/src/manage_sql_users.c b/src/manage_sql_users.c index a85ce6f6c..d2a4e1798 100644 --- a/src/manage_sql_users.c +++ b/src/manage_sql_users.c @@ -6,9 +6,15 @@ #include "manage_users.h" #include "manage_sql_users.h" #include "manage_acl.h" +#include "manage_authentication.h" #include "manage_sql.h" +#include "manage_sql_groups.h" +#include "manage_sql_roles.h" #include "sql.h" +#include +#include + /** * @file * @brief GVM management layer: Users SQL @@ -579,3 +585,286 @@ add_users (const gchar *type, resource_t resource, const char *users) return 0; } + +/** + * @brief Adds a new user to the GVM installation. + * + * @todo Adding users authenticating with certificates is not yet implemented. + * + * @param[in] name The name of the new user. + * @param[in] password The password of the new user. + * @param[in] comment Comment for the new user or NULL. + * @param[in] hosts The host the user is allowed/forbidden to scan. + * @param[in] hosts_allow Whether hosts is allow or forbid. + * @param[in] allowed_methods Allowed login methods. + * @param[in] groups Groups. + * @param[out] group_id_return ID of group on "failed to find" error. + * @param[in] roles Roles. + * @param[out] role_id_return ID of role on "failed to find" error. + * @param[out] r_errdesc If not NULL the address of a variable to receive + * a malloced string with the error description. Will + * always be set to NULL on success. + * @param[out] new_user Created user. + * @param[in] forbid_super_admin Whether to forbid creation of Super Admin. + * + * @return 0 if the user has been added successfully, 1 failed to find group, + * 2 failed to find role, 3 syntax error in hosts, 99 permission denied, + * -1 on error, -2 if user exists already, -3 if wrong number of methods, + * -4 error in method. + */ +int +create_user (const gchar * name, const gchar * password, const gchar *comment, + const gchar * hosts, int hosts_allow, + const array_t * allowed_methods, array_t *groups, + gchar **group_id_return, array_t *roles, gchar **role_id_return, + gchar **r_errdesc, user_t *new_user, int forbid_super_admin) +{ + char *errstr, *uuid; + gchar *quoted_hosts, *quoted_method, *quoted_name, *hash; + gchar *quoted_comment, *clean, *generated; + int index, max, ret; + user_t user; + GArray *cache_users; + + assert (name); + assert (password); + + if (r_errdesc) + *r_errdesc = NULL; + + /* allowed_methods is a NULL terminated array. */ + if (allowed_methods && (allowed_methods->len > 2)) + return -3; + + if (allowed_methods && (allowed_methods->len <= 1)) + allowed_methods = NULL; + + if (allowed_methods + && (auth_method_name_valid (g_ptr_array_index (allowed_methods, 0)) + == 0)) + return -4; + + if (validate_username (name) != 0) + { + g_warning ("Invalid characters in user name!"); + if (r_errdesc) + *r_errdesc = g_strdup ("Invalid characters in user name"); + return -1; + } + + if (allowed_methods && + (!strcmp (g_ptr_array_index (allowed_methods, 0), "ldap_connect") + || !strcmp (g_ptr_array_index (allowed_methods, 0), "radius_connect"))) + password = generated = gvm_uuid_make (); + else + generated = NULL; + + if ((errstr = gvm_validate_password (password, name))) + { + g_warning ("new password for '%s' rejected: %s", name, errstr); + if (r_errdesc) + *r_errdesc = errstr; + else + g_free (errstr); + g_free (generated); + return -1; + } + + sql_begin_immediate (); + + if (acl_user_may ("create_user") == 0) + { + sql_rollback (); + g_free (generated); + return 99; + } + + /* Check if user exists already. */ + + if (resource_with_name_exists_global (name, "user", 0)) + { + sql_rollback (); + g_free (generated); + return -2; + } + quoted_name = sql_quote (name); + + /* Check hosts. */ + + max = manage_max_hosts (); + manage_set_max_hosts (MANAGE_USER_MAX_HOSTS); + if (hosts && (manage_count_hosts (hosts, NULL) < 0)) + { + manage_set_max_hosts (max); + sql_rollback (); + g_free (generated); + return 3; + } + manage_set_max_hosts (max); + + /* Get the password hashes. */ + + hash = manage_authentication_hash (password); + + /* Get the quoted comment */ + + if (comment) + quoted_comment = sql_quote (comment); + else + quoted_comment = g_strdup (""); + + /* Add the user to the database. */ + + clean = clean_hosts (hosts ? hosts : "", &max); + quoted_hosts = sql_quote (clean); + g_free (clean); + quoted_method = sql_quote (allowed_methods + ? g_ptr_array_index (allowed_methods, 0) + : "file"); + + ret + = sql_error ("INSERT INTO users" + " (uuid, owner, name, password, comment, hosts, hosts_allow," + " method, creation_time, modification_time)" + " VALUES" + " (make_uuid ()," + " (SELECT id FROM users WHERE uuid = '%s')," + " '%s', '%s', '%s', '%s', %i," + " '%s', m_now (), m_now ());", + current_credentials.uuid, + quoted_name, + hash, + quoted_comment, + quoted_hosts, + hosts_allow, + quoted_method); + g_free (generated); + g_free (hash); + g_free (quoted_comment); + g_free (quoted_hosts); + g_free (quoted_method); + g_free (quoted_name); + + if (ret == 3) + { + sql_rollback (); + return -2; + } + else if (ret) + { + sql_rollback (); + return -1; + } + + user = sql_last_insert_id (); + + /* Add the user to any given groups. */ + + index = 0; + while (groups && (index < groups->len)) + { + gchar *group_id; + group_t group; + + group_id = (gchar*) g_ptr_array_index (groups, index); + if (strcmp (group_id, "0") == 0) + { + index++; + continue; + } + + if (find_group_with_permission (group_id, &group, "modify_group")) + { + sql_rollback (); + return -1; + } + + if (group == 0) + { + sql_rollback (); + if (group_id_return) *group_id_return = group_id; + return 1; + } + + sql ("INSERT INTO group_users (\"group\", \"user\") VALUES (%llu, %llu);", + group, + user); + + index++; + } + + /* Add the user to any given roles. */ + + index = 0; + while (roles && (index < roles->len)) + { + gchar *role_id; + role_t role; + + role_id = (gchar*) g_ptr_array_index (roles, index); + if (strcmp (role_id, "0") == 0) + { + index++; + continue; + } + + if (forbid_super_admin && acl_role_can_super_everyone (role_id)) + { + sql_rollback (); + return 99; + } + + if (find_role_with_permission (role_id, &role, "get_roles")) + { + sql_rollback (); + return -1; + } + + if (role == 0) + { + sql_rollback (); + if (role_id_return) *role_id_return = role_id; + return 2; + } + + sql ("INSERT INTO role_users (role, \"user\") VALUES (%llu, %llu);", + role, + user); + + index++; + } + + if (new_user) + *new_user = user; + + /* Ensure the user can see themself. */ + + uuid = user_uuid (user); + if (uuid == NULL) + { + g_warning ("%s: Failed to allocate UUID", __func__); + sql_rollback (); + return -1; + } + + create_permission_internal (1, + "GET_USERS", + "Automatically created when adding user", + NULL, + uuid, + "user", + uuid, + NULL); + + free (uuid); + + /* Cache permissions. */ + + cache_users = g_array_new (TRUE, TRUE, sizeof (user_t)); + g_array_append_val (cache_users, user); + cache_all_permissions_for_users (cache_users); + g_free (g_array_free (cache_users, TRUE)); + + sql_commit (); + return 0; +} diff --git a/src/manage_users.h b/src/manage_users.h index 7895d25cd..c5a5494e7 100644 --- a/src/manage_users.h +++ b/src/manage_users.h @@ -72,4 +72,9 @@ user_role_iterator_name (iterator_t *); int user_role_iterator_readable (iterator_t *); +int +create_user (const gchar *, const gchar *, const gchar *, const gchar *, + int, const array_t *, array_t *, gchar **, + array_t *, gchar **, gchar **, user_t *, int); + #endif /* not _GVMD_MANAGE_USERS_H */