mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-20 14:06:54 +02:00
More porting to new Buf system.
This commit is contained in:
parent
91ce4c4ea6
commit
59da359b06
22 changed files with 607 additions and 747 deletions
|
@ -51,7 +51,10 @@ set(core_src
|
|||
Buf.cpp
|
||||
C25519.cpp
|
||||
Capability.cpp
|
||||
CertificateOfMembership.cpp
|
||||
CertificateOfOwnership.cpp
|
||||
Credential.cpp
|
||||
Dictionary.cpp
|
||||
ECC384.cpp
|
||||
Endpoint.cpp
|
||||
Identity.cpp
|
||||
|
|
139
node/CertificateOfMembership.cpp
Normal file
139
node/CertificateOfMembership.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "CertificateOfMembership.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
||||
{
|
||||
_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
|
||||
_qualifiers[0].value = timestamp;
|
||||
_qualifiers[0].maxDelta = timestampMaxDelta;
|
||||
_qualifiers[1].id = COM_RESERVED_ID_NETWORK_ID;
|
||||
_qualifiers[1].value = nwid;
|
||||
_qualifiers[1].maxDelta = 0;
|
||||
_qualifiers[2].id = COM_RESERVED_ID_ISSUED_TO;
|
||||
_qualifiers[2].value = issuedTo.toInt();
|
||||
_qualifiers[2].maxDelta = 0xffffffffffffffffULL;
|
||||
_qualifierCount = 3;
|
||||
_signatureLength = 0;
|
||||
}
|
||||
|
||||
void CertificateOfMembership::setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
|
||||
{
|
||||
_signedBy.zero();
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
if (_qualifiers[i].id == id) {
|
||||
_qualifiers[i].value = value;
|
||||
_qualifiers[i].maxDelta = maxDelta;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
|
||||
_qualifiers[_qualifierCount].id = id;
|
||||
_qualifiers[_qualifierCount].value = value;
|
||||
_qualifiers[_qualifierCount].maxDelta = maxDelta;
|
||||
++_qualifierCount;
|
||||
std::sort(&(_qualifiers[0]),&(_qualifiers[_qualifierCount]));
|
||||
}
|
||||
}
|
||||
|
||||
bool CertificateOfMembership::sign(const Identity &with)
|
||||
{
|
||||
uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
|
||||
unsigned int ptr = 0;
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].id);
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].value);
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
|
||||
}
|
||||
|
||||
try {
|
||||
_signatureLength = with.sign(buf,ptr * sizeof(uint64_t),_signature,sizeof(_signature));
|
||||
_signedBy = with.address();
|
||||
return true;
|
||||
} catch ( ... ) {
|
||||
_signedBy.zero();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const
|
||||
{
|
||||
data[0] = 1;
|
||||
Utils::storeBigEndian<uint16_t>(data + 1,(uint16_t)_qualifierCount);
|
||||
int p = 3;
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].id); p += 8;
|
||||
Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].value); p += 8;
|
||||
Utils::storeBigEndian<uint64_t>(data + p,_qualifiers[i].maxDelta); p += 8;
|
||||
}
|
||||
_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||
if ((_signedBy)&&(_signatureLength == 96)) {
|
||||
// UGLY: Ed25519 signatures in ZT are 96 bytes (64 + 32 bytes of hash).
|
||||
// P-384 signatures are also 96 bytes, praise the horned one. That means
|
||||
// we don't need to include a length. If we ever do we will need a new
|
||||
// serialized object version, but only for those with length != 96.
|
||||
memcpy(data + p,_signature,96); p += 96;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int CertificateOfMembership::unmarshal(const uint8_t *data,int len)
|
||||
{
|
||||
if ((len < 3)||(data[0] != 1))
|
||||
return -1;
|
||||
unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
|
||||
if (numq > ZT_NETWORK_COM_MAX_QUALIFIERS)
|
||||
return -1;
|
||||
_qualifierCount = numq;
|
||||
int p = 3;
|
||||
for(unsigned int i=0;i<numq;++i) {
|
||||
if ((p + 24) > len)
|
||||
return -1;
|
||||
_qualifiers[i].id = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
|
||||
_qualifiers[i].value = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
|
||||
_qualifiers[i].maxDelta = Utils::loadBigEndian<uint64_t>(data + p); p += 8;
|
||||
}
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len)
|
||||
return -1;
|
||||
_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||
if (_signedBy) {
|
||||
if ((p + 96) > len)
|
||||
return -1;
|
||||
_signatureLength = 96;
|
||||
memcpy(_signature,data + p,96);
|
||||
p += 96;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool CertificateOfMembership::operator==(const CertificateOfMembership &c) const
|
||||
{
|
||||
if (_signedBy != c._signedBy)
|
||||
return false;
|
||||
if (_qualifierCount != c._qualifierCount)
|
||||
return false;
|
||||
if (_signatureLength != c._signatureLength)
|
||||
return false;
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
const _Qualifier &a = _qualifiers[i];
|
||||
const _Qualifier &b = c._qualifiers[i];
|
||||
if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta))
|
||||
return false;
|
||||
}
|
||||
return (memcmp(_signature,c._signature,_signatureLength) == 0);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
@ -34,6 +33,8 @@
|
|||
*/
|
||||
#define ZT_NETWORK_COM_MAX_QUALIFIERS 8
|
||||
|
||||
#define ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX (1 + 2 + (24 * ZT_NETWORK_COM_MAX_QUALIFIERS) + 5 + ZT_SIGNATURE_BUFFER_SIZE)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class RuntimeEnvironment;
|
||||
|
@ -113,29 +114,7 @@ public:
|
|||
* @param nwid Network ID
|
||||
* @param issuedTo Certificate recipient
|
||||
*/
|
||||
ZT_ALWAYS_INLINE CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
||||
{
|
||||
_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
|
||||
_qualifiers[0].value = timestamp;
|
||||
_qualifiers[0].maxDelta = timestampMaxDelta;
|
||||
_qualifiers[1].id = COM_RESERVED_ID_NETWORK_ID;
|
||||
_qualifiers[1].value = nwid;
|
||||
_qualifiers[1].maxDelta = 0;
|
||||
_qualifiers[2].id = COM_RESERVED_ID_ISSUED_TO;
|
||||
_qualifiers[2].value = issuedTo.toInt();
|
||||
_qualifiers[2].maxDelta = 0xffffffffffffffffULL;
|
||||
_qualifierCount = 3;
|
||||
_signatureLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from binary-serialized COM in buffer
|
||||
*
|
||||
* @param b Buffer to deserialize from
|
||||
* @param startAt Position to start in buffer
|
||||
*/
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
||||
CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo);
|
||||
|
||||
/**
|
||||
* @return True if there's something here
|
||||
|
@ -192,24 +171,7 @@ public:
|
|||
* @param value Qualifier value
|
||||
* @param maxDelta Qualifier maximum allowed difference (absolute value of difference)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
|
||||
{
|
||||
_signedBy.zero();
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
if (_qualifiers[i].id == id) {
|
||||
_qualifiers[i].value = value;
|
||||
_qualifiers[i].maxDelta = maxDelta;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
|
||||
_qualifiers[_qualifierCount].id = id;
|
||||
_qualifiers[_qualifierCount].value = value;
|
||||
_qualifiers[_qualifierCount].maxDelta = maxDelta;
|
||||
++_qualifierCount;
|
||||
std::sort(&(_qualifiers[0]),&(_qualifiers[_qualifierCount]));
|
||||
}
|
||||
}
|
||||
void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta);
|
||||
|
||||
ZT_ALWAYS_INLINE void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
|
||||
|
||||
|
@ -268,25 +230,7 @@ public:
|
|||
* @param with Identity to sign with, must include private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool sign(const Identity &with)
|
||||
{
|
||||
uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
|
||||
unsigned int ptr = 0;
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].id);
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].value);
|
||||
buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
|
||||
}
|
||||
|
||||
try {
|
||||
_signatureLength = with.sign(buf,ptr * sizeof(uint64_t),_signature,sizeof(_signature));
|
||||
_signedBy = with.address();
|
||||
return true;
|
||||
} catch ( ... ) {
|
||||
_signedBy.zero();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool sign(const Identity &with);
|
||||
|
||||
/**
|
||||
* Verify this COM and its signature
|
||||
|
@ -301,95 +245,21 @@ public:
|
|||
*/
|
||||
ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
{
|
||||
b.append((uint8_t)1);
|
||||
b.append((uint16_t)_qualifierCount);
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
b.append(_qualifiers[i].id);
|
||||
b.append(_qualifiers[i].value);
|
||||
b.append(_qualifiers[i].maxDelta);
|
||||
}
|
||||
_signedBy.appendTo(b);
|
||||
if ((_signedBy)&&(_signatureLength == 96)) {
|
||||
// UGLY: Ed25519 signatures in ZT are 96 bytes (64 + 32 bytes of hash).
|
||||
// P-384 signatures are also 96 bytes, praise the horned one. That means
|
||||
// we don't need to include a length. If we ever do we will need a new
|
||||
// serialized object version, but only for those with length != 96.
|
||||
b.append(_signature,96);
|
||||
}
|
||||
}
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX; }
|
||||
int marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const;
|
||||
int unmarshal(const uint8_t *data,int len);
|
||||
|
||||
template<unsigned int C>
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
unsigned int p = startAt;
|
||||
|
||||
_signedBy.zero();
|
||||
_qualifierCount = 0;
|
||||
_signatureLength = 0;
|
||||
|
||||
if (b[p++] != 1)
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
|
||||
|
||||
unsigned int numq = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
||||
uint64_t lastId = 0;
|
||||
for(unsigned int i=0;i<numq;++i) {
|
||||
const uint64_t qid = b.template at<uint64_t>(p);
|
||||
if (qid < lastId)
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING;
|
||||
else lastId = qid;
|
||||
if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
|
||||
_qualifiers[_qualifierCount].id = qid;
|
||||
_qualifiers[_qualifierCount].value = b.template at<uint64_t>(p + 8);
|
||||
_qualifiers[_qualifierCount].maxDelta = b.template at<uint64_t>(p + 16);
|
||||
p += 24;
|
||||
++_qualifierCount;
|
||||
} else {
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
|
||||
if (_signedBy) {
|
||||
// See "UGLY" comment in serialize()...
|
||||
_signatureLength = 96;
|
||||
memcpy(_signature,b.field(p,96),96);
|
||||
p += 96;
|
||||
}
|
||||
|
||||
return (p - startAt);
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const CertificateOfMembership &c) const
|
||||
{
|
||||
if (_signedBy != c._signedBy)
|
||||
return false;
|
||||
if (_qualifierCount != c._qualifierCount)
|
||||
return false;
|
||||
if (_signatureLength != c._signatureLength)
|
||||
return false;
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
const _Qualifier &a = _qualifiers[i];
|
||||
const _Qualifier &b = c._qualifiers[i];
|
||||
if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta))
|
||||
return false;
|
||||
}
|
||||
return (memcmp(_signature,c._signature,_signatureLength) == 0);
|
||||
}
|
||||
bool operator==(const CertificateOfMembership &c) const;
|
||||
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
|
||||
|
||||
private:
|
||||
struct _Qualifier
|
||||
{
|
||||
_Qualifier() : id(0),value(0),maxDelta(0) {}
|
||||
ZT_ALWAYS_INLINE _Qualifier() : id(0),value(0),maxDelta(0) {}
|
||||
uint64_t id;
|
||||
uint64_t value;
|
||||
uint64_t maxDelta;
|
||||
inline bool operator<(const _Qualifier &q) const { return (id < q.id); } // sort order
|
||||
ZT_ALWAYS_INLINE bool operator<(const _Qualifier &q) const { return (id < q.id); } // sort order
|
||||
};
|
||||
|
||||
Address _signedBy;
|
||||
|
|
118
node/CertificateOfOwnership.cpp
Normal file
118
node/CertificateOfOwnership.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "CertificateOfOwnership.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
void CertificateOfOwnership::addThing(const InetAddress &ip)
|
||||
{
|
||||
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
|
||||
if (ip.ss_family == AF_INET) {
|
||||
_thingTypes[_thingCount] = THING_IPV4_ADDRESS;
|
||||
memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
|
||||
++_thingCount;
|
||||
} else if (ip.ss_family == AF_INET6) {
|
||||
_thingTypes[_thingCount] = THING_IPV6_ADDRESS;
|
||||
memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
|
||||
++_thingCount;
|
||||
}
|
||||
}
|
||||
|
||||
void CertificateOfOwnership::addThing(const MAC &mac)
|
||||
{
|
||||
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
|
||||
_thingTypes[_thingCount] = THING_MAC_ADDRESS;
|
||||
mac.copyTo(_thingValues[_thingCount],6);
|
||||
++_thingCount;
|
||||
}
|
||||
|
||||
bool CertificateOfOwnership::sign(const Identity &signer)
|
||||
{
|
||||
uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16];
|
||||
if (signer.hasPrivate()) {
|
||||
_signedBy = signer.address();
|
||||
_signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign) const
|
||||
{
|
||||
int p = 0;
|
||||
if (forSign) {
|
||||
for(int k=0;k<16;++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
Utils::storeBigEndian<uint64_t>(data + p,_networkId);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 8,(uint64_t)_ts);
|
||||
Utils::storeBigEndian<uint64_t>(data + p + 16,_flags);
|
||||
Utils::storeBigEndian<uint32_t>(data + p + 24,_id);
|
||||
Utils::storeBigEndian<uint16_t>(data + p + 28,(uint16_t)_thingCount);
|
||||
p += 30;
|
||||
for(unsigned int i=0,j=_thingCount;i<j;++i) {
|
||||
data[p++] = _thingTypes[i];
|
||||
memcpy(data + p,_thingValues[i],ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
|
||||
p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
|
||||
}
|
||||
_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||
_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||
if (!forSign) {
|
||||
data[p++] = 1;
|
||||
Utils::storeBigEndian<uint16_t>(data + p,(uint16_t)_signatureLength); p += 2;
|
||||
memcpy(data + p,_signature,_signatureLength); p += (int)_signatureLength;
|
||||
}
|
||||
data[p++] = 0;
|
||||
data[p++] = 0;
|
||||
if (forSign) {
|
||||
for(int k=0;k<16;++k)
|
||||
data[p++] = 0x7f;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int CertificateOfOwnership::unmarshal(const uint8_t *data,int len)
|
||||
{
|
||||
if (len < 30)
|
||||
return -1;
|
||||
|
||||
_networkId = Utils::loadBigEndian<uint64_t>(data);
|
||||
_ts = (int64_t)Utils::loadBigEndian<uint64_t>(data + 8);
|
||||
_flags = Utils::loadBigEndian<uint64_t>(data + 16);
|
||||
_id = Utils::loadBigEndian<uint32_t>(data + 24);
|
||||
_thingCount = Utils::loadBigEndian<uint16_t>(data + 28);
|
||||
if (_thingCount > ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
|
||||
return -1;
|
||||
int p = 30;
|
||||
|
||||
for(unsigned int i=0,j=_thingCount;i<j;++i) {
|
||||
if ((p + 1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) > len)
|
||||
return -1;
|
||||
_thingTypes[i] = data[p++];
|
||||
memcpy(_thingValues[i],data + p,ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
|
||||
p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
|
||||
}
|
||||
|
||||
if ((p + ZT_ADDRESS_LENGTH + ZT_ADDRESS_LENGTH + 1 + 2) > len)
|
||||
return -1;
|
||||
_issuedTo.setTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||
_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1;
|
||||
|
||||
p += 2 + Utils::loadBigEndian<uint16_t>(data + p);
|
||||
if (p > len)
|
||||
return -1;
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
|
@ -24,7 +24,6 @@
|
|||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
|
||||
|
@ -34,6 +33,8 @@
|
|||
// Maximum size of a thing's value field in bytes
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
|
||||
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX (8 + 8 + 8 + 4 + 2 + ((1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) * ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class RuntimeEnvironment;
|
||||
|
@ -98,112 +99,20 @@ public:
|
|||
return this->_owns(THING_MAC_ADDRESS,tmp,6);
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE void addThing(const InetAddress &ip)
|
||||
{
|
||||
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
|
||||
if (ip.ss_family == AF_INET) {
|
||||
_thingTypes[_thingCount] = THING_IPV4_ADDRESS;
|
||||
memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
|
||||
++_thingCount;
|
||||
} else if (ip.ss_family == AF_INET6) {
|
||||
_thingTypes[_thingCount] = THING_IPV6_ADDRESS;
|
||||
memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
|
||||
++_thingCount;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE void addThing(const MAC &mac)
|
||||
{
|
||||
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
|
||||
_thingTypes[_thingCount] = THING_MAC_ADDRESS;
|
||||
mac.copyTo(_thingValues[_thingCount],6);
|
||||
++_thingCount;
|
||||
}
|
||||
void addThing(const InetAddress &ip);
|
||||
void addThing(const MAC &mac);
|
||||
|
||||
/**
|
||||
* @param signer Signing identity, must have private key
|
||||
* @return True if signature was successful
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool sign(const Identity &signer)
|
||||
{
|
||||
if (signer.hasPrivate()) {
|
||||
Buffer<sizeof(CertificateOfOwnership) + 64> tmp;
|
||||
_signedBy = signer.address();
|
||||
this->serialize(tmp,true);
|
||||
_signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool sign(const Identity &signer);
|
||||
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||
{
|
||||
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
|
||||
|
||||
b.append(_networkId);
|
||||
b.append(_ts);
|
||||
b.append(_flags);
|
||||
b.append(_id);
|
||||
b.append((uint16_t)_thingCount);
|
||||
for(unsigned int i=0,j=_thingCount;i<j;++i) {
|
||||
b.append((uint8_t)_thingTypes[i]);
|
||||
b.append(_thingValues[i],ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
|
||||
}
|
||||
|
||||
_issuedTo.appendTo(b);
|
||||
_signedBy.appendTo(b);
|
||||
if (!forSign) {
|
||||
b.append((uint8_t)1);
|
||||
b.append((uint16_t)_signatureLength); // length of signature
|
||||
b.append(_signature,_signatureLength);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
*this = CertificateOfOwnership();
|
||||
|
||||
_networkId = b.template at<uint64_t>(p); p += 8;
|
||||
_ts = b.template at<uint64_t>(p); p += 8;
|
||||
_flags = b.template at<uint64_t>(p); p += 8;
|
||||
_id = b.template at<uint32_t>(p); p += 4;
|
||||
_thingCount = b.template at<uint16_t>(p); p += 2;
|
||||
for(unsigned int i=0,j=_thingCount;i<j;++i) {
|
||||
if (i < ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
|
||||
_thingTypes[i] = (uint8_t)b[p++];
|
||||
memcpy(_thingValues[i],b.field(p,ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE),ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
|
||||
p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
||||
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
||||
if (b[p++] == 1) {
|
||||
_signatureLength = b.template at<uint16_t>(p);
|
||||
if (_signatureLength > sizeof(_signature))
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
|
||||
p += 2;
|
||||
memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
|
||||
} else {
|
||||
p += 2 + b.template at<uint16_t>(p);
|
||||
}
|
||||
|
||||
p += 2 + b.template at<uint16_t>(p);
|
||||
if (p > b.size())
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
|
||||
|
||||
return (p - startAt);
|
||||
}
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
|
||||
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign = false) const;
|
||||
int unmarshal(const uint8_t *data,int len);
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_ALWAYS_INLINE bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
|
||||
|
|
224
node/Dictionary.cpp
Normal file
224
node/Dictionary.cpp
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "Dictionary.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Dictionary::Dictionary(const char *s,unsigned int len)
|
||||
{
|
||||
for(unsigned int i=0;i<ZT_DICTIONARY_MAX_CAPACITY;++i) {
|
||||
if ((s)&&(i < len)) {
|
||||
if (!(_d[i] = *s))
|
||||
s = (const char *)0;
|
||||
else ++s;
|
||||
} else _d[i] = (char)0;
|
||||
}
|
||||
_d[ZT_DICTIONARY_MAX_CAPACITY-1] = (char)0;
|
||||
}
|
||||
|
||||
bool Dictionary::load(const char *s)
|
||||
{
|
||||
for(unsigned int i=0;i<ZT_DICTIONARY_MAX_CAPACITY;++i) {
|
||||
if (s) {
|
||||
if (!(_d[i] = *s))
|
||||
s = (const char *)0;
|
||||
else ++s;
|
||||
} else _d[i] = (char)0;
|
||||
}
|
||||
_d[ZT_DICTIONARY_MAX_CAPACITY - 1] = (char)0;
|
||||
return (!s);
|
||||
}
|
||||
|
||||
int Dictionary::get(const char *key,char *dest,unsigned int destlen) const
|
||||
{
|
||||
const char *p = _d;
|
||||
const char *const eof = p + ZT_DICTIONARY_MAX_CAPACITY;
|
||||
const char *k;
|
||||
bool esc;
|
||||
int j;
|
||||
|
||||
if (!destlen) // sanity check
|
||||
return -1;
|
||||
|
||||
while (*p) {
|
||||
k = key;
|
||||
while ((*k)&&(*p)) {
|
||||
if (*p != *k)
|
||||
break;
|
||||
++k;
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!*k)&&(*p == '=')) {
|
||||
j = 0;
|
||||
esc = false;
|
||||
++p;
|
||||
while ((*p != 0)&&(*p != 13)&&(*p != 10)) {
|
||||
if (esc) {
|
||||
esc = false;
|
||||
switch(*p) {
|
||||
case 'r': dest[j++] = 13; break;
|
||||
case 'n': dest[j++] = 10; break;
|
||||
case '0': dest[j++] = (char)0; break;
|
||||
case 'e': dest[j++] = '='; break;
|
||||
default: dest[j++] = *p; break;
|
||||
}
|
||||
if (j == (int)destlen) {
|
||||
dest[j-1] = (char)0;
|
||||
return j-1;
|
||||
}
|
||||
} else if (*p == '\\') {
|
||||
esc = true;
|
||||
} else {
|
||||
dest[j++] = *p;
|
||||
if (j == (int)destlen) {
|
||||
dest[j-1] = (char)0;
|
||||
return j-1;
|
||||
}
|
||||
}
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
dest[j] = (char)0;
|
||||
return j;
|
||||
} else {
|
||||
while ((*p)&&(*p != 13)&&(*p != 10)) {
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (*p) {
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Dictionary::add(const char *key,const char *value,int vlen)
|
||||
{
|
||||
for(unsigned int i=0;i<ZT_DICTIONARY_MAX_CAPACITY;++i) {
|
||||
if (!_d[i]) {
|
||||
unsigned int j = i;
|
||||
|
||||
if (j > 0) {
|
||||
_d[j++] = (char)10;
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *p = key;
|
||||
while (*p) {
|
||||
_d[j++] = *(p++);
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_d[j++] = '=';
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
|
||||
p = value;
|
||||
int k = 0;
|
||||
while ( ((vlen < 0)&&(*p)) || (k < vlen) ) {
|
||||
switch(*p) {
|
||||
case 0:
|
||||
case 13:
|
||||
case 10:
|
||||
case '\\':
|
||||
case '=':
|
||||
_d[j++] = '\\';
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
switch(*p) {
|
||||
case 0: _d[j++] = '0'; break;
|
||||
case 13: _d[j++] = 'r'; break;
|
||||
case 10: _d[j++] = 'n'; break;
|
||||
case '\\': _d[j++] = '\\'; break;
|
||||
case '=': _d[j++] = 'e'; break;
|
||||
}
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_d[j++] = *p;
|
||||
if (j == ZT_DICTIONARY_MAX_CAPACITY) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
++k;
|
||||
}
|
||||
|
||||
_d[j] = (char)0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Dictionary::add(const char *key,bool value)
|
||||
{
|
||||
return this->add(key,(value) ? "1" : "0",1);
|
||||
}
|
||||
|
||||
bool Dictionary::add(const char *key,uint64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(value,tmp),-1);
|
||||
}
|
||||
|
||||
bool Dictionary::add(const char *key,int64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
if (value >= 0) {
|
||||
return this->add(key,Utils::hex((uint64_t)value,tmp),-1);
|
||||
} else {
|
||||
tmp[0] = '-';
|
||||
return this->add(key,Utils::hex((uint64_t)(value * -1),tmp+1),-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool Dictionary::add(const char *key,const Address &a)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(a.toInt(),tmp),-1);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
|
@ -16,11 +16,13 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define ZT_DICTIONARY_MAX_CAPACITY 65536
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
@ -45,32 +47,14 @@ namespace ZeroTier {
|
|||
*
|
||||
* @tparam C Dictionary max capacity in bytes
|
||||
*/
|
||||
template<unsigned int C>
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
inline Dictionary() { memset(_d,0,sizeof(_d)); }
|
||||
inline Dictionary(const char *s) { this->load(s); }
|
||||
inline Dictionary(const char *s,unsigned int len)
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if ((s)&&(i < len)) {
|
||||
if (!(_d[i] = *s))
|
||||
s = (const char *)0;
|
||||
else ++s;
|
||||
} else _d[i] = (char)0;
|
||||
}
|
||||
_d[C - 1] = (char)0;
|
||||
}
|
||||
inline Dictionary(const Dictionary &d) { memcpy(_d,d._d,C); }
|
||||
ZT_ALWAYS_INLINE Dictionary() { _d[0] = 0; }
|
||||
explicit ZT_ALWAYS_INLINE Dictionary(const char *s) { this->load(s); }
|
||||
Dictionary(const char *s,unsigned int len);
|
||||
|
||||
inline Dictionary &operator=(const Dictionary &d)
|
||||
{
|
||||
memcpy(_d,d._d,C);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_d[0] != 0); }
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_d[0] != 0); }
|
||||
|
||||
/**
|
||||
* Load a dictionary from a C-string
|
||||
|
@ -78,35 +62,12 @@ public:
|
|||
* @param s Dictionary in string form
|
||||
* @return False if 's' was longer than our capacity
|
||||
*/
|
||||
inline bool load(const char *s)
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if (s) {
|
||||
if (!(_d[i] = *s))
|
||||
s = (const char *)0;
|
||||
else ++s;
|
||||
} else _d[i] = (char)0;
|
||||
}
|
||||
_d[C - 1] = (char)0;
|
||||
return (!s);
|
||||
}
|
||||
bool load(const char *s);
|
||||
|
||||
/**
|
||||
* Delete all entries
|
||||
*/
|
||||
inline void clear() { memset(_d,0,sizeof(_d)); }
|
||||
|
||||
/**
|
||||
* @return Size of dictionary in bytes not including terminating NULL
|
||||
*/
|
||||
inline unsigned int sizeBytes() const
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if (!_d[i])
|
||||
return i;
|
||||
}
|
||||
return C-1;
|
||||
}
|
||||
ZT_ALWAYS_INLINE void clear() { memset(_d,0,sizeof(_d)); }
|
||||
|
||||
/**
|
||||
* Get an entry
|
||||
|
@ -130,104 +91,7 @@ public:
|
|||
* @param destlen Size of destination buffer
|
||||
* @return -1 if not found, or actual number of bytes stored in dest[] minus trailing 0
|
||||
*/
|
||||
inline int get(const char *key,char *dest,unsigned int destlen) const
|
||||
{
|
||||
const char *p = _d;
|
||||
const char *const eof = p + C;
|
||||
const char *k;
|
||||
bool esc;
|
||||
int j;
|
||||
|
||||
if (!destlen) // sanity check
|
||||
return -1;
|
||||
|
||||
while (*p) {
|
||||
k = key;
|
||||
while ((*k)&&(*p)) {
|
||||
if (*p != *k)
|
||||
break;
|
||||
++k;
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!*k)&&(*p == '=')) {
|
||||
j = 0;
|
||||
esc = false;
|
||||
++p;
|
||||
while ((*p != 0)&&(*p != 13)&&(*p != 10)) {
|
||||
if (esc) {
|
||||
esc = false;
|
||||
switch(*p) {
|
||||
case 'r': dest[j++] = 13; break;
|
||||
case 'n': dest[j++] = 10; break;
|
||||
case '0': dest[j++] = (char)0; break;
|
||||
case 'e': dest[j++] = '='; break;
|
||||
default: dest[j++] = *p; break;
|
||||
}
|
||||
if (j == (int)destlen) {
|
||||
dest[j-1] = (char)0;
|
||||
return j-1;
|
||||
}
|
||||
} else if (*p == '\\') {
|
||||
esc = true;
|
||||
} else {
|
||||
dest[j++] = *p;
|
||||
if (j == (int)destlen) {
|
||||
dest[j-1] = (char)0;
|
||||
return j-1;
|
||||
}
|
||||
}
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
dest[j] = (char)0;
|
||||
return j;
|
||||
} else {
|
||||
while ((*p)&&(*p != 13)&&(*p != 10)) {
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (*p) {
|
||||
if (++p == eof) {
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
dest[0] = (char)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a key into a buffer
|
||||
*
|
||||
* @param key Key to get
|
||||
* @param dest Destination buffer
|
||||
* @return True if key was found (if false, dest will be empty)
|
||||
* @tparam BC Buffer capacity (usually inferred)
|
||||
*/
|
||||
template<unsigned int BC>
|
||||
inline bool get(const char *key,Buffer<BC> &dest) const
|
||||
{
|
||||
const int r = this->get(key,const_cast<char *>(reinterpret_cast<const char *>(dest.data())),BC);
|
||||
if (r >= 0) {
|
||||
dest.setSize((unsigned int)r);
|
||||
return true;
|
||||
} else {
|
||||
dest.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int get(const char *key,char *dest,unsigned int destlen) const;
|
||||
|
||||
/**
|
||||
* Get a boolean value
|
||||
|
@ -236,7 +100,7 @@ public:
|
|||
* @param dfl Default value if not found in dictionary
|
||||
* @return Boolean value of key or 'dfl' if not found
|
||||
*/
|
||||
inline bool getB(const char *key,bool dfl = false) const
|
||||
ZT_ALWAYS_INLINE bool getB(const char *key,bool dfl = false) const
|
||||
{
|
||||
char tmp[4];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 0)
|
||||
|
@ -251,7 +115,7 @@ public:
|
|||
* @param dfl Default value or 0 if unspecified
|
||||
* @return Decoded hex UInt value or 'dfl' if not found
|
||||
*/
|
||||
inline uint64_t getUI(const char *key,uint64_t dfl = 0) const
|
||||
ZT_ALWAYS_INLINE uint64_t getUI(const char *key,uint64_t dfl = 0) const
|
||||
{
|
||||
char tmp[128];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
||||
|
@ -266,7 +130,7 @@ public:
|
|||
* @param dfl Default value or 0 if unspecified
|
||||
* @return Decoded hex UInt value or 'dfl' if not found
|
||||
*/
|
||||
inline int64_t getI(const char *key,int64_t dfl = 0) const
|
||||
ZT_ALWAYS_INLINE int64_t getI(const char *key,int64_t dfl = 0) const
|
||||
{
|
||||
char tmp[128];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
||||
|
@ -288,137 +152,33 @@ public:
|
|||
* @param vlen Length of value in bytes or -1 to treat value[] as a C-string and look for terminating 0
|
||||
* @return True if there was enough room to add this key=value pair
|
||||
*/
|
||||
inline bool add(const char *key,const char *value,int vlen = -1)
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if (!_d[i]) {
|
||||
unsigned int j = i;
|
||||
|
||||
if (j > 0) {
|
||||
_d[j++] = (char)10;
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *p = key;
|
||||
while (*p) {
|
||||
_d[j++] = *(p++);
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_d[j++] = '=';
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
|
||||
p = value;
|
||||
int k = 0;
|
||||
while ( ((vlen < 0)&&(*p)) || (k < vlen) ) {
|
||||
switch(*p) {
|
||||
case 0:
|
||||
case 13:
|
||||
case 10:
|
||||
case '\\':
|
||||
case '=':
|
||||
_d[j++] = '\\';
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
switch(*p) {
|
||||
case 0: _d[j++] = '0'; break;
|
||||
case 13: _d[j++] = 'r'; break;
|
||||
case 10: _d[j++] = 'n'; break;
|
||||
case '\\': _d[j++] = '\\'; break;
|
||||
case '=': _d[j++] = 'e'; break;
|
||||
}
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_d[j++] = *p;
|
||||
if (j == C) {
|
||||
_d[i] = (char)0;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
++k;
|
||||
}
|
||||
|
||||
_d[j] = (char)0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool add(const char *key,const char *value,int vlen = -1);
|
||||
|
||||
/**
|
||||
* Add a boolean as a '1' or a '0'
|
||||
*/
|
||||
inline bool add(const char *key,bool value)
|
||||
{
|
||||
return this->add(key,(value) ? "1" : "0",1);
|
||||
}
|
||||
bool add(const char *key,bool value);
|
||||
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
inline bool add(const char *key,uint64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(value,tmp),-1);
|
||||
}
|
||||
bool add(const char *key,uint64_t value);
|
||||
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
inline bool add(const char *key,int64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
if (value >= 0) {
|
||||
return this->add(key,Utils::hex((uint64_t)value,tmp),-1);
|
||||
} else {
|
||||
tmp[0] = '-';
|
||||
return this->add(key,Utils::hex((uint64_t)(value * -1),tmp+1),-1);
|
||||
}
|
||||
}
|
||||
bool add(const char *key,int64_t value);
|
||||
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
inline bool add(const char *key,const Address &a)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(a.toInt(),tmp),-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a binary buffer's contents as a value
|
||||
*
|
||||
* @tparam BC Buffer capacity (usually inferred)
|
||||
*/
|
||||
template<unsigned int BC>
|
||||
inline bool add(const char *key,const Buffer<BC> &value)
|
||||
{
|
||||
return this->add(key,(const char *)value.data(),(int)value.size());
|
||||
}
|
||||
bool add(const char *key,const Address &a);
|
||||
|
||||
/**
|
||||
* @param key Key to check
|
||||
* @return True if key is present
|
||||
*/
|
||||
inline bool contains(const char *key) const
|
||||
ZT_ALWAYS_INLINE bool contains(const char *key) const
|
||||
{
|
||||
char tmp[2];
|
||||
return (this->get(key,tmp,2) >= 0);
|
||||
|
@ -427,13 +187,12 @@ public:
|
|||
/**
|
||||
* @return Value of C template parameter
|
||||
*/
|
||||
inline unsigned int capacity() const { return C; }
|
||||
ZT_ALWAYS_INLINE unsigned int capacity() const { return sizeof(_d); }
|
||||
|
||||
inline const char *data() const { return _d; }
|
||||
inline char *unsafeData() { return _d; }
|
||||
ZT_ALWAYS_INLINE const char *data() const { return _d; }
|
||||
|
||||
private:
|
||||
char _d[C];
|
||||
char _d[ZT_DICTIONARY_MAX_CAPACITY];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "ECC384.hpp"
|
||||
|
||||
|
@ -158,108 +157,6 @@ public:
|
|||
*/
|
||||
ZT_ALWAYS_INLINE const Address &address() const { return _address; }
|
||||
|
||||
/**
|
||||
* Serialize this identity (binary)
|
||||
*
|
||||
* @param b Destination buffer to append to
|
||||
* @param includePrivate If true, include private key component (if present) (default: false)
|
||||
*/
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b,bool includePrivate = false) const
|
||||
{
|
||||
_address.appendTo(b);
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
b.append((uint8_t)C25519);
|
||||
b.append(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
if ((_hasPrivate)&&(includePrivate)) {
|
||||
b.append((uint8_t)ZT_C25519_PRIVATE_KEY_LEN);
|
||||
b.append(_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
} else {
|
||||
b.append((uint8_t)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case P384:
|
||||
b.append((uint8_t)P384);
|
||||
b.append(&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE);
|
||||
if ((_hasPrivate)&&(includePrivate)) {
|
||||
b.append((uint8_t)(ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE));
|
||||
b.append(_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
b.append(_priv.p384,ZT_ECC384_PRIVATE_KEY_SIZE);
|
||||
} else {
|
||||
b.append((uint8_t)0);
|
||||
}
|
||||
b.append((uint8_t)0); // size of additional fields (should have included such a thing in v0!)
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a binary serialized identity
|
||||
*
|
||||
* If an exception is thrown, the Identity object is left in an undefined
|
||||
* state and should not be used.
|
||||
*
|
||||
* @param b Buffer containing serialized data
|
||||
* @param startAt Index within buffer of serialized data (default: 0)
|
||||
* @return Length of serialized data read from buffer
|
||||
*/
|
||||
template<unsigned int C>
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
_hasPrivate = false;
|
||||
unsigned int p = startAt;
|
||||
unsigned int pkl;
|
||||
|
||||
_address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
|
||||
switch((_type = (Type)b[p++])) {
|
||||
|
||||
case C25519:
|
||||
memcpy(_pub.c25519,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
|
||||
p += ZT_C25519_PUBLIC_KEY_LEN;
|
||||
pkl = (unsigned int)b[p++];
|
||||
if (pkl) {
|
||||
if (pkl != ZT_C25519_PRIVATE_KEY_LEN)
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
|
||||
_hasPrivate = true;
|
||||
memcpy(_priv.c25519,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
|
||||
p += ZT_C25519_PRIVATE_KEY_LEN;
|
||||
} else {
|
||||
_hasPrivate = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case P384:
|
||||
memcpy(&_pub,b.field(p,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE),ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE);
|
||||
p += ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE;
|
||||
pkl = (unsigned int)b[p++];
|
||||
if (pkl) {
|
||||
if (pkl != (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE))
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
|
||||
_hasPrivate = true;
|
||||
memcpy(_priv.c25519,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
|
||||
p += ZT_C25519_PRIVATE_KEY_LEN;
|
||||
memcpy(_priv.p384,b.field(p,ZT_ECC384_PRIVATE_KEY_SIZE),ZT_ECC384_PRIVATE_KEY_SIZE);
|
||||
p += ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
} else {
|
||||
_hasPrivate = false;
|
||||
}
|
||||
p += b.template at<uint8_t>(p) + 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
|
||||
|
||||
}
|
||||
|
||||
return (p - startAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize to a more human-friendly string
|
||||
*
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -498,62 +497,6 @@ public:
|
|||
int marshal(uint8_t data[19]) const;
|
||||
int unmarshal(const uint8_t *restrict data,const int len);
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
{
|
||||
// This is used in the protocol and must be the same as describe in places
|
||||
// like VERB_HELLO in Packet.hpp.
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
b.append((uint8_t)0x04);
|
||||
b.append(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr),4);
|
||||
b.append((uint16_t)port()); // just in case sin_port != uint16_t
|
||||
return;
|
||||
case AF_INET6:
|
||||
b.append((uint8_t)0x06);
|
||||
b.append(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
|
||||
b.append((uint16_t)port()); // just in case sin_port != uint16_t
|
||||
return;
|
||||
default:
|
||||
b.append((uint8_t)0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned int C>
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
unsigned int p = startAt;
|
||||
switch(b[p++]) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 0x01:
|
||||
// TODO: Ethernet address (but accept for forward compatibility)
|
||||
return 7;
|
||||
case 0x02:
|
||||
// TODO: Bluetooth address (but accept for forward compatibility)
|
||||
return 7;
|
||||
case 0x03:
|
||||
// TODO: Other address types (but accept for forward compatibility)
|
||||
// These could be extended/optional things like AF_UNIX, LTE Direct, shared memory, etc.
|
||||
return (unsigned int)(b.template at<uint16_t>(p) + 3); // other addresses begin with 16-bit non-inclusive length
|
||||
case 0x04:
|
||||
ss_family = AF_INET;
|
||||
memcpy(&(reinterpret_cast<struct sockaddr_in *>(this)->sin_addr.s_addr),b.field(p,4),4); p += 4;
|
||||
reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p)); p += 2;
|
||||
break;
|
||||
case 0x06:
|
||||
ss_family = AF_INET6;
|
||||
memcpy(reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,b.field(p,16),16); p += 16;
|
||||
reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p)); p += 2;
|
||||
break;
|
||||
default:
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING;
|
||||
}
|
||||
return (p - startAt);
|
||||
}
|
||||
|
||||
bool operator==(const InetAddress &a) const;
|
||||
bool operator<(const InetAddress &a) const;
|
||||
ZT_ALWAYS_INLINE bool operator!=(const InetAddress &a) const { return !(*this == a); }
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -39,9 +38,9 @@ public:
|
|||
((((uint64_t)d) & 0xffULL) << 16U) |
|
||||
((((uint64_t)e) & 0xffULL) << 8U) |
|
||||
(((uint64_t)f) & 0xffULL) ) {}
|
||||
ZT_ALWAYS_INLINE MAC(const uint8_t b[6]) { setTo(b); }
|
||||
explicit ZT_ALWAYS_INLINE MAC(const uint8_t b[6]) { setTo(b); }
|
||||
ZT_ALWAYS_INLINE MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); }
|
||||
ZT_ALWAYS_INLINE MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {}
|
||||
explicit ZT_ALWAYS_INLINE MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {}
|
||||
|
||||
/**
|
||||
* @return MAC in 64-bit integer
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Switch.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
// multicast address directly from the IP address, and it gives us
|
||||
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
||||
// to care about.
|
||||
const unsigned char *a = (const unsigned char *)ip.rawIpData();
|
||||
const uint8_t *a = (const uint8_t *)ip.rawIpData();
|
||||
return MulticastGroup(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0);
|
||||
}
|
||||
return MulticastGroup();
|
||||
|
|
|
@ -20,7 +20,28 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const
|
||||
NetworkConfig::NetworkConfig() :
|
||||
networkId(0),
|
||||
timestamp(0),
|
||||
credentialTimeMaxDelta(0),
|
||||
revision(0),
|
||||
issuedTo(),
|
||||
flags(0),
|
||||
mtu(0),
|
||||
multicastLimit(0),
|
||||
specialistCount(0),
|
||||
routeCount(0),
|
||||
staticIpCount(0),
|
||||
ruleCount(0),
|
||||
capabilityCount(0),
|
||||
tagCount(0),
|
||||
certificateOfOwnershipCount(0),
|
||||
type(ZT_NETWORK_TYPE_PRIVATE)
|
||||
{
|
||||
name[0] = 0;
|
||||
}
|
||||
|
||||
bool NetworkConfig::toDictionary(Dictionary &d,bool includeLegacy) const
|
||||
{
|
||||
ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
|
||||
char tmp2[128];
|
||||
|
@ -105,7 +126,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d)
|
||||
bool NetworkConfig::fromDictionary(const Dictionary &d)
|
||||
{
|
||||
static const NetworkConfig NIL_NC;
|
||||
ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
|
||||
|
@ -218,4 +239,20 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
|
|||
}
|
||||
}
|
||||
|
||||
bool NetworkConfig::addSpecialist(const Address &a,const uint64_t f)
|
||||
{
|
||||
const uint64_t aint = a.toInt();
|
||||
for(unsigned int i=0;i<specialistCount;++i) {
|
||||
if ((specialists[i] & 0xffffffffffULL) == aint) {
|
||||
specialists[i] |= f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
|
||||
specialists[specialistCount++] = f | aint;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -17,13 +17,11 @@
|
|||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Address.hpp"
|
||||
|
@ -168,26 +166,7 @@ namespace ZeroTier {
|
|||
*/
|
||||
struct NetworkConfig
|
||||
{
|
||||
inline NetworkConfig() :
|
||||
networkId(0),
|
||||
timestamp(0),
|
||||
credentialTimeMaxDelta(0),
|
||||
revision(0),
|
||||
issuedTo(),
|
||||
flags(0),
|
||||
mtu(0),
|
||||
multicastLimit(0),
|
||||
specialistCount(0),
|
||||
routeCount(0),
|
||||
staticIpCount(0),
|
||||
ruleCount(0),
|
||||
capabilityCount(0),
|
||||
tagCount(0),
|
||||
certificateOfOwnershipCount(0),
|
||||
type(ZT_NETWORK_TYPE_PRIVATE)
|
||||
{
|
||||
name[0] = 0;
|
||||
}
|
||||
NetworkConfig();
|
||||
|
||||
/**
|
||||
* Write this network config to a dictionary for transport
|
||||
|
@ -196,7 +175,7 @@ struct NetworkConfig
|
|||
* @param includeLegacy If true, include legacy fields for old node versions
|
||||
* @return True if dictionary was successfully created, false if e.g. overflow
|
||||
*/
|
||||
bool toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const;
|
||||
bool toDictionary(Dictionary &d,bool includeLegacy) const;
|
||||
|
||||
/**
|
||||
* Read this network config from a dictionary
|
||||
|
@ -204,33 +183,33 @@ struct NetworkConfig
|
|||
* @param d Dictionary (non-const since it might be modified during parse, should not be used after call)
|
||||
* @return True if dictionary was valid and network config successfully initialized
|
||||
*/
|
||||
bool fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d);
|
||||
bool fromDictionary(const Dictionary &d);
|
||||
|
||||
/**
|
||||
* @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network
|
||||
*/
|
||||
inline bool enableBroadcast() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); }
|
||||
ZT_ALWAYS_INLINE bool enableBroadcast() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); }
|
||||
|
||||
/**
|
||||
* @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns
|
||||
*/
|
||||
inline bool ndpEmulation() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); }
|
||||
ZT_ALWAYS_INLINE bool ndpEmulation() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); }
|
||||
|
||||
/**
|
||||
* @return Network type is public (no access control)
|
||||
*/
|
||||
inline bool isPublic() const { return (this->type == ZT_NETWORK_TYPE_PUBLIC); }
|
||||
ZT_ALWAYS_INLINE bool isPublic() const { return (this->type == ZT_NETWORK_TYPE_PUBLIC); }
|
||||
|
||||
/**
|
||||
* @return Network type is private (certificate access control)
|
||||
*/
|
||||
inline bool isPrivate() const { return (this->type == ZT_NETWORK_TYPE_PRIVATE); }
|
||||
ZT_ALWAYS_INLINE bool isPrivate() const { return (this->type == ZT_NETWORK_TYPE_PRIVATE); }
|
||||
|
||||
/**
|
||||
* @param fromPeer Peer attempting to bridge other Ethernet peers onto network
|
||||
* @return True if this network allows bridging
|
||||
*/
|
||||
inline bool permitsBridging(const Address &fromPeer) const
|
||||
ZT_ALWAYS_INLINE bool permitsBridging(const Address &fromPeer) const
|
||||
{
|
||||
for(unsigned int i=0;i<specialistCount;++i) {
|
||||
if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||
|
@ -239,9 +218,9 @@ struct NetworkConfig
|
|||
return false;
|
||||
}
|
||||
|
||||
inline operator bool() const { return (networkId != 0); }
|
||||
inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
|
||||
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (networkId != 0); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
||||
|
||||
/**
|
||||
* Add a specialist or mask flags if already present
|
||||
|
@ -253,23 +232,9 @@ struct NetworkConfig
|
|||
* @param f Flags (OR of specialist role/type flags)
|
||||
* @return True if successfully masked or added
|
||||
*/
|
||||
inline bool addSpecialist(const Address &a,const uint64_t f)
|
||||
{
|
||||
const uint64_t aint = a.toInt();
|
||||
for(unsigned int i=0;i<specialistCount;++i) {
|
||||
if ((specialists[i] & 0xffffffffffULL) == aint) {
|
||||
specialists[i] |= f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
|
||||
specialists[specialistCount++] = f | aint;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool addSpecialist(const Address &a,const uint64_t f);
|
||||
|
||||
inline const Capability *capability(const uint32_t id) const
|
||||
ZT_ALWAYS_INLINE const Capability *capability(const uint32_t id) const
|
||||
{
|
||||
for(unsigned int i=0;i<capabilityCount;++i) {
|
||||
if (capabilities[i].id() == id)
|
||||
|
@ -278,7 +243,7 @@ struct NetworkConfig
|
|||
return (Capability *)0;
|
||||
}
|
||||
|
||||
inline const Tag *tag(const uint32_t id) const
|
||||
ZT_ALWAYS_INLINE const Tag *tag(const uint32_t id) const
|
||||
{
|
||||
for(unsigned int i=0;i<tagCount;++i) {
|
||||
if (tags[i].id() == id)
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
#include "NetworkController.hpp"
|
||||
#include "Switch.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
|
@ -30,6 +28,7 @@
|
|||
#include "Trace.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Mutex.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -103,9 +104,9 @@ public:
|
|||
unsigned int hops,
|
||||
uint64_t packetId,
|
||||
unsigned int payloadLength,
|
||||
Packet::Verb verb,
|
||||
Protocol::Verb verb,
|
||||
uint64_t inRePacketId,
|
||||
Packet::Verb inReVerb,
|
||||
Protocol::Verb inReVerb,
|
||||
uint64_t networkId);
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "InetAddress.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
@ -30,6 +29,7 @@
|
|||
#include "SharedPtr.hpp"
|
||||
#include "IncomingPacket.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
|
@ -27,11 +30,6 @@
|
|||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace Utils {
|
||||
|
@ -166,13 +164,13 @@ void getSecureRandom(void *buf,unsigned int bytes)
|
|||
static Mutex globalLock;
|
||||
static bool initialized = false;
|
||||
static uint64_t randomState[8];
|
||||
static uint8_t randomBuf[65536];
|
||||
static unsigned long randomPtr = sizeof(randomBuf);
|
||||
static uint64_t randomBuf[8192];
|
||||
static unsigned int randomPtr = 65536;
|
||||
|
||||
Mutex::Lock gl(globalLock);
|
||||
|
||||
for(unsigned int i=0;i<bytes;++i) {
|
||||
if (randomPtr >= sizeof(randomBuf)) {
|
||||
if (randomPtr >= 65536) {
|
||||
randomPtr = 0;
|
||||
|
||||
if (!initialized) {
|
||||
|
@ -225,18 +223,22 @@ void getSecureRandom(void *buf,unsigned int bytes)
|
|||
#endif
|
||||
}
|
||||
|
||||
++randomState[0];
|
||||
SHA512(randomState,randomState,sizeof(randomState));
|
||||
AES aes(reinterpret_cast<const uint8_t *>(randomState));
|
||||
uint64_t ctr[2];
|
||||
uint64_t ctr[2],tmp[2];
|
||||
ctr[0] = randomState[6];
|
||||
ctr[1] = randomState[7];
|
||||
for(unsigned long i=0;i<sizeof(randomBuf);i+=16) {
|
||||
for(int k=0;k<8192;) {
|
||||
++ctr[0];
|
||||
aes.encrypt(reinterpret_cast<const uint8_t *>(ctr),randomBuf + i);
|
||||
aes.encrypt(reinterpret_cast<const uint8_t *>(ctr),reinterpret_cast<uint8_t *>(tmp));
|
||||
randomBuf[k] ^= tmp[0];
|
||||
randomBuf[k+1] ^= tmp[1];
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
reinterpret_cast<uint8_t *>(buf)[i] = randomBuf[randomPtr++];
|
||||
reinterpret_cast<uint8_t *>(buf)[i] = reinterpret_cast<uint8_t *>(randomBuf)[randomPtr++];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
#include <emmintrin.h>
|
||||
|
@ -26,12 +31,6 @@
|
|||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace Utils {
|
||||
|
@ -87,7 +86,7 @@ char *decimal(unsigned long n,char s[24]);
|
|||
* @return Pointer to s containing hex string with trailing zero byte
|
||||
*/
|
||||
template<typename I>
|
||||
static inline char *hex(I x,char *s)
|
||||
static ZT_ALWAYS_INLINE char *hex(I x,char *s)
|
||||
{
|
||||
char *const r = s;
|
||||
for(unsigned int i=0,b=(sizeof(x)*8);i<sizeof(x);++i) {
|
||||
|
|
Loading…
Add table
Reference in a new issue