aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_crypto_lib.h12
-rw-r--r--src/transport/gnunet-service-tng.c289
2 files changed, 228 insertions, 73 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 257fee48d..6822de2f1 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1955,7 +1955,7 @@ GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *ke
1955 */ 1955 */
1956struct GNUNET_CRYPTO_RsaPublicKey * 1956struct GNUNET_CRYPTO_RsaPublicKey *
1957GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, 1957GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
1958 size_t len); 1958 size_t len);
1959 1959
1960 1960
1961/** 1961/**
@@ -1977,7 +1977,7 @@ GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key);
1977 */ 1977 */
1978int 1978int
1979GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1, 1979GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
1980 struct GNUNET_CRYPTO_RsaSignature *s2); 1980 struct GNUNET_CRYPTO_RsaSignature *s2);
1981 1981
1982/** 1982/**
1983 * Compare the values of two private keys. 1983 * Compare the values of two private keys.
@@ -1988,7 +1988,7 @@ GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
1988 */ 1988 */
1989int 1989int
1990GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1, 1990GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
1991 struct GNUNET_CRYPTO_RsaPrivateKey *p2); 1991 struct GNUNET_CRYPTO_RsaPrivateKey *p2);
1992 1992
1993 1993
1994/** 1994/**
@@ -2000,7 +2000,7 @@ GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
2000 */ 2000 */
2001int 2001int
2002GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1, 2002GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
2003 struct GNUNET_CRYPTO_RsaPublicKey *p2); 2003 struct GNUNET_CRYPTO_RsaPublicKey *p2);
2004 2004
2005 2005
2006/** 2006/**
@@ -2065,7 +2065,7 @@ GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig);
2065 */ 2065 */
2066size_t 2066size_t
2067GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig, 2067GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
2068 char **buffer); 2068 char **buffer);
2069 2069
2070 2070
2071/** 2071/**
@@ -2078,7 +2078,7 @@ GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig
2078 */ 2078 */
2079struct GNUNET_CRYPTO_RsaSignature * 2079struct GNUNET_CRYPTO_RsaSignature *
2080GNUNET_CRYPTO_rsa_signature_decode (const char *buf, 2080GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
2081 size_t len); 2081 size_t len);
2082 2082
2083 2083
2084/** 2084/**
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index e685e28a6..ecff6b6e1 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -138,6 +138,10 @@
138 * When do we forget an invalid address for sure? 138 * When do we forget an invalid address for sure?
139 */ 139 */
140#define MAX_ADDRESS_VALID_UNTIL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1) 140#define MAX_ADDRESS_VALID_UNTIL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
141/**
142 * How long do we consider an address valid if we just checked?
143 */
144#define ADDRESS_VALIDATION_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
141 145
142/** 146/**
143 * What is the maximum frequency at which we do address validation? 147 * What is the maximum frequency at which we do address validation?
@@ -148,6 +152,14 @@
148#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS 152#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
149 153
150/** 154/**
155 * How many network RTTs before an address validation expires should we begin
156 * trying to revalidate? (Note that the RTT used here is the one that we
157 * experienced during the last validation, not necessarily the latest RTT
158 * observed).
159 */
160#define VALIDATION_RTT_BUFFER_FACTOR 3
161
162/**
151 * How many messages can we have pending for a given communicator 163 * How many messages can we have pending for a given communicator
152 * process before we start to throttle that communicator? 164 * process before we start to throttle that communicator?
153 * 165 *
@@ -1597,8 +1609,8 @@ struct ValidationState
1597 * Next time we will send the @e challenge to the peer, if this time is past 1609 * Next time we will send the @e challenge to the peer, if this time is past
1598 * @e valid_until, this validation state is released at this time. If the 1610 * @e valid_until, this validation state is released at this time. If the
1599 * address is valid, @e next_challenge is set to @e validated_until MINUS @e 1611 * address is valid, @e next_challenge is set to @e validated_until MINUS @e
1600 * validation_delay * 3, such that we will try to re-validate before the 1612 * validation_delay * #VALIDATION_RTT_BUFFER_FACTOR, such that we will try
1601 * validity actually expires. 1613 * to re-validate before the validity actually expires.
1602 */ 1614 */
1603 struct GNUNET_TIME_Absolute next_challenge; 1615 struct GNUNET_TIME_Absolute next_challenge;
1604 1616
@@ -3051,10 +3063,13 @@ store_pi (void *cls);
3051 3063
3052/** 3064/**
3053 * Function called when peerstore is done storing our address. 3065 * Function called when peerstore is done storing our address.
3066 *
3067 * @param cls a `struct AddressListEntry`
3068 * @param success #GNUNET_YES if peerstore was successful
3054 */ 3069 */
3055static void 3070static void
3056peerstore_store_cb (void *cls, 3071peerstore_store_own_cb (void *cls,
3057 int success) 3072 int success)
3058{ 3073{
3059 struct AddressListEntry *ale = cls; 3074 struct AddressListEntry *ale = cls;
3060 3075
@@ -3081,29 +3096,20 @@ static void
3081store_pi (void *cls) 3096store_pi (void *cls)
3082{ 3097{
3083 struct AddressListEntry *ale = cls; 3098 struct AddressListEntry *ale = cls;
3084 void *addr;
3085 size_t addr_len;
3086 struct GNUNET_TIME_Absolute expiration; 3099 struct GNUNET_TIME_Absolute expiration;
3087 3100
3088 ale->st = NULL; 3101 ale->st = NULL;
3089 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration); 3102 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
3090 GNUNET_HELLO_sign_address (ale->address,
3091 ale->nt,
3092 expiration,
3093 GST_my_private_key,
3094 &addr,
3095 &addr_len);
3096 ale->sc = GNUNET_PEERSTORE_store (peerstore, 3103 ale->sc = GNUNET_PEERSTORE_store (peerstore,
3097 "transport", 3104 "transport",
3098 &GST_my_identity, 3105 &GST_my_identity,
3099 GNUNET_HELLO_PEERSTORE_KEY, 3106 GNUNET_HELLO_PEERSTORE_KEY,
3100 addr, 3107 ale->address,
3101 addr_len, 3108 strlen (ale->address) + 1,
3102 expiration, 3109 expiration,
3103 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, 3110 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
3104 &peerstore_store_cb, 3111 &peerstore_store_own_cb,
3105 ale); 3112 ale);
3106 GNUNET_free (addr);
3107 if (NULL == ale->sc) 3113 if (NULL == ale->sc)
3108 { 3114 {
3109 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3115 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -3847,6 +3853,120 @@ handle_validation_challenge (void *cls,
3847 3853
3848 3854
3849/** 3855/**
3856 * Closure for #check_known_challenge.
3857 */
3858struct CheckKnownChallengeContext
3859{
3860 /**
3861 * Set to the challenge we are looking for.
3862 */
3863 const struct GNUNET_ShortHashCode *challenge;
3864
3865 /**
3866 * Set to a matching validation state, if one was found.
3867 */
3868 struct ValidationState *vs;
3869};
3870
3871
3872/**
3873 * Test if the validation state in @a value matches the
3874 * challenge from @a cls.
3875 *
3876 * @param cls a `struct CheckKnownChallengeContext`
3877 * @param pid unused (must match though)
3878 * @param value a `struct ValidationState`
3879 * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
3880 */
3881static int
3882check_known_challenge (void *cls,
3883 const struct GNUNET_PeerIdentity *pid,
3884 void *value)
3885{
3886 struct CheckKnownChallengeContext *ckac = cls;
3887 struct ValidationState *vs = value;
3888
3889 (void) pid;
3890 if (0 != GNUNET_memcmp (&vs->challenge,
3891 ckac->challenge))
3892 return GNUNET_OK;
3893 ckac->vs = vs;
3894 return GNUNET_NO;
3895}
3896
3897
3898/**
3899 * Function called when peerstore is done storing a
3900 * validated address.
3901 *
3902 * @param cls a `struct ValidationState`
3903 * @param success #GNUNET_YES on success
3904 */
3905static void
3906peerstore_store_validation_cb (void *cls,
3907 int success)
3908{
3909 struct ValidationState *vs = cls;
3910
3911 vs->sc = NULL;
3912 if (GNUNET_YES == success)
3913 return;
3914 GNUNET_STATISTICS_update (GST_stats,
3915 "# Peerstore failed to store foreign address",
3916 1,
3917 GNUNET_NO);
3918}
3919
3920
3921/**
3922 * Task run periodically to validate some address based on #validation_heap.
3923 *
3924 * @param cls NULL
3925 */
3926static void
3927validation_start_cb (void *cls);
3928
3929
3930/**
3931 * Set the time for next_challenge of @a vs to @a new_time.
3932 * Updates the heap and if necessary reschedules the job.
3933 *
3934 * @param vs validation state to update
3935 * @param new_time new time for revalidation
3936 */
3937static void
3938update_next_challenge_time (struct ValidationState *vs,
3939 struct GNUNET_TIME_Absolute new_time)
3940{
3941 struct GNUNET_TIME_Relative delta;
3942
3943 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
3944 return; /* be lazy */
3945 vs->next_challenge = new_time;
3946 if (NULL == vs->hn)
3947 vs->hn = GNUNET_CONTAINER_heap_insert (validation_heap,
3948 vs,
3949 new_time.abs_value_us);
3950 else
3951 GNUNET_CONTAINER_heap_update_cost (vs->hn,
3952 new_time.abs_value_us);
3953 if ( (vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
3954 (NULL != validation_task) )
3955 return;
3956 if (NULL != validation_task)
3957 GNUNET_SCHEDULER_cancel (validation_task);
3958 /* randomize a bit */
3959 delta.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
3960 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
3961 new_time = GNUNET_TIME_absolute_add (new_time,
3962 delta);
3963 validation_task = GNUNET_SCHEDULER_add_at (new_time,
3964 &validation_start_cb,
3965 NULL);
3966}
3967
3968
3969/**
3850 * Communicator gave us a transport address validation response. Process the request. 3970 * Communicator gave us a transport address validation response. Process the request.
3851 * 3971 *
3852 * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done) 3972 * @param cls a `struct CommunicatorMessageContext` (must call #finish_cmc_handling() when done)
@@ -3857,9 +3977,92 @@ handle_validation_response (void *cls,
3857 const struct TransportValidationResponse *tvr) 3977 const struct TransportValidationResponse *tvr)
3858{ 3978{
3859 struct CommunicatorMessageContext *cmc = cls; 3979 struct CommunicatorMessageContext *cmc = cls;
3980 struct ValidationState *vs;
3981 struct CheckKnownChallengeContext ckac = {
3982 .challenge = &tvr->challenge,
3983 .vs = NULL
3984 };
3985 struct GNUNET_TIME_Absolute origin_time;
3860 3986
3861 // FIXME: check for matching pending challenge and mark address 3987 /* check this is one of our challenges */
3862 // as valid if applicable (passing to PEERSTORE as well!) 3988 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
3989 &cmc->im.sender,
3990 &check_known_challenge,
3991 &ckac);
3992 if (NULL == (vs = ckac.vs))
3993 {
3994 /* This can happen simply if we 'forgot' the challenge by now,
3995 i.e. because we received the validation response twice */
3996 GNUNET_STATISTICS_update (GST_stats,
3997 "# Validations dropped, challenge unknown",
3998 1,
3999 GNUNET_NO);
4000 finish_cmc_handling (cmc);
4001 return;
4002 }
4003
4004 /* sanity check on origin time */
4005 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
4006 if ( (origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
4007 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us) )
4008 {
4009 GNUNET_break_op (0);
4010 finish_cmc_handling (cmc);
4011 return;
4012 }
4013
4014 {
4015 /* check signature */
4016 struct TransportValidationPS tvp = {
4017 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
4018 .purpose.size = htonl (sizeof (tvp)),
4019 .validity_duration = tvr->validity_duration,
4020 .challenge = tvr->challenge
4021 };
4022
4023 if (GNUNET_OK !=
4024 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE,
4025 &tvp.purpose,
4026 &tvr->signature,
4027 &cmc->im.sender.public_key))
4028 {
4029 GNUNET_break_op (0);
4030 finish_cmc_handling (cmc);
4031 return;
4032 }
4033 }
4034
4035 /* validity is capped by our willingness to keep track of the
4036 validation entry and the maximum the other peer allows */
4037 vs->valid_until
4038 = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_min (GNUNET_TIME_relative_ntoh (tvr->validity_duration),
4039 MAX_ADDRESS_VALID_UNTIL));
4040 vs->validated_until
4041 = GNUNET_TIME_absolute_min (vs->valid_until,
4042 GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME));
4043 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
4044 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
4045 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4046 &vs->challenge,
4047 sizeof (vs->challenge));
4048 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (vs->validated_until,
4049 GNUNET_TIME_relative_multiply (vs->validation_rtt,
4050 VALIDATION_RTT_BUFFER_FACTOR));
4051 vs->last_challenge_use = GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
4052 update_next_challenge_time (vs,
4053 vs->first_challenge_use);
4054 vs->sc = GNUNET_PEERSTORE_store (peerstore,
4055 "transport",
4056 &cmc->im.sender,
4057 GNUNET_HELLO_PEERSTORE_KEY,
4058 vs->address,
4059 strlen (vs->address) + 1,
4060 vs->valid_until,
4061 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
4062 &peerstore_store_validation_cb,
4063 vs);
4064 // FIXME: now that we know that the address is *valid*,
4065 // do we need to trigger _using_ it for something?
3863 finish_cmc_handling (cmc); 4066 finish_cmc_handling (cmc);
3864} 4067}
3865 4068
@@ -4708,54 +4911,6 @@ suggest_to_connect (const struct GNUNET_PeerIdentity *pid,
4708 4911
4709 4912
4710/** 4913/**
4711 * Task run periodically to validate some address based on #validation_heap.
4712 *
4713 * @param cls NULL
4714 */
4715static void
4716validation_start_cb (void *cls);
4717
4718
4719/**
4720 * Set the time for next_challenge of @a vs to @a new_time.
4721 * Updates the heap and if necessary reschedules the job.
4722 *
4723 * @param vs validation state to update
4724 * @param new_time new time for revalidation
4725 */
4726static void
4727update_next_challenge_time (struct ValidationState *vs,
4728 struct GNUNET_TIME_Absolute new_time)
4729{
4730 struct GNUNET_TIME_Relative delta;
4731
4732 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
4733 return; /* be lazy */
4734 vs->next_challenge = new_time;
4735 if (NULL == vs->hn)
4736 vs->hn = GNUNET_CONTAINER_heap_insert (validation_heap,
4737 vs,
4738 new_time.abs_value_us);
4739 else
4740 GNUNET_CONTAINER_heap_update_cost (vs->hn,
4741 new_time.abs_value_us);
4742 if ( (vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
4743 (NULL != validation_task) )
4744 return;
4745 if (NULL != validation_task)
4746 GNUNET_SCHEDULER_cancel (validation_task);
4747 /* randomize a bit */
4748 delta.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
4749 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
4750 new_time = GNUNET_TIME_absolute_add (new_time,
4751 delta);
4752 validation_task = GNUNET_SCHEDULER_add_at (new_time,
4753 &validation_start_cb,
4754 NULL);
4755}
4756
4757
4758/**
4759 * The queue @a q (which matches the peer and address in @a vs) is 4914 * The queue @a q (which matches the peer and address in @a vs) is
4760 * ready for queueing. We should now queue the validation request. 4915 * ready for queueing. We should now queue the validation request.
4761 * 4916 *
@@ -5468,7 +5623,7 @@ do_shutdown (void *cls)
5468 if (NULL != peerstore) 5623 if (NULL != peerstore)
5469 { 5624 {
5470 GNUNET_PEERSTORE_disconnect (peerstore, 5625 GNUNET_PEERSTORE_disconnect (peerstore,
5471 GNUNET_NO); 5626 GNUNET_NO);
5472 peerstore = NULL; 5627 peerstore = NULL;
5473 } 5628 }
5474 if (NULL != GST_stats) 5629 if (NULL != GST_stats)