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