From 78b8bc77e94763b26e8a07ac5b0c7d2debe6a2d9 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Thu, 29 Jan 2026 16:43:12 +0200 Subject: [PATCH 1/4] Change: move delete_permission to dedicated permission files --- src/manage.h | 3 - src/manage_permissions.h | 3 + src/manage_sql.c | 196 ----------------------------------- src/manage_sql_permissions.c | 196 +++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 199 deletions(-) diff --git a/src/manage.h b/src/manage.h index 72ba5e809..086cb9d51 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2909,9 +2909,6 @@ trash_permission_writable (permission_t); int permission_count (const get_data_t *); -int -delete_permission (const char*, int); - int modify_permission (const char *, const char *, const char *, const char *, const char *, const char *, const char *); diff --git a/src/manage_permissions.h b/src/manage_permissions.h index b73fbe868..84cd22893 100644 --- a/src/manage_permissions.h +++ b/src/manage_permissions.h @@ -51,4 +51,7 @@ permission_iterator_subject_in_trash (iterator_t*); int permission_iterator_subject_readable (iterator_t*); +int +delete_permission (const char *, int); + #endif /* not _GVMD_MANAGE_PERMISSIONS_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index d8d0ba33f..dbb01db47 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -33125,202 +33125,6 @@ trash_permission_writable (permission_t permission) return 1; } -/** - * @brief Find a permission with a given permission, given a UUID. - * - * @param[in] uuid UUID of permission. - * @param[out] resource Permission return, 0 if successfully failed to find - * permission. - * @param[in] permission Required permission, for example "delete". - * - * @return FALSE on success (including if failed to find permission), TRUE on - * error. - */ -static gboolean -find_permission_with_permission (const char *uuid, permission_t *resource, - const char *permission) -{ - gchar *quoted_uuid = sql_quote (uuid); - if (acl_user_has_access_uuid ("permission", quoted_uuid, permission, 0) == 0) - { - g_free (quoted_uuid); - *resource = 0; - return FALSE; - } - switch (sql_int64 (resource, - "SELECT id FROM permissions WHERE uuid = '%s';", - quoted_uuid)) - { - case 0: - break; - case 1: /* Too few rows in result of query. */ - *resource = 0; - break; - default: /* Programming error. */ - assert (0); - case -1: - g_free (quoted_uuid); - return TRUE; - break; - } - - g_free (quoted_uuid); - return FALSE; -} - -/** - * @brief Delete a permission. - * - * @param[in] permission_id UUID of permission. - * @param[in] ultimate Whether to remove entirely, or to trashcan. - * - * @return 0 success, 2 failed to find permission, 3 predefined permission, - * 99 permission denied, -1 error. - */ -int -delete_permission (const char *permission_id, int ultimate) -{ - permission_t permission = 0; - char *name, *subject_type, *resource_type; - resource_t subject, resource; - GHashTable *reports = NULL; - int clear_original = 0; - gchar *subject_where; - - if (strcasecmp (permission_id, PERMISSION_UUID_ADMIN_EVERYTHING) == 0) - return 3; - - sql_begin_immediate (); - - if (acl_user_may ("delete_permission") == 0) - { - sql_rollback (); - return 99; - } - - if (find_permission_with_permission (permission_id, &permission, - "delete_permission")) - { - sql_rollback (); - return -1; - } - - if (permission == 0) - { - if (find_trash ("permission", permission_id, &permission)) - { - sql_rollback (); - return -1; - } - if (permission == 0) - { - sql_rollback (); - return 2; - } - if (ultimate == 0) - { - /* It's already in the trashcan. */ - sql_commit (); - return 0; - } - - tags_remove_resource ("permission", permission, LOCATION_TRASH); - sql ("DELETE FROM permissions_trash WHERE id = %llu;", permission); - sql_commit (); - return 0; - } - - /* Prevent deletion of command level permissions for predefined roles. */ - subject_type = permission_subject_type (permission); - subject = permission_subject (permission); - resource = permission_resource (permission); - if (resource == 0 - && subject_type - && strcmp (subject_type, "role") == 0 - && subject - && role_is_predefined (subject)) - { - free (subject_type); - sql_rollback (); - return 99; - } - subject_where = subject_where_clause (subject_type, subject); - free (subject_type); - - if (ultimate == 0) - { - sql ("INSERT INTO permissions_trash" - " (uuid, owner, name, comment, resource_type, resource," - " resource_uuid, resource_location, subject_type, subject," - " subject_location, creation_time, modification_time)" - " SELECT uuid, owner, name, comment, resource_type, resource," - " resource_uuid, resource_location, subject_type, subject," - " subject_location, creation_time, modification_time" - " FROM permissions" - " WHERE id = %llu;", - permission); - tags_set_locations ("permission", permission, - sql_last_insert_id (), - LOCATION_TRASH); - } - else - tags_remove_resource ("permission", permission, LOCATION_TABLE); - - name = permission_name (permission); - resource_type = permission_resource_type (permission); - - sql ("DELETE FROM permissions WHERE id = %llu;", permission); - - /* Update Permissions cache */ - if (strcasecmp (name, "super") == 0) - cache_all_permissions_for_users (NULL); - else if (resource_type && resource) - cache_permissions_for_resource (resource_type, resource, NULL); - - /* Update Reports cache */ - if (resource_type && (resource > 0) && strcmp (resource_type, "override") - == 0) - { - reports = reports_for_override (resource); - } - else if (strcasecmp (name, "super") == 0) - { - reports = reports_hashtable (); - clear_original = 1; - } - free (name); - free (resource_type); - - if (reports && g_hash_table_size (reports)) - { - GHashTableIter reports_iter; - report_t *reports_ptr; - int auto_cache_rebuild; - - reports_ptr = NULL; - g_hash_table_iter_init (&reports_iter, reports); - auto_cache_rebuild = setting_auto_cache_rebuild_int (); - while (g_hash_table_iter_next (&reports_iter, - ((gpointer*)&reports_ptr), NULL)) - { - if (auto_cache_rebuild) - report_cache_counts (*reports_ptr, clear_original, 1, - subject_where); - else - report_clear_count_cache (*reports_ptr, clear_original, 1, - subject_where); - } - } - - g_free (subject_where); - - if (reports) - g_hash_table_destroy (reports); - - sql_commit (); - return 0; -} - // TODO temporarily, until modify_permission moved out char * permission_resource_id (permission_t); diff --git a/src/manage_sql_permissions.c b/src/manage_sql_permissions.c index 668cd9a6f..903853ff4 100644 --- a/src/manage_sql_permissions.c +++ b/src/manage_sql_permissions.c @@ -1343,3 +1343,199 @@ copy_permission (const char* comment, const char *permission_id, return 0; } + +/** + * @brief Find a permission with a given permission, given a UUID. + * + * @param[in] uuid UUID of permission. + * @param[out] resource Permission return, 0 if successfully failed to find + * permission. + * @param[in] permission Required permission, for example "delete". + * + * @return FALSE on success (including if failed to find permission), TRUE on + * error. + */ +static gboolean +find_permission_with_permission (const char *uuid, permission_t *resource, + const char *permission) +{ + gchar *quoted_uuid = sql_quote (uuid); + if (acl_user_has_access_uuid ("permission", quoted_uuid, permission, 0) == 0) + { + g_free (quoted_uuid); + *resource = 0; + return FALSE; + } + switch (sql_int64 (resource, + "SELECT id FROM permissions WHERE uuid = '%s';", + quoted_uuid)) + { + case 0: + break; + case 1: /* Too few rows in result of query. */ + *resource = 0; + break; + default: /* Programming error. */ + assert (0); + case -1: + g_free (quoted_uuid); + return TRUE; + break; + } + + g_free (quoted_uuid); + return FALSE; +} + +/** + * @brief Delete a permission. + * + * @param[in] permission_id UUID of permission. + * @param[in] ultimate Whether to remove entirely, or to trashcan. + * + * @return 0 success, 2 failed to find permission, 3 predefined permission, + * 99 permission denied, -1 error. + */ +int +delete_permission (const char *permission_id, int ultimate) +{ + permission_t permission = 0; + char *name, *subject_type, *resource_type; + resource_t subject, resource; + GHashTable *reports = NULL; + int clear_original = 0; + gchar *subject_where; + + if (strcasecmp (permission_id, PERMISSION_UUID_ADMIN_EVERYTHING) == 0) + return 3; + + sql_begin_immediate (); + + if (acl_user_may ("delete_permission") == 0) + { + sql_rollback (); + return 99; + } + + if (find_permission_with_permission (permission_id, &permission, + "delete_permission")) + { + sql_rollback (); + return -1; + } + + if (permission == 0) + { + if (find_trash ("permission", permission_id, &permission)) + { + sql_rollback (); + return -1; + } + if (permission == 0) + { + sql_rollback (); + return 2; + } + if (ultimate == 0) + { + /* It's already in the trashcan. */ + sql_commit (); + return 0; + } + + tags_remove_resource ("permission", permission, LOCATION_TRASH); + sql ("DELETE FROM permissions_trash WHERE id = %llu;", permission); + sql_commit (); + return 0; + } + + /* Prevent deletion of command level permissions for predefined roles. */ + subject_type = permission_subject_type (permission); + subject = permission_subject (permission); + resource = permission_resource (permission); + if (resource == 0 + && subject_type + && strcmp (subject_type, "role") == 0 + && subject + && role_is_predefined (subject)) + { + free (subject_type); + sql_rollback (); + return 99; + } + subject_where = subject_where_clause (subject_type, subject); + free (subject_type); + + if (ultimate == 0) + { + sql ("INSERT INTO permissions_trash" + " (uuid, owner, name, comment, resource_type, resource," + " resource_uuid, resource_location, subject_type, subject," + " subject_location, creation_time, modification_time)" + " SELECT uuid, owner, name, comment, resource_type, resource," + " resource_uuid, resource_location, subject_type, subject," + " subject_location, creation_time, modification_time" + " FROM permissions" + " WHERE id = %llu;", + permission); + tags_set_locations ("permission", permission, + sql_last_insert_id (), + LOCATION_TRASH); + } + else + tags_remove_resource ("permission", permission, LOCATION_TABLE); + + name = permission_name (permission); + resource_type = permission_resource_type (permission); + + sql ("DELETE FROM permissions WHERE id = %llu;", permission); + + /* Update Permissions cache */ + if (strcasecmp (name, "super") == 0) + cache_all_permissions_for_users (NULL); + else if (resource_type && resource) + cache_permissions_for_resource (resource_type, resource, NULL); + + /* Update Reports cache */ + if (resource_type && (resource > 0) && strcmp (resource_type, "override") + == 0) + { + reports = reports_for_override (resource); + } + else if (strcasecmp (name, "super") == 0) + { + reports = reports_hashtable (); + clear_original = 1; + } + free (name); + free (resource_type); + + if (reports && g_hash_table_size (reports)) + { + GHashTableIter reports_iter; + report_t *reports_ptr; + int auto_cache_rebuild; + + reports_ptr = NULL; + g_hash_table_iter_init (&reports_iter, reports); + auto_cache_rebuild = setting_auto_cache_rebuild_int (); + while (g_hash_table_iter_next (&reports_iter, + ((gpointer*)&reports_ptr), NULL)) + { + if (auto_cache_rebuild) + report_cache_counts (*reports_ptr, clear_original, 1, + subject_where); + else + report_clear_count_cache (*reports_ptr, clear_original, 1, + subject_where); + } + } + + g_free (subject_where); + + if (reports) + g_hash_table_destroy (reports); + + sql_commit (); + return 0; +} From 88d7b613dfd00839381fadb7c2bba86d0cb57e22 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Thu, 29 Jan 2026 16:46:52 +0200 Subject: [PATCH 2/4] Change: move predicates to dedicated permission files --- src/manage.h | 12 --------- src/manage_permissions.c | 54 ++++++++++++++++++++++++++++++++++++++++ src/manage_permissions.h | 12 +++++++++ src/manage_sql.c | 54 ---------------------------------------- 4 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/manage.h b/src/manage.h index 086cb9d51..660934154 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2894,18 +2894,6 @@ create_permission (const char *, const char *, const char *, const char *, int copy_permission (const char*, const char *, permission_t *); -int -permission_in_use (permission_t); - -int -trash_permission_in_use (permission_t); - -int -permission_writable (permission_t); - -int -trash_permission_writable (permission_t); - int permission_count (const get_data_t *); diff --git a/src/manage_permissions.c b/src/manage_permissions.c index 987e8669a..a7816c6d2 100644 --- a/src/manage_permissions.c +++ b/src/manage_permissions.c @@ -27,3 +27,57 @@ permission_is_admin (const char *permission_id) return strcmp (permission_id, PERMISSION_UUID_ADMIN_EVERYTHING); return 0; } + +/** + * @brief Return whether a permission is in use. + * + * @param[in] permission Permission. + * + * @return 1 if in use, else 0. + */ +int +permission_in_use (permission_t permission) +{ + return 0; +} + +/** + * @brief Return whether a trashcan permission is referenced by a task. + * + * @param[in] permission Permission. + * + * @return 1 if in use, else 0. + */ +int +trash_permission_in_use (permission_t permission) +{ + return 0; +} + +/** + * @brief Return whether a permission is writable. + * + * @param[in] permission Permission. + * + * @return 1 if writable, else 0. + */ +int +permission_writable (permission_t permission) +{ + if (permission_is_predefined (permission)) + return 0; + return 1; +} + +/** + * @brief Return whether a trashcan permission is writable. + * + * @param[in] permission Permission. + * + * @return 1 if writable, else 0. + */ +int +trash_permission_writable (permission_t permission) +{ + return 1; +} diff --git a/src/manage_permissions.h b/src/manage_permissions.h index 84cd22893..229a23e15 100644 --- a/src/manage_permissions.h +++ b/src/manage_permissions.h @@ -54,4 +54,16 @@ permission_iterator_subject_readable (iterator_t*); int delete_permission (const char *, int); +int +permission_in_use (permission_t); + +int +trash_permission_in_use (permission_t); + +int +permission_writable (permission_t); + +int +trash_permission_writable (permission_t); + #endif /* not _GVMD_MANAGE_PERMISSIONS_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index dbb01db47..3bd35b477 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -33071,60 +33071,6 @@ modify_schedule (const char *schedule_id, const char *name, const char *comment, /* Permissions. */ -/** - * @brief Return whether a permission is in use. - * - * @param[in] permission Permission. - * - * @return 1 if in use, else 0. - */ -int -permission_in_use (permission_t permission) -{ - return 0; -} - -/** - * @brief Return whether a trashcan permission is referenced by a task. - * - * @param[in] permission Permission. - * - * @return 1 if in use, else 0. - */ -int -trash_permission_in_use (permission_t permission) -{ - return 0; -} - -/** - * @brief Return whether a permission is writable. - * - * @param[in] permission Permission. - * - * @return 1 if writable, else 0. - */ -int -permission_writable (permission_t permission) -{ - if (permission_is_predefined (permission)) - return 0; - return 1; -} - -/** - * @brief Return whether a trashcan permission is writable. - * - * @param[in] permission Permission. - * - * @return 1 if writable, else 0. - */ -int -trash_permission_writable (permission_t permission) -{ - return 1; -} - // TODO temporarily, until modify_permission moved out char * permission_resource_id (permission_t); From 4603d299c789d8548fbb39faa74a8c6d3cd6bf14 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Thu, 29 Jan 2026 16:55:39 +0200 Subject: [PATCH 3/4] Change: move modify_permission to dedicated permission files --- src/manage.h | 4 - src/manage_permissions.h | 4 + src/manage_sql.c | 311 +---------------------------------- src/manage_sql.h | 9 + src/manage_sql_permissions.c | 299 ++++++++++++++++++++++++++++++++- 5 files changed, 311 insertions(+), 316 deletions(-) diff --git a/src/manage.h b/src/manage.h index 660934154..d84b987ae 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2897,10 +2897,6 @@ copy_permission (const char*, const char *, permission_t *); int permission_count (const get_data_t *); -int -modify_permission (const char *, const char *, const char *, const char *, - const char *, const char *, const char *); - /* Permission caching */ void diff --git a/src/manage_permissions.h b/src/manage_permissions.h index 229a23e15..749ce65ce 100644 --- a/src/manage_permissions.h +++ b/src/manage_permissions.h @@ -54,6 +54,10 @@ permission_iterator_subject_readable (iterator_t*); int delete_permission (const char *, int); +int +modify_permission (const char *, const char *, const char *, const char *, + const char *, const char *, const char *); + int permission_in_use (permission_t); diff --git a/src/manage_sql.c b/src/manage_sql.c index 3bd35b477..c369380c2 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -9184,7 +9184,7 @@ DEF_ACCESS (prognosis_iterator_cpe, 3); * * @return The newly allocated GHashTable */ -static GHashTable * +GHashTable * new_resources_hashtable () { return g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, NULL); @@ -9197,7 +9197,7 @@ new_resources_hashtable () * @param[in] reports_table The GHashtable to contain the report rowids. * @param[in] override The override that selected reports must be affected by. */ -static void +void reports_add_for_override (GHashTable *reports_table, override_t override) { @@ -9285,7 +9285,7 @@ reports_for_override (override_t override) * * @param[in] reports_table The GHashtable to contain the report rowids. */ -static void +void reports_add_all (GHashTable *reports_table) { iterator_t reports; @@ -33068,311 +33068,6 @@ modify_schedule (const char *schedule_id, const char *name, const char *comment, return 0; } - -/* Permissions. */ - -// TODO temporarily, until modify_permission moved out -char * -permission_resource_id (permission_t); -char * -permission_subject_id (permission_t); -gboolean -find_permission (const char *, permission_t *); -int -check_permission_args (gboolean, const char *, const char *, const char *, - const char *, const char *, gchar **, resource_t *, - char **, const char **, resource_t *); -/** - * @brief Modify a permission. - * - * @param[in] permission_id UUID of permission. - * @param[in] name_arg Name of permission. - * @param[in] comment Comment on permission. - * @param[in] resource_id_arg UUID of resource. - * @param[in] resource_type_arg Type of resource, for Super permissions. - * @param[in] subject_type Type of subject. - * @param[in] subject_id UUID of subject. - * - * @return 0 success, 1 failed to find permission, 2 failed to find subject, - * 3 failed to find resource, 4 permission_id required, 5 error in - * resource, 6 error in subject, 7 error in name, 8 name required to - * find resource, 9 permission does not accept resource, 99 permission - * denied, -1 internal error. - */ -int -modify_permission (const char *permission_id, const char *name_arg, - const char *comment, const char *resource_id_arg, - const char *resource_type_arg, const char *subject_type, - const char *subject_id) -{ - int ret; - permission_t permission; - resource_t resource, subject; - char *existing_subject_type, *new_name, *new_resource_type; - char *new_resource_id, *new_subject_type, *new_subject_id; - gchar *name, *quoted_name, *resource_type; - const char *resource_id; - char *old_name, *old_resource_type; - resource_t old_resource; - GHashTable *reports = NULL; - int clear_original = 0; - gchar *subject_where_old, *subject_where_new, *subject_where; - - if (permission_id == NULL) - return 4; - - sql_begin_immediate (); - - if (acl_user_may ("modify_permission") == 0) - { - sql_rollback (); - return 99; - } - - /* Find the permission. */ - - permission = 0; - /* There are no permissions on permissions, so no need for the - * "_with_permission" version. */ - if (find_permission (permission_id, &permission)) - { - sql_rollback (); - return -1; - } - - if (permission == 0) - { - sql_rollback (); - return 1; - } - - /* Refuse to modify command-level permissions on predefined roles. */ - - existing_subject_type = permission_subject_type (permission); - resource = permission_resource (permission); - subject = permission_subject (permission); - if (resource == 0 - && existing_subject_type - && strcmp (existing_subject_type, "role") == 0 - && subject - && role_is_predefined (subject)) - { - free (existing_subject_type); - sql_rollback (); - return 99; - } - - /* Get old subject clause */ - subject_where_old = subject_where_clause (existing_subject_type, subject); - - /* Set the comment first, to make things easier. */ - - if (comment) - { - gchar *quoted_comment; - - quoted_comment = sql_quote (comment); - sql ("UPDATE permissions SET" - " comment = '%s'," - " modification_time = m_now ()" - " WHERE id = %llu;", - quoted_comment, - permission); - g_free (quoted_comment); - } - - /* Check the arguments. */ - - new_name = name_arg ? NULL : permission_name (permission); - if (resource_type_arg && resource_id_arg && strcmp (resource_id_arg, "0")) - /* Given a resource. */ - new_resource_type = NULL; - else if (resource_id_arg && (strcmp (resource_id_arg, "0") == 0)) - /* User wants to clear the resource. */ - new_resource_type = NULL; - else - { - new_resource_type = permission_resource_type (permission); - if (new_resource_type - && strcmp (new_resource_type, "group") - && strcmp (new_resource_type, "role") - && strcmp (new_resource_type, "user")) - /* Type will come from command name. */ - new_resource_type = NULL; - } - - new_resource_id = (resource_id_arg && strcmp (resource_id_arg, "")) - ? NULL - : permission_resource_id (permission); - new_subject_type = subject_type ? NULL : existing_subject_type; - new_subject_id = subject_id ? NULL : permission_subject_id (permission); - - ret = check_permission_args - (TRUE, new_name ? new_name : name_arg, - new_resource_type ? new_resource_type : resource_type_arg, - new_resource_id ? new_resource_id : resource_id_arg, - new_subject_type ? new_subject_type : subject_type, - new_subject_id ? new_subject_id : subject_id, - &name, - &resource, - &resource_type, - &resource_id, - &subject); - - free (new_name); - - if (ret) - { - free (new_resource_type); - free (new_resource_id); - free (existing_subject_type); - free (new_subject_id); - g_free (subject_where_old); - sql_rollback (); - return ret; - } - - subject_where_new = subject_where_clause (new_subject_type - ? new_subject_type - : subject_type, - subject); - - if (strcmp (subject_where_new, subject_where_old)) - { - subject_where = g_strdup_printf ("(%s) OR (%s)", - subject_where_new, subject_where_old); - g_free (subject_where_new); - g_free (subject_where_old); - } - else - { - subject_where = subject_where_old; - g_free (subject_where_new); - } - - /* Get old values and check if caches are affected by previous resource. */ - - old_name = permission_name (permission); - old_resource_type = permission_resource_type (permission); - old_resource = permission_resource (permission); - - - if (old_resource - && strcmp (old_resource_type, "override") == 0) - { - reports = reports_for_override (resource); - } - else if (strcasecmp (old_name, "super")) - { - reports = reports_hashtable (); - clear_original = 1; - } - else - { - reports = new_resources_hashtable (); - } - - /* Modify the permission. */ - - assert (subject); - assert ((resource_id == new_resource_id) - || (resource_id == resource_id_arg) - || (resource_id == NULL)); - - quoted_name = sql_quote (name); - - sql ("UPDATE permissions SET" - " name = '%s'," - " resource_type = '%s'," - " resource_uuid = '%s'," - " resource = %llu," - " resource_location = " G_STRINGIFY (LOCATION_TABLE) "," - " subject_type = '%s'," - " subject = %llu," - " modification_time = m_now ()" - " WHERE id = %llu;", - quoted_name, - (resource_id && resource_type) ? resource_type : "", - resource_id ? resource_id : "", - resource, - new_subject_type ? new_subject_type : subject_type, - subject, - permission); - - /* Update permission caches according to the modifications. */ - - if (strcasecmp (name, "super") == 0 || strcasecmp (old_name, "super") == 0) - cache_all_permissions_for_users (NULL); - else - { - if (resource_type && resource_id && strcmp (resource_id, "")) - cache_permissions_for_resource (resource_type, resource, NULL); - - if (old_resource - && old_resource_type - && ((resource != old_resource) - || (resource_type - && strcmp (old_resource_type, resource_type)))) - cache_permissions_for_resource (old_resource_type, old_resource, NULL); - } - - /* Check if caches are affected by the permission and update reports cache */ - - if (resource_type - && resource - && (resource != old_resource - || strcmp (old_resource_type, "override")) - && strcmp (resource_type, "override") == 0) - { - reports_add_for_override (reports, resource); - } - else if (strcasecmp (quoted_name, "super") == 0 - && strcasecmp (old_name, quoted_name)) - { - reports_add_all (reports); - clear_original = 1; - } - - if (reports) - { - GHashTableIter reports_iter; - report_t *reports_ptr; - int auto_cache_rebuild; - - g_hash_table_iter_init (&reports_iter, reports); - reports_ptr = NULL; - auto_cache_rebuild = setting_auto_cache_rebuild_int (); - while (g_hash_table_iter_next (&reports_iter, - ((gpointer*)&reports_ptr), NULL)) - { - if (auto_cache_rebuild) - report_cache_counts (*reports_ptr, clear_original, 1, - subject_where); - else - report_clear_count_cache (*reports_ptr, clear_original, 1, - subject_where); - } - g_hash_table_destroy (reports); - reports = NULL; - } - - /* Cleanup. */ - - g_free (quoted_name); - free (new_resource_type); - free (new_resource_id); - free (existing_subject_type); - free (new_subject_id); - g_free (name); - free (old_name); - free (old_resource_type); - g_free (subject_where); - - sql_commit (); - - return 0; -} - /* Schema. */ diff --git a/src/manage_sql.h b/src/manage_sql.h index f7e2c240a..d9818a9a2 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -534,6 +534,12 @@ reports_clear_count_cache_dynamic (); GHashTable * reports_for_override (override_t); +void +reports_add_all (GHashTable *); + +void +reports_add_for_override (GHashTable *, override_t); + GHashTable * reports_hashtable (); @@ -543,6 +549,9 @@ report_cache_counts (report_t, int, int, const char *); void report_clear_count_cache (report_t, int, int, const char *); +GHashTable * +new_resources_hashtable (); + int cleanup_config_sequences (); diff --git a/src/manage_sql_permissions.c b/src/manage_sql_permissions.c index 903853ff4..545f87ad2 100644 --- a/src/manage_sql_permissions.c +++ b/src/manage_sql_permissions.c @@ -99,7 +99,7 @@ permission_subject (permission_t permission) * * @return Newly allocated subject ID if available, else NULL. */ -char * +static char * permission_subject_id (permission_t permission) { return sql_string ("SELECT subject_id FROM permissions WHERE id = %llu;", @@ -127,7 +127,7 @@ permission_resource_type (permission_t permission) * * @return Newly allocated resource ID if available, else NULL. */ -char * +static char * permission_resource_id (permission_t permission) { return sql_string ("SELECT resource_id FROM permissions WHERE id = %llu;", @@ -788,7 +788,7 @@ subject_where_clause (const char* subject_type, resource_t subject) * @return FALSE on success (including if failed to find permission), TRUE on * error. */ -gboolean +static gboolean find_permission (const char* uuid, permission_t* permission) { return find_resource ("permission", uuid, permission); @@ -815,7 +815,7 @@ find_permission (const char* uuid, permission_t* permission) * 8 permission on permission, 9 permission does not accept resource, * 99 permission denied, -1 error. */ -int +static int check_permission_args (gboolean check_access, const char *name_arg, const char *resource_type_arg, const char *resource_id_arg, const char *subject_type, @@ -1539,3 +1539,294 @@ delete_permission (const char *permission_id, int ultimate) sql_commit (); return 0; } + +/** + * @brief Modify a permission. + * + * @param[in] permission_id UUID of permission. + * @param[in] name_arg Name of permission. + * @param[in] comment Comment on permission. + * @param[in] resource_id_arg UUID of resource. + * @param[in] resource_type_arg Type of resource, for Super permissions. + * @param[in] subject_type Type of subject. + * @param[in] subject_id UUID of subject. + * + * @return 0 success, 1 failed to find permission, 2 failed to find subject, + * 3 failed to find resource, 4 permission_id required, 5 error in + * resource, 6 error in subject, 7 error in name, 8 name required to + * find resource, 9 permission does not accept resource, 99 permission + * denied, -1 internal error. + */ +int +modify_permission (const char *permission_id, const char *name_arg, + const char *comment, const char *resource_id_arg, + const char *resource_type_arg, const char *subject_type, + const char *subject_id) +{ + int ret; + permission_t permission; + resource_t resource, subject; + char *existing_subject_type, *new_name, *new_resource_type; + char *new_resource_id, *new_subject_type, *new_subject_id; + gchar *name, *quoted_name, *resource_type; + const char *resource_id; + char *old_name, *old_resource_type; + resource_t old_resource; + GHashTable *reports = NULL; + int clear_original = 0; + gchar *subject_where_old, *subject_where_new, *subject_where; + + if (permission_id == NULL) + return 4; + + sql_begin_immediate (); + + if (acl_user_may ("modify_permission") == 0) + { + sql_rollback (); + return 99; + } + + /* Find the permission. */ + + permission = 0; + /* There are no permissions on permissions, so no need for the + * "_with_permission" version. */ + if (find_permission (permission_id, &permission)) + { + sql_rollback (); + return -1; + } + + if (permission == 0) + { + sql_rollback (); + return 1; + } + + /* Refuse to modify command-level permissions on predefined roles. */ + + existing_subject_type = permission_subject_type (permission); + resource = permission_resource (permission); + subject = permission_subject (permission); + if (resource == 0 + && existing_subject_type + && strcmp (existing_subject_type, "role") == 0 + && subject + && role_is_predefined (subject)) + { + free (existing_subject_type); + sql_rollback (); + return 99; + } + + /* Get old subject clause */ + subject_where_old = subject_where_clause (existing_subject_type, subject); + + /* Set the comment first, to make things easier. */ + + if (comment) + { + gchar *quoted_comment; + + quoted_comment = sql_quote (comment); + sql ("UPDATE permissions SET" + " comment = '%s'," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_comment, + permission); + g_free (quoted_comment); + } + + /* Check the arguments. */ + + new_name = name_arg ? NULL : permission_name (permission); + if (resource_type_arg && resource_id_arg && strcmp (resource_id_arg, "0")) + /* Given a resource. */ + new_resource_type = NULL; + else if (resource_id_arg && (strcmp (resource_id_arg, "0") == 0)) + /* User wants to clear the resource. */ + new_resource_type = NULL; + else + { + new_resource_type = permission_resource_type (permission); + if (new_resource_type + && strcmp (new_resource_type, "group") + && strcmp (new_resource_type, "role") + && strcmp (new_resource_type, "user")) + /* Type will come from command name. */ + new_resource_type = NULL; + } + + new_resource_id = (resource_id_arg && strcmp (resource_id_arg, "")) + ? NULL + : permission_resource_id (permission); + new_subject_type = subject_type ? NULL : existing_subject_type; + new_subject_id = subject_id ? NULL : permission_subject_id (permission); + + ret = check_permission_args + (TRUE, new_name ? new_name : name_arg, + new_resource_type ? new_resource_type : resource_type_arg, + new_resource_id ? new_resource_id : resource_id_arg, + new_subject_type ? new_subject_type : subject_type, + new_subject_id ? new_subject_id : subject_id, + &name, + &resource, + &resource_type, + &resource_id, + &subject); + + free (new_name); + + if (ret) + { + free (new_resource_type); + free (new_resource_id); + free (existing_subject_type); + free (new_subject_id); + g_free (subject_where_old); + sql_rollback (); + return ret; + } + + subject_where_new = subject_where_clause (new_subject_type + ? new_subject_type + : subject_type, + subject); + + if (strcmp (subject_where_new, subject_where_old)) + { + subject_where = g_strdup_printf ("(%s) OR (%s)", + subject_where_new, subject_where_old); + g_free (subject_where_new); + g_free (subject_where_old); + } + else + { + subject_where = subject_where_old; + g_free (subject_where_new); + } + + /* Get old values and check if caches are affected by previous resource. */ + + old_name = permission_name (permission); + old_resource_type = permission_resource_type (permission); + old_resource = permission_resource (permission); + + + if (old_resource + && strcmp (old_resource_type, "override") == 0) + { + reports = reports_for_override (resource); + } + else if (strcasecmp (old_name, "super")) + { + reports = reports_hashtable (); + clear_original = 1; + } + else + { + reports = new_resources_hashtable (); + } + + /* Modify the permission. */ + + assert (subject); + assert ((resource_id == new_resource_id) + || (resource_id == resource_id_arg) + || (resource_id == NULL)); + + quoted_name = sql_quote (name); + + sql ("UPDATE permissions SET" + " name = '%s'," + " resource_type = '%s'," + " resource_uuid = '%s'," + " resource = %llu," + " resource_location = " G_STRINGIFY (LOCATION_TABLE) "," + " subject_type = '%s'," + " subject = %llu," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_name, + (resource_id && resource_type) ? resource_type : "", + resource_id ? resource_id : "", + resource, + new_subject_type ? new_subject_type : subject_type, + subject, + permission); + + /* Update permission caches according to the modifications. */ + + if (strcasecmp (name, "super") == 0 || strcasecmp (old_name, "super") == 0) + cache_all_permissions_for_users (NULL); + else + { + if (resource_type && resource_id && strcmp (resource_id, "")) + cache_permissions_for_resource (resource_type, resource, NULL); + + if (old_resource + && old_resource_type + && ((resource != old_resource) + || (resource_type + && strcmp (old_resource_type, resource_type)))) + cache_permissions_for_resource (old_resource_type, old_resource, NULL); + } + + /* Check if caches are affected by the permission and update reports cache */ + + if (resource_type + && resource + && (resource != old_resource + || strcmp (old_resource_type, "override")) + && strcmp (resource_type, "override") == 0) + { + reports_add_for_override (reports, resource); + } + else if (strcasecmp (quoted_name, "super") == 0 + && strcasecmp (old_name, quoted_name)) + { + reports_add_all (reports); + clear_original = 1; + } + + if (reports) + { + GHashTableIter reports_iter; + report_t *reports_ptr; + int auto_cache_rebuild; + + g_hash_table_iter_init (&reports_iter, reports); + reports_ptr = NULL; + auto_cache_rebuild = setting_auto_cache_rebuild_int (); + while (g_hash_table_iter_next (&reports_iter, + ((gpointer*)&reports_ptr), NULL)) + { + if (auto_cache_rebuild) + report_cache_counts (*reports_ptr, clear_original, 1, + subject_where); + else + report_clear_count_cache (*reports_ptr, clear_original, 1, + subject_where); + } + g_hash_table_destroy (reports); + reports = NULL; + } + + /* Cleanup. */ + + g_free (quoted_name); + free (new_resource_type); + free (new_resource_id); + free (existing_subject_type); + free (new_subject_id); + g_free (name); + free (old_name); + free (old_resource_type); + g_free (subject_where); + + sql_commit (); + + return 0; +} From a9d4ebee0feaf178c3c10f064ebf6ff89cf30435 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Thu, 29 Jan 2026 16:57:29 +0200 Subject: [PATCH 4/4] Change: move stray headers to dedicated permission files --- src/manage.h | 12 ------------ src/manage_permissions.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/manage.h b/src/manage.h index d84b987ae..0bb0d5729 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2885,18 +2885,6 @@ void set_schedule_timeout (int); -/* Permissions. */ - -int -create_permission (const char *, const char *, const char *, const char *, - const char *, const char *, permission_t *); - -int -copy_permission (const char*, const char *, permission_t *); - -int -permission_count (const get_data_t *); - /* Permission caching */ void diff --git a/src/manage_permissions.h b/src/manage_permissions.h index 749ce65ce..4b013fc77 100644 --- a/src/manage_permissions.h +++ b/src/manage_permissions.h @@ -15,6 +15,9 @@ permission_is_admin (const char *); char * permission_uuid (permission_t); +int +permission_count (const get_data_t *); + int init_permission_iterator (iterator_t*, get_data_t *); @@ -51,6 +54,13 @@ permission_iterator_subject_in_trash (iterator_t*); int permission_iterator_subject_readable (iterator_t*); +int +create_permission (const char *, const char *, const char *, const char *, + const char *, const char *, permission_t *); + +int +copy_permission (const char*, const char *, permission_t *); + int delete_permission (const char *, int);