diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_peerstore_service.h | 8 | ||||
-rw-r--r-- | src/transport/gnunet-service-tng.c | 172 |
2 files changed, 166 insertions, 14 deletions
diff --git a/src/include/gnunet_peerstore_service.h b/src/include/gnunet_peerstore_service.h index b20c1f3c7..ad80a3fa3 100644 --- a/src/include/gnunet_peerstore_service.h +++ b/src/include/gnunet_peerstore_service.h | |||
@@ -61,6 +61,14 @@ extern "C" { | |||
61 | "transport-backchannel-monotonic-time" | 61 | "transport-backchannel-monotonic-time" |
62 | 62 | ||
63 | /** | 63 | /** |
64 | * Key used to store sender's monotonic time from DV learn | ||
65 | * messages. | ||
66 | */ | ||
67 | #define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME \ | ||
68 | "transport-dv-learn-monotonic-time" | ||
69 | |||
70 | |||
71 | /** | ||
64 | * Options for storing values in PEERSTORE | 72 | * Options for storing values in PEERSTORE |
65 | */ | 73 | */ |
66 | enum GNUNET_PEERSTORE_StoreOption | 74 | enum GNUNET_PEERSTORE_StoreOption |
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index baf443f03..9fb8141bf 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -24,12 +24,6 @@ | |||
24 | * | 24 | * |
25 | * TODO: | 25 | * TODO: |
26 | * Implement next: | 26 | * Implement next: |
27 | * - FIXME: handle_client_send(): pick DVH path, and box | ||
28 | * message accordingly (if applicable, see FIXMEs) | ||
29 | * - proper use/initialization of timestamps in messages exchanged | ||
30 | * during DV learning | ||
31 | * - persistence of monotonic time from DVInit to prevent | ||
32 | * replay attacks using DVInit messages | ||
33 | * - dv hop-by-hop signature verification (at least at initiator) | 27 | * - dv hop-by-hop signature verification (at least at initiator) |
34 | * - persistence of monotonic time obtained from other peers | 28 | * - persistence of monotonic time obtained from other peers |
35 | * in PEERSTORE (by message type) -- done for backchannel, needed elsewhere? | 29 | * in PEERSTORE (by message type) -- done for backchannel, needed elsewhere? |
@@ -720,6 +714,20 @@ struct TransportDVLearnMessage | |||
720 | struct GNUNET_TIME_RelativeNBO non_network_delay; | 714 | struct GNUNET_TIME_RelativeNBO non_network_delay; |
721 | 715 | ||
722 | /** | 716 | /** |
717 | * Time at the initiator when generating the signature. | ||
718 | * | ||
719 | * Note that the receiver MUST IGNORE the absolute time, and only interpret | ||
720 | * the value as a mononic time and reject "older" values than the last one | ||
721 | * observed. This is necessary as we do not want to require synchronized | ||
722 | * clocks and may not have a bidirectional communication channel. | ||
723 | * | ||
724 | * Even with this, there is no real guarantee against replay achieved here, | ||
725 | * unless the latest timestamp is persisted. Persistence should be | ||
726 | * provided via PEERSTORE if possible. | ||
727 | */ | ||
728 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | ||
729 | |||
730 | /** | ||
723 | * Signature of this hop over the path, of purpose | 731 | * Signature of this hop over the path, of purpose |
724 | * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR | 732 | * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR |
725 | */ | 733 | */ |
@@ -1664,6 +1672,18 @@ struct Neighbour | |||
1664 | struct GNUNET_SCHEDULER_Task *timeout_task; | 1672 | struct GNUNET_SCHEDULER_Task *timeout_task; |
1665 | 1673 | ||
1666 | /** | 1674 | /** |
1675 | * Handle for an operation to fetch @e last_dv_learn_monotime information from | ||
1676 | * the PEERSTORE, or NULL. | ||
1677 | */ | ||
1678 | struct GNUNET_PEERSTORE_IterateContext *get; | ||
1679 | |||
1680 | /** | ||
1681 | * Handle to a PEERSTORE store operation to store this @e pid's @e | ||
1682 | * @e last_dv_learn_monotime. NULL if no PEERSTORE operation is pending. | ||
1683 | */ | ||
1684 | struct GNUNET_PEERSTORE_StoreContext *sc; | ||
1685 | |||
1686 | /** | ||
1667 | * Quota at which CORE is allowed to transmit to this peer | 1687 | * Quota at which CORE is allowed to transmit to this peer |
1668 | * (note that the value CORE should actually be told is this | 1688 | * (note that the value CORE should actually be told is this |
1669 | * value plus the respective value in `struct DistanceVector`). | 1689 | * value plus the respective value in `struct DistanceVector`). |
@@ -1678,6 +1698,12 @@ struct Neighbour | |||
1678 | struct GNUNET_BANDWIDTH_Value32NBO quota_out; | 1698 | struct GNUNET_BANDWIDTH_Value32NBO quota_out; |
1679 | 1699 | ||
1680 | /** | 1700 | /** |
1701 | * Latest DVLearn monotonic time seen from this peer. Initialized only | ||
1702 | * if @e dl_monotime_available is #GNUNET_YES. | ||
1703 | */ | ||
1704 | struct GNUNET_TIME_Absolute last_dv_learn_monotime; | ||
1705 | |||
1706 | /** | ||
1681 | * What is the earliest timeout of any message in @e pending_msg_tail? | 1707 | * What is the earliest timeout of any message in @e pending_msg_tail? |
1682 | */ | 1708 | */ |
1683 | struct GNUNET_TIME_Absolute earliest_timeout; | 1709 | struct GNUNET_TIME_Absolute earliest_timeout; |
@@ -1687,6 +1713,12 @@ struct Neighbour | |||
1687 | * CORE? | 1713 | * CORE? |
1688 | */ | 1714 | */ |
1689 | int core_visible; | 1715 | int core_visible; |
1716 | |||
1717 | /** | ||
1718 | * Do we have the lastest value for @e last_dv_learn_monotime from | ||
1719 | * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE? | ||
1720 | */ | ||
1721 | int dv_monotime_available; | ||
1690 | }; | 1722 | }; |
1691 | 1723 | ||
1692 | 1724 | ||
@@ -2886,7 +2918,20 @@ free_neighbour (struct Neighbour *neighbour) | |||
2886 | free_dv_route (dv); | 2918 | free_dv_route (dv); |
2887 | } | 2919 | } |
2888 | if (NULL != neighbour->reassembly_timeout_task) | 2920 | if (NULL != neighbour->reassembly_timeout_task) |
2921 | { | ||
2889 | GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task); | 2922 | GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task); |
2923 | neighbour->reassembly_timeout_task = NULL; | ||
2924 | } | ||
2925 | if (NULL != neighbour->get) | ||
2926 | { | ||
2927 | GNUNET_PEERSTORE_iterate_cancel (neighbour->get); | ||
2928 | neighbour->get = NULL; | ||
2929 | } | ||
2930 | if (NULL != neighbour->sc) | ||
2931 | { | ||
2932 | GNUNET_PEERSTORE_store_cancel (neighbour->sc); | ||
2933 | neighbour->sc = NULL; | ||
2934 | } | ||
2890 | GNUNET_free (neighbour); | 2935 | GNUNET_free (neighbour); |
2891 | } | 2936 | } |
2892 | 2937 | ||
@@ -6004,6 +6049,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, | |||
6004 | /** | 6049 | /** |
6005 | * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR | 6050 | * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR |
6006 | * | 6051 | * |
6052 | * @param sender_monotonic_time monotonic time of the initiator | ||
6007 | * @param init the signer | 6053 | * @param init the signer |
6008 | * @param challenge the challenge that was signed | 6054 | * @param challenge the challenge that was signed |
6009 | * @param init_sig signature presumably by @a init | 6055 | * @param init_sig signature presumably by @a init |
@@ -6011,6 +6057,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, | |||
6011 | */ | 6057 | */ |
6012 | static int | 6058 | static int |
6013 | validate_dv_initiator_signature ( | 6059 | validate_dv_initiator_signature ( |
6060 | struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, | ||
6014 | const struct GNUNET_PeerIdentity *init, | 6061 | const struct GNUNET_PeerIdentity *init, |
6015 | const struct ChallengeNonceP *challenge, | 6062 | const struct ChallengeNonceP *challenge, |
6016 | const struct GNUNET_CRYPTO_EddsaSignature *init_sig) | 6063 | const struct GNUNET_CRYPTO_EddsaSignature *init_sig) |
@@ -6018,6 +6065,7 @@ validate_dv_initiator_signature ( | |||
6018 | struct DvInitPS ip = {.purpose.purpose = htonl ( | 6065 | struct DvInitPS ip = {.purpose.purpose = htonl ( |
6019 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), | 6066 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), |
6020 | .purpose.size = htonl (sizeof (ip)), | 6067 | .purpose.size = htonl (sizeof (ip)), |
6068 | .monotonic_time = sender_monotonic_time, | ||
6021 | .challenge = *challenge}; | 6069 | .challenge = *challenge}; |
6022 | 6070 | ||
6023 | if ( | 6071 | if ( |
@@ -6224,6 +6272,24 @@ calculate_fork_degree (unsigned int hops_taken, | |||
6224 | 6272 | ||
6225 | 6273 | ||
6226 | /** | 6274 | /** |
6275 | * Function called when peerstore is done storing a DV monotonic time. | ||
6276 | * | ||
6277 | * @param cls a `struct Neighbour` | ||
6278 | * @param success #GNUNET_YES if peerstore was successful | ||
6279 | */ | ||
6280 | static void | ||
6281 | neighbour_store_dvmono_cb (void *cls, int success) | ||
6282 | { | ||
6283 | struct Neighbour *n = cls; | ||
6284 | |||
6285 | n->sc = NULL; | ||
6286 | if (GNUNET_YES != success) | ||
6287 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
6288 | "Failed to store other peer's monotonic time in peerstore!\n"); | ||
6289 | } | ||
6290 | |||
6291 | |||
6292 | /** | ||
6227 | * Communicator gave us a DV learn message. Process the request. | 6293 | * Communicator gave us a DV learn message. Process the request. |
6228 | * | 6294 | * |
6229 | * @param cls a `struct CommunicatorMessageContext` (must call | 6295 | * @param cls a `struct CommunicatorMessageContext` (must call |
@@ -6242,6 +6308,7 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) | |||
6242 | int do_fwd; | 6308 | int do_fwd; |
6243 | int did_initiator; | 6309 | int did_initiator; |
6244 | struct GNUNET_TIME_Absolute in_time; | 6310 | struct GNUNET_TIME_Absolute in_time; |
6311 | struct Neighbour *n; | ||
6245 | 6312 | ||
6246 | nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */ | 6313 | nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */ |
6247 | bi_history = ntohs (dvl->bidirectional); | 6314 | bi_history = ntohs (dvl->bidirectional); |
@@ -6276,15 +6343,44 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) | |||
6276 | /* continue communicator here, everything else can happen asynchronous! */ | 6343 | /* continue communicator here, everything else can happen asynchronous! */ |
6277 | finish_cmc_handling (cmc); | 6344 | finish_cmc_handling (cmc); |
6278 | 6345 | ||
6279 | /* OPTIMIZE-FIXME: Technically, we only need to bother checking | 6346 | n = lookup_neighbour (&dvl->initiator); |
6280 | the initiator signature if we send the message back to the initiator... | 6347 | if (NULL != n) |
6281 | */ | ||
6282 | if (GNUNET_OK != validate_dv_initiator_signature (&dvl->initiator, | ||
6283 | &dvl->challenge, | ||
6284 | &dvl->init_sig)) | ||
6285 | { | 6348 | { |
6286 | GNUNET_break_op (0); | 6349 | if ((n->dv_monotime_available == GNUNET_YES) && |
6287 | return; | 6350 | (GNUNET_TIME_absolute_ntoh (dvl->monotonic_time).abs_value_us < |
6351 | n->last_dv_learn_monotime.abs_value_us)) | ||
6352 | { | ||
6353 | GNUNET_STATISTICS_update (GST_stats, | ||
6354 | "# DV learn discarded due to time travel", | ||
6355 | 1, | ||
6356 | GNUNET_NO); | ||
6357 | return; | ||
6358 | } | ||
6359 | if (GNUNET_OK != validate_dv_initiator_signature (dvl->monotonic_time, | ||
6360 | &dvl->initiator, | ||
6361 | &dvl->challenge, | ||
6362 | &dvl->init_sig)) | ||
6363 | { | ||
6364 | GNUNET_break_op (0); | ||
6365 | return; | ||
6366 | } | ||
6367 | n->last_dv_learn_monotime = GNUNET_TIME_absolute_ntoh (dvl->monotonic_time); | ||
6368 | if (GNUNET_YES == n->dv_monotime_available) | ||
6369 | { | ||
6370 | if (NULL != n->sc) | ||
6371 | GNUNET_PEERSTORE_store_cancel (n->sc); | ||
6372 | n->sc = | ||
6373 | GNUNET_PEERSTORE_store (peerstore, | ||
6374 | "transport", | ||
6375 | &dvl->initiator, | ||
6376 | GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, | ||
6377 | &dvl->monotonic_time, | ||
6378 | sizeof (dvl->monotonic_time), | ||
6379 | GNUNET_TIME_UNIT_FOREVER_ABS, | ||
6380 | GNUNET_PEERSTORE_STOREOPTION_REPLACE, | ||
6381 | &neighbour_store_dvmono_cb, | ||
6382 | n); | ||
6383 | } | ||
6288 | } | 6384 | } |
6289 | // FIXME: asynchronously (!) verify hop-by-hop signatures! | 6385 | // FIXME: asynchronously (!) verify hop-by-hop signatures! |
6290 | // => if signature verification load too high, implement random drop | 6386 | // => if signature verification load too high, implement random drop |
@@ -8057,10 +8153,13 @@ start_dv_learn (void *cls) | |||
8057 | dvl.num_hops = htons (0); | 8153 | dvl.num_hops = htons (0); |
8058 | dvl.bidirectional = htons (0); | 8154 | dvl.bidirectional = htons (0); |
8059 | dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO); | 8155 | dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO); |
8156 | dvl.monotonic_time = | ||
8157 | GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg)); | ||
8060 | { | 8158 | { |
8061 | struct DvInitPS dvip = {.purpose.purpose = htonl ( | 8159 | struct DvInitPS dvip = {.purpose.purpose = htonl ( |
8062 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), | 8160 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR), |
8063 | .purpose.size = htonl (sizeof (dvip)), | 8161 | .purpose.size = htonl (sizeof (dvip)), |
8162 | .monotonic_time = dvl.monotonic_time, | ||
8064 | .challenge = lle->challenge}; | 8163 | .challenge = lle->challenge}; |
8065 | 8164 | ||
8066 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, | 8165 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, |
@@ -8122,6 +8221,44 @@ check_validation_request_pending (void *cls, | |||
8122 | 8221 | ||
8123 | 8222 | ||
8124 | /** | 8223 | /** |
8224 | * Function called with the monotonic time of a DV initiator | ||
8225 | * by PEERSTORE. Updates the time. | ||
8226 | * | ||
8227 | * @param cls a `struct Neighbour` | ||
8228 | * @param record the information found, NULL for the last call | ||
8229 | * @param emsg error message | ||
8230 | */ | ||
8231 | static void | ||
8232 | neighbour_dv_monotime_cb (void *cls, | ||
8233 | const struct GNUNET_PEERSTORE_Record *record, | ||
8234 | const char *emsg) | ||
8235 | { | ||
8236 | struct Neighbour *n = cls; | ||
8237 | struct GNUNET_TIME_AbsoluteNBO *mtbe; | ||
8238 | struct GNUNET_TIME_Absolute mt; | ||
8239 | |||
8240 | (void) emsg; | ||
8241 | if (NULL == record) | ||
8242 | { | ||
8243 | /* we're done with #neighbour_dv_monotime_cb() invocations, | ||
8244 | continue normal processing */ | ||
8245 | n->get = NULL; | ||
8246 | n->dv_monotime_available = GNUNET_YES; | ||
8247 | return; | ||
8248 | } | ||
8249 | if (sizeof (*mtbe) != record->value_size) | ||
8250 | { | ||
8251 | GNUNET_break (0); | ||
8252 | return; | ||
8253 | } | ||
8254 | mtbe = record->value; | ||
8255 | n->last_dv_learn_monotime = | ||
8256 | GNUNET_TIME_absolute_max (n->last_dv_learn_monotime, | ||
8257 | GNUNET_TIME_absolute_ntoh (*mtbe)); | ||
8258 | } | ||
8259 | |||
8260 | |||
8261 | /** | ||
8125 | * New queue became available. Process the request. | 8262 | * New queue became available. Process the request. |
8126 | * | 8263 | * |
8127 | * @param cls the client | 8264 | * @param cls the client |
@@ -8157,6 +8294,13 @@ handle_add_queue_message (void *cls, | |||
8157 | &neighbour->pid, | 8294 | &neighbour->pid, |
8158 | neighbour, | 8295 | neighbour, |
8159 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 8296 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
8297 | neighbour->get = | ||
8298 | GNUNET_PEERSTORE_iterate (peerstore, | ||
8299 | "transport", | ||
8300 | &neighbour->pid, | ||
8301 | GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, | ||
8302 | &neighbour_dv_monotime_cb, | ||
8303 | neighbour); | ||
8160 | } | 8304 | } |
8161 | addr_len = ntohs (aqm->header.size) - sizeof (*aqm); | 8305 | addr_len = ntohs (aqm->header.size) - sizeof (*aqm); |
8162 | addr = (const char *) &aqm[1]; | 8306 | addr = (const char *) &aqm[1]; |