aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_validation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-transport_validation.c')
-rw-r--r--src/transport/gnunet-service-transport_validation.c212
1 files changed, 173 insertions, 39 deletions
diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c
index 8421969..3598a34 100644
--- a/src/transport/gnunet-service-transport_validation.c
+++ b/src/transport/gnunet-service-transport_validation.c
@@ -34,6 +34,7 @@
#include "gnunet_peerinfo_service.h"
#include "gnunet_signatures.h"
+#define KEEP_093_COMPATIBILITY GNUNET_NO
/**
* How long is a PONG signature valid? We'll recycle a signature until
@@ -307,6 +308,16 @@ static struct GNUNET_PEERINFO_NotifyContext *pnc;
/**
+ * Minimum delay between to validations
+ */
+static struct GNUNET_TIME_Relative validation_delay;
+
+/**
+ * When is next validation allowed
+ */
+static struct GNUNET_TIME_Absolute validation_next;
+
+/**
* Context for the validation entry match function.
*/
struct ValidationEntryMatchContext
@@ -334,7 +345,7 @@ struct ValidationEntryMatchContext
* GNUNET_NO if the entry does match
*/
static int
-validation_entry_match (void *cls, const GNUNET_HashCode * key, void *value)
+validation_entry_match (void *cls, const struct GNUNET_HashCode * key, void *value)
{
struct ValidationEntryMatchContext *vemc = cls;
struct ValidationEntry *ve = value;
@@ -357,7 +368,7 @@ validation_entry_match (void *cls, const GNUNET_HashCode * key, void *value)
* @return GNUNET_YES (continue to iterate)
*/
static int
-cleanup_validation_entry (void *cls, const GNUNET_HashCode * key, void *value)
+cleanup_validation_entry (void *cls, const struct GNUNET_HashCode * key, void *value)
{
struct ValidationEntry *ve = value;
@@ -432,6 +443,7 @@ transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid,
struct ValidationEntry *ve = cls;
struct TransportPingMessage ping;
struct GNUNET_TRANSPORT_PluginFunctions *papi;
+ struct GNUNET_TIME_Absolute next;
const struct GNUNET_MessageHeader *hello;
ssize_t ret;
size_t tsize;
@@ -439,8 +451,20 @@ transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid,
uint16_t hsize;
ve->bc = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting plain PING to `%s' %s\n",
- GNUNET_i2s (pid), GST_plugins_a2s (ve->address));
+
+ if (GNUNET_NO == result)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist denies to send PING to `%s' %s %s\n",
+ GNUNET_i2s (pid), GST_plugins_a2s (ve->address), ve->address->transport_name);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting plain PING to `%s' %s %s\n",
+ GNUNET_i2s (pid), GST_plugins_a2s (ve->address), ve->address->transport_name);
+
+ next = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), validation_delay);
+ if (next.abs_value > validation_next.abs_value)
+ validation_next = next; /* We're going to send a PING so delay next validation */
slen = strlen (ve->address->transport_name) + 1;
hello = GST_hello_get ();
@@ -478,7 +502,7 @@ transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid,
memcpy (&message_buf[sizeof (struct TransportPingMessage) + hsize],
ve->address->transport_name, slen);
memcpy (&message_buf[sizeof (struct TransportPingMessage) + slen + hsize],
- ve->address, ve->address->address_length);
+ ve->address->address, ve->address->address_length);
papi = GST_plugins_find (ve->address->transport_name);
if (papi == NULL)
ret = -1;
@@ -528,6 +552,7 @@ revalidate_address (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
struct ValidationEntry *ve = cls;
struct GNUNET_TIME_Relative canonical_delay;
struct GNUNET_TIME_Relative delay;
+ struct GNUNET_TIME_Relative blocked_for;
struct GST_BlacklistCheck *bc;
uint32_t rdelay;
@@ -552,16 +577,39 @@ revalidate_address (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
return;
}
+ blocked_for = GNUNET_TIME_absolute_get_remaining(validation_next);
+ if ((blocked_for.rel_value) > 0)
+ {
+ /* Validations are blocked, have to wait for blocked_for ms */
+ ve->revalidation_task =
+ GNUNET_SCHEDULER_add_delayed (blocked_for, &revalidate_address, ve);
+ return;
+ }
ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay);
/* schedule next PINGing with some extra random delay to avoid synchronous re-validations */
rdelay =
GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
canonical_delay.rel_value);
- delay =
- GNUNET_TIME_relative_add (canonical_delay,
+
+ /* Debug code for mantis 0002726*/
+ if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value ==
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rdelay).rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Revalidation interval for peer `%s' for is FOREVER (debug: rdelay: %llu, canonical delay %llu)\n",
+ GNUNET_i2s (&ve->pid),
+ (unsigned long long) delay.rel_value,
+ (unsigned long long) canonical_delay.rel_value);
+ delay = canonical_delay;
+ }
+ else
+ {
+ delay = GNUNET_TIME_relative_add (canonical_delay,
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MILLISECONDS, rdelay));
+ }
+ /* End debug code for mantis 0002726*/
ve->revalidation_task =
GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
@@ -661,7 +709,7 @@ add_valid_address (void *cls, const struct GNUNET_HELLO_Address *address,
if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task)
ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
- GNUNET_ATS_address_update (GST_ats, address, NULL, NULL, 0);
+ GNUNET_ATS_address_add (GST_ats, address, NULL, NULL, 0);
return GNUNET_OK;
}
@@ -691,11 +739,17 @@ process_peerinfo_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
/**
* Start the validation subsystem.
+ *
+ * @param max_fds maximum number of fds to use
*/
void
-GST_validation_start ()
+GST_validation_start (unsigned int max_fds)
{
- validation_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE);
+ validation_next = GNUNET_TIME_absolute_get();
+ validation_delay.rel_value = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value) / max_fds;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delay between validations: %u ms\n ", validation_delay.rel_value);
+ validation_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE,
+ GNUNET_NO);
pnc = GNUNET_PEERINFO_notify (GST_cfg, &process_peerinfo_hello, NULL);
}
@@ -788,6 +842,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
size_t alen;
size_t slen;
ssize_t ret;
+ int buggy = GNUNET_NO;
struct GNUNET_HELLO_Address address;
if (ntohs (hdr->size) < sizeof (struct TransportPingMessage))
@@ -817,7 +872,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
sig_cache = NULL;
sig_cache_exp = NULL;
- if (0 < alen)
+ if (alen > 0)
{
addrend = memchr (addr, '\0', alen);
if (NULL == addrend)
@@ -831,15 +886,45 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
address.address = addrend;
address.address_length = alen;
address.transport_name = addr;
- address.peer = *sender;
- if (GNUNET_YES !=
- GST_hello_test_address (&address, &sig_cache, &sig_cache_exp))
+ address.peer = GST_my_identity;
+
+
+ if (GNUNET_YES != GST_hello_test_address (&address, &sig_cache, &sig_cache_exp))
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
- GST_plugins_a2s (&address));
- return;
+#if KEEP_093_COMPATIBILITY
+ int idsize = sizeof (GST_my_identity);
+ if (alen <= idsize)
+ {
+ if (0 == memcmp (address.address, &GST_my_identity, alen))
+ buggy = GNUNET_YES;
+ }
+ else if (alen <= (idsize + strlen (address.transport_name)))
+ {
+ char *achar = (char *) &address.address;
+ if ((0 == memcmp (address.address, &GST_my_identity, idsize)) &&
+ (0 == memcmp (&achar[idsize], address.transport_name, alen - idsize)))
+ buggy = GNUNET_YES;
+ }
+ else
+ {
+ /* Not predicatable */
+ return;
+ }
+#endif
+ if (GNUNET_NO == buggy)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n",
+ GNUNET_i2s (sender),
+ GST_plugins_a2s (&address));
+ return;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Received a PING message with validation bug from `%s'\n"),
+ GNUNET_i2s (sender));
+ }
}
}
else
@@ -853,6 +938,14 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
sig_cache_exp = &no_address_signature_expiration;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "I am `%s', sending PONG to peer `%s'\n",
+ GNUNET_h2s (&GST_my_identity.hashPubKey),
+ GNUNET_i2s (sender));
+
+ /* message with structure:
+ * [TransportPongMessage][Transport name][Address] */
+
pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
pong->header.size =
htons (sizeof (struct TransportPongMessage) + alen + slen);
@@ -862,27 +955,64 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
alen + slen);
pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
- pong->challenge = ping->challenge;
+ memcpy (&pong->challenge, &ping->challenge, sizeof (ping->challenge));
pong->addrlen = htonl (alen + slen);
- memcpy (&pong[1], addr, slen);
- memcpy (&((char *) &pong[1])[slen], addrend, alen);
- if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value <
- PONG_SIGNATURE_LIFETIME.rel_value / 4)
+ memcpy (&pong[1], addr, slen); /* Copy transport plugin */
+#if KEEP_093_COMPATIBILITY
+ if (GNUNET_YES == buggy)
{
- /* create / update cached sig */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating PONG signature to indicate ownership.\n");
- *sig_cache_exp = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
- pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
+ int idsize = sizeof (GST_my_identity);
+ if (alen <= idsize)
+ {
+ memcpy (&((char *) &pong[1])[slen], &GST_my_identity, alen);
+ }
+ else if (alen <= (idsize + strlen (address.transport_name) + 1))
+ {
+ memcpy (&((char *) &pong[1])[slen], &GST_my_identity, idsize);
+ memcpy (&((char *) &pong[1])[slen + idsize], address.transport_name, alen-idsize);
+ }
+ else
+ {
+ /* If this would happen, we would have a inconsistent PING we cannot reproduce */
+ GNUNET_free (pong);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating buggy PONG signature to indicate ownership.\n");
+ pong->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_rsa_sign (GST_my_private_key, &pong->purpose,
- sig_cache));
+ &pong->signature));
}
else
{
- pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
+#endif
+ if (alen > 0)
+ {
+ GNUNET_assert (NULL != addrend);
+ memcpy (&((char *) &pong[1])[slen], addrend, alen);
+ }
+ if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value <
+ PONG_SIGNATURE_LIFETIME.rel_value / 4)
+ {
+ /* create / update cached sig */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating PONG signature to indicate ownership.\n");
+ *sig_cache_exp = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
+ pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_sign (GST_my_private_key, &pong->purpose,
+ sig_cache));
+ }
+ else
+ {
+ pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
+ }
+ pong->signature = *sig_cache;
+
+#if KEEP_093_COMPATIBILITY
}
- pong->signature = *sig_cache;
+#endif
GNUNET_assert (sender_address != NULL);
@@ -1031,6 +1161,9 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
gettext_noop ("# PONG messages received"), 1,
GNUNET_NO);
+ /* message with structure:
+ * [TransportPongMessage][Transport name][Address] */
+
pong = (const struct TransportPongMessage *) hdr;
tname = (const char *) &pong[1];
size = ntohs (hdr->size) - sizeof (struct TransportPongMessage);
@@ -1068,7 +1201,10 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
&pong->purpose, &pong->signature,
&ve->public_key))
{
- GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid signature on address %s:%s from peer `%s'\n",
+ tname, GST_plugins_a2s (ve->address),
+ GNUNET_i2s (sender));
return;
}
@@ -1083,7 +1219,6 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Address validated for peer `%s' with plugin `%s': `%s'\n",
-
GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address));
/* validity achieved, remember it! */
ve->expecting_pong = GNUNET_NO;
@@ -1091,10 +1226,9 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
ve->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
{
struct GNUNET_ATS_Information ats;
-
ats.type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
ats.value = htonl ((uint32_t) ve->latency.rel_value);
- GNUNET_ATS_address_update (GST_ats, ve->address, NULL, &ats, 1);
+ GNUNET_ATS_address_add (GST_ats, ve->address, NULL, &ats, 1);
}
/* build HELLO to store in PEERINFO */
ve->copied = GNUNET_NO;
@@ -1131,11 +1265,11 @@ GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello)
/* Add peer identity without addresses to peerinfo service */
h = GNUNET_HELLO_create (&vac.public_key, NULL, NULL);
GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL);
-#if VERBOSE_VALIDATION
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
_("Adding `%s' without addresses for peer `%s'\n"), "HELLO",
GNUNET_i2s (&vac.pid));
-#endif
+
GNUNET_free (h);
GNUNET_assert (NULL ==
GNUNET_HELLO_iterate_addresses (hm, GNUNET_NO,
@@ -1171,7 +1305,7 @@ struct IteratorContext
* @return GNUNET_OK (continue to iterate)
*/
static int
-iterate_addresses (void *cls, const GNUNET_HashCode * key, void *value)
+iterate_addresses (void *cls, const struct GNUNET_HashCode * key, void *value)
{
struct IteratorContext *ic = cls;
struct ValidationEntry *ve = value;