From 7e105343e22c3129a3285472bcd996e27f05fb30 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Jul 2019 16:53:33 -0500 Subject: [PATCH] WIP --- node/Locator.cpp | 68 +++++++++++++++++++++++++ node/Locator.hpp | 128 +++++++++++++++++++++++++++++++++++++++++++++++ node/Packet.hpp | 5 +- node/Utils.cpp | 74 +++++++++++++++++++++++++-- node/Utils.hpp | 28 ++--------- 5 files changed, 273 insertions(+), 30 deletions(-) create mode 100644 node/Locator.cpp create mode 100644 node/Locator.hpp diff --git a/node/Locator.cpp b/node/Locator.cpp new file mode 100644 index 000000000..63a56c8a6 --- /dev/null +++ b/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 . + * + * -- + * + * 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 +#include + +#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 *const sb = new Buffer(); + _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 *const sb = new Buffer(); + 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 *const sb = new Buffer(); + delete sb; +} + +} // namespace ZeroTier diff --git a/node/Locator.hpp b/node/Locator.hpp new file mode 100644 index 000000000..ec0633d14 --- /dev/null +++ b/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 . + * + * -- + * + * 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 + +#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 &physical() const { return _physical; } + inline const std::vector &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 + inline void serialize(Buffer &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::const_iterator i(_physical.begin());i!=_physical.end();++i) + i->serialize(b); + b.append((uint16_t)_virtual.size()); + for(std::vector::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 + inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0) + { + unsigned int p = startAt; + + _ts = (uint64_t)b.template at(p); p += 8; + p += _id.deserialize(b,p); + p += _organization.deserialize(b,p); + unsigned int cnt = b.template at(p); p += 2; + if (cnt > ZT_LOCATOR_MAX_PHYSICAL_ENDPOINTS) + throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; + _physical.resize(cnt); + for(std::vector::iterator i(_physical.begin());i!=_physical.end();++i) + p += i->deserialize(b,p); + cnt = b.template at(p); p += 2; + if (cnt > ZT_LOCATOR_MAX_VIRTUAL_ENDPOINTS) + throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; + _virtual.resize(cnt); + for(std::vector::iterator i(_virtual.begin());i!=_virtual.end();++i) + p += i->deserialize(b,p); + p += 2 + b.template at(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 _physical; + std::vector _virtual; + unsigned int _signatureLength; + unsigned int _orgSignatureLength; + uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + uint8_t _orgSignature[ZT_SIGNATURE_BUFFER_SIZE]; +}; + +} // namespace ZeroTier + +#endif diff --git a/node/Packet.hpp b/node/Packet.hpp index 426274d77..ae7090cb0 100644 --- a/node/Packet.hpp +++ b/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 diff --git a/node/Utils.cpp b/node/Utils.cpp index 1a88b7b45..80005aaa6 100644 --- a/node/Utils.cpp +++ b/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= '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 diff --git a/node/Utils.hpp b/node/Utils.hpp index c5fa8756a..3a2ddfec9 100644 --- a/node/Utils.hpp +++ b/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