-added vpn gns test, fixes
[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, "%hu %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   char s_peer[104];
445   char s_serv[253];
446   struct vpn_data* vpn;
447   uint16_t proto;
448   int ret;
449   
450   switch (type)
451   {
452   case 0:
453     return GNUNET_SYSERR;
454   case GNUNET_DNSPARSER_TYPE_A:
455     if (1 != inet_pton (AF_INET, s, &value_a))
456       return GNUNET_SYSERR;
457     *data = GNUNET_malloc (sizeof (struct in_addr));
458     memcpy (*data, &value_a, sizeof (value_a));
459     *data_size = sizeof (value_a);
460     return GNUNET_OK;
461   case GNUNET_DNSPARSER_TYPE_NS:
462     *data = GNUNET_strdup (s);
463     *data_size = strlen (s);
464     return GNUNET_OK;
465   case GNUNET_DNSPARSER_TYPE_CNAME:
466     *data = GNUNET_strdup (s);
467     *data_size = strlen (s);
468     return GNUNET_OK;
469   case GNUNET_DNSPARSER_TYPE_SOA:
470     
471     if (SSCANF(s, "rname=%s mname=%s %u,%u,%u,%u,%u",
472                soa_rname, soa_mname,
473                &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min) 
474         != 7)
475       return GNUNET_SYSERR;
476     
477     *data_size = sizeof (struct soa_data)+strlen(soa_rname)+strlen(soa_mname)+2;
478     *data = GNUNET_malloc (*data_size);
479     soa = (struct soa_data*)*data;
480     soa->serial = htonl(soa_serial);
481     soa->refresh = htonl(soa_refresh);
482     soa->retry = htonl(soa_retry);
483     soa->expire = htonl(soa_expire);
484     soa->minimum = htonl(soa_min);
485     strcpy((char*)&soa[1], soa_rname);
486     strcpy((char*)&soa[1]+strlen(*data)+1, soa_mname);
487     return GNUNET_OK;
488
489   case GNUNET_DNSPARSER_TYPE_PTR:
490     *data = GNUNET_strdup (s);
491     *data_size = strlen (s);
492     return GNUNET_OK;
493   case GNUNET_DNSPARSER_TYPE_MX:
494     if (SSCANF(s, "%hu,%s", &mx_pref, result) != 2)
495       return GNUNET_SYSERR;
496     *data_size = sizeof (uint16_t)+strlen(result)+1;
497     *data = GNUNET_malloc (*data_size);
498     mx_pref_n = htons(mx_pref);
499     memcpy(*data, &mx_pref_n, sizeof (uint16_t));
500     strcpy((*data)+sizeof (uint16_t), result);
501     return GNUNET_OK;
502   case GNUNET_DNSPARSER_TYPE_TXT:
503     *data = GNUNET_strdup (s);
504     *data_size = strlen (s);
505     return GNUNET_OK;
506   case GNUNET_DNSPARSER_TYPE_AAAA:
507     if (1 != inet_pton (AF_INET6, s, &value_aaaa))    
508       return GNUNET_SYSERR;    
509     *data = GNUNET_malloc (sizeof (struct in6_addr));
510     *data_size = sizeof (struct in6_addr);
511     memcpy (*data, &value_aaaa, sizeof (value_aaaa));
512     return GNUNET_OK;
513   case GNUNET_NAMESTORE_TYPE_PKEY:
514     if (GNUNET_OK !=
515         GNUNET_CRYPTO_short_hash_from_string (s, &pkey))
516       return GNUNET_SYSERR;
517     *data = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode));
518     memcpy (*data, &pkey, sizeof (pkey));
519     *data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode);
520     return GNUNET_OK;
521   case GNUNET_NAMESTORE_TYPE_PSEU:
522     *data = GNUNET_strdup (s);
523     *data_size = strlen (s);
524     return GNUNET_OK;
525   case GNUNET_NAMESTORE_TYPE_LEHO:
526     *data = GNUNET_strdup (s);
527     *data_size = strlen (s);
528     return GNUNET_OK;
529   case GNUNET_NAMESTORE_TYPE_VPN:
530     
531     ret = SSCANF (s,"%hu %s %s",
532                   &proto, s_peer, s_serv);
533     if (3 != ret)
534     {
535       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
536                   "Unable to parse VPN record string %s %d\n", s, ret);
537       return GNUNET_SYSERR;
538     }
539     *data_size = sizeof (struct vpn_data) + strlen (s_serv) + 1;
540     
541     *data = GNUNET_malloc (*data_size);
542
543     vpn = (struct vpn_data*)*data;
544     
545     if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_peer, &vpn->peer))
546     {
547       GNUNET_free (*data);
548       return GNUNET_SYSERR;
549     }
550
551     vpn->proto = htons (proto);
552     strcpy ((char*)&vpn[1], s_serv);
553     return GNUNET_OK;
554   default:
555     GNUNET_break (0);
556   }
557   return GNUNET_SYSERR;
558 }
559
560
561 static struct { 
562   const char *name; 
563   uint32_t number; 
564 } name_map[] = {
565   { "A", GNUNET_DNSPARSER_TYPE_A },
566   { "NS", GNUNET_DNSPARSER_TYPE_NS },
567   { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
568   { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
569   { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
570   { "MX", GNUNET_DNSPARSER_TYPE_MX },
571   { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
572   { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
573   { "PKEY",  GNUNET_NAMESTORE_TYPE_PKEY },
574   { "PSEU",  GNUNET_NAMESTORE_TYPE_PSEU },
575   { "LEHO",  GNUNET_NAMESTORE_TYPE_LEHO },
576   { NULL, UINT32_MAX }
577 };
578
579
580 /**
581  * Convert a type name (i.e. "AAAA") to the corresponding number.
582  *
583  * @param typename name to convert
584  * @return corresponding number, UINT32_MAX on error
585  */
586 uint32_t
587 GNUNET_NAMESTORE_typename_to_number (const char *typename)
588 {
589   unsigned int i;
590
591   i=0;
592   while ( (name_map[i].name != NULL) &&
593           (0 != strcasecmp (typename, name_map[i].name)) )
594     i++;
595   return name_map[i].number;  
596 }
597
598
599 /**
600  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
601  *
602  * @param type number of a type to convert
603  * @return corresponding typestring, NULL on error
604  */
605 const char *
606 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
607 {
608   unsigned int i;
609
610   i=0;
611   while ( (name_map[i].name != NULL) &&
612           (type != name_map[i].number) )
613     i++;
614   return name_map[i].name;  
615 }
616
617
618
619 /* end of namestore_common.c */