X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fgns%2Fgnunet-service-gns.c;h=c376ddfcc390478ec44771d7fa67e33c0cca23a0;hb=620bdac536dff4b17317d9d20b8a6840836d6490;hp=7c1dfaba24059571f99b446ae2d7203f79b0791c;hpb=5672e0e27b671fa878143e5eed8a9b677588b178;p=oweals%2Fgnunet.git diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index 7c1dfaba2..c376ddfcc 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2011-2013 GNUnet e.V. + Copyright (C) 2011-2018 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -29,14 +29,11 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_dht_service.h" #include "gnunet_namecache_service.h" -#include "gnunet_namestore_service.h" -#include "gnunet_identity_service.h" +#include "gnunet_gnsrecord_lib.h" #include "gnunet_gns_service.h" #include "gnunet_statistics_service.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" -#include "gnunet-service-gns_reverser.h" -#include "gnunet-service-gns_shorten.h" #include "gnunet-service-gns_interceptor.h" #include "gnunet_protocols.h" @@ -47,7 +44,7 @@ struct GnsClient; /** - * Handle to a lookup operation from api + * Handle to a lookup operation from client via API. */ struct ClientLookupHandle { @@ -61,7 +58,7 @@ struct ClientLookupHandle * We keep these in a DLL. */ struct ClientLookupHandle *prev; - + /** * Client handle */ @@ -72,11 +69,6 @@ struct ClientLookupHandle */ struct GNS_ResolverHandle *lookup; - /** - * Active handle for a reverse lookup - */ - struct GNS_ReverserHandle *rev_lookup; - /** * request id */ @@ -84,6 +76,10 @@ struct ClientLookupHandle }; + +/** + * Information we track per connected client. + */ struct GnsClient { /** @@ -108,6 +104,38 @@ struct GnsClient }; +/** + * Representation of a TLD, mapping the respective TLD string + * (i.e. ".gnu") to the respective public key of the zone. + */ +struct GNS_TopLevelDomain +{ + + /** + * Kept in a DLL, as there are unlikely enough of these to + * warrant a hash map. + */ + struct GNS_TopLevelDomain *next; + + /** + * Kept in a DLL, as there are unlikely enough of these to + * warrant a hash map. + */ + struct GNS_TopLevelDomain *prev; + + /** + * Public key associated with the @a tld. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey pkey; + + /** + * Top-level domain as a string, including leading ".". + */ + char *tld; + +}; + + /** * Our handle to the DHT */ @@ -119,73 +147,106 @@ static struct GNUNET_DHT_Handle *dht_handle; static struct GNUNET_NAMECACHE_Handle *namecache_handle; /** - * Our handle to the namestore service + * #GNUNET_YES if ipv6 is supported */ -static struct GNUNET_NAMESTORE_Handle *namestore_handle; +static int v6_enabled; /** - * Our handle to the identity service + * #GNUNET_YES if ipv4 is supported */ -static struct GNUNET_IDENTITY_Handle *identity_handle; +static int v4_enabled; /** - * Our handle to the identity operation to find the master zone - * for intercepted queries. + * Handle to the statistics service */ -static struct GNUNET_IDENTITY_Operation *identity_op; +static struct GNUNET_STATISTICS_Handle *statistics; /** - * #GNUNET_YES if ipv6 is supported + * Head of DLL of TLDs we map to GNS zones. */ -static int v6_enabled; +static struct GNS_TopLevelDomain *tld_head; /** - * #GNUNET_YES if ipv4 is supported + * Tail of DLL of TLDs we map to GNS zones. */ -static int v4_enabled; +static struct GNS_TopLevelDomain *tld_tail; + /** - * Handle to the statistics service + * Find GNS zone belonging to TLD @a tld. + * + * @param tld_str top-level domain to look up + * @param[out] pkey public key to set + * @return #GNUNET_YES if @a tld was found #GNUNET_NO if not */ -static struct GNUNET_STATISTICS_Handle *statistics; +int +GNS_find_tld (const char *tld_str, + struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) +{ + if ('\0' == *tld_str) + return GNUNET_NO; + for (struct GNS_TopLevelDomain *tld = tld_head; + NULL != tld; + tld = tld->next) + { + if (0 == strcasecmp (tld_str, + tld->tld)) + { + *pkey = tld->pkey; + return GNUNET_YES; + } + } + if (GNUNET_OK == + GNUNET_GNSRECORD_zkey_to_pkey (tld_str + 1, + pkey)) + return GNUNET_YES; /* TLD string *was* the public key */ + return GNUNET_NO; +} + + +/** + * Obtain the TLD of the given @a name. + * + * @param name a name + * @return the part of @a name after the last ".", + * or @a name if @a name does not contain a "." + */ +const char * +GNS_get_tld (const char *name) +{ + const char *tld; + + tld = strrchr (name, + (unsigned char) '.'); + if (NULL == tld) + tld = name; + else + tld++; /* skip the '.' */ + return tld; +} /** * Task run during shutdown. * - * @param cls unused - * @param tc unused + * @param cls unused, NULL */ static void shutdown_task (void *cls) { + struct GNS_TopLevelDomain *tld; + + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n"); GNS_interceptor_done (); - if (NULL != identity_op) - { - GNUNET_IDENTITY_cancel (identity_op); - identity_op = NULL; - } - if (NULL != identity_handle) - { - GNUNET_IDENTITY_disconnect (identity_handle); - identity_handle = NULL; - } GNS_resolver_done (); - GNS_reverse_done (); - GNS_shorten_done (); if (NULL != statistics) { GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); statistics = NULL; } - if (NULL != namestore_handle) - { - GNUNET_NAMESTORE_disconnect (namestore_handle); - namestore_handle = NULL; - } if (NULL != namecache_handle) { GNUNET_NAMECACHE_disconnect (namecache_handle); @@ -196,6 +257,14 @@ shutdown_task (void *cls) GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } + while (NULL != (tld = tld_head)) + { + GNUNET_CONTAINER_DLL_remove (tld_head, + tld_tail, + tld); + GNUNET_free (tld->tld); + GNUNET_free (tld); + } } @@ -214,6 +283,7 @@ client_disconnect_cb (void *cls, struct ClientLookupHandle *clh; struct GnsClient *gc = app_ctx; + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); @@ -221,15 +291,13 @@ client_disconnect_cb (void *cls, { if (NULL != clh->lookup) GNS_resolver_lookup_cancel (clh->lookup); - if (NULL != clh->rev_lookup) - GNS_reverse_lookup_cancel (clh->rev_lookup); GNUNET_CONTAINER_DLL_remove (gc->clh_head, gc->clh_tail, clh); GNUNET_free (clh); } - GNUNET_free (gc); + GNUNET_free (gc); } @@ -247,6 +315,8 @@ client_connect_cb (void *cls, struct GNUNET_MQ_Handle *mq) { struct GnsClient *gc; + + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); @@ -288,7 +358,9 @@ send_lookup_response (void* cls, (char*) &rmsg[1]); GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->gc->client), env); - GNUNET_CONTAINER_DLL_remove (clh->gc->clh_head, clh->gc->clh_tail, clh); + GNUNET_CONTAINER_DLL_remove (clh->gc->clh_head, + clh->gc->clh_tail, + clh); GNUNET_free (clh); GNUNET_STATISTICS_update (statistics, "Completed lookups", 1, @@ -299,47 +371,6 @@ send_lookup_response (void* cls, GNUNET_NO); } -/** - * Reply to client with the result from our reverse lookup. - * - * @param cls the closure (our client lookup handle) - * @param rd_count the number of records in @a rd - * @param rd the record data - */ -static void -send_reverse_lookup_response (void* cls, - const char *name) -{ - struct ClientLookupHandle *clh = cls; - struct GNUNET_MQ_Envelope *env; - struct ReverseLookupResultMessage *rmsg; - size_t len; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending LOOKUP_RESULT message with %s\n", - name); - - if (NULL == name) - len = 1; - else - len = strlen (name) + 1; - env = GNUNET_MQ_msg_extra (rmsg, - len, - GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT); - rmsg->id = clh->request_id; - if (1 < len) - GNUNET_memcpy ((char*) &rmsg[1], - name, - strlen (name)); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->gc->client), - env); - GNUNET_CONTAINER_DLL_remove (clh->gc->clh_head, clh->gc->clh_tail, clh); - GNUNET_free (clh); - GNUNET_STATISTICS_update (statistics, - "Completed reverse lookups", 1, - GNUNET_NO); -} - /** * Checks a #GNUNET_MESSAGE_TYPE_GNS_LOOKUP message @@ -355,6 +386,7 @@ check_lookup (void *cls, size_t msg_size; const char* name; + (void) cls; msg_size = ntohs (l_msg->header.size); if (msg_size < sizeof (struct LookupMessage)) { @@ -371,6 +403,7 @@ check_lookup (void *cls, return GNUNET_OK; } + /** * Handle lookup requests from client * @@ -387,20 +420,19 @@ handle_lookup (void *cls, struct ClientLookupHandle *clh; char *nameptr = name; const char *utf_in; - const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received LOOKUP message\n"); GNUNET_SERVICE_client_continue (gc->client); - if (GNUNET_YES == ntohs (sh_msg->have_key)) - key = &sh_msg->shorten_key; - else - key = NULL; utf_in = (const char *) &sh_msg[1]; - GNUNET_STRINGS_utf8_tolower (utf_in, nameptr); + GNUNET_STRINGS_utf8_tolower (utf_in, + nameptr); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received LOOKUP `%s' message\n", + name); clh = GNUNET_new (struct ClientLookupHandle); - GNUNET_CONTAINER_DLL_insert (gc->clh_head, gc->clh_tail, clh); + GNUNET_CONTAINER_DLL_insert (gc->clh_head, + gc->clh_tail, + clh); clh->gc = gc; clh->request_id = sh_msg->id; if ( (GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) && @@ -408,7 +440,9 @@ handle_lookup (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LOOKUP: Query for A record but AF_INET not supported!"); - send_lookup_response (clh, 0, NULL); + send_lookup_response (clh, + 0, + NULL); return; } if ( (GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) && @@ -416,13 +450,14 @@ handle_lookup (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LOOKUP: Query for AAAA record but AF_INET6 not supported!"); - send_lookup_response (clh, 0, NULL); + send_lookup_response (clh, + 0, + NULL); return; } clh->lookup = GNS_resolver_lookup (&sh_msg->zone, ntohl (sh_msg->type), name, - key, (enum GNUNET_GNS_LocalOptions) ntohs (sh_msg->options), &send_lookup_response, clh); GNUNET_STATISTICS_update (statistics, @@ -430,135 +465,46 @@ handle_lookup (void *cls, 1, GNUNET_NO); } -/** - * Handle reverse lookup requests from client - * - * @param cls the closure - * @param client the client - * @param message the message - */ -static void -handle_rev_lookup (void *cls, - const struct ReverseLookupMessage *sh_msg) -{ - struct GnsClient *gc = cls; - struct ClientLookupHandle *clh; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received REVERSE_LOOKUP message\n"); - GNUNET_SERVICE_client_continue (gc->client); - - clh = GNUNET_new (struct ClientLookupHandle); - GNUNET_CONTAINER_DLL_insert (gc->clh_head, gc->clh_tail, clh); - clh->gc = gc; - clh->request_id = sh_msg->id; - clh->rev_lookup = GNS_reverse_lookup (&sh_msg->zone_pkey, - &sh_msg->root_pkey, - &send_reverse_lookup_response, - clh); - GNUNET_STATISTICS_update (statistics, - "Reverse lookup attempts", - 1, GNUNET_NO); -} - /** - * Method called to inform about the ego to be used for the master zone - * for DNS interceptions. + * Reads the configuration and populates TLDs * - * This function is only called ONCE, and 'NULL' being passed in - * @a ego does indicate that interception is not configured. - * If @a ego is non-NULL, we should start to intercept DNS queries - * and resolve ".gnu" queries using the given ego as the master zone. - * - * @param cls closure, our `const struct GNUNET_CONFIGURATION_Handle *c` - * @param ego ego handle - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param name name assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used - */ -static void -identity_reverse_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - identity_op = NULL; - - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("No ego configured for `%s`\n"), - "gns-master"); - - return; - } - if (GNUNET_SYSERR == - GNS_reverse_init (namestore_handle, - GNUNET_IDENTITY_ego_get_private_key (ego), - name)) - { - GNUNET_break (0); - GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); - return; - } -} - - -/** - * Method called to inform about the ego to be used for the master zone - * for DNS interceptions. - * - * This function is only called ONCE, and 'NULL' being passed in - * @a ego does indicate that interception is not configured. - * If @a ego is non-NULL, we should start to intercept DNS queries - * and resolve ".gnu" queries using the given ego as the master zone. - * - * @param cls closure, our `const struct GNUNET_CONFIGURATION_Handle *c` - * @param ego ego handle - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param name name assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used + * @param cls unused + * @param section name of section in config, always "gns" + * @param option name of the option, TLDs start with "." + * @param value value for the option, public key for TLDs */ static void -identity_intercept_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) +read_service_conf (void *cls, + const char *section, + const char *option, + const char *value) { - const struct GNUNET_CONFIGURATION_Handle *cfg = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey dns_root; - identity_op = NULL; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Looking for gns-intercept ego\n"); - identity_op = GNUNET_IDENTITY_get (identity_handle, - "gns-reverse", - &identity_reverse_cb, - (void*)cfg); - - - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("No ego configured for `%s`\n"), - "gns-intercept"); + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + struct GNS_TopLevelDomain *tld; + (void) cls; + (void) section; + if (option[0] != '.') return; - } - GNUNET_IDENTITY_ego_get_public_key (ego, - &dns_root); - if (GNUNET_SYSERR == - GNS_interceptor_init (&dns_root, cfg)) + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (value, + strlen (value), + &pk, + sizeof (pk))) { - GNUNET_break (0); - GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + option, + _("Properly base32-encoded public key required")); return; } + tld = GNUNET_new (struct GNS_TopLevelDomain); + tld->tld = GNUNET_strdup (&option[1]); + tld->pkey = pk; + GNUNET_CONTAINER_DLL_insert (tld_head, + tld_tail, + tld); } @@ -574,19 +520,15 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service) { - unsigned long long max_parallel_bg_queries = 0; + unsigned long long max_parallel_bg_queries = 16; + GNUNET_CONFIGURATION_iterate_section_values (c, + "gns", + &read_service_conf, + NULL); v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); - v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); - namestore_handle = GNUNET_NAMESTORE_connect (c); - if (NULL == namestore_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to the namestore!\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - namecache_handle = GNUNET_NAMECACHE_connect (c); + v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); + namecache_handle = GNUNET_NAMECACHE_connect (c); if (NULL == namecache_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -594,43 +536,46 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } - + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_number (c, + "gns", + "MAX_PARALLEL_BACKGROUND_QUERIES", + &max_parallel_bg_queries)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Number of allowed parallel background queries: %llu\n", + max_parallel_bg_queries); + } dht_handle = GNUNET_DHT_connect (c, (unsigned int) max_parallel_bg_queries); if (NULL == dht_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to DHT!\n")); - GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, + NULL); return; } - - identity_handle = GNUNET_IDENTITY_connect (c, - NULL, - NULL); - if (NULL == identity_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Could not connect to identity service!\n"); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Looking for gns-intercept ego\n"); - identity_op = GNUNET_IDENTITY_get (identity_handle, - "gns-intercept", - &identity_intercept_cb, - (void *) c); - } GNS_resolver_init (namecache_handle, dht_handle, c, max_parallel_bg_queries); - GNS_shorten_init (namestore_handle, - namecache_handle, - dht_handle); - statistics = GNUNET_STATISTICS_create ("gns", c); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); + if ( (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_yesno (c, + "gns", + "INTERCEPT_DNS")) && + (GNUNET_SYSERR == + GNS_interceptor_init (c)) ) + { + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&shutdown_task, + NULL); + return; + } + statistics = GNUNET_STATISTICS_create ("gns", + c); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); } @@ -648,10 +593,6 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_GNS_LOOKUP, struct LookupMessage, NULL), - GNUNET_MQ_hd_fixed_size (rev_lookup, - GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP, - struct ReverseLookupMessage, - NULL), GNUNET_MQ_handler_end());