Skip to content

Commit

Permalink
Fix: allow/deny hosts. (#1420)
Browse files Browse the repository at this point in the history
This PR fix an issue which produces the scan to be interrupted, because the denied hosts are not removed from the hosts list, and the final host count doesn't match with the amount of alive hosts. This ends with an interrupted scan produced by a wrong scan progress calculation.

These fix depends on PR greenbone/gvm-libs#771. However, it is not a breaking change, since a pre-processor directive check for a flag. Without an updated gvm-libs behaves as before and uses the feature (the fix) if enabled.

Jira SC-837
  • Loading branch information
jjnicola authored May 15, 2023
1 parent 68bf4de commit c4ca804
Showing 1 changed file with 90 additions and 29 deletions.
119 changes: 90 additions & 29 deletions src/attack.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,33 +797,6 @@ attack_host (struct scan_globals *globals, struct in6_addr *ip,
host_set_time (get_main_kb (), ip_str, "HOST_END");
}

/*
* Checks if a host is authorized to be scanned.
*
* @param[in] host Host to check access to.
* @param[in] addr Pointer to address so a hostname isn't resolved multiple
* times.
* @param[in] hosts_allow Hosts whitelist.
* @param[in] hosts_deny Hosts blacklist.
*
* @return 1 if host authorized, 0 otherwise.
*/
static int
host_authorized (const gvm_host_t *host, const struct in6_addr *addr,
const gvm_hosts_t *hosts_allow, const gvm_hosts_t *hosts_deny)
{
/* Check Hosts Access. */
if (host == NULL)
return 0;

if (hosts_deny && gvm_host_in_hosts (host, addr, hosts_deny))
return 0;
if (hosts_allow && !gvm_host_in_hosts (host, addr, hosts_allow))
return 0;

return 1;
}

/*
* Converts the vhosts list to a comma-separated char string.
*
Expand Down Expand Up @@ -886,6 +859,34 @@ check_deprecated_prefs (void)
}
}

#ifndef FEATURE_HOSTS_ALLOWED_ONLY
/*
* Checks if a host is authorized to be scanned.
*
* @param[in] host Host to check access to.
* @param[in] addr Pointer to address so a hostname isn't resolved multiple
* times.
* @param[in] hosts_allow Hosts whitelist.
* @param[in] hosts_deny Hosts blacklist.
*
* @return 1 if host authorized, 0 otherwise.
*/
static int
host_authorized (const gvm_host_t *host, const struct in6_addr *addr,
const gvm_hosts_t *hosts_allow, const gvm_hosts_t *hosts_deny)
{
/* Check Hosts Access. */
if (host == NULL)
return 0;

if (hosts_deny && gvm_host_in_hosts (host, addr, hosts_deny))
return 0;
if (hosts_allow && !gvm_host_in_hosts (host, addr, hosts_allow))
return 0;

return 1;
}

/*
* Check if a scan is authorized on a host.
*
Expand Down Expand Up @@ -918,6 +919,7 @@ check_host_authorization (gvm_host_t *host, const struct in6_addr *addr)
gvm_hosts_free (sys_hosts_deny);
return 0;
}
#endif

/**
* @brief Set up some data and jump into attack_host()
Expand All @@ -932,7 +934,7 @@ attack_start (struct ipc_context *ipcc, struct attack_start_args *args)
struct timeval then;
kb_t kb = args->host_kb;
kb_t main_kb = get_main_kb ();
int ret, ret_host_auth;
int ret;
args->ipc_context = ipcc;

nvticache_reset ();
Expand All @@ -953,7 +955,8 @@ attack_start (struct ipc_context *ipcc, struct attack_start_args *args)
gvm_host_get_addr6 (args->host, &hostip);
addr6_to_str (&hostip, ip_str);

ret_host_auth = check_host_authorization (args->host, &hostip);
#ifndef FEATURE_HOSTS_ALLOWED_ONLY
int ret_host_auth = check_host_authorization (args->host, &hostip);
if (ret_host_auth < 0)
{
if (ret_host_auth == -1)
Expand All @@ -966,6 +969,7 @@ attack_start (struct ipc_context *ipcc, struct attack_start_args *args)
g_warning ("Host %s access denied.", ip_str);
return;
}
#endif

if (prefs_get_bool ("test_empty_vhost"))
{
Expand Down Expand Up @@ -1019,6 +1023,55 @@ apply_hosts_excluded (gvm_hosts_t *hosts)
}
}

#ifdef FEATURE_HOSTS_ALLOWED_ONLY
static void
print_host_access_denied (gpointer data, gpointer systemwide)
{
kb_t kb = NULL;
int *sw = systemwide;
connect_main_kb (&kb);
if (*sw == 0)
message_to_client ((kb_t) kb, "Host access denied.", (gchar *) data, NULL,
"ERRMSG");
else if (*sw == 1)
message_to_client ((kb_t) kb,
"Host access denied (system-wide restriction).",
(gchar *) data, NULL, "ERRMSG");
kb_item_set_str_with_main_kb_check ((kb_t) kb, "internal/host_deny", "True",
0);
kb_lnk_reset (kb);
g_warning ("Host %s access denied.", (gchar *) data);
}

static void
apply_hosts_allow_deny (gvm_hosts_t *hosts)
{
GSList *removed = NULL;
const char *allow_hosts = prefs_get ("hosts_allow");
const char *deny_hosts = prefs_get ("hosts_deny");
int systemwide;
if (allow_hosts || deny_hosts)
{
systemwide = 0;
removed = gvm_hosts_allowed_only (hosts, deny_hosts, allow_hosts);
g_slist_foreach (removed, print_host_access_denied,
(gpointer) &systemwide);
g_slist_free_full (removed, g_free);
}

const char *sys_allow_hosts = prefs_get ("sys_hosts_allow");
const char *sys_deny_hosts = prefs_get ("sys_hosts_deny");
if (sys_allow_hosts || sys_deny_hosts)
{
systemwide = 1;
removed = gvm_hosts_allowed_only (hosts, sys_deny_hosts, sys_allow_hosts);
g_slist_foreach (removed, print_host_access_denied,
(gpointer) &systemwide);
g_slist_free_full (removed, g_free);
}
}
#endif

static void
apply_hosts_preferences_ordering (gvm_hosts_t *hosts)
{
Expand Down Expand Up @@ -1272,13 +1325,21 @@ attack_network (struct scan_globals *globals)
apply_hosts_preferences_ordering (hosts);
apply_hosts_reverse_lookup_preferences (hosts);

#ifdef FEATURE_HOSTS_ALLOWED_ONLY
// Remove hosts which are denied and/or keep the ones in the allowed host
// lists
// for both, user and system wide settings.
apply_hosts_allow_deny (hosts);
#endif

/* Send the hosts count to the client, after removing duplicated and
* unresolved hosts.*/
sprintf (buf, "%d", gvm_hosts_count (hosts));
connect_main_kb (&main_kb);
message_to_client (main_kb, buf, NULL, NULL, "HOSTS_COUNT");
kb_lnk_reset (main_kb);

// Remove the excluded hosts
apply_hosts_excluded (hosts);

host = gvm_hosts_next (hosts);
Expand Down

0 comments on commit c4ca804

Please sign in to comment.