Adam Ierymenko 6 lat temu
rodzic
commit
7e105343e2
5 zmienionych plików z 273 dodań i 30 usunięć
  1. 68 0
      node/Locator.cpp
  2. 128 0
      node/Locator.hpp
  3. 3 2
      node/Packet.hpp
  4. 71 3
      node/Utils.cpp
  5. 3 25
      node/Utils.hpp

+ 68 - 0
node/Locator.cpp

@@ -0,0 +1,68 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2019  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
+ */
+
+#include "Locator.hpp"
+#include "Utils.hpp"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define ZT_LOCATOR_SIGNING_BUFFER_SIZE (64 + (18 * ZT_LOCATOR_MAX_PHYSICAL_ENDPOINTS) + (256 * ZT_LOCATOR_MAX_VIRTUAL_ENDPOINTS))
+
+namespace ZeroTier {
+
+void Locator::sign(const Identity &id,const Identity &organization,const int64_t timestamp)
+{
+	Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE> *const sb = new Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE>();
+	_ts = timestamp;
+	_id = id;
+	_organization = organization;
+	serialize(*sb,true);
+	if (id)
+		_signatureLength = id.sign(sb->data(),sb->size(),_signature,sizeof(_signature));
+	if (organization)
+		_orgSignatureLength = organization.sign(sb->data(),sb->size(),_orgSignature,sizeof(_orgSignature));
+	delete sb;
+}
+
+bool Locator::verify() const
+{
+	Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE> *const sb = new Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE>();
+	serialize(*sb,true);
+	bool ok = _id.verify(sb->data(),sb->size(),_signature,_signatureLength);
+	if ((ok)&&(_organization))
+		ok &= _organization.verify(sb->data(),sb->size(),_orgSignature,_orgSignatureLength);
+	delete sb;
+	return ok;
+}
+
+void Locator::generateDNSRecords(char *buf,unsigned int buflen)
+{
+	Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE> *const sb = new Buffer<ZT_LOCATOR_SIGNING_BUFFER_SIZE>();
+	delete sb;
+}
+
+} // namespace ZeroTier

+ 128 - 0
node/Locator.hpp

@@ -0,0 +1,128 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2019  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
+ */
+
+#ifndef ZT_LOCATOR_HPP
+#define ZT_LOCATOR_HPP
+
+#include "Constants.hpp"
+#include "Identity.hpp"
+#include "InetAddress.hpp"
+
+#include <vector>
+
+#define ZT_LOCATOR_MAX_PHYSICAL_ENDPOINTS 32
+#define ZT_LOCATOR_MAX_VIRTUAL_ENDPOINTS 32
+
+namespace ZeroTier {
+
+/**
+ * Signed information about a node's location on the network
+ */
+class Locator
+{
+public:
+	Locator() :
+		_signatureLength(0),
+		_orgSignatureLength(0) {}
+
+	inline void addLocation(const InetAddress &phy) { if (_physical.size() < ZT_LOCATOR_MAX_PHYSICAL_ENDPOINTS) _physical.push_back(phy); }
+	inline void addLocation(const Identity &v) { if (_virtual.size() < ZT_LOCATOR_MAX_VIRTUAL_ENDPOINTS) _virtual.push_back(v); }
+
+	inline const std::vector<InetAddress> &physical() const { return _physical; }
+	inline const std::vector<Identity> &virt() const { return _virtual; }
+
+	void sign(const Identity &id,const Identity &organization,const int64_t timestamp);
+	bool verify() const;
+
+	void generateDNSRecords(char *buf,unsigned int buflen);
+
+	template<unsigned int C>
+	inline void serialize(Buffer<C> &b,const bool forSign = false) const
+	{
+		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
+
+		b.append((uint64_t)_ts);
+		_id.serialize(b,false);
+		_organization.serialize(b,false);
+		b.append((uint16_t)_physical.size());
+		for(std::vector<InetAddress>::const_iterator i(_physical.begin());i!=_physical.end();++i)
+			i->serialize(b);
+		b.append((uint16_t)_virtual.size());
+		for(std::vector<InetAddress>::const_iterator i(_virtual.begin());i!=_virtual.end();++i)
+			i->serialize(b,false);
+		if (!forSign) {
+			b.append((uint16_t)_signatureLength);
+			b.append(_signature,_signatureLength);
+			b.append((uint16_t)_orgSignatureLength);
+			b.append(_orgSignature,_orgSignatureLength);
+		}
+		b.append((uint16_t)0); // length of additional fields, currently 0
+
+		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
+	}
+
+	template<unsigned int C>
+	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	{
+		unsigned int p = startAt;
+
+		_ts = (uint64_t)b.template at<uint64_t>(p); p += 8;
+		p += _id.deserialize(b,p);
+		p += _organization.deserialize(b,p);
+		unsigned int cnt = b.template at<uint16_t>(p); p += 2;
+		if (cnt > ZT_LOCATOR_MAX_PHYSICAL_ENDPOINTS)
+			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
+		_physical.resize(cnt);
+		for(std::vector<InetAddress>::iterator i(_physical.begin());i!=_physical.end();++i)
+			p += i->deserialize(b,p);
+		cnt = b.template at<uint16_t>(p); p += 2;
+		if (cnt > ZT_LOCATOR_MAX_VIRTUAL_ENDPOINTS)
+			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
+		_virtual.resize(cnt);
+		for(std::vector<Identity>::iterator i(_virtual.begin());i!=_virtual.end();++i)
+			p += i->deserialize(b,p);
+		p += 2 + b.template at<uint16_t>(p);
+		if (p > b.size())
+			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
+
+		return (p - startAt);
+	}
+
+private:
+	int64_t _ts;
+	Identity _id;
+	Identity _organization;
+	std::vector<InetAddress> _physical;
+	std::vector<Identity> _virtual;
+	unsigned int _signatureLength;
+	unsigned int _orgSignatureLength;
+	uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
+	uint8_t _orgSignature[ZT_SIGNATURE_BUFFER_SIZE];
+};
+
+} // namespace ZeroTier
+
+#endif

+ 3 - 2
node/Packet.hpp

@@ -68,12 +68,13 @@
  *    + Tags and Capabilities
  *    + Inline push of CertificateOfMembership deprecated
  * 9  - 1.2.0 ... 1.2.14
- * 10 - 1.4.0 ... CURRENT
+ * 10 - 1.4.0 ... 1.6.0
  *    + Multipath capability and load balancing
+ * 11 - 1.6.0 ... CURRENT
  *    + Peer-to-peer multicast replication (optional)
  *    + Old planet/moon stuff is DEAD!
  */
-#define ZT_PROTO_VERSION 10
+#define ZT_PROTO_VERSION 11
 
 /**
  * Minimum supported protocol version

+ 71 - 3
node/Utils.cpp

@@ -55,9 +55,6 @@ namespace ZeroTier {
 
 const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
 
-const char Utils::BASE32CHARS[32] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' };
-const uint8_t Utils::BASE32BITS[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
-
 // Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers.
 static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
 {
@@ -174,4 +171,75 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
 #endif // __WINDOWS__ or not
 }
 
+int Utils::b32d(const char *encoded, uint8_t *result, int bufSize)
+{
+  int buffer = 0;
+  int bitsLeft = 0;
+  int count = 0;
+  for (const uint8_t *ptr = (const uint8_t *)encoded;count<bufSize && *ptr; ++ptr) {
+    uint8_t ch = *ptr;
+    if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-' || ch == '.') {
+      continue;
+    }
+    buffer <<= 5;
+
+    if (ch == '0') {
+      ch = 'O';
+    } else if (ch == '1') {
+      ch = 'L';
+    } else if (ch == '8') {
+      ch = 'B';
+    }
+
+    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+      ch = (ch & 0x1F) - 1;
+    } else if (ch >= '2' && ch <= '7') {
+      ch -= '2' - 26;
+    } else {
+      return -1;
+    }
+
+    buffer |= ch;
+    bitsLeft += 5;
+    if (bitsLeft >= 8) {
+      result[count++] = buffer >> (bitsLeft - 8);
+      bitsLeft -= 8;
+    }
+  }
+  if (count < bufSize)
+    result[count] = (uint8_t)0;
+  return count;
+}
+
+int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)
+{
+  if (length < 0 || length > (1 << 28))
+    return -1;
+  int count = 0;
+  if (length > 0) {
+    int buffer = data[0];
+    int next = 1;
+    int bitsLeft = 8;
+    while (count < bufSize && (bitsLeft > 0 || next < length)) {
+      if (bitsLeft < 5) {
+        if (next < length) {
+          buffer <<= 8;
+          buffer |= data[next++] & 0xFF;
+          bitsLeft += 8;
+        } else {
+          int pad = 5 - bitsLeft;
+          buffer <<= pad;
+          bitsLeft += pad;
+        }
+      }
+      int index = 0x1F & (buffer >> (bitsLeft - 5));
+      bitsLeft -= 5;
+      result[count++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[index];
+    }
+  }
+  if (count < bufSize)
+    result[count] = (char)0;
+  return count;
+}
+
 } // namespace ZeroTier

+ 3 - 25
node/Utils.hpp

@@ -246,6 +246,9 @@ public:
 	 */
 	static void getSecureRandom(void *buf,unsigned int bytes);
 
+	static int Utils::b32d(const char *encoded, uint8_t *result, int bufSize);
+	static int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize);
+
 	/**
 	 * Tokenize a string (alias for strtok_r or strtok_s depending on platform)
 	 *
@@ -442,35 +445,10 @@ public:
 	}
 	static inline int64_t ntoh(int64_t n) { return (int64_t)ntoh((uint64_t)n); }
 
-	static inline void base325to8(const uint8_t *const in,char *const out)
-	{
-		out[0] = BASE32CHARS[(in[0]) >> 3];
-		out[1] = BASE32CHARS[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6];
-		out[2] = BASE32CHARS[(in[1] & 0x3e) >> 1];
-		out[3] = BASE32CHARS[(in[1] & 0x01) << 4 | (in[2] & 0xf0) >> 4];
-		out[4] = BASE32CHARS[(in[2] & 0x0f) << 1 | (in[3] & 0x80) >> 7];
-		out[5] = BASE32CHARS[(in[3] & 0x7c) >> 2];
-		out[6] = BASE32CHARS[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5];
-		out[7] = BASE32CHARS[(in[4] & 0x1f)];
-	}
-
-	static inline void base328to5(const char *const in,uint8_t *const out)
-	{
-		out[0] = ((BASE32BITS[(unsigned int)in[0]]) << 3) | (BASE32BITS[(unsigned int)in[1]] & 0x1C) >> 2;
-		out[1] = ((BASE32BITS[(unsigned int)in[1]] & 0x03) << 6) | (BASE32BITS[(unsigned int)in[2]]) << 1 | (BASE32BITS[(unsigned int)in[3]] & 0x10) >> 4;
-		out[2] = ((BASE32BITS[(unsigned int)in[3]] & 0x0F) << 4) | (BASE32BITS[(unsigned int)in[4]] & 0x1E) >> 1;
-		out[3] = ((BASE32BITS[(unsigned int)in[4]] & 0x01) << 7) | (BASE32BITS[(unsigned int)in[5]]) << 2 | (BASE32BITS[(unsigned int)in[6]] & 0x18) >> 3;
-		out[4] = ((BASE32BITS[(unsigned int)in[6]] & 0x07) << 5) | (BASE32BITS[(unsigned int)in[7]]);
-	}
-
 	/**
 	 * Hexadecimal characters 0-f
 	 */
 	static const char HEXCHARS[16];
-
-private:
-	static const char BASE32CHARS[32];
-	static const uint8_t BASE32BITS[256];
 };
 
 } // namespace ZeroTier