-more debug messages
[oweals/gnunet.git] / src / namestore / namestore_common.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file namestore/namestore_common.c
23  * @brief API to access the NAMESTORE service
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  */
27
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_arm_service.h"
33 #include "gnunet_namestore_service.h"
34 #include "gnunet_dnsparser_lib.h"
35 #include "../dns/dnsparser.h"
36 #include "namestore.h"
37
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
40
41 GNUNET_NETWORK_STRUCT_BEGIN
42
43 /**
44  * Internal format of a record in the serialized form.
45  */
46 struct NetworkRecord
47 {
48
49   /**
50    * Expiration time for the DNS record; relative or absolute depends
51    * on 'flags', network byte order.
52    */
53   uint64_t expiration_time GNUNET_PACKED;
54
55   /**
56    * Number of bytes in 'data', network byte order.
57    */
58   uint32_t data_size GNUNET_PACKED;
59
60   /**
61    * Type of the GNS/DNS record, network byte order.
62    */
63   uint32_t record_type GNUNET_PACKED;
64
65   /**
66    * Flags for the record, network byte order.
67    */
68   uint32_t flags GNUNET_PACKED;
69   
70 };
71
72 GNUNET_NETWORK_STRUCT_END
73
74
75 /**
76  * Convert a short hash to a string (for printing debug messages).
77  * This is one of the very few calls in the entire API that is
78  * NOT reentrant!
79  *
80  * @param hc the short hash code
81  * @return string form; will be overwritten by next call to GNUNET_h2s.
82  */
83 const char *
84 GNUNET_short_h2s (const struct GNUNET_CRYPTO_ShortHashCode * hc)
85 {
86   static struct GNUNET_CRYPTO_ShortHashAsciiEncoded ret;
87
88   GNUNET_CRYPTO_short_hash_to_enc (hc, &ret);
89   return (const char *) &ret;
90 }
91
92
93 /**
94  * Calculate how many bytes we will need to serialize the given
95  * records.
96  *
97  * @param rd_count number of records in the rd array
98  * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
99  *
100  * @return the required size to serialize
101  *
102  */
103 size_t
104 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
105                                    const struct GNUNET_NAMESTORE_RecordData *rd)
106 {
107   unsigned int i;
108   size_t ret;
109
110   ret = sizeof (struct NetworkRecord) * rd_count;
111   for (i=0;i<rd_count;i++)
112   {
113     GNUNET_assert ((ret + rd[i].data_size) >= ret);
114     ret += rd[i].data_size;
115   }
116   return ret;  
117 }
118
119
120 /**
121  * Serialize the given records to the given destination buffer.
122  *
123  * @param rd_count number of records in the rd array
124  * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
125  * @param dest_size size of the destination array
126  * @param dest where to write the result
127  *
128  * @return the size of serialized records
129  */
130 ssize_t
131 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
132                                     const struct GNUNET_NAMESTORE_RecordData *rd,
133                                     size_t dest_size,
134                                     char *dest)
135 {
136   struct NetworkRecord rec;
137   unsigned int i;
138   size_t off;
139   
140   off = 0;
141   for (i=0;i<rd_count;i++)
142   {
143     rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
144     rec.data_size = htonl ((uint32_t) rd[i].data_size);
145     rec.record_type = htonl (rd[i].record_type);
146     rec.flags = htonl (rd[i].flags);
147     if (off + sizeof (rec) > dest_size)
148       return -1;
149     memcpy (&dest[off], &rec, sizeof (rec));
150     off += sizeof (rec);
151     if (off + rd[i].data_size > dest_size)
152       return -1;
153     memcpy (&dest[off], rd[i].data, rd[i].data_size);
154     off += rd[i].data_size;
155   }
156   return off;
157 }
158
159
160 /**
161  * Compares if two records are equal (ignoring flags such
162  * as authority, private and pending, but not relative vs.
163  * absolute expiration time).
164  *
165  * @param a record
166  * @param b record
167  * @return GNUNET_YES if the records are equal or GNUNET_NO if they are not
168  */
169 int
170 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
171                               const struct GNUNET_NAMESTORE_RecordData *b)
172 {
173   if ((a->record_type == b->record_type) &&
174       (a->expiration_time == b->expiration_time) &&
175       ((a->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) 
176        == (b->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) &&
177       (a->data_size == b->data_size) &&
178       (0 == memcmp (a->data, b->data, a->data_size)))
179     return GNUNET_YES;
180   return GNUNET_NO;
181 }
182
183
184 /**
185  * Deserialize the given records to the given destination.
186  *
187  * @param len size of the serialized record data
188  * @param src the serialized record data
189  * @param rd_count number of records in the rd array
190  * @param dest where to put the data
191  *
192  * @return GNUNET_OK on success, GNUNET_SYSERR on error
193  */
194 int
195 GNUNET_NAMESTORE_records_deserialize (size_t len,
196                                       const char *src,
197                                       unsigned int rd_count,
198                                       struct GNUNET_NAMESTORE_RecordData *dest)
199 {
200   struct NetworkRecord rec;
201   unsigned int i;
202   size_t off;
203   
204   off = 0;
205   for (i=0;i<rd_count;i++)
206   {
207     if (off + sizeof (rec) > len)
208       return GNUNET_SYSERR;
209     memcpy (&rec, &src[off], sizeof (rec));
210     dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
211     dest[i].data_size = ntohl ((uint32_t) rec.data_size);
212     dest[i].record_type = ntohl (rec.record_type);
213     dest[i].flags = ntohl (rec.flags);
214     off += sizeof (rec);
215
216     if (off + dest[i].data_size > len)
217       return GNUNET_SYSERR;
218     dest[i].data = &src[off];
219     off += dest[i].data_size;
220   }
221   return GNUNET_OK; 
222 }
223
224
225 /**
226  * Sign name and records
227  *
228  * @param key the private key
229  * @param expire block expiration
230  * @param name the name
231  * @param rd record data
232  * @param rd_count number of records
233  *
234  * @return the signature
235  */
236 struct GNUNET_CRYPTO_RsaSignature *
237 GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
238                                    struct GNUNET_TIME_Absolute expire,
239                                    const char *name,
240                                    const struct GNUNET_NAMESTORE_RecordData *rd,
241                                    unsigned int rd_count)
242 {
243   struct GNUNET_CRYPTO_RsaSignature *sig;
244   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
245   struct GNUNET_TIME_AbsoluteNBO expire_nbo;
246   size_t rd_ser_len;
247   size_t name_len;
248   struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
249   char * name_tmp;
250   char * rd_tmp;
251   int res;
252   uint32_t sig_len;
253
254   if (NULL == name)
255   {
256     GNUNET_break (0);
257     return NULL;
258   }
259   sig = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaSignature));
260   name_len = strlen (name) + 1;
261   expire_nbo = GNUNET_TIME_absolute_hton (expire);
262   rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
263   {
264     char rd_ser[rd_ser_len];
265
266     GNUNET_assert (rd_ser_len ==
267                    GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser));
268     sig_len = sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
269     sig_purpose = GNUNET_malloc (sig_len);
270     sig_purpose->size = htonl (sig_len);
271     sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
272     expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
273     memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
274     name_tmp = (char *) &expire_tmp[1];
275     memcpy (name_tmp, name, name_len);
276     rd_tmp = &name_tmp[name_len];
277     memcpy (rd_tmp, rd_ser, rd_ser_len);
278     res = GNUNET_CRYPTO_rsa_sign (key, sig_purpose, sig);
279     GNUNET_free (sig_purpose);
280   }
281   if (GNUNET_OK != res)
282   {
283     GNUNET_break (0);
284     GNUNET_free (sig);
285     return NULL;
286   }
287   return sig;
288 }
289
290 /**
291  * Checks if a name is wellformed
292  *
293  * @param name the name to check
294  * @return GNUNET_OK on success, GNUNET_SYSERR on error
295  */
296 int
297 GNUNET_NAMESTORE_check_name (const char * name)
298 {
299   if (name == NULL)
300     return GNUNET_SYSERR;
301   if (strlen (name) > 63)
302     return GNUNET_SYSERR;
303   return GNUNET_OK;
304 }
305
306
307 /**
308  * Convert the 'value' of a record to a string.
309  *
310  * @param type type of the record
311  * @param data value in binary encoding
312  * @param data_size number of bytes in data
313  * @return NULL on error, otherwise human-readable representation of the value
314  */
315 char *
316 GNUNET_NAMESTORE_value_to_string (uint32_t type,
317                                   const void *data,
318                                   size_t data_size)
319 {
320   char tmp[INET6_ADDRSTRLEN];
321   struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
322   uint16_t mx_pref;
323   char* result;
324   char* soa_rname;
325   char* soa_mname;
326   struct soa_data *soa;
327
328   struct vpn_data *vpn;
329   char* vpn_str;
330   char* srv_str;
331   struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
332   struct srv_data *srv;
333
334   switch (type)
335   {
336   case 0:
337     return NULL;
338   case GNUNET_DNSPARSER_TYPE_A:
339     if (data_size != sizeof (struct in_addr))
340       return NULL;
341     if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
342       return NULL;
343     return GNUNET_strdup (tmp);
344   case GNUNET_DNSPARSER_TYPE_NS:
345     return GNUNET_strndup (data, data_size);
346   case GNUNET_DNSPARSER_TYPE_CNAME:
347     return GNUNET_strndup (data, data_size);
348   case GNUNET_DNSPARSER_TYPE_SOA:
349     soa = (struct soa_data*)data;
350     soa_rname = (char*)&soa[1];
351     soa_mname = (char*)&soa[1]+strlen(soa_rname)+1;
352     if (GNUNET_asprintf(&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", 
353                      soa_rname, soa_mname,
354                      ntohl (soa->serial), ntohl (soa->refresh),
355                      ntohl (soa->retry), ntohl (soa->expire), ntohl (soa->minimum)))
356       return result;
357     else
358       return NULL;
359   case GNUNET_DNSPARSER_TYPE_PTR:
360     return GNUNET_strndup (data, data_size);
361   case GNUNET_DNSPARSER_TYPE_MX:
362     mx_pref = ntohs(*((uint16_t*)data));
363     if (GNUNET_asprintf(&result, "%hu,%s", mx_pref, data+sizeof(uint16_t))
364         != 0)
365       return result;
366     else
367       return NULL;
368   case GNUNET_DNSPARSER_TYPE_TXT:
369     return GNUNET_strndup (data, data_size);
370   case GNUNET_DNSPARSER_TYPE_AAAA:
371     if (data_size != sizeof (struct in6_addr))
372       return NULL;
373     if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
374       return NULL;
375     return GNUNET_strdup (tmp);
376   case GNUNET_NAMESTORE_TYPE_PKEY:
377     if (data_size != sizeof (struct GNUNET_CRYPTO_ShortHashCode))
378       return NULL;
379     GNUNET_CRYPTO_short_hash_to_enc (data,
380                                      &enc);
381     return GNUNET_strdup ((const char*) enc.short_encoding);
382   case GNUNET_NAMESTORE_TYPE_PSEU:
383     return GNUNET_strndup (data, data_size);
384   case GNUNET_NAMESTORE_TYPE_LEHO:
385     return GNUNET_strndup (data, data_size);
386   case GNUNET_NAMESTORE_TYPE_VPN:
387     vpn = (struct vpn_data*)data;
388
389     GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer);
390     if (GNUNET_OK != GNUNET_asprintf (&vpn_str, "%d:%s:%s",
391                                       vpn->proto,
392                                       (char*)&s_peer,
393                                       (char*)&vpn[1]))
394       return NULL;
395     return vpn_str;
396   case GNUNET_DNSPARSER_TYPE_SRV:
397     srv = (struct srv_data*)data;
398
399     if (GNUNET_OK != GNUNET_asprintf (&srv_str, "%d:%d:%d:%s",
400                                       ntohs (srv->prio),
401                                       ntohs (srv->weight),
402                                       ntohs (srv->port),
403                                       (char*)&srv[1]))
404       return NULL;
405     return srv_str;
406   default:
407     GNUNET_break (0);
408   }
409   GNUNET_break (0); // not implemented
410   return NULL;
411 }
412
413
414 /**
415  * Convert human-readable version of a 'value' of a record to the binary
416  * representation.
417  *
418  * @param type type of the record
419  * @param s human-readable string
420  * @param data set to value in binary encoding (will be allocated)
421  * @param data_size set to number of bytes in data
422  * @return GNUNET_OK on success
423  */
424 int
425 GNUNET_NAMESTORE_string_to_value (uint32_t type,
426                                   const char *s,
427                                   void **data,
428                                   size_t *data_size)
429 {
430   struct in_addr value_a;
431   struct in6_addr value_aaaa;
432   struct GNUNET_CRYPTO_ShortHashCode pkey;
433   uint16_t mx_pref;
434   uint16_t mx_pref_n;
435   struct soa_data *soa;
436   char result[253];
437   char soa_rname[63];
438   char soa_mname[63];
439   uint32_t soa_serial;
440   uint32_t soa_refresh;
441   uint32_t soa_retry;
442   uint32_t soa_expire;
443   uint32_t soa_min;
444   struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
445   char s_serv[253];
446   struct vpn_data* vpn;
447   uint16_t proto;
448   
449   switch (type)
450   {
451   case 0:
452     return GNUNET_SYSERR;
453   case GNUNET_DNSPARSER_TYPE_A:
454     if (1 != inet_pton (AF_INET, s, &value_a))
455       return GNUNET_SYSERR;
456     *data = GNUNET_malloc (sizeof (struct in_addr));
457     memcpy (*data, &value_a, sizeof (value_a));
458     *data_size = sizeof (value_a);
459     return GNUNET_OK;
460   case GNUNET_DNSPARSER_TYPE_NS:
461     *data = GNUNET_strdup (s);
462     *data_size = strlen (s);
463     return GNUNET_OK;
464   case GNUNET_DNSPARSER_TYPE_CNAME:
465     *data = GNUNET_strdup (s);
466     *data_size = strlen (s);
467     return GNUNET_OK;
468   case GNUNET_DNSPARSER_TYPE_SOA:
469     
470     if (SSCANF(s, "rname=%s mname=%s %u,%u,%u,%u,%u",
471                soa_rname, soa_mname,
472                &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min) 
473         != 7)
474       return GNUNET_SYSERR;
475     
476     *data_size = sizeof (struct soa_data)+strlen(soa_rname)+strlen(soa_mname)+2;
477     *data = GNUNET_malloc (*data_size);
478     soa = (struct soa_data*)*data;
479     soa->serial = htonl(soa_serial);
480     soa->refresh = htonl(soa_refresh);
481     soa->retry = htonl(soa_retry);
482     soa->expire = htonl(soa_expire);
483     soa->minimum = htonl(soa_min);
484     strcpy((char*)&soa[1], soa_rname);
485     strcpy((char*)&soa[1]+strlen(*data)+1, soa_mname);
486     return GNUNET_OK;
487
488   case GNUNET_DNSPARSER_TYPE_PTR:
489     *data = GNUNET_strdup (s);
490     *data_size = strlen (s);
491     return GNUNET_OK;
492   case GNUNET_DNSPARSER_TYPE_MX:
493     if (SSCANF(s, "%hu,%s", &mx_pref, result) != 2)
494       return GNUNET_SYSERR;
495     *data_size = sizeof (uint16_t)+strlen(result)+1;
496     *data = GNUNET_malloc (*data_size);
497     mx_pref_n = htons(mx_pref);
498     memcpy(*data, &mx_pref_n, sizeof (uint16_t));
499     strcpy((*data)+sizeof (uint16_t), result);
500     return GNUNET_OK;
501   case GNUNET_DNSPARSER_TYPE_TXT:
502     *data = GNUNET_strdup (s);
503     *data_size = strlen (s);
504     return GNUNET_OK;
505   case GNUNET_DNSPARSER_TYPE_AAAA:
506     if (1 != inet_pton (AF_INET6, s, &value_aaaa))    
507       return GNUNET_SYSERR;    
508     *data = GNUNET_malloc (sizeof (struct in6_addr));
509     *data_size = sizeof (struct in6_addr);
510     memcpy (*data, &value_aaaa, sizeof (value_aaaa));
511     return GNUNET_OK;
512   case GNUNET_NAMESTORE_TYPE_PKEY:
513     if (GNUNET_OK !=
514         GNUNET_CRYPTO_short_hash_from_string (s, &pkey))
515       return GNUNET_SYSERR;
516     *data = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode));
517     memcpy (*data, &pkey, sizeof (pkey));
518     *data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode);
519     return GNUNET_OK;
520   case GNUNET_NAMESTORE_TYPE_PSEU:
521     *data = GNUNET_strdup (s);
522     *data_size = strlen (s);
523     return GNUNET_OK;
524   case GNUNET_NAMESTORE_TYPE_LEHO:
525     *data = GNUNET_strdup (s);
526     *data_size = strlen (s);
527     return GNUNET_OK;
528   case GNUNET_NAMESTORE_TYPE_VPN:
529     
530     
531     if (4 != SSCANF (s,"%hu:%s:%s",
532                      &proto, (char*)&s_peer, s_serv))
533     {
534       return GNUNET_SYSERR;
535     }
536     *data_size = sizeof (struct vpn_data) + strlen (s_serv) + 1;
537     
538     *data = GNUNET_malloc (*data_size);
539
540     vpn = (struct vpn_data*)*data;
541     
542     if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_peer, &vpn->peer))
543     {
544       GNUNET_free (*data);
545       return GNUNET_SYSERR;
546     }
547
548     vpn->proto = htons (proto);
549     strcpy ((char*)&vpn[1], s_serv);
550     return GNUNET_OK;
551   default:
552     GNUNET_break (0);
553   }
554   return GNUNET_SYSERR;
555 }
556
557
558 static struct { 
559   const char *name; 
560   uint32_t number; 
561 } name_map[] = {
562   { "A", GNUNET_DNSPARSER_TYPE_A },
563   { "NS", GNUNET_DNSPARSER_TYPE_NS },
564   { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
565   { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
566   { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
567   { "MX", GNUNET_DNSPARSER_TYPE_MX },
568   { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
569   { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
570   { "PKEY",  GNUNET_NAMESTORE_TYPE_PKEY },
571   { "PSEU",  GNUNET_NAMESTORE_TYPE_PSEU },
572   { "LEHO",  GNUNET_NAMESTORE_TYPE_LEHO },
573   { NULL, UINT32_MAX }
574 };
575
576
577 /**
578  * Convert a type name (i.e. "AAAA") to the corresponding number.
579  *
580  * @param typename name to convert
581  * @return corresponding number, UINT32_MAX on error
582  */
583 uint32_t
584 GNUNET_NAMESTORE_typename_to_number (const char *typename)
585 {
586   unsigned int i;
587
588   i=0;
589   while ( (name_map[i].name != NULL) &&
590           (0 != strcasecmp (typename, name_map[i].name)) )
591     i++;
592   return name_map[i].number;  
593 }
594
595
596 /**
597  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
598  *
599  * @param type number of a type to convert
600  * @return corresponding typestring, NULL on error
601  */
602 const char *
603 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
604 {
605   unsigned int i;
606
607   i=0;
608   while ( (name_map[i].name != NULL) &&
609           (type != name_map[i].number) )
610     i++;
611   return name_map[i].name;  
612 }
613
614
615
616 /* end of namestore_common.c */