Root.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. ZT_ALWAYS_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. ZT_ALWAYS_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. ZT_ALWAYS_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. ZT_ALWAYS_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. ZT_ALWAYS_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. ZT_ALWAYS_INLINE const Str dnsName() const { return _dnsName; }
  94. /**
  95. * @return Latest locator or NIL locator object if none
  96. */
  97. ZT_ALWAYS_INLINE Locator locator() const { return _lastFetchedLocator; }
  98. /**
  99. * @return Timestamp of latest retrieved locator or 0 if none
  100. */
  101. ZT_ALWAYS_INLINE int64_t locatorTimestamp() const { return _lastFetchedLocator.timestamp(); }
  102. /**
  103. * Update locator, returning true if new locator is valid and newer than existing
  104. */
  105. ZT_ALWAYS_INLINE bool updateLocator(const Locator &loc)
  106. {
  107. if (!loc.verify())
  108. return false;
  109. if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
  110. _lastFetchedLocator = loc;
  111. return true;
  112. }
  113. return false;
  114. }
  115. /**
  116. * Update this root's locator from a series of TXT records
  117. */
  118. template<typename I>
  119. ZT_ALWAYS_INLINE bool updateLocatorFromTxt(I start,I end)
  120. {
  121. try {
  122. if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
  123. return false;
  124. Locator loc;
  125. if (!loc.decodeTxtRecords(start,end,_dnsPublicKey)) // also does verify()
  126. return false;
  127. if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
  128. _lastFetchedLocator = loc;
  129. return true;
  130. }
  131. return false;
  132. } catch ( ... ) {}
  133. return false;
  134. }
  135. /**
  136. * Pick a random physical IP for this root with the given address family
  137. *
  138. * @param addressFamily AF_INET or AF_INET6
  139. * @return Address or InetAddress::NIL if no addresses exist for the given family
  140. */
  141. ZT_ALWAYS_INLINE const InetAddress &pickPhysical(const int addressFamily) const
  142. {
  143. std::vector<const InetAddress *> pickList;
  144. const std::vector<InetAddress> *const av = (_lastFetchedLocator) ? &(_lastFetchedLocator.phy()) : &_defaultAddresses;
  145. for(std::vector<InetAddress>::const_iterator i(av->begin());i!=av->end();++i) {
  146. if (addressFamily == (int)i->ss_family) {
  147. pickList.push_back(&(*i));
  148. }
  149. }
  150. if (pickList.size() == 1)
  151. return *pickList[0];
  152. else if (pickList.size() > 1)
  153. return *pickList[(unsigned long)Utils::random() % (unsigned long)pickList.size()];
  154. return InetAddress::NIL;
  155. }
  156. private:
  157. Identity _defaultIdentity;
  158. std::vector<InetAddress> _defaultAddresses;
  159. Str _dnsName;
  160. Locator _lastFetchedLocator;
  161. unsigned int _dnsPublicKeySize;
  162. uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
  163. };
  164. } // namespace ZeroTier
  165. #endif