2
0

Locator.cpp 7.3 KB

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