/**
* @file transport/gnunet-service-transport_blacklist.c
* @brief blacklisting implementation
- * @author Christian Grothoff
+ * @author Christian Grothoff, Matthias Wachs
+ * @details This is the blacklisting component of transport service. With
+ * blacklisting it is possible to deny connections to specific peers of
+ * to use a specific plugin to a specific peer. Peers can be blacklisted using
+ * the configuration or a blacklist client can be asked.
+ *
+ * To blacklist peers using the configuration you have to add a section to your
+ * configuration containing the peer id of the peer to blacklist and the plugin
+ * if required.
+ *
+ * Example:
+ * To blacklist connections to P565... on peer AG2P... using tcp add:
+ * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
+ * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = tcp
+ *
+ * To blacklist connections to P565... on peer AG2P... using all plugins add:
+ * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
+ * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G =
+ *
+ * You can also add a blacklist client usign the blacklist api. On a blacklist
+ * check, blacklisting first checks internally if the peer is blacklisted and
+ * if not, it asks the blacklisting clients. Clients are asked if it is OK to
+ * connect to a peer ID, the plugin is omitted.
+ *
+ * On blacklist check for (peer, plugin)
+ * - Do we have a local blacklist entry for this peer and this plugin?
+ * - YES: disallow connection
+ * - Do we have a local blacklist entry for this peer and all plugins?
+ * - YES: disallow connection
+ * - Does one of the clients disallow?
+ * - YES: disallow connection
+ *
*/
#include "platform.h"
#include "gnunet-service-transport.h"
#include "gnunet-service-transport_neighbours.h"
#include "transport.h"
-
/**
* Size of the blacklist hash map.
*/
/**
- * Read the blacklist file, containing transport:peer entries.
- * Provided the transport is loaded, set up hashmap with these
- * entries to blacklist peers by transport.
+ * Function to iterate over options in the blacklisting section for a peer.
*
+ * @param cls closure
+ * @param section name of the section
+ * @param option name of the option
+ * @param value value of the option
*/
-static void
-read_blacklist_file ()
+static void
+blacklist_cfg_iter (void *cls, const char *section,
+ const char *option,
+ const char *value)
{
- char *fn;
- char *data;
- size_t pos;
- size_t colon_pos;
- int tsize;
- struct GNUNET_PeerIdentity pid;
- uint64_t fsize;
- struct GNUNET_CRYPTO_HashAsciiEncoded enc;
- unsigned int entries_found;
- char *transport_name;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (GST_cfg, "TRANSPORT",
- "BLACKLIST_FILE", &fn))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_DEBUG,
- "transport", "BLACKLIST_FILE");
- return;
- }
- if (GNUNET_OK != GNUNET_DISK_file_test (fn))
- {
- GNUNET_free (fn);
- return; /* no blacklist */
- }
- if (GNUNET_OK != GNUNET_DISK_file_size (fn,
- &fsize, GNUNET_NO, GNUNET_YES))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Could not read blacklist file `%s'\n"), fn);
- GNUNET_free (fn);
- return;
- }
- if (0 == fsize)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist file `%s' is empty.\n",
- fn);
- GNUNET_free (fn);
+ unsigned int *res = cls;
+ struct GNUNET_PeerIdentity peer;
+ char *plugs;
+ char *pos;
+
+ if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string2 (option,
+ strlen (option),
+ &peer.hashPubKey))
return;
- }
- /* FIXME: use mmap */
- data = GNUNET_malloc_large (fsize);
- GNUNET_assert (data != NULL);
- if (fsize != GNUNET_DISK_fn_read (fn, data, fsize))
+
+ if ((NULL == value) || (0 == strcmp(value, "")))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to read blacklist from `%s'\n"), fn);
- GNUNET_free (fn);
- GNUNET_free (data);
- return;
+ /* Blacklist whole peer */
+ GST_blacklist_add_peer (&peer, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Adding blacklisting entry for peer `%s'\n"), GNUNET_i2s (&peer));
}
- entries_found = 0;
- pos = 0;
- while ((pos < fsize) && isspace ((unsigned char) data[pos]))
- pos++;
- while ((fsize >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
- (pos <=
- fsize - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
+ else
{
- colon_pos = pos;
- while ((colon_pos < fsize) && (data[colon_pos] != ':') &&
- (!isspace ((unsigned char) data[colon_pos])))
- colon_pos++;
- if (colon_pos >= fsize)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Syntax error in blacklist file at offset %llu, giving up!\n"),
- (unsigned long long) colon_pos);
- GNUNET_free (fn);
- GNUNET_free (data);
- return;
- }
-
- if (isspace ((unsigned char) data[colon_pos]))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
- (unsigned long long) colon_pos);
- pos = colon_pos;
- while ((pos < fsize) && isspace ((unsigned char) data[pos]))
- pos++;
- continue;
- }
- tsize = colon_pos - pos;
- if ((pos >= fsize) || (pos + tsize >= fsize) ||
- (tsize == 0))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Syntax error in blacklist file at offset %llu, giving up!\n"),
- (unsigned long long) colon_pos);
- GNUNET_free (fn);
- GNUNET_free (data);
- return;
- }
-
- if (tsize < 1)
- continue;
-
- transport_name = GNUNET_malloc (tsize + 1);
- memcpy (transport_name, &data[pos], tsize);
- pos = colon_pos + 1;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Read transport name `%s' in blacklist file.\n",
- transport_name);
- memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
- if (!isspace
- ((unsigned char)
- enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
- (unsigned long long) pos);
- pos++;
- while ((pos < fsize) && (!isspace ((unsigned char) data[pos])))
- pos++;
- GNUNET_free_non_null (transport_name);
- continue;
- }
- enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
- if (GNUNET_OK !=
- GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Syntax error in blacklist file at offset %llu, skipping bytes `%s'.\n"),
- (unsigned long long) pos, &enc);
- }
- else
- {
- if (0 !=
- memcmp (&pid, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity)))
+ plugs = GNUNET_strdup (value);
+ for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " "))
{
- entries_found++;
- GST_blacklist_add_peer (&pid, transport_name);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Adding blacklisting entry for peer `%s':`%s'\n"),
+ GNUNET_i2s (&peer), pos);
+ GST_blacklist_add_peer (&peer, pos);
}
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Found myself `%s' in blacklist (useless, ignored)\n"),
- GNUNET_i2s (&pid));
- }
- }
- pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
- GNUNET_free_non_null (transport_name);
- while ((pos < fsize) && isspace ((unsigned char) data[pos]))
- pos++;
+ GNUNET_free (plugs);
}
- GNUNET_STATISTICS_update (GST_stats, "# Transport entries blacklisted",
- entries_found, GNUNET_NO);
- GNUNET_free (data);
- GNUNET_free (fn);
+ (*res)++;
+}
+
+
+/**
+ * Read blacklist configuration
+ *
+ * @param cfg the configuration handle
+ * @param my_id my peer identity
+ */
+static void
+read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const struct GNUNET_PeerIdentity *my_id)
+{
+ char cfg_sect[512];
+ unsigned int res = 0;
+
+ GNUNET_snprintf (cfg_sect,
+ sizeof (cfg_sect),
+ "transport-blacklist-%s",
+ GNUNET_i2s_full (my_id));
+ GNUNET_CONFIGURATION_iterate_section_values (cfg, cfg_sect, &blacklist_cfg_iter, &res);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Loaded %u blacklisting entries from configuration\n", res);
}
* Start blacklist subsystem.
*
* @param server server used to accept clients from
+ * @param cfg configuration handle
+ * @param my_id my peer id
*/
void
-GST_blacklist_start (struct GNUNET_SERVER_Handle *server)
+GST_blacklist_start (struct GNUNET_SERVER_Handle *server,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const struct GNUNET_PeerIdentity *my_id)
{
- read_blacklist_file ();
+ GNUNET_assert (NULL != cfg);
+ GNUNET_assert (NULL != my_id);
+ read_blacklist_configuration (cfg, my_id);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
NULL);
}
{
char *be = value;
- GNUNET_free (be);
+ GNUNET_free_non_null (be);
return GNUNET_OK;
}
*
* @param cls the 'struct TestConnectionContest'
* @param neighbour neighbour's identity
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
* @param address the address
* @param bandwidth_in inbound quota in NBO
* @param bandwidth_out outbound quota in NBO
}
}
/* check if any other bc's are waiting for this blacklister */
- bc = bc_head;
for (bc = bc_head; bc != NULL; bc = bc->next)
if ((bc->bl_pos == bl) && (GNUNET_SCHEDULER_NO_TASK == bc->task))
{
GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
const char *transport_name)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ char * transport = NULL;
+ if (NULL != transport_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding peer `%s' with plugin `%s' to blacklist\n",
GNUNET_i2s (peer), transport_name);
+ transport = GNUNET_strdup (transport_name);
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Adding peer `%s' with all plugins to blacklist\n",
+ GNUNET_i2s (peer));
if (blacklist == NULL)
blacklist =
GNUNET_CONTAINER_multihashmap_create (TRANSPORT_BLACKLIST_HT_SIZE,
GNUNET_NO);
+
GNUNET_CONTAINER_multihashmap_put (blacklist, &peer->hashPubKey,
- GNUNET_strdup (transport_name),
+ transport,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
}
const char *transport_name = cls;
char *be = value;
- /* blacklist check for specific no specific transport*/
- if (transport_name == NULL)
- return GNUNET_NO;
+ /* Blacklist entry be:
+ * (NULL == be): peer is blacklisted with all plugins
+ * (NULL != be): peer is blacklisted for a specific plugin
+ *
+ * If (NULL != transport_name) we look for a transport specific entry:
+ * if (transport_name == be) forbidden
+ *
+ */
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n",
+ GNUNET_h2s (key),
+ (NULL == transport_name) ? "unspecified" : transport_name,
+ (NULL == be) ? "all plugins" : be);
+ /* all plugins for this peer were blacklisted: disallow */
+ if (NULL == value)
+ return GNUNET_NO;
/* blacklist check for specific transport */
- if (0 == strcmp (transport_name, be))
- return GNUNET_NO; /* abort iteration! */
+ if ((NULL != transport_name) && (NULL != value))
+ {
+ if (0 == strcmp (transport_name, be))
+ return GNUNET_NO; /* plugin is blacklisted! */
+ }
return GNUNET_OK;
}
struct GST_BlacklistCheck *bc;
GNUNET_assert (peer != NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist check for peer `%s':%s\n",
+ GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : "unspecified");
+ /* Check local blacklist by iterating over hashmap
+ * If iteration is aborted, we found a matching blacklist entry */
if ((blacklist != NULL) &&
(GNUNET_SYSERR ==
GNUNET_CONTAINER_multihashmap_get_multiple (blacklist, &peer->hashPubKey,
&test_blacklisted,
(void *) transport_name)))
{
- /* disallowed by config, disapprove instantly */
+ /* Disallowed by config, disapprove instantly */
GNUNET_STATISTICS_update (GST_stats,
gettext_noop ("# disconnects due to blacklist"),
1, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disallowing connection to peer `%s' on transport %s\n",
+ GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : "unspecified");
if (cont != NULL)
cont (cont_cls, peer, GNUNET_NO);
return NULL;
/* no blacklist clients, approve instantly */
if (cont != NULL)
cont (cont_cls, peer, GNUNET_OK);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allowing connection to peer `%s' %s\n",
+ GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : "");
return NULL;
}