first batch of license fixes (boring)
[oweals/gnunet.git] / src / gns / gns_tld_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 2016, 2018 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15 /**
16  * @file gns/gns_tld_api.c
17  * @brief library to access the GNS service, including TLD lookup
18  * @author Martin Schanzenbach
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_constants.h"
24 #include "gnunet_arm_service.h"
25 #include "gnunet_identity_service.h"
26 #include "gnunet_hello_lib.h"
27 #include "gnunet_protocols.h"
28 #include "gnunet_dht_service.h"
29 #include "gns.h"
30 #include "gns_api.h"
31
32
33 #define LOG(kind,...) GNUNET_log_from (kind, "gns-tld-api",__VA_ARGS__)
34
35
36
37 /**
38  * Handle to a lookup request
39  */
40 struct GNUNET_GNS_LookupWithTldRequest
41 {
42
43   /**
44    * handle to gns
45    */
46   struct GNUNET_GNS_Handle *gns_handle;
47
48   /**
49    * processor to call on lookup result
50    */
51   GNUNET_GNS_LookupResultProcessor2 lookup_proc;
52
53   /**
54    * Domain name we are resolving.
55    */
56   char *name;
57
58   /**
59    * @e lookup_proc closure
60    */
61   void *lookup_proc_cls;
62
63   /**
64    * Underlying GNS lookup.
65    */
66   struct GNUNET_GNS_LookupRequest *lr;
67
68   /**
69    * Lookup an ego with the identity service.
70    */
71   struct GNUNET_IDENTITY_EgoLookup *id_op;
72
73   /**
74    * Desired result record type.
75    */
76   uint32_t type;
77
78   /**
79    * Lookup options.
80    */
81   enum GNUNET_GNS_LocalOptions options;
82 };
83
84
85 /**
86  * Obtain the TLD of the given @a name.
87  *
88  * @param name a name
89  * @return the part of @a name after the last ".",
90  *         or @a name if @a name does not contain a "."
91  */
92 static char *
93 get_tld (const char *name)
94 {
95   const char *tld;
96
97   tld = strrchr (name,
98                  (unsigned char) '.');
99   if (NULL == tld)
100     tld = name;
101   else
102     tld++; /* skip the '.' */
103   return GNUNET_strdup (tld);
104 }
105
106
107 /**
108  * Eat the TLD of the given @a name.
109  *
110  * @param[in,out] name a name
111  */
112 static void
113 eat_tld (char *name)
114 {
115   char *tld;
116
117   GNUNET_assert (0 < strlen (name));
118   tld = strrchr (name,
119                  (unsigned char) '.');
120   if (NULL == tld)
121     strcpy (name,
122             GNUNET_GNS_EMPTY_LABEL_AT);
123   else
124     *tld = '\0';
125 }
126
127
128 /**
129  * Function called with the result of a GNS lookup.
130  *
131  * @param cls a `struct GNUNET_GNS_LookupWithTldRequest *`
132  * @param rd_count number of records returned
133  * @param rd array of @a rd_count records with the results
134  */
135 static void
136 process_lookup_result (void *cls,
137                        uint32_t rd_count,
138                        const struct GNUNET_GNSRECORD_Data *rd)
139 {
140   struct GNUNET_GNS_LookupWithTldRequest *ltr = cls;
141
142   ltr->lr = NULL;
143   ltr->lookup_proc (ltr->lookup_proc_cls,
144                     GNUNET_YES,
145                     rd_count,
146                     rd);
147   GNUNET_GNS_lookup_with_tld_cancel (ltr);
148 }
149
150
151 /**
152  * Perform the actual resolution, starting with the zone
153  * identified by the given public key.
154  *
155  * @param pkey public key to use for the zone, can be NULL
156  */
157 static void
158 lookup_with_public_key (struct GNUNET_GNS_LookupWithTldRequest *ltr,
159                         const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
160 {
161   ltr->lr = GNUNET_GNS_lookup (ltr->gns_handle,
162                                ltr->name,
163                                pkey,
164                                ltr->type,
165                                ltr->options,
166                                &process_lookup_result,
167                                ltr);
168 }
169
170
171 /**
172  * Method called to with the ego we are to use for the lookup,
173  * when the ego is determined by a name.
174  *
175  * @param cls a `struct GNUNET_GNS_LookupWithTldRequest *`
176  * @param ego ego handle, NULL if not found
177  */
178 static void
179 identity_zone_cb (void *cls,
180                   const struct GNUNET_IDENTITY_Ego *ego)
181 {
182   struct GNUNET_GNS_LookupWithTldRequest *ltr = cls;
183   struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
184
185   ltr->id_op = NULL;
186   if (NULL == ego)
187   {
188     ltr->lookup_proc (ltr->lookup_proc_cls,
189                       GNUNET_NO,
190                       0,
191                       NULL);
192     GNUNET_GNS_lookup_with_tld_cancel (ltr);
193     return;
194   }
195   else
196   {
197     GNUNET_IDENTITY_ego_get_public_key (ego,
198                                         &pkey);
199     lookup_with_public_key (ltr,
200                             &pkey);
201   }
202 }
203
204
205 /**
206  * Perform an asynchronous lookup operation on the GNS,
207  * determining the zone using the TLD of the given name
208  * and the current configuration to resolve TLDs to zones.
209  *
210  * @param handle handle to the GNS service
211  * @param name the name to look up, including TLD
212  * @param type the record type to look up
213  * @param options local options for the lookup
214  * @param proc processor to call on result
215  * @param proc_cls closure for @a proc
216  * @return handle to the get request, NULL on error (i.e. bad configuration)
217  */
218 struct GNUNET_GNS_LookupWithTldRequest *
219 GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle,
220                             const char *name,
221                             uint32_t type,
222                             enum GNUNET_GNS_LocalOptions options,
223                             GNUNET_GNS_LookupResultProcessor2 proc,
224                             void *proc_cls)
225 {
226   struct GNUNET_GNS_LookupWithTldRequest *ltr;
227   char *tld;
228   char *dot_tld;
229   char *zonestr;
230   struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
231
232   ltr = GNUNET_new (struct GNUNET_GNS_LookupWithTldRequest);
233   ltr->gns_handle = handle;
234   ltr->name = GNUNET_strdup (name);
235   ltr->type = type;
236   ltr->options = options;
237   ltr->lookup_proc = proc;
238   ltr->lookup_proc_cls = proc_cls;
239   /* start with trivial case: TLD is zkey */
240   tld = get_tld (ltr->name);
241   if (GNUNET_OK ==
242       GNUNET_CRYPTO_ecdsa_public_key_from_string (tld,
243                                                   strlen (tld),
244                                                   &pkey))
245   {
246     eat_tld (ltr->name);
247     lookup_with_public_key (ltr,
248                             &pkey);
249     GNUNET_free (tld);
250     return ltr;
251   }
252
253   /* second case: TLD is mapped in our configuration file */
254   GNUNET_asprintf (&dot_tld,
255                    ".%s",
256                    tld);
257   if (GNUNET_OK ==
258       GNUNET_CONFIGURATION_get_value_string (handle->cfg,
259                                              "gns",
260                                              dot_tld,
261                                              &zonestr))
262   {
263     if (GNUNET_OK !=
264         GNUNET_CRYPTO_ecdsa_public_key_from_string (zonestr,
265                                                     strlen (zonestr),
266                                                     &pkey))
267     {
268       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
269                                  "gns",
270                                  dot_tld,
271                                  _("Expected a base32-encoded public zone key\n"));
272       GNUNET_free (zonestr);
273       GNUNET_free (dot_tld);
274       GNUNET_free (ltr->name);
275       GNUNET_free (ltr);
276       GNUNET_free (tld);
277       return NULL;
278     }
279     GNUNET_free (dot_tld);
280     GNUNET_free (zonestr);
281     eat_tld (ltr->name);
282     lookup_with_public_key (ltr,
283                             &pkey);
284     GNUNET_free (tld);
285     return ltr;
286   }
287   GNUNET_free (dot_tld);
288
289   /* Final case: TLD matches one of our egos */
290   eat_tld (ltr->name);
291
292   /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */
293   if (NULL == strchr (ltr->name,
294                       (unsigned char) '.'))
295     ltr->options = GNUNET_GNS_LO_NO_DHT;
296   else
297     ltr->options = GNUNET_GNS_LO_LOCAL_MASTER;
298   ltr->id_op = GNUNET_IDENTITY_ego_lookup (ltr->gns_handle->cfg,
299                                            tld,
300                                            &identity_zone_cb,
301                                            ltr);
302   GNUNET_free (tld);
303   if (NULL == ltr->id_op)
304   {
305     GNUNET_free (ltr->name);
306     GNUNET_free (ltr);
307     return NULL;
308   }
309   return ltr;
310 }
311
312
313 /**
314  * Cancel pending lookup request
315  *
316  * @param ltr the lookup request to cancel
317  */
318 void
319 GNUNET_GNS_lookup_with_tld_cancel (struct GNUNET_GNS_LookupWithTldRequest *ltr)
320 {
321   if (NULL != ltr->id_op)
322   {
323     GNUNET_IDENTITY_ego_lookup_cancel (ltr->id_op);
324     ltr->id_op = NULL;
325   }
326   if (NULL != ltr->lr)
327   {
328     GNUNET_GNS_lookup_cancel (ltr->lr);
329     ltr->lr = NULL;
330   }
331   GNUNET_free (ltr->name);
332   GNUNET_free (ltr);
333 }
334
335 /* end of gns_tld_api.c */