Skip to content

Commit

Permalink
Change: Use WHERE for results of vulnerabilities
Browse files Browse the repository at this point in the history
Instead of using a function to check which results of the current user
belong to a vulnerability, a WHERE clause and JOIN are used instead.

This improves performance, especially when there are multiple users
with large amounts of results.
  • Loading branch information
timopollmeier authored and a-h-abdelsalam committed Dec 14, 2023
1 parent 28054e8 commit 3e0ca4c
Showing 1 changed file with 172 additions and 54 deletions.
226 changes: 172 additions & 54 deletions src/manage_sql.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,13 @@ static gboolean
find_group_with_permission (const char *, group_t *, const char *);

static gchar*
vulns_extra_where ();
vulns_extra_where (int);

static gchar*
vuln_iterator_opts_from_filter (const char*);

static gchar*
vuln_iterator_extra_with_from_filter ();

static int
task_last_report_any_status (task_t, report_t *);
Expand Down Expand Up @@ -17660,15 +17666,17 @@ resource_count (const char *type, const get_data_t *get)
static const char *filter_columns[] = { "owner", NULL };
static column_t select_columns[] = {{ "owner", NULL }, { NULL, NULL }};
get_data_t count_get;
gchar *extra_where;
gchar *extra_where, *extra_with, *extra_tables;
int rc;

memset (&count_get, '\0', sizeof (count_get));
count_get.trash = get->trash;
if (type_owned (type))
count_get.filter = "rows=-1 first=1 permission=any owner=any";
count_get.filter = "rows=-1 first=1 permission=any owner=any min_qod=0";
else
count_get.filter = "rows=-1 first=1 permission=any";
count_get.filter = "rows=-1 first=1 permission=any min_qod=0";

extra_with = extra_tables = NULL;

if (strcasecmp (type, "config") == 0)
{
Expand All @@ -17693,25 +17701,29 @@ resource_count (const char *type, const get_data_t *get)
}
else if (strcmp (type, "vuln") == 0)
{
extra_where = g_strdup (" AND vuln_results_exist"
" (vulns.uuid,"
" cast (null AS integer),"
" cast (null AS integer),"
" cast (null AS text))");
extra_where = vulns_extra_where (filter_term_min_qod (count_get.filter));
extra_with = vuln_iterator_extra_with_from_filter (count_get.filter);
extra_tables = vuln_iterator_opts_from_filter (count_get.filter);
}
else
extra_where = NULL;

rc = count (get->subtype ? get->subtype : type,
&count_get,
type_owned (type) ? select_columns : NULL,
type_owned (type) ? select_columns : NULL,
type_owned (type) ? filter_columns : NULL,
0, NULL,
extra_where,
type_owned (type));
rc = count2 (get->subtype ? get->subtype : type,
&count_get,
type_owned (type) ? select_columns : NULL,
type_owned (type) ? select_columns : NULL,
NULL,
NULL,
type_owned (type) ? filter_columns : NULL,
0,
extra_tables,
extra_where,
extra_with,
type_owned (type));

g_free (extra_where);
g_free (extra_with);
g_free (extra_tables);
return rc;
}

Expand Down Expand Up @@ -55254,7 +55266,7 @@ user_resources_in_use (user_t user,
{ "''", "owner", KEYWORD_TYPE_STRING }, \
/* Type specific columns */ \
{ \
"vuln_results (uuid, opts.task, opts.report, opts.host)", \
"vuln_results.result_count", \
"results", \
KEYWORD_TYPE_INTEGER \
}, \
Expand All @@ -55276,20 +55288,109 @@ user_resources_in_use (user_t user,
"type", NULL, KEYWORD_TYPE_INTEGER \
}, \
{ \
"(SELECT min (date) FROM results" \
VULN_RESULTS_WHERE ")", \
"vuln_results.oldest", \
"oldest", \
KEYWORD_TYPE_INTEGER \
}, \
{ \
"(SELECT max (date) FROM results" \
VULN_RESULTS_WHERE ")", \
"vuln_results.newest", \
"newest", \
KEYWORD_TYPE_INTEGER \
}, \
{ NULL, NULL, KEYWORD_TYPE_UNKNOWN } \
}

/**
* @brief Generate the extra_with string for a vuln iterator.
*
* @param[in] task_id UUID of the task to limit vulns to.
* @param[in] report_id UUID of the report to limit vulns to.
* @param[in] host IP address of the task to limit vulns to.
* @param[in] min_qod Minimum QoD.
*
* @return Newly allocated string with the extra_with clause.
*/
static gchar*
vuln_iterator_extra_with (const gchar *task_id, const gchar *report_id,
const gchar *host)
{
GString *ret;

ret = g_string_new ("");

g_string_append_printf (ret,
"vuln_results AS ("
" SELECT nvt, count(*) as result_count,"
" min(date) AS oldest, max(date) AS newest"
" FROM results"
" WHERE severity != " G_STRINGIFY (SEVERITY_ERROR)
" AND (" ACL_USER_OWNS ()
" OR results.task IN"
" (SELECT task FROM permissions_get_tasks"
" WHERE \"user\" ="
" (SELECT users.id FROM users WHERE"
" uuid = '%s')"
" AND has_permission))",
current_credentials.uuid,
current_credentials.uuid);

if (task_id && strcmp (task_id, ""))
{
task_t task = 0;
find_task_with_permission (task_id, &task, "get_tasks");
g_string_append_printf (ret, " AND results.task = %llu", task);
}

if (report_id && strcmp (report_id, ""))
{
report_t report = 0;
find_report_with_permission (task_id, &report, "get_reports");
g_string_append_printf (ret, " AND results.report = %llu", report);
}

if (host && strcmp (host, ""))
{
gchar *quoted_host = sql_quote (host);
g_string_append_printf (ret, " AND results.host = '%s'", quoted_host);
g_free (quoted_host);
}

g_string_append (ret, " GROUP BY nvt)");

return g_string_free (ret, FALSE);
}

/**
* @brief Generate the extra_with string for a vuln iterator using a filter.
*
* @param[in] filter The filter term to use.
*
* @return Newly allocated string with the extra_with clause.
*/
static gchar*
vuln_iterator_extra_with_from_filter (const gchar *filter)
{
gchar *task_id, *report_id, *host;
gchar *ret;

if (filter)
{
task_id = filter_term_value (filter, "task_id");
report_id = filter_term_value (filter, "report_id");
host = filter_term_value (filter, "host");
}
else
task_id = report_id = host = NULL;

ret = vuln_iterator_extra_with (task_id, report_id, host);

g_free (task_id);
g_free (report_id);
g_free (host);

return ret;
}

/**
* @brief Generate the extra_tables string for a vuln iterator.
*
Expand All @@ -55306,7 +55407,8 @@ vuln_iterator_opts_table (const gchar *task_id, const gchar *report_id,
{
GString *ret;

ret = g_string_new (", (SELECT");
ret = g_string_new (" JOIN vuln_results ON vuln_results.nvt = vulns.uuid,"
" (SELECT");

if (task_id && strcmp (task_id, ""))
{
Expand Down Expand Up @@ -55394,7 +55496,7 @@ init_vuln_iterator (iterator_t* iterator, const get_data_t *get)
{
int ret;
gchar *filter;
gchar *extra_tables, *extra_where;
gchar *extra_with, *extra_tables, *extra_where;
static const char *filter_columns[] = VULN_ITERATOR_FILTER_COLUMNS;
static column_t select_columns[] = VULN_ITERATOR_COLUMNS;

Expand All @@ -55413,28 +55515,35 @@ init_vuln_iterator (iterator_t* iterator, const get_data_t *get)
else
filter = NULL;

extra_with
= vuln_iterator_extra_with_from_filter (filter ? filter : get->filter);

extra_tables
= vuln_iterator_opts_from_filter (filter ? filter : get->filter);

extra_where
= vulns_extra_where ();

ret = init_get_iterator2 (iterator,
"vuln",
get,
select_columns,
NULL, /* trash_select_columns */
NULL, /* where_columns */
NULL, /* trash_where_columns */
filter_columns,
0 /* distinct */,
extra_tables, /* extra_tables */
extra_where, /* extra_where */
NULL, /* extra_where_single */
0, /* owned */
0, /* ignore_id */
NULL);/* extra_order */
= vulns_extra_where (filter_term_min_qod (filter ? filter : get->filter));

ret = init_get_iterator2_with (iterator,
"vuln",
get,
select_columns,
NULL, /* trash_select_columns */
NULL, /* where_columns */
NULL, /* trash_where_columns */
filter_columns,
0 /* distinct */,
extra_tables, /* extra_tables */
extra_where, /* extra_where */
NULL, /* extra_where_single */
0, /* owned */
0, /* ignore_id */
NULL, /* extra_order */
extra_with,
0, /* acl_with_optional */
0); /* assume_permitted */

g_free (extra_with);
g_free (extra_tables);
g_free (extra_where);

Expand Down Expand Up @@ -55552,7 +55661,7 @@ vuln_count (const get_data_t *get)
gchar *filter;
static const char *filter_columns[] = VULN_ITERATOR_FILTER_COLUMNS;
static column_t columns[] = VULN_ITERATOR_COLUMNS;
gchar *extra_tables, *extra_where;
gchar *extra_with, *extra_tables, *extra_where;
int ret;

if (get->filt_id && strcmp (get->filt_id, FILT_ID_NONE))
Expand All @@ -55570,16 +55679,21 @@ vuln_count (const get_data_t *get)
else
filter = NULL;

extra_with
= vuln_iterator_extra_with_from_filter (filter ? filter : get->filter);

extra_tables
= vuln_iterator_opts_from_filter (filter ? filter : get->filter);

extra_where
= vulns_extra_where ();
= vulns_extra_where (filter_term_min_qod (filter ? filter : get->filter));

ret = count ("vuln", get, columns, NULL /*trash_columns*/, filter_columns, 0,
extra_tables, extra_where, FALSE);
ret = count2 ("vuln", get, columns, NULL /*trash_columns*/, NULL, NULL,
filter_columns, 0, extra_tables, extra_where, extra_with,
FALSE);

g_free (filter);
g_free (extra_with);
g_free (extra_tables);
g_free (extra_where);

Expand All @@ -55592,11 +55706,10 @@ vuln_count (const get_data_t *get)
* @return WHERE clause.
*/
static gchar*
vulns_extra_where ()
vulns_extra_where (int min_qod)
{
return g_strdup (" AND vuln_results_exist (uuid, opts.task, opts.report,"
" opts.host)"
" AND (qod >= opts.min_qod)");
return g_strdup_printf (" AND (vulns.qod >= %d)",
min_qod);
}

/**
Expand Down Expand Up @@ -57581,7 +57694,7 @@ type_extra_where (const char *type, int trash, const char *filter,
}
else if (strcasecmp (type, "VULN") == 0)
{
extra_where = vulns_extra_where ();
extra_where = vulns_extra_where (filter_term_min_qod (filter));
}
else
extra_where = g_strdup ("");
Expand All @@ -57596,9 +57709,13 @@ type_extra_where (const char *type, int trash, const char *filter,
*
* @return The extra WITH clauses.
*/
static const char *
type_extra_with (const char *type)
static gchar *
type_extra_with (const char *type, const char *filter)
{
if (strcasecmp (type, "VULN") == 0)
{
return vuln_iterator_extra_with_from_filter(filter);
}
return NULL;
}

Expand Down Expand Up @@ -57631,7 +57748,7 @@ type_build_select (const char *type, const char *columns_str,
int first, max;
gchar *owned_clause, *owner_filter;
array_t *permissions;
const char *extra_with;
gchar *extra_with;

column_t *select_columns, *where_columns;
const char **filter_columns;
Expand Down Expand Up @@ -57716,7 +57833,7 @@ type_build_select (const char *type, const char *columns_str,
sql_select_limit (max),
first);

extra_with = type_extra_with (type);
extra_with = type_extra_with (type, filter ? filter : get->filter);

if (extra_with)
{
Expand Down Expand Up @@ -57762,6 +57879,7 @@ type_build_select (const char *type, const char *columns_str,
g_free (from_table);
g_free (opts_table);
g_free (owned_clause);
g_free (extra_with);
g_free (extra_where);
g_free (pagination_clauses);

Expand Down

0 comments on commit 3e0ca4c

Please sign in to comment.