From c457ee81954163e0b7295fbd4a713474b3059abf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 10 Apr 2019 21:53:53 +0200 Subject: send validation challenges --- src/include/gnunet_protocols.h | 12 ++ src/transport/gnunet-service-tng.c | 276 ++++++++++++++++++++++++------------- src/transport/transport.h | 2 +- 3 files changed, 191 insertions(+), 99 deletions(-) diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 4f97d3078..f461249eb 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -3196,6 +3196,18 @@ extern "C" #define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION 1302 +/** + * P2P message: transport requests confirmation that an address works. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE 1303 + +/** + * P2P message: transport proves that an address worked. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE 1304 + + + /* ************** NEW (NG) ATS Messages ************* */ /* NOTE: it is not clear ATS will survive in TNG */ diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 937ae249e..e685e28a6 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -553,7 +553,7 @@ struct TransportValidationChallenge { /** - * Type is #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE + * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE */ struct GNUNET_MessageHeader header; @@ -609,7 +609,7 @@ struct TransportValidationResponse { /** - * Type is #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_RESPONSE + * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE */ struct GNUNET_MessageHeader header; @@ -3802,7 +3802,7 @@ handle_dv_box (void *cls, cmc->im.sender = dvb->origin; cmc->total_hops = ntohs (dvb->total_hops); demultiplex_with_cmc (cmc, - inbox); + inbox); } @@ -3829,6 +3829,41 @@ check_incoming_msg (void *cls, } +/** + * Communicator gave us a transport address validation challenge. Process the request. + * + * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) + * @param tvc the message that was received + */ +static void +handle_validation_challenge (void *cls, + const struct TransportValidationChallenge *tvc) +{ + struct CommunicatorMessageContext *cmc = cls; + + // FIXME: sign challenge and try to get it back to the origin! + finish_cmc_handling (cmc); +} + + +/** + * Communicator gave us a transport address validation response. Process the request. + * + * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) + * @param tvr the message that was received + */ +static void +handle_validation_response (void *cls, + const struct TransportValidationResponse *tvr) +{ + struct CommunicatorMessageContext *cmc = cls; + + // FIXME: check for matching pending challenge and mark address + // as valid if applicable (passing to PEERSTORE as well!) + finish_cmc_handling (cmc); +} + + /** * Incoming meessage. Process the request. * @@ -3844,7 +3879,7 @@ handle_incoming_msg (void *cls, cmc->tc = tc; cmc->im = *im; demultiplex_with_cmc (cmc, - (const struct GNUNET_MessageHeader *) &im[1]); + (const struct GNUNET_MessageHeader *) &im[1]); } @@ -3857,43 +3892,51 @@ handle_incoming_msg (void *cls, */ static void demultiplex_with_cmc (struct CommunicatorMessageContext *cmc, - const struct GNUNET_MessageHeader *msg) + const struct GNUNET_MessageHeader *msg) { struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size (fragment_box, - GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, - struct TransportFragmentBox, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, + struct TransportFragmentBox, + &cmc), GNUNET_MQ_hd_fixed_size (fragment_ack, - GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK, - struct TransportFragmentAckMessage, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK, + struct TransportFragmentAckMessage, + &cmc), GNUNET_MQ_hd_var_size (reliability_box, - GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, - struct TransportReliabilityBox, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, + struct TransportReliabilityBox, + &cmc), GNUNET_MQ_hd_fixed_size (reliability_ack, - GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, - struct TransportReliabilityAckMessage, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, + struct TransportReliabilityAckMessage, + &cmc), GNUNET_MQ_hd_var_size (backchannel_encapsulation, - GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, - struct TransportBackchannelEncapsulationMessage, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, + struct TransportBackchannelEncapsulationMessage, + &cmc), GNUNET_MQ_hd_var_size (dv_learn, - GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, - struct TransportDVLearn, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, + struct TransportDVLearn, + &cmc), GNUNET_MQ_hd_var_size (dv_box, - GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, - struct TransportDVBox, - &cmc), + GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, + struct TransportDVBox, + &cmc), + GNUNET_MQ_hd_fixed_size (validation_challenge, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE, + struct TransportValidationChallenge, + &cmc), + GNUNET_MQ_hd_fixed_size (validation_response, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, + struct TransportValidationResponse, + &cmc), GNUNET_MQ_handler_end() }; int ret; ret = GNUNET_MQ_handle_message (handlers, - msg); + msg); if (GNUNET_SYSERR == ret) { GNUNET_break (0); @@ -3905,7 +3948,7 @@ demultiplex_with_cmc (struct CommunicatorMessageContext *cmc, { /* unencapsulated 'raw' message */ handle_raw_message (&cmc, - msg); + msg); } } @@ -4145,7 +4188,6 @@ transmit_on_queue (void *cls) { struct Queue *queue = cls; struct Neighbour *n = queue->neighbour; - struct QueueEntry *qe; struct PendingMessage *pm; struct PendingMessage *s; uint32_t overhead; @@ -4191,27 +4233,32 @@ transmit_on_queue (void *cls) } /* Pass 's' for transission to the communicator */ - qe = GNUNET_new (struct QueueEntry); - qe->mid = queue->mid_gen++; - qe->queue = queue; - // qe->pm = s; // FIXME: not so easy, reference management on 'free(s)'! - GNUNET_CONTAINER_DLL_insert (queue->queue_head, - queue->queue_tail, - qe); env = GNUNET_MQ_msg_extra (smt, - s->bytes_msg, - GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG); + s->bytes_msg, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG); smt->qid = queue->qid; - smt->mid = qe->mid; + smt->mid = queue->mid_gen; smt->receiver = n->pid; memcpy (&smt[1], &s[1], s->bytes_msg); - GNUNET_assert (CT_COMMUNICATOR == queue->tc->type); - queue->queue_length++; - queue->tc->details.communicator.total_queue_length++; - GNUNET_MQ_send (queue->tc->mq, - env); + { + /* Pass the env to the communicator of queue for transmission. */ + struct QueueEntry *qe; + + qe = GNUNET_new (struct QueueEntry); + qe->mid = queue->mid_gen++; + qe->queue = queue; + // qe->pm = s; // FIXME: not so easy, reference management on 'free(s)'! + GNUNET_CONTAINER_DLL_insert (queue->queue_head, + queue->queue_tail, + qe); + GNUNET_assert (CT_COMMUNICATOR == queue->tc->type); + queue->queue_length++; + queue->tc->details.communicator.total_queue_length++; + GNUNET_MQ_send (queue->tc->mq, + env); + } // FIXME: do something similar to the logic below // in defragmentation / reliability ACK handling! @@ -4719,13 +4766,17 @@ static void validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs) { - struct TransportValidationChallenge tvc; + struct GNUNET_MQ_Envelope *env; + struct TransportValidationChallenge *tvc; vs->last_challenge_use = GNUNET_TIME_absolute_get (); - tvc.reserved = htonl (0); - tvc.challenge = vs->challenge; - tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use); - // FIXME: actually send on queue! + env = GNUNET_MQ_msg (tvc, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE); + tvc->reserved = htonl (0); + tvc->challenge = vs->challenge; + tvc->sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use); + GNUNET_MQ_send (q->tc->mq, + env); } @@ -5163,75 +5214,58 @@ check_known_address (void *cls, /** - * Given another peers address, consider checking it for validity - * and then adding it to the Peerstore. + * Start address validation. * - * @param cls a `struct TransportClient` - * @param hdr message containing the raw address data and - * signature in the body, see #GNUNET_HELLO_extract_address() + * @param pid peer the @a address is for + * @param address an address to reach @a pid (presumably) + * @param expiration when did @a pid claim @a address will become invalid + * @param nt network type of @a address */ static void -handle_address_consider_verify (void *cls, - const struct GNUNET_TRANSPORT_AddressToVerify *hdr) +start_address_validation (const struct GNUNET_PeerIdentity *pid, + const char *address, + struct GNUNET_TIME_Absolute expiration, + enum GNUNET_NetworkType nt) { - char *address; - enum GNUNET_NetworkType nt; - struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Absolute now; struct ValidationState *vs; + struct CheckKnownAddressContext ckac = { + .address = address, + .vs = NULL + }; + - (void) cls; - // FIXME: checking that we know this address already should - // be done BEFORE checking the signature => HELLO API change! - // FIXME: pre-check: rate-limit signature verification / validation?! - address = GNUNET_HELLO_extract_address (&hdr[1], - ntohs (hdr->header.size) - sizeof (*hdr), - &hdr->peer, - &nt, - &expiration); - if (NULL == address) - { - GNUNET_break_op (0); - return; - } if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) return; /* expired */ - { - struct CheckKnownAddressContext ckac = { - .address = address, - .vs = NULL - }; - (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, - &hdr->peer, - &check_known_address, - &ckac); - if (NULL != (vs = ckac.vs)) + (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, + pid, + &check_known_address, + &ckac); + if (NULL != (vs = ckac.vs)) + { + /* if 'vs' is not currently valid, we need to speed up retrying the validation */ + if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) { - /* if 'vs' is not currently valid, we need to speed up retrying the validation */ - if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) - { - /* reduce backoff as we got a fresh advertisement */ - vs->challenge_backoff = GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ, - GNUNET_TIME_relative_divide (vs->challenge_backoff, - 2)); - update_next_challenge_time (vs, - GNUNET_TIME_relative_to_absolute (vs->challenge_backoff)); - } - GNUNET_free (address); - return; + /* reduce backoff as we got a fresh advertisement */ + vs->challenge_backoff = GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ, + GNUNET_TIME_relative_divide (vs->challenge_backoff, + 2)); + update_next_challenge_time (vs, + GNUNET_TIME_relative_to_absolute (vs->challenge_backoff)); } + return; } now = GNUNET_TIME_absolute_get(); vs = GNUNET_new (struct ValidationState); - vs->pid = hdr->peer; + vs->pid = *pid; vs->valid_until = expiration; vs->first_challenge_use = now; vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &vs->challenge, sizeof (vs->challenge)); - vs->address = address; + vs->address = GNUNET_strdup (address); vs->nt = nt; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (validation_map, @@ -5243,6 +5277,46 @@ handle_address_consider_verify (void *cls, } +/** + * Given another peers address, consider checking it for validity + * and then adding it to the Peerstore. + * + * @param cls a `struct TransportClient` + * @param hdr message containing the raw address data and + * signature in the body, see #GNUNET_HELLO_extract_address() + */ +static void +handle_address_consider_verify (void *cls, + const struct GNUNET_TRANSPORT_AddressToVerify *hdr) +{ + struct TransportClient *tc = cls; + char *address; + enum GNUNET_NetworkType nt; + struct GNUNET_TIME_Absolute expiration; + + (void) cls; + // FIXME: checking that we know this address already should + // be done BEFORE checking the signature => HELLO API change! + // FIXME: pre-check: rate-limit signature verification / validation?! + address = GNUNET_HELLO_extract_address (&hdr[1], + ntohs (hdr->header.size) - sizeof (*hdr), + &hdr->peer, + &nt, + &expiration); + if (NULL == address) + { + GNUNET_break_op (0); + return; + } + start_address_validation (&hdr->peer, + address, + expiration, + nt); + GNUNET_free (address); + GNUNET_SERVICE_client_continue (tc->client); +} + + /** * Check #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION * messages. @@ -5271,7 +5345,13 @@ static void handle_request_hello_validation (void *cls, const struct RequestHelloValidationMessage *m) { - // FIXME: implement validation! + struct TransportClient *tc = cls; + + start_address_validation (&m->peer, + (const char *) &m[1], + GNUNET_TIME_absolute_ntoh (m->expiration), + (enum GNUNET_NetworkType) ntohl (m->nt)); + GNUNET_SERVICE_client_continue (tc->client); } diff --git a/src/transport/transport.h b/src/transport/transport.h index fe1044383..7e0d9c2d4 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -1146,7 +1146,7 @@ struct ExpressPreferenceMessage struct RequestHelloValidationMessage { - /** + /** * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION. */ struct GNUNET_MessageHeader header; -- cgit v1.2.3