Locator.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2024-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "Locator.hpp"
  14. #include "Identity.hpp"
  15. #include <algorithm>
  16. namespace ZeroTier {
  17. Locator::Locator(const char *const str) noexcept
  18. {
  19. if (!fromString(str)) {
  20. m_ts = 0;
  21. m_signer.zero();
  22. m_endpoints.clear();
  23. m_signature.clear();
  24. }
  25. }
  26. bool Locator::add(const Endpoint &ep)
  27. {
  28. if (m_endpoints.size() < ZT_LOCATOR_MAX_ENDPOINTS) {
  29. if (std::find(m_endpoints.begin(), m_endpoints.end(), ep) == m_endpoints.end())
  30. m_endpoints.push_back(ep);
  31. return true;
  32. }
  33. return false;
  34. }
  35. bool Locator::sign(const int64_t ts, const Identity &id) noexcept
  36. {
  37. m_ts = ts;
  38. m_signer = id.fingerprint();
  39. std::sort(m_endpoints.begin(), m_endpoints.end());
  40. uint8_t signdata[ZT_LOCATOR_MARSHAL_SIZE_MAX];
  41. const unsigned int signlen = marshal(signdata, true);
  42. const unsigned int siglen = id.sign(signdata, signlen, m_signature.data(), m_signature.capacity());
  43. if (siglen == 0)
  44. return false;
  45. m_signature.unsafeSetSize(siglen);
  46. return true;
  47. }
  48. bool Locator::verify(const Identity &id) const noexcept
  49. {
  50. try {
  51. if ((m_ts > 0) && (m_signer == id.fingerprint())) {
  52. uint8_t signdata[ZT_LOCATOR_MARSHAL_SIZE_MAX];
  53. const unsigned int signlen = marshal(signdata, true);
  54. return id.verify(signdata, signlen, m_signature.data(), m_signature.size());
  55. }
  56. } catch (...) {} // fail verify on any unexpected exception
  57. return false;
  58. }
  59. char *Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
  60. {
  61. static_assert(ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1), "overflow");
  62. uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
  63. Address(m_signer.address).toString(s);
  64. s[ZT_ADDRESS_LENGTH_HEX] = '@';
  65. Utils::b32e(bin, marshal(bin, false), s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
  66. return s;
  67. }
  68. bool Locator::fromString(const char *s) noexcept
  69. {
  70. if (!s)
  71. return false;
  72. if (strlen(s) < (ZT_ADDRESS_LENGTH_HEX + 1))
  73. return false;
  74. uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
  75. const int bl = Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), bin, ZT_LOCATOR_MARSHAL_SIZE_MAX);
  76. if ((bl <= 0) || (bl > ZT_LOCATOR_MARSHAL_SIZE_MAX))
  77. return false;
  78. return unmarshal(bin, bl) > 0;
  79. }
  80. int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
  81. {
  82. Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_ts);
  83. int p = 8;
  84. int l = m_signer.marshal(data + p);
  85. if (l <= 0)
  86. return -1;
  87. p += l;
  88. Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_endpoints.size());
  89. p += 2;
  90. for (Vector<Endpoint>::const_iterator e(m_endpoints.begin());e != m_endpoints.end();++e) {
  91. l = e->marshal(data + p);
  92. if (l <= 0)
  93. return -1;
  94. p += l;
  95. }
  96. Utils::storeAsIsEndian<uint16_t>(data + p, 0); // length of meta-data, currently always 0
  97. p += 2;
  98. if (!excludeSignature) {
  99. Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signature.size());
  100. p += 2;
  101. Utils::copy(data + p, m_signature.data(), m_signature.size());
  102. p += (int) m_signature.size();
  103. }
  104. return p;
  105. }
  106. int Locator::unmarshal(const uint8_t *data, const int len) noexcept
  107. {
  108. if (unlikely(len < 8))
  109. return -1;
  110. m_ts = (int64_t) Utils::loadBigEndian<uint64_t>(data);
  111. int p = 8;
  112. int l = m_signer.unmarshal(data + p, len - p);
  113. if (l <= 0)
  114. return -1;
  115. p += l;
  116. if (unlikely(p + 2) > len)
  117. return -1;
  118. unsigned int endpointCount = Utils::loadBigEndian<uint16_t>(data + p);
  119. p += 2;
  120. if (unlikely(endpointCount > ZT_LOCATOR_MAX_ENDPOINTS))
  121. return -1;
  122. m_endpoints.resize(endpointCount);
  123. m_endpoints.shrink_to_fit();
  124. for (unsigned int i = 0;i < endpointCount;++i) {
  125. l = m_endpoints[i].unmarshal(data + p, len - p);
  126. if (l <= 0)
  127. return -1;
  128. p += l;
  129. }
  130. if (unlikely((p + 2) > len))
  131. return -1;
  132. p += 2 + (int) Utils::loadBigEndian<uint16_t>(data + p);
  133. if (unlikely((p + 2) > len))
  134. return -1;
  135. const unsigned int siglen = Utils::loadBigEndian<uint16_t>(data + p);
  136. p += 2;
  137. if (unlikely((siglen > ZT_SIGNATURE_BUFFER_SIZE) || ((p + (int) siglen) > len)))
  138. return -1;
  139. m_signature.unsafeSetSize(siglen);
  140. Utils::copy(m_signature.data(), data + p, siglen);
  141. p += siglen;
  142. if (unlikely(p > len))
  143. return -1;
  144. return p;
  145. }
  146. } // namespace ZeroTier
  147. extern "C" {
  148. ZT_Locator *ZT_Locator_create(
  149. int64_t ts,
  150. const ZT_Endpoint *endpoints,
  151. unsigned int endpointCount,
  152. const ZT_Identity *signer)
  153. {
  154. try {
  155. if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer))
  156. return nullptr;
  157. ZeroTier::Locator *loc = new ZeroTier::Locator();
  158. for (unsigned int i = 0;i < endpointCount;++i)
  159. loc->add(reinterpret_cast<const ZeroTier::Endpoint *>(endpoints)[i]);
  160. if (!loc->sign(ts, *reinterpret_cast<const ZeroTier::Identity *>(signer))) {
  161. delete loc;
  162. return nullptr;
  163. }
  164. return reinterpret_cast<ZT_Locator *>(loc);
  165. } catch (...) {
  166. return nullptr;
  167. }
  168. }
  169. ZT_Locator *ZT_Locator_fromString(const char *str)
  170. {
  171. try {
  172. if (!str)
  173. return nullptr;
  174. ZeroTier::Locator *loc = new ZeroTier::Locator();
  175. if (!loc->fromString(str)) {
  176. delete loc;
  177. return nullptr;
  178. }
  179. return reinterpret_cast<ZT_Locator *>(loc);
  180. } catch ( ... ) {
  181. return nullptr;
  182. }
  183. }
  184. ZT_Locator *ZT_Locator_unmarshal(
  185. const void *data,
  186. unsigned int len)
  187. {
  188. try {
  189. if ((!data) || (len == 0))
  190. return nullptr;
  191. ZeroTier::Locator *loc = new ZeroTier::Locator();
  192. if (loc->unmarshal(reinterpret_cast<const uint8_t *>(data), (int) len) <= 0) {
  193. delete loc;
  194. return nullptr;
  195. }
  196. return reinterpret_cast<ZT_Locator *>(loc);
  197. } catch (...) {
  198. return nullptr;
  199. }
  200. }
  201. int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize)
  202. {
  203. if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX))
  204. return -1;
  205. return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf), (int) bufSize);
  206. }
  207. char *ZT_Locator_toString(
  208. const ZT_Locator *loc,
  209. char *buf,
  210. int capacity)
  211. {
  212. if ((!loc) || (capacity < ZT_LOCATOR_STRING_SIZE_MAX))
  213. return nullptr;
  214. return reinterpret_cast<const ZeroTier::Locator *>(loc)->toString(buf);
  215. }
  216. const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc)
  217. {
  218. if (!loc)
  219. return nullptr;
  220. return (ZT_Fingerprint *) (&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer()));
  221. }
  222. int64_t ZT_Locator_timestamp(const ZT_Locator *loc)
  223. {
  224. if (!loc)
  225. return 0;
  226. return reinterpret_cast<const ZeroTier::Locator *>(loc)->timestamp();
  227. }
  228. unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc)
  229. {
  230. return (loc) ? (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0;
  231. }
  232. const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep)
  233. {
  234. if (!loc)
  235. return nullptr;
  236. if (ep >= (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()))
  237. return nullptr;
  238. return reinterpret_cast<const ZT_Endpoint *>(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints()[ep]));
  239. }
  240. int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer)
  241. {
  242. if ((!loc) || (!signer))
  243. return 0;
  244. return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0;
  245. }
  246. void ZT_Locator_delete(ZT_Locator *loc)
  247. {
  248. if (loc)
  249. delete reinterpret_cast<ZeroTier::Locator *>(loc);
  250. }
  251. } // C API functions