Root.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (c)2019 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: 2023-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. #ifndef ZT_ROOT_HPP
  14. #define ZT_ROOT_HPP
  15. #include "Constants.hpp"
  16. #include "Str.hpp"
  17. #include "ECC384.hpp"
  18. #include "Locator.hpp"
  19. #include "InetAddress.hpp"
  20. #include "Utils.hpp"
  21. #include "Identity.hpp"
  22. #include "Mutex.hpp"
  23. namespace ZeroTier {
  24. /**
  25. * A root entry pointing to a node capable of global identity lookup and indirect transit
  26. *
  27. * Root entries point to DNS records that contain TXT entries that decode to Locator objects
  28. * pointing to actual root nodes. A default root identity and static addresses can also be
  29. * provided as fallback if DNS is not available.
  30. *
  31. * Note that root identities can change if DNS returns a different result, but that DNS entries
  32. * are authenticated using their own signature scheme. This allows a root DNS name to serve
  33. * up different roots based on factors like location or relative load of different roots.
  34. *
  35. * It's also possible to create a root with no DNS and no DNS validator public key. This root
  36. * will be a static entry pointing to a single root identity and set of physical addresses.
  37. */
  38. class Root
  39. {
  40. public:
  41. inline Root() : _dnsPublicKeySize(0) {}
  42. /**
  43. * Create a new root entry
  44. *
  45. * @param dn DNS name
  46. * @param dnspk DNS public key for record validation
  47. * @param dnspksize Size of DNS public key (currently always the size of a NIST P-384 point compressed public key)
  48. * @param dflId Default identity if DNS is not available
  49. * @param dflAddrs Default IP addresses if DNS is not available
  50. */
  51. template<typename S>
  52. inline Root(S dn,const uint8_t *const dnspk,const unsigned int dnspksize,const Identity &dflId,const std::vector<InetAddress> &dflAddrs) :
  53. _defaultIdentity(dflId),
  54. _defaultAddresses(dflAddrs),
  55. _dnsName(dn),
  56. _dnsPublicKeySize(dnspksize)
  57. {
  58. if (dnspksize != 0) {
  59. if (dnspksize > sizeof(_dnsPublicKey))
  60. throw ZT_EXCEPTION_INVALID_ARGUMENT;
  61. memcpy(_dnsPublicKey,dnspk,dnspksize);
  62. }
  63. }
  64. /**
  65. * @return Current identity (either default or latest locator)
  66. */
  67. inline const Identity id() const
  68. {
  69. if (_lastFetchedLocator.id())
  70. return _lastFetchedLocator.id();
  71. return _defaultIdentity;
  72. }
  73. /**
  74. * @param id Identity to check
  75. * @return True if identity equals this root's current identity
  76. */
  77. inline bool is(const Identity &id) const
  78. {
  79. return ((_lastFetchedLocator.id()) ? (id == _lastFetchedLocator.id()) : (id == _defaultIdentity));
  80. }
  81. /**
  82. * @return Current ZeroTier address (either default or latest locator)
  83. */
  84. inline const Address address() const
  85. {
  86. if (_lastFetchedLocator.id())
  87. return _lastFetchedLocator.id().address();
  88. return _defaultIdentity.address();
  89. }
  90. /**
  91. * @return DNS name for this root or empty string if static entry with no DNS
  92. */
  93. inline const Str dnsName() const
  94. {
  95. return _dnsName;
  96. }
  97. /**
  98. * @return Latest locator or NIL locator object if none
  99. */
  100. inline Locator locator() const
  101. {
  102. return _lastFetchedLocator;
  103. }
  104. /**
  105. * @return Timestamp of latest retrieved locator or 0 if none
  106. */
  107. inline int64_t locatorTimestamp() const
  108. {
  109. return _lastFetchedLocator.timestamp();
  110. }
  111. /**
  112. * Update locator, returning true if new locator is valid and newer than existing
  113. */
  114. inline bool updateLocator(const Locator &loc)
  115. {
  116. if (!loc.verify())
  117. return false;
  118. if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
  119. _lastFetchedLocator = loc;
  120. return true;
  121. }
  122. return false;
  123. }
  124. /**
  125. * Update this root's locator from a series of TXT records
  126. */
  127. template<typename I>
  128. inline bool updateLocatorFromTxt(I start,I end)
  129. {
  130. try {
  131. if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
  132. return false;
  133. Locator loc;
  134. if (!loc.decodeTxtRecords(start,end,_dnsPublicKey)) // also does verify()
  135. return false;
  136. if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
  137. _lastFetchedLocator = loc;
  138. return true;
  139. }
  140. return false;
  141. } catch ( ... ) {}
  142. return false;
  143. }
  144. /**
  145. * Pick a random physical IP for this root with the given address family
  146. *
  147. * @param addressFamily AF_INET or AF_INET6
  148. * @return Address or InetAddress::NIL if no addresses exist for the given family
  149. */
  150. inline const InetAddress &pickPhysical(const int addressFamily) const
  151. {
  152. std::vector<const InetAddress *> pickList;
  153. const std::vector<InetAddress> *const av = (_lastFetchedLocator) ? &(_lastFetchedLocator.phy()) : &_defaultAddresses;
  154. for(std::vector<InetAddress>::const_iterator i(av->begin());i!=av->end();++i) {
  155. if (addressFamily == (int)i->ss_family) {
  156. pickList.push_back(&(*i));
  157. }
  158. }
  159. if (pickList.size() == 1)
  160. return *pickList[0];
  161. else if (pickList.size() > 1)
  162. return *pickList[(unsigned long)Utils::random() % (unsigned long)pickList.size()];
  163. return InetAddress::NIL;
  164. }
  165. private:
  166. Identity _defaultIdentity;
  167. std::vector<InetAddress> _defaultAddresses;
  168. Str _dnsName;
  169. Locator _lastFetchedLocator;
  170. unsigned int _dnsPublicKeySize;
  171. uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
  172. };
  173. } // namespace ZeroTier
  174. #endif