gnsrecord_misc.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009-2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file gnsrecord/gnsrecord_misc.c
  19. * @brief MISC functions related to GNS records
  20. * @author Martin Schanzenbach
  21. * @author Matthias Wachs
  22. * @author Christian Grothoff
  23. */
  24. #include "platform.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_constants.h"
  27. #include "gnunet_signatures.h"
  28. #include "gnunet_arm_service.h"
  29. #include "gnunet_gnsrecord_lib.h"
  30. #include "gnunet_dnsparser_lib.h"
  31. #include "gnunet_tun_lib.h"
  32. #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
  33. /**
  34. * Convert a UTF-8 string to UTF-8 lowercase
  35. * @param src source string
  36. * @return converted result
  37. */
  38. char *
  39. GNUNET_GNSRECORD_string_to_lowercase (const char *src)
  40. {
  41. char *res;
  42. res = GNUNET_strdup (src);
  43. GNUNET_STRINGS_utf8_tolower (src, res);
  44. return res;
  45. }
  46. /**
  47. * Convert a zone key to a string (for printing debug messages).
  48. * This is one of the very few calls in the entire API that is
  49. * NOT reentrant!
  50. *
  51. * @param z the zone key
  52. * @return string form; will be overwritten by next call to #GNUNET_GNSRECORD_z2s
  53. */
  54. const char *
  55. GNUNET_GNSRECORD_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z)
  56. {
  57. static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8];
  58. char *end;
  59. end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
  60. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
  61. buf, sizeof (buf));
  62. if (NULL == end)
  63. {
  64. GNUNET_break (0);
  65. return NULL;
  66. }
  67. *end = '\0';
  68. return buf;
  69. }
  70. /**
  71. * Compares if two records are equal (ignoring flags such
  72. * as authority, private and pending, but not relative vs.
  73. * absolute expiration time).
  74. *
  75. * @param a record
  76. * @param b record
  77. * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
  78. */
  79. int
  80. GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a,
  81. const struct GNUNET_GNSRECORD_Data *b)
  82. {
  83. LOG (GNUNET_ERROR_TYPE_DEBUG,
  84. "Comparing records\n");
  85. if (a->record_type != b->record_type)
  86. {
  87. LOG (GNUNET_ERROR_TYPE_DEBUG,
  88. "Record type %lu != %lu\n", a->record_type, b->record_type);
  89. return GNUNET_NO;
  90. }
  91. if ((a->expiration_time != b->expiration_time) &&
  92. ((a->expiration_time != 0) && (b->expiration_time != 0)))
  93. {
  94. LOG (GNUNET_ERROR_TYPE_DEBUG,
  95. "Expiration time %llu != %llu\n",
  96. a->expiration_time,
  97. b->expiration_time);
  98. return GNUNET_NO;
  99. }
  100. if ((a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS)
  101. != (b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS))
  102. {
  103. LOG (GNUNET_ERROR_TYPE_DEBUG,
  104. "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
  105. a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS, b->flags,
  106. b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS);
  107. return GNUNET_NO;
  108. }
  109. if (a->data_size != b->data_size)
  110. {
  111. LOG (GNUNET_ERROR_TYPE_DEBUG,
  112. "Data size %lu != %lu\n",
  113. a->data_size,
  114. b->data_size);
  115. return GNUNET_NO;
  116. }
  117. if (0 != memcmp (a->data, b->data, a->data_size))
  118. {
  119. LOG (GNUNET_ERROR_TYPE_DEBUG,
  120. "Data contents do not match\n");
  121. return GNUNET_NO;
  122. }
  123. LOG (GNUNET_ERROR_TYPE_DEBUG,
  124. "Records are equal\n");
  125. return GNUNET_YES;
  126. }
  127. /**
  128. * Returns the expiration time of the given block of records. The block
  129. * expiration time is the expiration time of the record with smallest
  130. * expiration time.
  131. *
  132. * @param rd_count number of records given in @a rd
  133. * @param rd array of records
  134. * @return absolute expiration time
  135. */
  136. struct GNUNET_TIME_Absolute
  137. GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
  138. const struct GNUNET_GNSRECORD_Data *rd)
  139. {
  140. unsigned int c;
  141. unsigned int c2;
  142. struct GNUNET_TIME_Absolute expire;
  143. struct GNUNET_TIME_Absolute at;
  144. struct GNUNET_TIME_Relative rt;
  145. struct GNUNET_TIME_Absolute at_shadow;
  146. struct GNUNET_TIME_Relative rt_shadow;
  147. if (NULL == rd)
  148. return GNUNET_TIME_UNIT_ZERO_ABS;
  149. expire = GNUNET_TIME_UNIT_FOREVER_ABS;
  150. for (c = 0; c < rd_count; c++)
  151. {
  152. if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
  153. {
  154. rt.rel_value_us = rd[c].expiration_time;
  155. at = GNUNET_TIME_relative_to_absolute (rt);
  156. }
  157. else
  158. {
  159. at.abs_value_us = rd[c].expiration_time;
  160. }
  161. for (c2 = 0; c2 < rd_count; c2++)
  162. {
  163. /* Check for shadow record */
  164. if ((c == c2) ||
  165. (rd[c].record_type != rd[c2].record_type) ||
  166. (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)))
  167. continue;
  168. /* We have a shadow record */
  169. if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
  170. {
  171. rt_shadow.rel_value_us = rd[2].expiration_time;
  172. at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow);
  173. }
  174. else
  175. {
  176. at_shadow.abs_value_us = rd[c2].expiration_time;
  177. }
  178. at = GNUNET_TIME_absolute_max (at, at_shadow);
  179. }
  180. expire = GNUNET_TIME_absolute_min (at, expire);
  181. }
  182. LOG (GNUNET_ERROR_TYPE_DEBUG,
  183. "Determined expiration time for block with %u records to be %s\n",
  184. rd_count,
  185. GNUNET_STRINGS_absolute_time_to_string (expire));
  186. return expire;
  187. }
  188. /**
  189. * Test if a given record is expired.
  190. *
  191. * @return #GNUNET_YES if the record is expired,
  192. * #GNUNET_NO if not
  193. */
  194. int
  195. GNUNET_GNSRECORD_is_expired (const struct GNUNET_GNSRECORD_Data *rd)
  196. {
  197. struct GNUNET_TIME_Absolute at;
  198. if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
  199. return GNUNET_NO;
  200. at.abs_value_us = rd->expiration_time;
  201. return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
  202. }
  203. /**
  204. * Convert public key to the respective absolute domain name in the
  205. * ".zkey" pTLD.
  206. * This is one of the very few calls in the entire API that is
  207. * NOT reentrant!
  208. *
  209. * @param pkey a public key with a point on the eliptic curve
  210. * @return string "X.zkey" where X is the public
  211. * key in an encoding suitable for DNS labels.
  212. */
  213. const char *
  214. GNUNET_GNSRECORD_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
  215. {
  216. static char ret[128];
  217. char *pkeys;
  218. pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey);
  219. GNUNET_snprintf (ret,
  220. sizeof (ret),
  221. "%s.zkey",
  222. pkeys);
  223. GNUNET_free (pkeys);
  224. return ret;
  225. }
  226. /**
  227. * Convert an absolute domain name in the ".zkey" pTLD to the
  228. * respective public key.
  229. *
  230. * @param zkey string "X.zkey" where X is the coordinates of the public
  231. * key in an encoding suitable for DNS labels.
  232. * @param pkey set to a public key on the eliptic curve
  233. * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
  234. */
  235. int
  236. GNUNET_GNSRECORD_zkey_to_pkey (const char *zkey,
  237. struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
  238. {
  239. char *cpy;
  240. char *dot;
  241. const char *x;
  242. cpy = GNUNET_strdup (zkey);
  243. x = cpy;
  244. if (NULL == (dot = strchr (x, (int) '.')))
  245. goto error;
  246. *dot = '\0';
  247. if (0 != strcasecmp (dot + 1,
  248. "zkey"))
  249. goto error;
  250. if (GNUNET_OK !=
  251. GNUNET_CRYPTO_ecdsa_public_key_from_string (x,
  252. strlen (x),
  253. pkey))
  254. goto error;
  255. GNUNET_free (cpy);
  256. return GNUNET_OK;
  257. error:
  258. GNUNET_free (cpy);
  259. return GNUNET_SYSERR;
  260. }
  261. /* end of gnsrecord_misc.c */