#include "platform.h"
#include "gnunet-service-transport_validation.h"
#include "gnunet-service-transport_plugins.h"
+#include "gnunet-service-transport_hello.h"
#include "gnunet-service-transport.h"
#include "gnunet_hello_lib.h"
#include "gnunet_peerinfo_service.h"
*/
const struct GNUNET_HELLO_Message *hello;
- /**
- * Context for peerinfo iteration.
- */
- struct GNUNET_PEERINFO_IteratorContext *piter;
-
};
*/
static struct GNUNET_CONTAINER_MultiHashMap *notify_map;
-
/**
- * Start the validation subsystem.
+ * Context for peerinfo iteration.
*/
-void
-GST_validation_start ()
-{
- validation_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE);
- notify_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE);
-}
-
-
-/**
- * Iterate over validation entries and free them.
- *
- * @param cls (unused)
- * @param key peer identity (unused)
- * @param value a 'struct ValidationEntry' to clean up
- * @return GNUNET_YES (continue to iterate)
- */
-static int
-cleanup_validation_entry (void *cls,
- const GNUNET_HashCode *key,
- void *value)
-{
- struct ValidationEntry *ve = value;
-
- GNUNET_free (ve->transport_name);
- if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ve->timeout_task);
- ve->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- GNUNET_free (ve);
- return GNUNET_OK;
-}
-
-
-/**
- * Stop the validation subsystem.
- */
-void
-GST_validation_stop ()
-{
- struct CheckHelloValidatedContext *chvc;
-
- GNUNET_CONTAINER_multihashmap_iterate (validation_map,
- &cleanup_validation_entry,
- NULL);
- GNUNET_CONTAINER_multihashmap_destroy (validation_map);
- validation_map = NULL;
- GNUNET_assert (GNUNET_CONTAINER_multihashmap_size (notify_map) == 0);
- GNUNET_CONTAINER_multihashmap_destroy (notify_map);
- notify_map = NULL;
- while (NULL != (chvc = chvc_head))
- {
- GNUNET_CONTAINER_DLL_remove (chvc_head,
- chvc_tail,
- chvc);
- GNUNET_PEERINFO_iterate_cancel (chvc->piter);
- GNUNET_free (chvc);
- }
-}
-
-
-/**
- * Address validation cleanup task (record no longer needed).
- *
- * @param cls the 'struct ValidationEntry'
- * @param tc scheduler context (unused)
- */
-static void
-timeout_hello_validation (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ValidationEntry *va = cls;
-
- va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop ("# address records discarded"),
- 1,
- GNUNET_NO);
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (validation_map,
- &va->pid.hashPubKey,
- va));
- GNUNET_free (va->transport_name);
- GNUNET_free (va);
-}
+static struct GNUNET_PEERINFO_NotifyContext *pnc;
/**
}
+/**
+ * Iterator which adds the given address to the set of validated
+ * addresses.
+ *
+ * @param cls original HELLO message
+ * @param tname name of the transport
+ * @param expiration expiration time
+ * @param addr the address
+ * @param addrlen length of the address
+ * @return GNUNET_OK (keep the address)
+ */
+static int
+add_valid_address (void *cls,
+ const char *tname,
+ struct GNUNET_TIME_Absolute expiration,
+ const void *addr,
+ uint16_t addrlen)
+{
+ const struct GNUNET_HELLO_Message *hello = cls;
+ struct ValidationEntry *ve;
+ struct GNUNET_PeerIdentity pid;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
+
+ if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0)
+ return GNUNET_OK; /* expired */
+ if ( (GNUNET_OK !=
+ GNUNET_HELLO_get_id (hello, &pid)) ||
+ (GNUNET_OK !=
+ GNUNET_HELLO_get_key (hello, &public_key)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_OK; /* invalid HELLO !? */
+ }
+
+ ve = find_validation_entry (&public_key, &pid, tname, addr, addrlen);
+ ve->valid_until = GNUNET_TIME_absolute_max (ve->valid_until,
+ expiration);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called for any HELLO known to PEERINFO.
+ *
+ * @param cls unused
+ * @param peer id of the peer, NULL for last call
+ * @param hello hello message for the peer (can be NULL)
+ * @param error message
+ */
+static void
+process_peerinfo_hello (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Message *hello,
+ const char *err_msg)
+{
+ GNUNET_assert (NULL != peer);
+ if (NULL == hello)
+ return;
+ GNUNET_assert (NULL ==
+ GNUNET_HELLO_iterate_addresses (hello,
+ GNUNET_NO,
+ &add_valid_address,
+ (void*) hello));
+}
+
+
+/**
+ * Start the validation subsystem.
+ */
+void
+GST_validation_start ()
+{
+ validation_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE);
+ notify_map = GNUNET_CONTAINER_multihashmap_create (VALIDATION_MAP_SIZE);
+ pnc = GNUNET_PEERINFO_notify (GST_cfg,
+ &process_peerinfo_hello,
+ NULL);
+}
+
+
+/**
+ * Iterate over validation entries and free them.
+ *
+ * @param cls (unused)
+ * @param key peer identity (unused)
+ * @param value a 'struct ValidationEntry' to clean up
+ * @return GNUNET_YES (continue to iterate)
+ */
+static int
+cleanup_validation_entry (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct ValidationEntry *ve = value;
+
+ GNUNET_free (ve->transport_name);
+ if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (ve->timeout_task);
+ ve->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_free (ve);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Stop the validation subsystem.
+ */
+void
+GST_validation_stop ()
+{
+ struct CheckHelloValidatedContext *chvc;
+
+ GNUNET_CONTAINER_multihashmap_iterate (validation_map,
+ &cleanup_validation_entry,
+ NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (validation_map);
+ validation_map = NULL;
+ GNUNET_assert (GNUNET_CONTAINER_multihashmap_size (notify_map) == 0);
+ GNUNET_CONTAINER_multihashmap_destroy (notify_map);
+ notify_map = NULL;
+ while (NULL != (chvc = chvc_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (chvc_head,
+ chvc_tail,
+ chvc);
+ GNUNET_free (chvc);
+ }
+ GNUNET_PEERINFO_notify_cancel (pnc);
+}
+
+
+/**
+ * Address validation cleanup task (record no longer needed).
+ *
+ * @param cls the 'struct ValidationEntry'
+ * @param tc scheduler context (unused)
+ */
+static void
+timeout_hello_validation (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ValidationEntry *va = cls;
+
+ va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop ("# address records discarded"),
+ 1,
+ GNUNET_NO);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (validation_map,
+ &va->pid.hashPubKey,
+ va));
+ GNUNET_free (va->transport_name);
+ GNUNET_free (va);
+}
+
+
/**
* Send the given PONG to the given address.
*
* @param cls the PONG message
+ * @param public_key public key for the peer, never NULL
* @param target peer this change is about, never NULL
* @param valid_until is ZERO if we never validated the address,
* otherwise a time up to when we consider it (or was) valid
*/
static void
multicast_pong (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
const struct GNUNET_PeerIdentity *target,
struct GNUNET_TIME_Absolute valid_until,
struct GNUNET_TIME_Absolute validation_block,
const struct TransportPingMessage *ping;
struct TransportPongMessage *pong;
struct GNUNET_TRANSPORT_PluginFunctions *papi;
+ struct SessionHeader *session_header;
const char *addr;
const char *addrend;
size_t alen;
/* peer wants to confirm that we have an outbound connection to him;
we handle this case here even though it has nothing to do with
address validation (!) */
- if (sender_address == NULL)
+ if ( (sender_address == NULL) || (session == NULL) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
_("Refusing to create PONG since I do initiate the session with `%s'.\n"),
GNUNET_i2s (sender));
return;
}
+ session_header = (struct SessionHeader *)session;
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Creating PONG indicating that we initiated a connection to peer `%s' using address `%s' \n",
memcpy (&((char*)&pong[1])[slen],
sender_address,
sender_address_len);
-#if 0
- /* FIXME: lookup signature! */
if (GNUNET_TIME_absolute_get_remaining (session_header->pong_sig_expires).rel_value <
PONG_SIGNATURE_LIFETIME.rel_value / 4)
{
session_header->pong_sig_expires = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_rsa_sign (my_private_key,
+ GNUNET_CRYPTO_rsa_sign (GST_my_private_key,
&pong->purpose,
&session_header->pong_signature));
}
{
pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
}
- memcpy (&pong->signature,
- &session_header->pong_signature,
- sizeof (struct GNUNET_CRYPTO_RsaSignature));
-#else
- 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,
- &pong->signature));
-#endif
+ pong->signature = session_header->pong_signature;
}
else
{
/* peer wants to confirm that this is one of our addresses, this is what is
used for address validation */
+ struct GNUNET_CRYPTO_RsaSignature *sig_cache;
+ struct GNUNET_TIME_Absolute *sig_cache_exp;
+
addrend = memchr (addr, '\0', alen);
if (NULL == addrend)
{
addrend++;
slen = strlen(addr);
alen -= slen;
- papi = GST_plugins_find (addr);
-
- if ( (NULL == papi) ||
- (GNUNET_OK !=
- papi->check_address (papi->cls,
- addrend,
- alen)) )
+
+ if (GNUNET_YES !=
+ GST_hello_test_address (addr,
+ addrend,
+ alen,
+ &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"),
pong->pid = GST_my_identity;
memcpy (&pong[1], addr, slen);
memcpy (&((char*)&pong[1])[slen], addrend, alen);
-#if 0
- if ( (oal != NULL) &&
- (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).rel_value < PONG_SIGNATURE_LIFETIME.rel_value / 4) )
+ if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value < PONG_SIGNATURE_LIFETIME.rel_value / 4)
{
/* create / update cached sig */
#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Creating PONG signature to indicate ownership.\n");
#endif
- oal->pong_sig_expires = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
- pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_rsa_sign (my_private_key,
- &pong->purpose,
- &oal->pong_signature));
- memcpy (&pong->signature,
- &oal->pong_signature,
- sizeof (struct GNUNET_CRYPTO_RsaSignature));
- }
- else if (oal == NULL)
- {
-#else
- /* not using cache (typically DV-only) */
- pong->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
+ *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,
- &pong->signature));
-#endif
-#if 0
+ sig_cache));
}
else
{
- /* can used cached version */
- pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
- memcpy (&pong->signature,
- &oal->pong_signature,
- sizeof (struct GNUNET_CRYPTO_RsaSignature));
+ pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
}
-#endif
+ pong->signature = *sig_cache;
}
/* first see if the session we got this PING from can be used to transmit
struct ValidationEntry *ve = value;
vic->cb (vic->cb_cls,
+ &ve->public_key,
&ve->pid,
ve->valid_until,
ve->validation_block,