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