From aad2f0838ef0586366fe4e3921013b7af6a4ea65 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 6 Aug 2011 18:47:22 +0000 Subject: [PATCH] send validation PING --- .../gnunet-service-transport_clients.c | 8 +- .../gnunet-service-transport_validation.c | 150 ++++++++++++++++-- .../gnunet-service-transport_validation.h | 7 +- 3 files changed, 145 insertions(+), 20 deletions(-) diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c index 3b42c7a79..454f544fd 100644 --- a/src/transport/gnunet-service-transport_clients.c +++ b/src/transport/gnunet-service-transport_clients.c @@ -592,9 +592,7 @@ GST_clients_handle_address_lookup (void *cls, * * @param cls our 'struct GNUNET_SERVER_TransmitContext' (for sending) * @param target peer this change is about, never NULL - * @param last_validated_at is FOREVER if the address has not been validated (we're currently checking) - * is ZERO if the address was validated a long time ago (from PEERINFO) - * is a time in the past if this process validated the address + * @param valid_until until what time do we consider the address valid? * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO) * is ZERO if the address is considered valid (no validation needed) * is a time in the future if we're currently denying re-validation @@ -605,7 +603,7 @@ GST_clients_handle_address_lookup (void *cls, static void send_address_to_client (void *cls, const struct GNUNET_PeerIdentity *target, - struct GNUNET_TIME_Absolute last_validated_at, + struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const char *plugin_name, const void *plugin_address, @@ -622,7 +620,7 @@ send_address_to_client (void *cls, (GNUNET_YES == GST_neighbours_test_connected (target)) ? "CONNECTED" : "DISCONNECTED", - (last_validated_at.abs_value < GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) + (GNUNET_TIME_absolute_get_remaining (valid_until).rel_value > 0) ? "VALIDATED" : "UNVALIDATED"); transmit_address_to_client (tc, addr_buf); diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index 23140b7c3..9a8bf0b47 100644 --- a/src/transport/gnunet-service-transport_validation.c +++ b/src/transport/gnunet-service-transport_validation.c @@ -25,10 +25,12 @@ */ #include "platform.h" #include "gnunet-service-transport_validation.h" +#include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport.h" #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" + /** * How long until a HELLO verification attempt should time out? * Must be rather small, otherwise a partially successful HELLO @@ -55,7 +57,6 @@ */ #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) - /** * How long before an existing address expires should we again try to * validate it? Must be (significantly) smaller than @@ -63,11 +64,107 @@ */ #define HELLO_REVALIDATION_START_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1) +/** + * How long before we try to check an address again (if it turned out to + * be invalid the first time)? + */ +#define MAX_REVALIDATION_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1) + /** * Size of the validation map hashmap. */ #define VALIDATION_MAP_SIZE 256 +/** + * Priority to use for PINGs and PONGs + */ +#define PING_PRIORITY 1 + +/** + * Message used to ask a peer to validate receipt (to check an address + * from a HELLO). Followed by the address we are trying to validate, + * or an empty address if we are just sending a PING to confirm that a + * connection which the receiver (of the PING) initiated is still valid. + */ +struct TransportPingMessage +{ + + /** + * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING + */ + struct GNUNET_MessageHeader header; + + /** + * Challenge code (to ensure fresh reply). + */ + uint32_t challenge GNUNET_PACKED; + + /** + * Who is the intended recipient? + */ + struct GNUNET_PeerIdentity target; + +}; + + +/** + * Message used to validate a HELLO. The challenge is included in the + * confirmation to make matching of replies to requests possible. The + * signature signs our public key, an expiration time and our address.

+ * + * This message is followed by our transport address that the PING tried + * to confirm (if we liked it). The address can be empty (zero bytes) + * if the PING had not address either (and we received the request via + * a connection that we initiated). + */ +struct TransportPongMessage +{ + + /** + * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG + */ + struct GNUNET_MessageHeader header; + + /** + * Challenge code from PING (showing freshness). Not part of what + * is signed so that we can re-use signatures. + */ + uint32_t challenge GNUNET_PACKED; + + /** + * Signature. + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * What are we signing and why? Two possible reason codes can be here: + * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a + * plausible address for this peer (pid is set to identity of signer); or + * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING to confirm that this is + * an address we used to connect to the peer with the given pid. + */ + struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; + + /** + * When does this signature expire? + */ + struct GNUNET_TIME_AbsoluteNBO expiration; + + /** + * Either the identity of the peer Who signed this message, or the + * identity of the peer that we're connected to using the given + * address (depending on purpose.type). + */ + struct GNUNET_PeerIdentity pid; + + /** + * Size of address appended to this message (part of what is + * being signed, hence not redundant). + */ + uint32_t addrlen; + +}; + /** * Information about an address under validation @@ -102,12 +199,10 @@ struct ValidationEntry struct GNUNET_TIME_Absolute send_time; /** - * When did we last succeed with validating this address? - * FOREVER if the address has not been validated (we're currently checking) - * ZERO if the address was validated a long time ago (from PEERINFO) - * otherwise a time in the past if this process validated the address + * Until when is this address valid? + * ZERO if it is not currently considered valid. */ - struct GNUNET_TIME_Absolute last_validated_at; + struct GNUNET_TIME_Absolute valid_until; /** * How long until we can try to validate this address again? @@ -367,9 +462,10 @@ find_validation_entry (struct GNUNET_PeerIdentity *neighbour, ve->transport_name = GNUNET_strdup (tname); ve->addr = (void*) &ve[1]; ve->pid = *neighbour; + ve->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + UINT32_MAX); memcpy (&ve[1], addr, addrlen); ve->addrlen = addrlen; - ve->last_validated_at = GNUNET_TIME_UNIT_FOREVER_ABS; GNUNET_CONTAINER_multihashmap_put (validation_map, &neighbour->hashPubKey, ve, @@ -439,12 +535,44 @@ validate_address (void *cls, { struct GNUNET_PeerIdentity *pid = cls; struct ValidationEntry *ve; - + struct TransportPingMessage ping; + struct GNUNET_TRANSPORT_PluginFunctions *papi; + ssize_t ret; + if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0) return GNUNET_OK; /* expired */ ve = find_validation_entry (pid, tname, addr, addrlen); - // FIXME: check if validated/blocked, if not start validation... - ve++; // make compiler happy + if (GNUNET_TIME_absolute_get_remaining (ve->validation_block).rel_value > 0) + return GNUNET_OK; /* blocked */ + if (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value > 0) + return GNUNET_OK; /* valid */ + ve->validation_block = GNUNET_TIME_relative_to_absolute (MAX_REVALIDATION_FREQUENCY); + + ping.header.size = htons(sizeof(struct TransportPingMessage)); + ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING); + ping.challenge = htonl(ve->challenge); + ping.target = *pid; + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# PING without HELLO messages sent"), + 1, + GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting plain PING to `%s'\n", + GNUNET_i2s (pid)); + papi = GST_plugins_find (ve->transport_name); + ret = papi->send (papi->cls, + pid, + (const char*) &ping, + sizeof (struct TransportPingMessage), + PING_PRIORITY, + HELLO_VERIFICATION_TIMEOUT, + NULL /* no session */, + ve->addr, + ve->addrlen, + GNUNET_YES, + NULL, NULL); + if (-1 != ret) + ve->send_time = GNUNET_TIME_absolute_get (); return GNUNET_OK; } @@ -517,7 +645,7 @@ iterate_addresses (void *cls, vic->cb (vic->cb_cls, &ve->pid, - ve->last_validated_at, + ve->valid_until, ve->validation_block, ve->transport_name, ve->addr, diff --git a/src/transport/gnunet-service-transport_validation.h b/src/transport/gnunet-service-transport_validation.h index 17f4a1cd7..218b45457 100644 --- a/src/transport/gnunet-service-transport_validation.h +++ b/src/transport/gnunet-service-transport_validation.h @@ -103,9 +103,8 @@ struct GST_ValidationIteratorContext; * * @param cls closure * @param target peer this change is about, never NULL - * @param last_validated_at is FOREVER if the address has not been validated (we're currently checking) - * is ZERO if the address was validated a long time ago (from PEERINFO) - * otherwise a time in the past if this process validated the address + * @param valid_until is ZERO if we never validated the address, + * otherwise a time up to when we consider it (or was) valid * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO) * is ZERO if the address is considered valid (no validation needed) * otherwise a time in the future if we're currently denying re-validation @@ -115,7 +114,7 @@ struct GST_ValidationIteratorContext; */ typedef void (*GST_ValidationAddressCallback)(void *cls, const struct GNUNET_PeerIdentity *target, - struct GNUNET_TIME_Absolute last_validated_at, + struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const char *plugin_name, const void *plugin_address, -- 2.25.1