From 34c384edf42db39955b54a640dc37e7067217229 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 28 Jun 2010 11:07:52 +0000 Subject: [PATCH] fixes to plugin API for DV --- src/transport/Makefile.am | 2 +- src/transport/gnunet-service-transport.c | 47 ++++++++++----- src/transport/plugin_transport.h | 22 +++---- src/transport/plugin_transport_tcp.c | 40 +++++++------ src/transport/plugin_transport_template.c | 3 +- src/transport/plugin_transport_udp.c | 70 ++++++++++++++++------- 6 files changed, 121 insertions(+), 63 deletions(-) diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index e65c93286..58e02f995 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -6,7 +6,7 @@ if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif -if HAVE_MHD +if MINGW GN_LIBMHD = -lmicrohttpd HTTP_PLUGIN_LA = libgnunet_plugin_transport_http.la HTTP_PLUGIN_CHECK = test_plugin_transport_http diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 56480d020..4390377a6 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -4338,6 +4338,18 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message, /* peer wants to confirm that this is one of our addresses */ addr += slen; alen -= slen; + if (GNUNET_OK != + plugin->api->check_address (plugin->api->cls, + addr, + alen)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"), + a2s (plugin->short_name, + addr, + alen)); + return GNUNET_NO; + } oal = plugin->addresses; while (NULL != oal) { @@ -4348,15 +4360,6 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message, break; oal = oal->next; } - if (oal == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"), - a2s (plugin->short_name, - addr, - alen)); - return GNUNET_NO; - } pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen); pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen); pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); @@ -4372,8 +4375,9 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message, &my_identity, sizeof(struct GNUNET_PeerIdentity)); memcpy (&pong[1], plugin->short_name, slen); - memcpy (&((char*)&pong[1])[slen], &oal[1], alen); - if (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4) + memcpy (&((char*)&pong[1])[slen], addr, alen); + if ( (oal != NULL) && + (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4) ) { /* create / update cached sig */ #if DEBUG_TRANSPORT @@ -4386,15 +4390,28 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message, GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_rsa_sign (my_private_key, &pong->purpose, - &oal->pong_signature)); + &oal->pong_signature)); + memcpy (&pong->signature, + &oal->pong_signature, + sizeof (struct GNUNET_CRYPTO_RsaSignature)); + } + else if (oal == NULL) + { + /* not using cache (typically DV-only) */ + pong->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME)); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_rsa_sign (my_private_key, + &pong->purpose, + &pong->signature)); } else { + /* can used cached version */ pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires); + memcpy (&pong->signature, + &oal->pong_signature, + sizeof (struct GNUNET_CRYPTO_RsaSignature)); } - memcpy (&pong->signature, - &oal->pong_signature, - sizeof (struct GNUNET_CRYPTO_RsaSignature)); } n = find_neighbour(peer); GNUNET_assert (n != NULL); diff --git a/src/transport/plugin_transport.h b/src/transport/plugin_transport.h index bb64a1bfc..ef5303df5 100644 --- a/src/transport/plugin_transport.h +++ b/src/transport/plugin_transport.h @@ -359,16 +359,18 @@ typedef void * plugin. Check that this could be a valid address. This function * is not expected to 'validate' the address in the sense of trying to * connect to it but simply to see if the binary format is technically - * legal for establishing a connection. + * legal for establishing a connection to this peer (and make sure that + * the address really corresponds to our network connection/settings + * and not some potential man-in-the-middle). * - * @param addr pointer to the address, may be modified (slightly) + * @param addr pointer to the address * @param addrlen length of addr * @return GNUNET_OK if this is a plausible address for this peer * and transport, GNUNET_SYSERR if not */ typedef int - (*GNUNET_TRANSPORT_CheckAddress) (void *cls, - void *addr, size_t addrlen); +(*GNUNET_TRANSPORT_CheckAddress) (void *cls, + const void *addr, size_t addrlen); /** @@ -426,15 +428,15 @@ struct GNUNET_TRANSPORT_PluginFunctions /** * Function that will be called to check if a binary address - * for this plugin is well-formed. If clearly needed, patch - * up information such as port numbers. - * FIXME: this API will likely change in the near future since - * it currently does not allow the size of the patched address - * to be different! + * for this plugin is well-formed and corresponds to an + * address for THIS peer (as per our configuration). Naturally, + * if absolutely necessary, plugins can be a bit conservative in + * their answer, but in general plugins should make sure that the + * address does not redirect traffic to a 3rd party that might + * try to man-in-the-middle our traffic. */ GNUNET_TRANSPORT_CheckAddress check_address; - /** * Function that will be called to convert a binary address * to a string (numeric conversion only). diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 08bb00ff6..edf403ac6 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c @@ -1366,29 +1366,29 @@ tcp_plugin_address_pretty_printer (void *cls, /** * Check if the given port is plausible (must be either * our listen port or our advertised port). If it is - * neither, we return one of these two ports at random. + * neither, we return GNUNET_SYSERR. * * @param plugin global variables * @param in_port port number to check - * @return either in_port or a more plausible port + * @return GNUNET_OK if port is either open_port or adv_port */ -static uint16_t +static int check_port (struct Plugin *plugin, uint16_t in_port) { if ((in_port == plugin->adv_port) || (in_port == plugin->open_port)) - return in_port; - return (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - 2) == 0) - ? plugin->open_port : plugin->adv_port; + return GNUNET_OK; + return GNUNET_SYSERR; } -/** - * Another peer has suggested an address for this peer and transport - * plugin. Check that this could be a valid address. This function - * is not expected to 'validate' the address in the sense of trying to - * connect to it but simply to see if the binary format is technically - * legal for establishing a connection. +/** + * Function that will be called to check if a binary address for this + * plugin is well-formed and corresponds to an address for THIS peer + * (as per our configuration). Naturally, if absolutely necessary, + * plugins can be a bit conservative in their answer, but in general + * plugins should make sure that the address does not redirect + * traffic to a 3rd party that might try to man-in-the-middle our + * traffic. * * @param cls closure, our 'struct Plugin*' * @param addr pointer to the address @@ -1397,7 +1397,9 @@ check_port (struct Plugin *plugin, uint16_t in_port) * and transport, GNUNET_SYSERR if not */ static int -tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) +tcp_plugin_check_address (void *cls, + const void *addr, + size_t addrlen) { struct Plugin *plugin = cls; struct IPv4TcpAddress *v4; @@ -1412,7 +1414,10 @@ tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) if (addrlen == sizeof (struct IPv4TcpAddress)) { v4 = (struct IPv4TcpAddress *) addr; - v4->t_port = htons (check_port (plugin, ntohs (v4->t_port))); + if (GNUNET_OK != + check_port (plugin, ntohs (v4->t_port))) + return GNUNET_SYSERR; + /* FIXME: check IP! */ } else { @@ -1422,7 +1427,10 @@ tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) GNUNET_break_op (0); return GNUNET_SYSERR; } - v6->t6_port = htons (check_port (plugin, ntohs (v6->t6_port))); + if (GNUNET_OK != + check_port (plugin, ntohs (v6->t6_port))) + return GNUNET_SYSERR; + /* FIXME: check IP! */ } return GNUNET_OK; } diff --git a/src/transport/plugin_transport_template.c b/src/transport/plugin_transport_template.c index f5eec84d3..27cb9044e 100644 --- a/src/transport/plugin_transport_template.c +++ b/src/transport/plugin_transport_template.c @@ -232,7 +232,8 @@ template_plugin_address_pretty_printer (void *cls, */ static int template_plugin_address_suggested (void *cls, - void *addr, size_t addrlen) + const void *addr, + size_t addrlen) { /* struct Plugin *plugin = cls; */ diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c index 52e598189..724dfe6b3 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c @@ -1586,47 +1586,77 @@ udp_transport_server_start (void *cls) } + +/** + * Check if the given port is plausible (must be either + * our listen port or our advertised port). If it is + * neither, we return GNUNET_SYSERR. + * + * @param plugin global variables + * @param in_port port number to check + * @return GNUNET_OK if port is either open_port or adv_port + */ +static int +check_port (struct Plugin *plugin, uint16_t in_port) +{ + if (in_port == plugin->port) + return GNUNET_OK; + return GNUNET_SYSERR; +} + + /** - * Another peer has suggested an address for this peer and transport - * plugin. Check that this could be a valid address. This function - * is not expected to 'validate' the address in the sense of trying to - * connect to it but simply to see if the binary format is technically - * legal for establishing a connection. + * Function that will be called to check if a binary address for this + * plugin is well-formed and corresponds to an address for THIS peer + * (as per our configuration). Naturally, if absolutely necessary, + * plugins can be a bit conservative in their answer, but in general + * plugins should make sure that the address does not redirect + * traffic to a 3rd party that might try to man-in-the-middle our + * traffic. * * @param cls closure, should be our handle to the Plugin - * @param addr pointer to the address, may be modified (slightly) + * @param addr pointer to the address * @param addrlen length of addr * @return GNUNET_OK if this is a plausible address for this peer * and transport, GNUNET_SYSERR if not * */ static int -udp_check_address (void *cls, void *addr, size_t addrlen) +udp_check_address (void *cls, + const void *addr, + size_t addrlen) { struct Plugin *plugin = cls; - char buf[sizeof (struct sockaddr_in6)]; + struct IPv4UdpAddress *v4; + struct IPv6UdpAddress *v6; - struct sockaddr_in *v4; - struct sockaddr_in6 *v6; - - if ((addrlen != sizeof (struct sockaddr_in)) && - (addrlen != sizeof (struct sockaddr_in6))) + if ((addrlen != sizeof (struct IPv4UdpAddress)) && + (addrlen != sizeof (struct IPv6UdpAddress))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - memcpy (buf, addr, sizeof (struct sockaddr_in6)); - if (addrlen == sizeof (struct sockaddr_in)) + if (addrlen == sizeof (struct IPv4UdpAddress)) { - v4 = (struct sockaddr_in *) buf; - v4->sin_port = htons (plugin->port); + v4 = (struct IPv4UdpAddress *) addr; + if (GNUNET_OK != + check_port (plugin, ntohs (v4->u_port))) + return GNUNET_SYSERR; + /* FIXME: check IP! */ } else { - v6 = (struct sockaddr_in6 *) buf; - v6->sin6_port = htons (plugin->port); + v6 = (struct IPv6UdpAddress *) addr; + if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + check_port (plugin, ntohs (v6->u6_port))) + return GNUNET_SYSERR; + /* FIXME: check IP! */ } - #if DEBUG_UDP GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", -- 2.25.1