Tag.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  4. *
  5. * (c) ZeroTier, Inc.
  6. * https://www.zerotier.com/
  7. */
  8. #ifndef ZT_TAG_HPP
  9. #define ZT_TAG_HPP
  10. #include "Address.hpp"
  11. #include "Buffer.hpp"
  12. #include "Constants.hpp"
  13. #include "Credential.hpp"
  14. #include "ECC.hpp"
  15. #include "Identity.hpp"
  16. #include <stdint.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. namespace ZeroTier {
  21. class RuntimeEnvironment;
  22. /**
  23. * A tag that can be associated with members and matched in rules
  24. *
  25. * Capabilities group rules, while tags group members subject to those
  26. * rules. Tag values can be matched in rules, and tags relevant to a
  27. * capability are presented along with it.
  28. *
  29. * E.g. a capability might be "can speak Samba/CIFS within your
  30. * department." This cap might have a rule to allow TCP/137 but
  31. * only if a given tag ID's value matches between two peers. The
  32. * capability is what members can do, while the tag is who they are.
  33. * Different departments might have tags with the same ID but different
  34. * values.
  35. *
  36. * Unlike capabilities tags are signed only by the issuer and are never
  37. * transferable.
  38. */
  39. class Tag : public Credential {
  40. public:
  41. static inline Credential::Type credentialType()
  42. {
  43. return Credential::CREDENTIAL_TYPE_TAG;
  44. }
  45. Tag() : _id(0), _value(0), _networkId(0), _ts(0)
  46. {
  47. memset(_signature.data, 0, sizeof(_signature.data));
  48. }
  49. /**
  50. * @param nwid Network ID
  51. * @param ts Timestamp
  52. * @param issuedTo Address to which this tag was issued
  53. * @param id Tag ID
  54. * @param value Tag value
  55. */
  56. Tag(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id, const uint32_t value) : _id(id), _value(value), _networkId(nwid), _ts(ts), _issuedTo(issuedTo), _signedBy()
  57. {
  58. memset(_signature.data, 0, sizeof(_signature.data));
  59. }
  60. inline uint32_t id() const
  61. {
  62. return _id;
  63. }
  64. inline const uint32_t& value() const
  65. {
  66. return _value;
  67. }
  68. inline uint64_t networkId() const
  69. {
  70. return _networkId;
  71. }
  72. inline int64_t timestamp() const
  73. {
  74. return _ts;
  75. }
  76. inline const Address& issuedTo() const
  77. {
  78. return _issuedTo;
  79. }
  80. inline const Address& signedBy() const
  81. {
  82. return _signedBy;
  83. }
  84. /**
  85. * Sign this tag
  86. *
  87. * @param signer Signing identity, must have private key
  88. * @return True if signature was successful
  89. */
  90. inline bool sign(const Identity& signer)
  91. {
  92. if (signer.hasPrivate()) {
  93. Buffer<sizeof(Tag) + 64> tmp;
  94. _signedBy = signer.address();
  95. this->serialize(tmp, true);
  96. _signature = signer.sign(tmp.data(), tmp.size());
  97. return true;
  98. }
  99. return false;
  100. }
  101. /**
  102. * Check this tag's signature
  103. *
  104. * @param RR Runtime environment to allow identity lookup for signedBy
  105. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  106. * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or tag
  107. */
  108. int verify(const RuntimeEnvironment* RR, void* tPtr) const;
  109. template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
  110. {
  111. if (forSign) {
  112. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  113. }
  114. b.append(_networkId);
  115. b.append(_ts);
  116. b.append(_id);
  117. b.append(_value);
  118. _issuedTo.appendTo(b);
  119. _signedBy.appendTo(b);
  120. if (! forSign) {
  121. b.append((uint8_t)1); // 1 == Ed25519
  122. b.append((uint16_t)ZT_ECC_SIGNATURE_LEN); // length of signature
  123. b.append(_signature.data, ZT_ECC_SIGNATURE_LEN);
  124. }
  125. b.append((uint16_t)0); // length of additional fields, currently 0
  126. if (forSign) {
  127. b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
  128. }
  129. }
  130. template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
  131. {
  132. unsigned int p = startAt;
  133. *this = Tag();
  134. _networkId = b.template at<uint64_t>(p);
  135. p += 8;
  136. _ts = b.template at<uint64_t>(p);
  137. p += 8;
  138. _id = b.template at<uint32_t>(p);
  139. p += 4;
  140. _value = b.template at<uint32_t>(p);
  141. p += 4;
  142. _issuedTo.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  143. p += ZT_ADDRESS_LENGTH;
  144. _signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  145. p += ZT_ADDRESS_LENGTH;
  146. if (b[p++] == 1) {
  147. if (b.template at<uint16_t>(p) != ZT_ECC_SIGNATURE_LEN) {
  148. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
  149. }
  150. p += 2;
  151. memcpy(_signature.data, b.field(p, ZT_ECC_SIGNATURE_LEN), ZT_ECC_SIGNATURE_LEN);
  152. p += ZT_ECC_SIGNATURE_LEN;
  153. }
  154. else {
  155. p += 2 + b.template at<uint16_t>(p);
  156. }
  157. p += 2 + b.template at<uint16_t>(p);
  158. if (p > b.size()) {
  159. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
  160. }
  161. return (p - startAt);
  162. }
  163. // Provides natural sort order by ID
  164. inline bool operator<(const Tag& t) const
  165. {
  166. return (_id < t._id);
  167. }
  168. inline bool operator==(const Tag& t) const
  169. {
  170. return (memcmp(this, &t, sizeof(Tag)) == 0);
  171. }
  172. inline bool operator!=(const Tag& t) const
  173. {
  174. return (memcmp(this, &t, sizeof(Tag)) != 0);
  175. }
  176. // For searching sorted arrays or lists of Tags by ID
  177. struct IdComparePredicate {
  178. inline bool operator()(const Tag& a, const Tag& b) const
  179. {
  180. return (a.id() < b.id());
  181. }
  182. inline bool operator()(const uint32_t a, const Tag& b) const
  183. {
  184. return (a < b.id());
  185. }
  186. inline bool operator()(const Tag& a, const uint32_t b) const
  187. {
  188. return (a.id() < b);
  189. }
  190. inline bool operator()(const Tag* a, const Tag* b) const
  191. {
  192. return (a->id() < b->id());
  193. }
  194. inline bool operator()(const Tag* a, const Tag& b) const
  195. {
  196. return (a->id() < b.id());
  197. }
  198. inline bool operator()(const Tag& a, const Tag* b) const
  199. {
  200. return (a.id() < b->id());
  201. }
  202. inline bool operator()(const uint32_t a, const Tag* b) const
  203. {
  204. return (a < b->id());
  205. }
  206. inline bool operator()(const Tag* a, const uint32_t b) const
  207. {
  208. return (a->id() < b);
  209. }
  210. inline bool operator()(const uint32_t a, const uint32_t b) const
  211. {
  212. return (a < b);
  213. }
  214. };
  215. private:
  216. uint32_t _id;
  217. uint32_t _value;
  218. uint64_t _networkId;
  219. int64_t _ts;
  220. Address _issuedTo;
  221. Address _signedBy;
  222. ECC::Signature _signature;
  223. };
  224. } // namespace ZeroTier
  225. #endif