X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=inline;f=src%2Ftransport%2Fgnunet-service-transport_validation.c;h=e61d1337d1c9130d3281b5ea24aa6ec1b6b04cdd;hb=86be3237abd7ff9bf06f1911802e8a38fb985650;hp=83940d43d1bddebe88220765b826526f00bdffb4;hpb=5b9e61b9c3832e69164ee8574fff6711b2f18ef6;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index 83940d43d..e61d1337d 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_YES /** * How long is a PONG signature valid? We'll recycle a signature until @@ -251,6 +252,10 @@ struct ValidationEntry * Are we expecting a PONG message for this validation entry? */ int expecting_pong; + + /* FIXME: DEBUGGING */ + int last_line_set_to_no; + int last_line_set_to_yes; }; @@ -330,7 +335,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; @@ -353,7 +358,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; @@ -435,8 +440,8 @@ 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)); + 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); slen = strlen (ve->address->transport_name) + 1; hello = GST_hello_get (); @@ -474,7 +479,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; @@ -486,7 +491,7 @@ transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, if (session != NULL) { - ret = papi->send_with_session (papi->cls, session, + ret = papi->send (papi->cls, session, message_buf, tsize, PING_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); @@ -494,9 +499,8 @@ transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, else { /* Could not get a valid session */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not get a valid session for `%s' %s\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not get a valid session for `%s' %s\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address)); - GNUNET_break (0); ret = -1; } } @@ -601,6 +605,9 @@ find_validation_entry (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded if (public_key == NULL) return NULL; ve = GNUNET_malloc (sizeof (struct ValidationEntry)); + ve->in_use = GNUNET_SYSERR; /* not defined */ + ve->last_line_set_to_no = 0; + ve->last_line_set_to_yes = 0; ve->address = GNUNET_HELLO_address_copy (address); ve->public_key = *public_key; ve->pid = address->peer; @@ -655,7 +662,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; } @@ -751,7 +758,7 @@ multicast_pong (void *cls, return; } - papi->send_with_session (papi->cls, session, + papi->send (papi->cls, session, (const char *) pong, ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); @@ -782,6 +789,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)) @@ -825,15 +833,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 @@ -859,26 +897,63 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, pong->challenge = 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) +#if KEEP_093_COMPATIBILITY + if (GNUNET_YES == buggy) { - /* create / update cached sig */ -#if DEBUG_TRANSPORT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating PONG signature to indicate ownership.\n"); -#endif - *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, alen); + 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 + 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 (GNUNET_OK == GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, + &pong->purpose, &pong->signature, + &GST_my_public_key)); + + GNUNET_assert (sender_address != NULL); /* first see if the session we got this PING from can be used to transmit * a response reliably */ @@ -890,7 +965,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, GNUNET_assert (papi->send != NULL); GNUNET_assert (papi->get_session != NULL); - if ((session == NULL) && (sender_address != NULL)) + if (session == NULL) { session = papi->get_session (papi->cls, sender_address); } @@ -901,7 +976,7 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, } else { - ret = papi->send_with_session (papi->cls, session, + ret = papi->send (papi->cls, session, (const char *) pong, ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); @@ -1075,28 +1150,23 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, GNUNET_NO); return; } -#if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Address validated for peer `%s' with plugin `%s': `%s'\n", - GNUNET_i2s (sender), tname, GST_plugins_a2s (tname, addr, - addrlen)); -#endif - + GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address)); /* validity achieved, remember it! */ ve->expecting_pong = GNUNET_NO; ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); 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; hello = GNUNET_HELLO_create (&ve->public_key, &add_valid_peer_address, ve); - GNUNET_PEERINFO_add_peer (GST_peerinfo, hello); + GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL); GNUNET_free (hello); } @@ -1127,12 +1197,12 @@ GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello) return; /* Add peer identity without addresses to peerinfo service */ h = GNUNET_HELLO_create (&vac.public_key, NULL, NULL); - GNUNET_PEERINFO_add_peer (GST_peerinfo, h); -#if VERBOSE_VALIDATION + GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL); + 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, @@ -1168,7 +1238,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; @@ -1210,11 +1280,13 @@ GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, * @param session the session * @param in_use GNUNET_YES if we are now using the address for a connection, * GNUNET_NO if we are no longer using the address for a connection + * @param line line of caller just for DEBUGGING! */ void GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, struct Session *session, - int in_use) + int in_use, + int line) { struct ValidationEntry *ve; @@ -1228,10 +1300,33 @@ GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, return; } if (ve->in_use == in_use) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "GST_validation_set_address_use: %s %s: ve->in_use %i <-> in_use %i\n", - GNUNET_i2s (&address->peer), GST_plugins_a2s (address), ve->in_use, - in_use); + { + + if (GNUNET_YES == in_use) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error setting address in use for peer `%s' `%s' to USED: set last time by %i, called now by %i\n", + GNUNET_i2s (&address->peer), GST_plugins_a2s (address), + ve->last_line_set_to_yes, line); + } + if (GNUNET_NO == in_use) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error setting address in use for peer `%s' `%s' to NOT_USED: set last time by %i, called now by %i\n", + GNUNET_i2s (&address->peer), GST_plugins_a2s (address), + ve->last_line_set_to_no, line); + } + } + + if (GNUNET_YES == in_use) + { + ve->last_line_set_to_yes = line; + } + if (GNUNET_NO == in_use) + { + ve->last_line_set_to_no = line; + } + GNUNET_break (ve->in_use != in_use); /* should be different... */ ve->in_use = in_use; if (in_use == GNUNET_YES)