mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +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
|
Buf.cpp
|
||||||
C25519.cpp
|
C25519.cpp
|
||||||
Capability.cpp
|
Capability.cpp
|
||||||
|
CertificateOfMembership.cpp
|
||||||
|
CertificateOfOwnership.cpp
|
||||||
Credential.cpp
|
Credential.cpp
|
||||||
|
Dictionary.cpp
|
||||||
ECC384.cpp
|
ECC384.cpp
|
||||||
Endpoint.cpp
|
Endpoint.cpp
|
||||||
Identity.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 "Constants.hpp"
|
||||||
#include "Credential.hpp"
|
#include "Credential.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "C25519.hpp"
|
#include "C25519.hpp"
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
|
@ -34,6 +33,8 @@
|
||||||
*/
|
*/
|
||||||
#define ZT_NETWORK_COM_MAX_QUALIFIERS 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 {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
class RuntimeEnvironment;
|
||||||
|
@ -113,29 +114,7 @@ public:
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
* @param issuedTo Certificate recipient
|
* @param issuedTo Certificate recipient
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
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); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if there's something here
|
* @return True if there's something here
|
||||||
|
@ -192,24 +171,7 @@ public:
|
||||||
* @param value Qualifier value
|
* @param value Qualifier value
|
||||||
* @param maxDelta Qualifier maximum allowed difference (absolute value of difference)
|
* @param maxDelta Qualifier maximum allowed difference (absolute value of difference)
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE void setQualifier(uint64_t id,uint64_t value,uint64_t maxDelta)
|
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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,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
|
* @param with Identity to sign with, must include private key
|
||||||
* @return True if signature was successful
|
* @return True if signature was successful
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE bool sign(const Identity &with)
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify this COM and its signature
|
* Verify this COM and its signature
|
||||||
|
@ -301,95 +245,21 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; }
|
ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; }
|
||||||
|
|
||||||
template<unsigned int C>
|
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX; }
|
||||||
inline void serialize(Buffer<C> &b) const
|
int marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const;
|
||||||
{
|
int unmarshal(const uint8_t *data,int len);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<unsigned int C>
|
bool operator==(const CertificateOfMembership &c) const;
|
||||||
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);
|
|
||||||
}
|
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
|
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _Qualifier
|
struct _Qualifier
|
||||||
{
|
{
|
||||||
_Qualifier() : id(0),value(0),maxDelta(0) {}
|
ZT_ALWAYS_INLINE _Qualifier() : id(0),value(0),maxDelta(0) {}
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
uint64_t maxDelta;
|
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;
|
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 "C25519.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "MAC.hpp"
|
#include "MAC.hpp"
|
||||||
|
|
||||||
|
@ -34,6 +33,8 @@
|
||||||
// Maximum size of a thing's value field in bytes
|
// Maximum size of a thing's value field in bytes
|
||||||
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
|
#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 {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
class RuntimeEnvironment;
|
||||||
|
@ -98,112 +99,20 @@ public:
|
||||||
return this->_owns(THING_MAC_ADDRESS,tmp,6);
|
return this->_owns(THING_MAC_ADDRESS,tmp,6);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void addThing(const InetAddress &ip)
|
void addThing(const InetAddress &ip);
|
||||||
{
|
void addThing(const MAC &mac);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param signer Signing identity, must have private key
|
* @param signer Signing identity, must have private key
|
||||||
* @return True if signature was successful
|
* @return True if signature was successful
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE bool sign(const Identity &signer)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||||
|
|
||||||
template<unsigned int C>
|
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
|
||||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign = false) const;
|
||||||
{
|
int unmarshal(const uint8_t *data,int len);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provides natural sort order by ID
|
// Provides natural sort order by ID
|
||||||
ZT_ALWAYS_INLINE bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._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 "Constants.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
|
#include "Buf.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define ZT_DICTIONARY_MAX_CAPACITY 65536
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,32 +47,14 @@ namespace ZeroTier {
|
||||||
*
|
*
|
||||||
* @tparam C Dictionary max capacity in bytes
|
* @tparam C Dictionary max capacity in bytes
|
||||||
*/
|
*/
|
||||||
template<unsigned int C>
|
|
||||||
class Dictionary
|
class Dictionary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Dictionary() { memset(_d,0,sizeof(_d)); }
|
ZT_ALWAYS_INLINE Dictionary() { _d[0] = 0; }
|
||||||
inline Dictionary(const char *s) { this->load(s); }
|
explicit ZT_ALWAYS_INLINE Dictionary(const char *s) { this->load(s); }
|
||||||
inline Dictionary(const char *s,unsigned int len)
|
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); }
|
|
||||||
|
|
||||||
inline Dictionary &operator=(const Dictionary &d)
|
ZT_ALWAYS_INLINE operator bool() const { return (_d[0] != 0); }
|
||||||
{
|
|
||||||
memcpy(_d,d._d,C);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator bool() const { return (_d[0] != 0); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a dictionary from a C-string
|
* Load a dictionary from a C-string
|
||||||
|
@ -78,35 +62,12 @@ public:
|
||||||
* @param s Dictionary in string form
|
* @param s Dictionary in string form
|
||||||
* @return False if 's' was longer than our capacity
|
* @return False if 's' was longer than our capacity
|
||||||
*/
|
*/
|
||||||
inline bool load(const char *s)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all entries
|
* Delete all entries
|
||||||
*/
|
*/
|
||||||
inline void clear() { memset(_d,0,sizeof(_d)); }
|
ZT_ALWAYS_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an entry
|
* Get an entry
|
||||||
|
@ -130,104 +91,7 @@ public:
|
||||||
* @param destlen Size of destination buffer
|
* @param destlen Size of destination buffer
|
||||||
* @return -1 if not found, or actual number of bytes stored in dest[] minus trailing 0
|
* @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
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a boolean value
|
* Get a boolean value
|
||||||
|
@ -236,7 +100,7 @@ public:
|
||||||
* @param dfl Default value if not found in dictionary
|
* @param dfl Default value if not found in dictionary
|
||||||
* @return Boolean value of key or 'dfl' if not found
|
* @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];
|
char tmp[4];
|
||||||
if (this->get(key,tmp,sizeof(tmp)) >= 0)
|
if (this->get(key,tmp,sizeof(tmp)) >= 0)
|
||||||
|
@ -251,7 +115,7 @@ public:
|
||||||
* @param dfl Default value or 0 if unspecified
|
* @param dfl Default value or 0 if unspecified
|
||||||
* @return Decoded hex UInt value or 'dfl' if not found
|
* @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];
|
char tmp[128];
|
||||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
||||||
|
@ -266,7 +130,7 @@ public:
|
||||||
* @param dfl Default value or 0 if unspecified
|
* @param dfl Default value or 0 if unspecified
|
||||||
* @return Decoded hex UInt value or 'dfl' if not found
|
* @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];
|
char tmp[128];
|
||||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
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
|
* @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
|
* @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)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a boolean as a '1' or a '0'
|
* Add a boolean as a '1' or a '0'
|
||||||
*/
|
*/
|
||||||
inline bool add(const char *key,bool value)
|
bool add(const char *key,bool value);
|
||||||
{
|
|
||||||
return this->add(key,(value) ? "1" : "0",1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a 64-bit integer (unsigned) as a hex value
|
* Add a 64-bit integer (unsigned) as a hex value
|
||||||
*/
|
*/
|
||||||
inline bool add(const char *key,uint64_t value)
|
bool add(const char *key,uint64_t value);
|
||||||
{
|
|
||||||
char tmp[32];
|
|
||||||
return this->add(key,Utils::hex(value,tmp),-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a 64-bit integer (unsigned) as a hex value
|
* Add a 64-bit integer (unsigned) as a hex value
|
||||||
*/
|
*/
|
||||||
inline bool add(const char *key,int64_t value)
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a 64-bit integer (unsigned) as a hex value
|
* Add a 64-bit integer (unsigned) as a hex value
|
||||||
*/
|
*/
|
||||||
inline bool add(const char *key,const Address &a)
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key Key to check
|
* @param key Key to check
|
||||||
* @return True if key is present
|
* @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];
|
char tmp[2];
|
||||||
return (this->get(key,tmp,2) >= 0);
|
return (this->get(key,tmp,2) >= 0);
|
||||||
|
@ -427,13 +187,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return Value of C template parameter
|
* @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; }
|
ZT_ALWAYS_INLINE const char *data() const { return _d; }
|
||||||
inline char *unsafeData() { return _d; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char _d[C];
|
char _d[ZT_DICTIONARY_MAX_CAPACITY];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "C25519.hpp"
|
#include "C25519.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "SHA512.hpp"
|
#include "SHA512.hpp"
|
||||||
#include "ECC384.hpp"
|
#include "ECC384.hpp"
|
||||||
|
|
||||||
|
@ -158,108 +157,6 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE const Address &address() const { return _address; }
|
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
|
* Serialize to a more human-friendly string
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "MAC.hpp"
|
#include "MAC.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -498,62 +497,6 @@ public:
|
||||||
int marshal(uint8_t data[19]) const;
|
int marshal(uint8_t data[19]) const;
|
||||||
int unmarshal(const uint8_t *restrict data,const int len);
|
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;
|
||||||
bool operator<(const InetAddress &a) const;
|
bool operator<(const InetAddress &a) const;
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const InetAddress &a) const { return !(*this == a); }
|
ZT_ALWAYS_INLINE bool operator!=(const InetAddress &a) const { return !(*this == a); }
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -39,9 +38,9 @@ public:
|
||||||
((((uint64_t)d) & 0xffULL) << 16U) |
|
((((uint64_t)d) & 0xffULL) << 16U) |
|
||||||
((((uint64_t)e) & 0xffULL) << 8U) |
|
((((uint64_t)e) & 0xffULL) << 8U) |
|
||||||
(((uint64_t)f) & 0xffULL) ) {}
|
(((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 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
|
* @return MAC in 64-bit integer
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "Peer.hpp"
|
#include "Peer.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
#include "Packet.hpp"
|
|
||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
// multicast address directly from the IP address, and it gives us
|
// multicast address directly from the IP address, and it gives us
|
||||||
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
||||||
// to care about.
|
// 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(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0);
|
||||||
}
|
}
|
||||||
return MulticastGroup();
|
return MulticastGroup();
|
||||||
|
|
|
@ -20,7 +20,28 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
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>());
|
ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
|
||||||
char tmp2[128];
|
char tmp2[128];
|
||||||
|
@ -105,7 +126,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d)
|
bool NetworkConfig::fromDictionary(const Dictionary &d)
|
||||||
{
|
{
|
||||||
static const NetworkConfig NIL_NC;
|
static const NetworkConfig NIL_NC;
|
||||||
ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
|
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
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -17,13 +17,11 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "MulticastGroup.hpp"
|
#include "MulticastGroup.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
|
@ -168,26 +166,7 @@ namespace ZeroTier {
|
||||||
*/
|
*/
|
||||||
struct NetworkConfig
|
struct NetworkConfig
|
||||||
{
|
{
|
||||||
inline 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write this network config to a dictionary for transport
|
* 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
|
* @param includeLegacy If true, include legacy fields for old node versions
|
||||||
* @return True if dictionary was successfully created, false if e.g. overflow
|
* @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
|
* 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)
|
* @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
|
* @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
|
* @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
|
* @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)
|
* @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)
|
* @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
|
* @param fromPeer Peer attempting to bridge other Ethernet peers onto network
|
||||||
* @return True if this network allows bridging
|
* @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) {
|
for(unsigned int i=0;i<specialistCount;++i) {
|
||||||
if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||||
|
@ -239,9 +218,9 @@ struct NetworkConfig
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator bool() const { return (networkId != 0); }
|
ZT_ALWAYS_INLINE operator bool() const { return (networkId != 0); }
|
||||||
inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
|
ZT_ALWAYS_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 bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a specialist or mask flags if already present
|
* Add a specialist or mask flags if already present
|
||||||
|
@ -253,23 +232,9 @@ struct NetworkConfig
|
||||||
* @param f Flags (OR of specialist role/type flags)
|
* @param f Flags (OR of specialist role/type flags)
|
||||||
* @return True if successfully masked or added
|
* @return True if successfully masked or added
|
||||||
*/
|
*/
|
||||||
inline bool addSpecialist(const Address &a,const uint64_t f)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
for(unsigned int i=0;i<capabilityCount;++i) {
|
||||||
if (capabilities[i].id() == id)
|
if (capabilities[i].id() == id)
|
||||||
|
@ -278,7 +243,7 @@ struct NetworkConfig
|
||||||
return (Capability *)0;
|
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) {
|
for(unsigned int i=0;i<tagCount;++i) {
|
||||||
if (tags[i].id() == id)
|
if (tags[i].id() == id)
|
||||||
|
|
|
@ -21,8 +21,6 @@
|
||||||
#include "NetworkController.hpp"
|
#include "NetworkController.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "Packet.hpp"
|
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
#include "SelfAwareness.hpp"
|
#include "SelfAwareness.hpp"
|
||||||
|
@ -30,6 +28,7 @@
|
||||||
#include "Trace.hpp"
|
#include "Trace.hpp"
|
||||||
#include "ScopedPtr.hpp"
|
#include "ScopedPtr.hpp"
|
||||||
#include "Locator.hpp"
|
#include "Locator.hpp"
|
||||||
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
#include "Endpoint.hpp"
|
#include "Endpoint.hpp"
|
||||||
#include "Locator.hpp"
|
#include "Locator.hpp"
|
||||||
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -103,9 +104,9 @@ public:
|
||||||
unsigned int hops,
|
unsigned int hops,
|
||||||
uint64_t packetId,
|
uint64_t packetId,
|
||||||
unsigned int payloadLength,
|
unsigned int payloadLength,
|
||||||
Packet::Verb verb,
|
Protocol::Verb verb,
|
||||||
uint64_t inRePacketId,
|
uint64_t inRePacketId,
|
||||||
Packet::Verb inReVerb,
|
Protocol::Verb inReVerb,
|
||||||
uint64_t networkId);
|
uint64_t networkId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "C25519.hpp"
|
#include "C25519.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "Peer.hpp"
|
#include "Peer.hpp"
|
||||||
#include "SelfAwareness.hpp"
|
#include "SelfAwareness.hpp"
|
||||||
#include "Packet.hpp"
|
|
||||||
#include "Trace.hpp"
|
#include "Trace.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
#include "MAC.hpp"
|
#include "MAC.hpp"
|
||||||
#include "Packet.hpp"
|
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
|
@ -30,6 +29,7 @@
|
||||||
#include "SharedPtr.hpp"
|
#include "SharedPtr.hpp"
|
||||||
#include "IncomingPacket.hpp"
|
#include "IncomingPacket.hpp"
|
||||||
#include "Hashtable.hpp"
|
#include "Hashtable.hpp"
|
||||||
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "C25519.hpp"
|
#include "C25519.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
#include "Buffer.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "Mutex.hpp"
|
||||||
|
#include "AES.hpp"
|
||||||
|
#include "SHA512.hpp"
|
||||||
|
|
||||||
#ifdef __UNIX_LIKE__
|
#ifdef __UNIX_LIKE__
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -27,11 +30,6 @@
|
||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Utils.hpp"
|
|
||||||
#include "Mutex.hpp"
|
|
||||||
#include "AES.hpp"
|
|
||||||
#include "SHA512.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
@ -166,13 +164,13 @@ void getSecureRandom(void *buf,unsigned int bytes)
|
||||||
static Mutex globalLock;
|
static Mutex globalLock;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
static uint64_t randomState[8];
|
static uint64_t randomState[8];
|
||||||
static uint8_t randomBuf[65536];
|
static uint64_t randomBuf[8192];
|
||||||
static unsigned long randomPtr = sizeof(randomBuf);
|
static unsigned int randomPtr = 65536;
|
||||||
|
|
||||||
Mutex::Lock gl(globalLock);
|
Mutex::Lock gl(globalLock);
|
||||||
|
|
||||||
for(unsigned int i=0;i<bytes;++i) {
|
for(unsigned int i=0;i<bytes;++i) {
|
||||||
if (randomPtr >= sizeof(randomBuf)) {
|
if (randomPtr >= 65536) {
|
||||||
randomPtr = 0;
|
randomPtr = 0;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
|
@ -225,18 +223,22 @@ void getSecureRandom(void *buf,unsigned int bytes)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++randomState[0];
|
||||||
SHA512(randomState,randomState,sizeof(randomState));
|
SHA512(randomState,randomState,sizeof(randomState));
|
||||||
AES aes(reinterpret_cast<const uint8_t *>(randomState));
|
AES aes(reinterpret_cast<const uint8_t *>(randomState));
|
||||||
uint64_t ctr[2];
|
uint64_t ctr[2],tmp[2];
|
||||||
ctr[0] = randomState[6];
|
ctr[0] = randomState[6];
|
||||||
ctr[1] = randomState[7];
|
ctr[1] = randomState[7];
|
||||||
for(unsigned long i=0;i<sizeof(randomBuf);i+=16) {
|
for(int k=0;k<8192;) {
|
||||||
++ctr[0];
|
++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 <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#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))
|
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
@ -26,12 +31,6 @@
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "Constants.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
namespace Utils {
|
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
|
* @return Pointer to s containing hex string with trailing zero byte
|
||||||
*/
|
*/
|
||||||
template<typename I>
|
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;
|
char *const r = s;
|
||||||
for(unsigned int i=0,b=(sizeof(x)*8);i<sizeof(x);++i) {
|
for(unsigned int i=0,b=(sizeof(x)*8);i<sizeof(x);++i) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue