Locator.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
  51. {
  52. Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_ts);
  53. int p = 8;
  54. int l = m_signer.marshal(data + p);
  55. if (l <= 0)
  56. return -1;
  57. p += l;
  58. Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_endpoints.size());
  59. p += 2;
  60. for (Vector<Endpoint>::const_iterator e(m_endpoints.begin());e != m_endpoints.end();++e) {
  61. l = e->marshal(data + p);
  62. if (l <= 0)
  63. return -1;
  64. p += l;
  65. }
  66. Utils::storeAsIsEndian<uint16_t>(data + p, 0); // length of meta-data, currently always 0
  67. p += 2;
  68. if (!excludeSignature) {
  69. Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_signature.size());
  70. p += 2;
  71. Utils::copy(data + p, m_signature.data(), m_signature.size());
  72. p += (int) m_signature.size();
  73. }
  74. return p;
  75. }
  76. int Locator::unmarshal(const uint8_t *data, const int len) noexcept
  77. {
  78. if (unlikely(len < 8))
  79. return -1;
  80. m_ts = (int64_t) Utils::loadBigEndian<uint64_t>(data);
  81. int p = 8;
  82. int l = m_signer.unmarshal(data + p,len - p);
  83. if (l <= 0)
  84. return -1;
  85. p += l;
  86. if (unlikely(p + 2) > len)
  87. return -1;
  88. unsigned int endpointCount = Utils::loadBigEndian<uint16_t>(data + 8);
  89. if (unlikely(endpointCount > ZT_LOCATOR_MAX_ENDPOINTS))
  90. return -1;
  91. m_endpoints.resize(endpointCount);
  92. m_endpoints.shrink_to_fit();
  93. for (unsigned int i = 0;i < endpointCount;++i) {
  94. l = m_endpoints[i].unmarshal(data + p, len - p);
  95. if (l <= 0)
  96. return -1;
  97. p += l;
  98. }
  99. if (unlikely((p + 2) > len))
  100. return -1;
  101. p += 2 + (int) Utils::loadBigEndian<uint16_t>(data + p);
  102. if (unlikely((p + 2) > len))
  103. return -1;
  104. const unsigned int siglen = Utils::loadBigEndian<uint16_t>(data + p);
  105. p += 2;
  106. if (unlikely((siglen > ZT_SIGNATURE_BUFFER_SIZE) || ((p + (int)siglen) > len)))
  107. return -1;
  108. m_signature.unsafeSetSize(siglen);
  109. Utils::copy(m_signature.data(), data + p, siglen);
  110. p += siglen;
  111. if (unlikely(p > len))
  112. return -1;
  113. return p;
  114. }
  115. } // namespace ZeroTier
  116. extern "C" {
  117. ZT_Locator *ZT_Locator_create(
  118. int64_t ts,
  119. const ZT_Endpoint *endpoints,
  120. unsigned int endpointCount,
  121. const ZT_Identity *signer)
  122. {
  123. try {
  124. if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer))
  125. return nullptr;
  126. ZeroTier::Locator *loc = new ZeroTier::Locator();
  127. for(unsigned int i=0;i<endpointCount;++i)
  128. loc->add(reinterpret_cast<const ZeroTier::Endpoint *>(endpoints)[i]);
  129. if (!loc->sign(ts,*reinterpret_cast<const ZeroTier::Identity *>(signer))) {
  130. delete loc;
  131. return nullptr;
  132. }
  133. return reinterpret_cast<ZT_Locator *>(loc);
  134. } catch ( ... ) {
  135. return nullptr;
  136. }
  137. }
  138. ZT_Locator *ZT_Locator_unmarshal(
  139. const void *data,
  140. unsigned int len)
  141. {
  142. try {
  143. if ((!data) || (len == 0))
  144. return nullptr;
  145. ZeroTier::Locator *loc = new ZeroTier::Locator();
  146. if (loc->unmarshal(reinterpret_cast<const uint8_t *>(data),(int)len) <= 0) {
  147. delete loc;
  148. return nullptr;
  149. }
  150. return reinterpret_cast<ZT_Locator *>(loc);
  151. } catch ( ... ) {
  152. return nullptr;
  153. }
  154. }
  155. int ZT_Locator_marshal(const ZT_Locator *loc,void *buf,unsigned int bufSize)
  156. {
  157. if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX))
  158. return -1;
  159. return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf),(int)bufSize);
  160. }
  161. const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc)
  162. {
  163. if (!loc)
  164. return nullptr;
  165. return (ZT_Fingerprint *)(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer()));
  166. }
  167. unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc)
  168. {
  169. return (loc) ? (unsigned int)(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0;
  170. }
  171. const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc,const unsigned int ep)
  172. {
  173. if (!loc)
  174. return nullptr;
  175. if (ep >= (unsigned int)(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()))
  176. return nullptr;
  177. return reinterpret_cast<const ZT_Endpoint *>(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints()[ep]));
  178. }
  179. int ZT_Locator_verify(const ZT_Locator *loc,const ZT_Identity *signer)
  180. {
  181. if ((!loc) || (!signer))
  182. return 0;
  183. return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0;
  184. }
  185. void ZT_Locator_delete(ZT_Locator *loc)
  186. {
  187. if (loc)
  188. delete reinterpret_cast<ZeroTier::Locator *>(loc);
  189. }
  190. } // C API functions