mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-14 19:16:54 +02:00
Certificate of ownership -- used to secure against IP address spoofing, especially for IPv4 and regular IPv6.
This commit is contained in:
parent
33b94e8478
commit
10185e92fa
15 changed files with 553 additions and 97 deletions
|
@ -1706,6 +1706,15 @@ void EmbeddedNetworkController::_request(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue a certificate of ownership for all static IPs
|
||||||
|
if (nc.staticIpCount) {
|
||||||
|
nc.certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1);
|
||||||
|
for(unsigned int i=0;i<nc.staticIpCount;++i)
|
||||||
|
nc.certificatesOfOwnership[0].addThing(nc.staticIps[i]);
|
||||||
|
nc.certificatesOfOwnership[0].sign(_signingId);
|
||||||
|
nc.certificateOfOwnershipCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
CertificateOfMembership com(now,credentialtmd,nwid,identity.address());
|
CertificateOfMembership com(now,credentialtmd,nwid,identity.address());
|
||||||
if (com.sign(_signingId)) {
|
if (com.sign(_signingId)) {
|
||||||
nc.com = com;
|
nc.com = com;
|
||||||
|
|
|
@ -136,6 +136,11 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define ZT_MAX_CAPABILITY_RULES 64
|
#define ZT_MAX_CAPABILITY_RULES 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of certificates of ownership to assign to a single network member
|
||||||
|
*/
|
||||||
|
#define ZT_MAX_CERTIFICATES_OF_OWNERSHIP 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global maximum length for capability chain of custody (including initial issue)
|
* Global maximum length for capability chain of custody (including initial issue)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -396,7 +396,6 @@ public:
|
||||||
|
|
||||||
unsigned int p = startAt;
|
unsigned int p = startAt;
|
||||||
|
|
||||||
// These are the same between Tag and Capability
|
|
||||||
_nwid = b.template at<uint64_t>(p); p += 8;
|
_nwid = b.template at<uint64_t>(p); p += 8;
|
||||||
_ts = b.template at<uint64_t>(p); p += 8;
|
_ts = b.template at<uint64_t>(p); p += 8;
|
||||||
_id = b.template at<uint32_t>(p); p += 4;
|
_id = b.template at<uint32_t>(p); p += 4;
|
||||||
|
|
46
node/CertificateOfOwnership.cpp
Normal file
46
node/CertificateOfOwnership.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* ZeroTier One - Network Virtualization Everywhere
|
||||||
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CertificateOfOwnership.hpp"
|
||||||
|
#include "RuntimeEnvironment.hpp"
|
||||||
|
#include "Identity.hpp"
|
||||||
|
#include "Topology.hpp"
|
||||||
|
#include "Switch.hpp"
|
||||||
|
#include "Network.hpp"
|
||||||
|
|
||||||
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR) const
|
||||||
|
{
|
||||||
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
|
||||||
|
return -1;
|
||||||
|
const Identity id(RR->topology->getIdentity(_signedBy));
|
||||||
|
if (!id) {
|
||||||
|
RR->sw->requestWhois(_signedBy);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Buffer<(sizeof(CertificateOfOwnership) + 64)> tmp;
|
||||||
|
this->serialize(tmp,true);
|
||||||
|
return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
|
||||||
|
} catch ( ... ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ZeroTier
|
251
node/CertificateOfOwnership.hpp
Normal file
251
node/CertificateOfOwnership.hpp
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* ZeroTier One - Network Virtualization Everywhere
|
||||||
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||||
|
#define ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Constants.hpp"
|
||||||
|
#include "C25519.hpp"
|
||||||
|
#include "Address.hpp"
|
||||||
|
#include "Identity.hpp"
|
||||||
|
#include "Buffer.hpp"
|
||||||
|
#include "InetAddress.hpp"
|
||||||
|
#include "MAC.hpp"
|
||||||
|
|
||||||
|
// Max things per CertificateOfOwnership
|
||||||
|
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16
|
||||||
|
|
||||||
|
// Maximum size of a thing's value field in bytes
|
||||||
|
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
|
||||||
|
|
||||||
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
class RuntimeEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certificate indicating ownership of a network identifier
|
||||||
|
*/
|
||||||
|
class CertificateOfOwnership
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Thing
|
||||||
|
{
|
||||||
|
THING_NULL = 0,
|
||||||
|
THING_MAC_ADDRESS = 1,
|
||||||
|
THING_IPV4_ADDRESS = 2,
|
||||||
|
THING_IPV6_ADDRESS = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
CertificateOfOwnership() :
|
||||||
|
_networkId(0),
|
||||||
|
_ts(0),
|
||||||
|
_id(0),
|
||||||
|
_thingCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CertificateOfOwnership(const uint64_t nwid,const uint64_t ts,const Address &issuedTo,const uint32_t id) :
|
||||||
|
_networkId(nwid),
|
||||||
|
_ts(ts),
|
||||||
|
_flags(0),
|
||||||
|
_id(id),
|
||||||
|
_thingCount(0),
|
||||||
|
_issuedTo(issuedTo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t networkId() const { return _networkId; }
|
||||||
|
inline uint64_t timestamp() const { return _ts; }
|
||||||
|
inline uint32_t id() const { return _id; }
|
||||||
|
inline unsigned int thingCount() const { return (unsigned int)_thingCount; }
|
||||||
|
|
||||||
|
inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
|
||||||
|
inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
|
||||||
|
|
||||||
|
inline const Address &issuedTo() const { return _issuedTo; }
|
||||||
|
|
||||||
|
inline bool owns(const Thing &t,const void *v,unsigned int l)
|
||||||
|
{
|
||||||
|
for(unsigned int i=0,j=_thingCount;i<j;++i) {
|
||||||
|
if (_thingTypes[i] == (uint8_t)t) {
|
||||||
|
unsigned int k = 0;
|
||||||
|
while (k < l) {
|
||||||
|
if (reinterpret_cast<const uint8_t *>(v)[k] != _thingValues[i][k])
|
||||||
|
break;
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
if (k == l)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool owns(const InetAddress &ip)
|
||||||
|
{
|
||||||
|
if (ip.ss_family == AF_INET)
|
||||||
|
return this->owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
|
||||||
|
if (ip.ss_family == AF_INET6)
|
||||||
|
return this->owns(THING_IPV6_ADDRESS,reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool owns(const MAC &mac)
|
||||||
|
{
|
||||||
|
uint8_t tmp[6];
|
||||||
|
mac.copyTo(tmp,6);
|
||||||
|
return this->owns(THING_MAC_ADDRESS,tmp,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
* @return True if signature was successful
|
||||||
|
*/
|
||||||
|
inline bool sign(const Identity &signer)
|
||||||
|
{
|
||||||
|
if (signer.hasPrivate()) {
|
||||||
|
Buffer<sizeof(CertificateOfOwnership) + 64> tmp;
|
||||||
|
_signedBy = signer.address();
|
||||||
|
this->serialize(tmp,true);
|
||||||
|
_signature = signer.sign(tmp.data(),tmp.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RR Runtime environment to allow identity lookup for signedBy
|
||||||
|
* @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature
|
||||||
|
*/
|
||||||
|
int verify(const RuntimeEnvironment *RR) const;
|
||||||
|
|
||||||
|
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); // 1 == Ed25519
|
||||||
|
b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
|
||||||
|
b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
memset(this,0,sizeof(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) {
|
||||||
|
if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN)
|
||||||
|
throw std::runtime_error("invalid signature length");
|
||||||
|
p += 2;
|
||||||
|
memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN;
|
||||||
|
} else {
|
||||||
|
p += 2 + b.template at<uint16_t>(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 2 + b.template at<uint16_t>(p);
|
||||||
|
if (p > b.size())
|
||||||
|
throw std::runtime_error("extended field overflow");
|
||||||
|
|
||||||
|
return (p - startAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provides natural sort order by ID
|
||||||
|
inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
|
||||||
|
|
||||||
|
inline bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); }
|
||||||
|
inline bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t _networkId;
|
||||||
|
uint64_t _ts;
|
||||||
|
uint64_t _flags;
|
||||||
|
uint32_t _id;
|
||||||
|
uint16_t _thingCount;
|
||||||
|
uint8_t _thingTypes[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS];
|
||||||
|
uint8_t _thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE];
|
||||||
|
Address _issuedTo;
|
||||||
|
Address _signedBy;
|
||||||
|
C25519::Signature _signature;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ZeroTier
|
||||||
|
|
||||||
|
#endif
|
|
@ -832,6 +832,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
||||||
Capability cap;
|
Capability cap;
|
||||||
Tag tag;
|
Tag tag;
|
||||||
Revocation revocation;
|
Revocation revocation;
|
||||||
|
CertificateOfOwnership coo;
|
||||||
bool trustEstablished = false;
|
bool trustEstablished = false;
|
||||||
|
|
||||||
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
||||||
|
@ -909,6 +910,24 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unsigned int numCoos = at<uint16_t>(p); p += 2;
|
||||||
|
for(unsigned int i=0;i<numCoos;++i) {
|
||||||
|
p += coo.deserialize(*this,p);
|
||||||
|
const SharedPtr<Network> network(RR->node->network(coo.networkId()));
|
||||||
|
if (network) {
|
||||||
|
switch(network->addCredential(coo)) {
|
||||||
|
case Membership::ADD_REJECTED:
|
||||||
|
break;
|
||||||
|
case Membership::ADD_ACCEPTED_NEW:
|
||||||
|
case Membership::ADD_ACCEPTED_REDUNDANT:
|
||||||
|
trustEstablished = true;
|
||||||
|
break;
|
||||||
|
case Membership::ADD_DEFERRED_FOR_WHOIS:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished);
|
peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished);
|
||||||
|
|
|
@ -37,6 +37,7 @@ Membership::Membership() :
|
||||||
{
|
{
|
||||||
for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) _remoteTags[i] = &(_tagMem[i]);
|
for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) _remoteTags[i] = &(_tagMem[i]);
|
||||||
for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) _remoteCaps[i] = &(_capMem[i]);
|
for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) _remoteCaps[i] = &(_capMem[i]);
|
||||||
|
for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) _remoteCoos[i] = &(_cooMem[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
|
void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
|
||||||
|
@ -62,8 +63,19 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CertificateOfOwnership *sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
|
||||||
|
unsigned int sendCooCount = 0;
|
||||||
|
for(unsigned int c=0;c<nconf.certificateOfOwnershipCount;++c) {
|
||||||
|
if ( (_localCoos[c].id != nconf.certificatesOfOwnership[c].id()) || ((now - _localCoos[c].lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) {
|
||||||
|
_localCoos[c].lastPushed = now;
|
||||||
|
_localCoos[c].id = nconf.certificatesOfOwnership[c].id();
|
||||||
|
sendCoos[sendCooCount++] = &(nconf.certificatesOfOwnership[c]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int tagPtr = 0;
|
unsigned int tagPtr = 0;
|
||||||
while ((tagPtr < sendTagCount)||(sendCom)||(sendCap)) {
|
unsigned int cooPtr = 0;
|
||||||
|
while ((tagPtr < sendTagCount)||(cooPtr < sendCooCount)||(sendCom)||(sendCap)) {
|
||||||
Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||||
|
|
||||||
if (sendCom) {
|
if (sendCom) {
|
||||||
|
@ -82,7 +94,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now
|
||||||
const unsigned int tagCountAt = outp.size();
|
const unsigned int tagCountAt = outp.size();
|
||||||
outp.addSize(2);
|
outp.addSize(2);
|
||||||
unsigned int thisPacketTagCount = 0;
|
unsigned int thisPacketTagCount = 0;
|
||||||
while ((tagPtr < sendTagCount)&&((outp.size() + sizeof(Tag) + 32) < ZT_PROTO_MAX_PACKET_LENGTH)) {
|
while ((tagPtr < sendTagCount)&&((outp.size() + sizeof(Tag) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
|
||||||
sendTags[tagPtr++]->serialize(outp);
|
sendTags[tagPtr++]->serialize(outp);
|
||||||
++thisPacketTagCount;
|
++thisPacketTagCount;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +103,15 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now
|
||||||
// No revocations, these propagate differently
|
// No revocations, these propagate differently
|
||||||
outp.append((uint16_t)0);
|
outp.append((uint16_t)0);
|
||||||
|
|
||||||
|
const unsigned int cooCountAt = outp.size();
|
||||||
|
outp.addSize(2);
|
||||||
|
unsigned int thisPacketCooCount = 0;
|
||||||
|
while ((cooPtr < sendCooCount)&&((outp.size() + sizeof(CertificateOfOwnership) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
|
||||||
|
sendCoos[cooPtr++]->serialize(outp);
|
||||||
|
++thisPacketCooCount;
|
||||||
|
}
|
||||||
|
outp.setAt(cooCountAt,(uint16_t)thisPacketCooCount);
|
||||||
|
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true);
|
RR->sw->send(outp,true);
|
||||||
}
|
}
|
||||||
|
@ -98,14 +119,14 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now
|
||||||
|
|
||||||
const Capability *Membership::getCapability(const NetworkConfig &nconf,const uint32_t id) const
|
const Capability *Membership::getCapability(const NetworkConfig &nconf,const uint32_t id) const
|
||||||
{
|
{
|
||||||
const _RemoteCapability *const *c = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)id,_RemoteCredentialSorter<_RemoteCapability>());
|
const _RemoteCredential<Capability> *const *c = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)id,_RemoteCredentialComp<Capability>());
|
||||||
return ( ((c != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*c)->id == (uint64_t)id)) ? ((((*c)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*c)->cap,**c))) ? &((*c)->cap) : (const Capability *)0) : (const Capability *)0);
|
return ( ((c != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*c)->id == (uint64_t)id)) ? ((((*c)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*c)->credential,**c))) ? &((*c)->credential) : (const Capability *)0) : (const Capability *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tag *Membership::getTag(const NetworkConfig &nconf,const uint32_t id) const
|
const Tag *Membership::getTag(const NetworkConfig &nconf,const uint32_t id) const
|
||||||
{
|
{
|
||||||
const _RemoteTag *const *t = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)id,_RemoteCredentialSorter<_RemoteTag>());
|
const _RemoteCredential<Tag> *const *t = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)id,_RemoteCredentialComp<Tag>());
|
||||||
return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*t)->tag,**t))) ? &((*t)->tag) : (const Tag *)0) : (const Tag *)0);
|
return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*t)->credential,**t))) ? &((*t)->credential) : (const Tag *)0) : (const Tag *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com)
|
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com)
|
||||||
|
@ -141,14 +162,14 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
|
|
||||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag)
|
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag)
|
||||||
{
|
{
|
||||||
_RemoteTag *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialSorter<_RemoteTag>());
|
_RemoteCredential<Tag> *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialComp<Tag>());
|
||||||
_RemoteTag *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteTag *)0;
|
_RemoteCredential<Tag> *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteCredential<Tag> *)0;
|
||||||
if (have) {
|
if (have) {
|
||||||
if ( (!_isCredentialTimestampValid(nconf,tag,*have)) || (have->tag.timestamp() > tag.timestamp()) ) {
|
if ( (!_isCredentialTimestampValid(nconf,tag,*have)) || (have->credential.timestamp() > tag.timestamp()) ) {
|
||||||
TRACE("addCredential(Tag) for %s on %.16llx REJECTED (revoked or too old)",tag.issuedTo().toString().c_str(),tag.networkId());
|
TRACE("addCredential(Tag) for %s on %.16llx REJECTED (revoked or too old)",tag.issuedTo().toString().c_str(),tag.networkId());
|
||||||
return ADD_REJECTED;
|
return ADD_REJECTED;
|
||||||
}
|
}
|
||||||
if (have->tag == tag) {
|
if (have->credential == tag) {
|
||||||
TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (redundant)",tag.issuedTo().toString().c_str(),tag.networkId());
|
TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (redundant)",tag.issuedTo().toString().c_str(),tag.networkId());
|
||||||
return ADD_ACCEPTED_REDUNDANT;
|
return ADD_ACCEPTED_REDUNDANT;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +183,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (new)",tag.issuedTo().toString().c_str(),tag.networkId());
|
TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (new)",tag.issuedTo().toString().c_str(),tag.networkId());
|
||||||
if (!have) have = _newTag(tag.id());
|
if (!have) have = _newTag(tag.id());
|
||||||
have->lastReceived = RR->node->now();
|
have->lastReceived = RR->node->now();
|
||||||
have->tag = tag;
|
have->credential = tag;
|
||||||
return ADD_ACCEPTED_NEW;
|
return ADD_ACCEPTED_NEW;
|
||||||
case 1:
|
case 1:
|
||||||
return ADD_DEFERRED_FOR_WHOIS;
|
return ADD_DEFERRED_FOR_WHOIS;
|
||||||
|
@ -171,14 +192,14 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
|
|
||||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap)
|
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap)
|
||||||
{
|
{
|
||||||
_RemoteCapability *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialSorter<_RemoteCapability>());
|
_RemoteCredential<Capability> *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialComp<Capability>());
|
||||||
_RemoteCapability *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCapability *)0;
|
_RemoteCredential<Capability> *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCredential<Capability> *)0;
|
||||||
if (have) {
|
if (have) {
|
||||||
if ( (!_isCredentialTimestampValid(nconf,cap,*have)) || (have->cap.timestamp() > cap.timestamp()) ) {
|
if ( (!_isCredentialTimestampValid(nconf,cap,*have)) || (have->credential.timestamp() > cap.timestamp()) ) {
|
||||||
TRACE("addCredential(Capability) for %s on %.16llx REJECTED (revoked or too old)",cap.issuedTo().toString().c_str(),cap.networkId());
|
TRACE("addCredential(Capability) for %s on %.16llx REJECTED (revoked or too old)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
return ADD_REJECTED;
|
return ADD_REJECTED;
|
||||||
}
|
}
|
||||||
if (have->cap == cap) {
|
if (have->credential == cap) {
|
||||||
TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (redundant)",cap.issuedTo().toString().c_str(),cap.networkId());
|
TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (redundant)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
return ADD_ACCEPTED_REDUNDANT;
|
return ADD_ACCEPTED_REDUNDANT;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +213,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (new)",cap.issuedTo().toString().c_str(),cap.networkId());
|
TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (new)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
if (!have) have = _newCapability(cap.id());
|
if (!have) have = _newCapability(cap.id());
|
||||||
have->lastReceived = RR->node->now();
|
have->lastReceived = RR->node->now();
|
||||||
have->cap = cap;
|
have->credential = cap;
|
||||||
return ADD_ACCEPTED_NEW;
|
return ADD_ACCEPTED_NEW;
|
||||||
case 1:
|
case 1:
|
||||||
return ADD_DEFERRED_FOR_WHOIS;
|
return ADD_DEFERRED_FOR_WHOIS;
|
||||||
|
@ -209,13 +230,15 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
switch(rev.type()) {
|
switch(rev.type()) {
|
||||||
default:
|
default:
|
||||||
//case Revocation::CREDENTIAL_TYPE_ALL:
|
//case Revocation::CREDENTIAL_TYPE_ALL:
|
||||||
return ( (_revokeCom(rev)||_revokeCap(rev,now)||_revokeTag(rev,now)) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT );
|
return ( (_revokeCom(rev)||_revokeCap(rev,now)||_revokeTag(rev,now)||_revokeCoo(rev,now)) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT );
|
||||||
case Revocation::CREDENTIAL_TYPE_COM:
|
case Revocation::CREDENTIAL_TYPE_COM:
|
||||||
return (_revokeCom(rev) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
return (_revokeCom(rev) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
||||||
case Revocation::CREDENTIAL_TYPE_CAPABILITY:
|
case Revocation::CREDENTIAL_TYPE_CAPABILITY:
|
||||||
return (_revokeCap(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
return (_revokeCap(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
||||||
case Revocation::CREDENTIAL_TYPE_TAG:
|
case Revocation::CREDENTIAL_TYPE_TAG:
|
||||||
return (_revokeTag(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
return (_revokeTag(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
||||||
|
case Revocation::CREDENTIAL_TYPE_COO:
|
||||||
|
return (_revokeCoo(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -223,9 +246,40 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Membership::_RemoteTag *Membership::_newTag(const uint64_t id)
|
|
||||||
|
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo)
|
||||||
{
|
{
|
||||||
_RemoteTag *t = NULL;
|
_RemoteCredential<CertificateOfOwnership> *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)coo.id(),_RemoteCredentialComp<CertificateOfOwnership>());
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)coo.id())) ? *htmp : (_RemoteCredential<CertificateOfOwnership> *)0;
|
||||||
|
if (have) {
|
||||||
|
if ( (!_isCredentialTimestampValid(nconf,coo,*have)) || (have->credential.timestamp() > coo.timestamp()) ) {
|
||||||
|
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (revoked or too old)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
|
return ADD_REJECTED;
|
||||||
|
}
|
||||||
|
if (have->credential == coo) {
|
||||||
|
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx ACCEPTED (redundant)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
|
return ADD_ACCEPTED_REDUNDANT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(coo.verify(RR)) {
|
||||||
|
default:
|
||||||
|
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
|
return ADD_REJECTED;
|
||||||
|
case 0:
|
||||||
|
TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx ACCEPTED (new)",cap.issuedTo().toString().c_str(),cap.networkId());
|
||||||
|
if (!have) have = _newCoo(coo.id());
|
||||||
|
have->lastReceived = RR->node->now();
|
||||||
|
have->credential = coo;
|
||||||
|
return ADD_ACCEPTED_NEW;
|
||||||
|
case 1:
|
||||||
|
return ADD_DEFERRED_FOR_WHOIS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Membership::_RemoteCredential<Tag> *Membership::_newTag(const uint64_t id)
|
||||||
|
{
|
||||||
|
_RemoteCredential<Tag> *t = NULL;
|
||||||
uint64_t minlr = 0xffffffffffffffffULL;
|
uint64_t minlr = 0xffffffffffffffffULL;
|
||||||
for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) {
|
for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) {
|
||||||
if (_remoteTags[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) {
|
if (_remoteTags[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) {
|
||||||
|
@ -236,21 +290,21 @@ Membership::_RemoteTag *Membership::_newTag(const uint64_t id)
|
||||||
minlr = _remoteTags[i]->lastReceived;
|
minlr = _remoteTags[i]->lastReceived;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t) {
|
|
||||||
t->id = id;
|
|
||||||
t->lastReceived = 0;
|
|
||||||
t->revocationThreshold = 0;
|
|
||||||
t->tag = Tag();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),_RemoteCredentialSorter<_RemoteTag>());
|
if (t) {
|
||||||
|
t->id = id;
|
||||||
|
t->lastReceived = 0;
|
||||||
|
t->revocationThreshold = 0;
|
||||||
|
t->credential = Tag();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Membership::_RemoteCapability *Membership::_newCapability(const uint64_t id)
|
Membership::_RemoteCredential<Capability> *Membership::_newCapability(const uint64_t id)
|
||||||
{
|
{
|
||||||
_RemoteCapability *c = NULL;
|
_RemoteCredential<Capability> *c = NULL;
|
||||||
uint64_t minlr = 0xffffffffffffffffULL;
|
uint64_t minlr = 0xffffffffffffffffULL;
|
||||||
for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) {
|
for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) {
|
||||||
if (_remoteCaps[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) {
|
if (_remoteCaps[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) {
|
||||||
|
@ -266,10 +320,35 @@ Membership::_RemoteCapability *Membership::_newCapability(const uint64_t id)
|
||||||
c->id = id;
|
c->id = id;
|
||||||
c->lastReceived = 0;
|
c->lastReceived = 0;
|
||||||
c->revocationThreshold = 0;
|
c->revocationThreshold = 0;
|
||||||
c->cap = Capability();
|
c->credential = Capability();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),_RemoteCredentialSorter<_RemoteCapability>());
|
std::sort(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Membership::_RemoteCredential<CertificateOfOwnership> *Membership::_newCoo(const uint64_t id)
|
||||||
|
{
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *c = NULL;
|
||||||
|
uint64_t minlr = 0xffffffffffffffffULL;
|
||||||
|
for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) {
|
||||||
|
if (_remoteCoos[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) {
|
||||||
|
c = _remoteCoos[i];
|
||||||
|
break;
|
||||||
|
} else if (_remoteCoos[i]->lastReceived <= minlr) {
|
||||||
|
c = _remoteCoos[i];
|
||||||
|
minlr = _remoteCoos[i]->lastReceived;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
c->id = id;
|
||||||
|
c->lastReceived = 0;
|
||||||
|
c->revocationThreshold = 0;
|
||||||
|
c->credential = CertificateOfOwnership();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]));
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,8 +363,8 @@ bool Membership::_revokeCom(const Revocation &rev)
|
||||||
|
|
||||||
bool Membership::_revokeCap(const Revocation &rev,const uint64_t now)
|
bool Membership::_revokeCap(const Revocation &rev,const uint64_t now)
|
||||||
{
|
{
|
||||||
_RemoteCapability *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)rev.credentialId(),_RemoteCredentialSorter<_RemoteCapability>());
|
_RemoteCredential<Capability> *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<Capability>());
|
||||||
_RemoteCapability *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCapability *)0;
|
_RemoteCredential<Capability> *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<Capability> *)0;
|
||||||
if (!have) have = _newCapability(rev.credentialId());
|
if (!have) have = _newCapability(rev.credentialId());
|
||||||
if (rev.threshold() > have->revocationThreshold) {
|
if (rev.threshold() > have->revocationThreshold) {
|
||||||
have->lastReceived = now;
|
have->lastReceived = now;
|
||||||
|
@ -297,8 +376,8 @@ bool Membership::_revokeCap(const Revocation &rev,const uint64_t now)
|
||||||
|
|
||||||
bool Membership::_revokeTag(const Revocation &rev,const uint64_t now)
|
bool Membership::_revokeTag(const Revocation &rev,const uint64_t now)
|
||||||
{
|
{
|
||||||
_RemoteTag *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)rev.credentialId(),_RemoteCredentialSorter<_RemoteTag>());
|
_RemoteCredential<Tag> *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<Tag>());
|
||||||
_RemoteTag *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteTag *)0;
|
_RemoteCredential<Tag> *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<Tag> *)0;
|
||||||
if (!have) have = _newTag(rev.credentialId());
|
if (!have) have = _newTag(rev.credentialId());
|
||||||
if (rev.threshold() > have->revocationThreshold) {
|
if (rev.threshold() > have->revocationThreshold) {
|
||||||
have->lastReceived = now;
|
have->lastReceived = now;
|
||||||
|
@ -308,4 +387,17 @@ bool Membership::_revokeTag(const Revocation &rev,const uint64_t now)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Membership::_revokeCoo(const Revocation &rev,const uint64_t now)
|
||||||
|
{
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<CertificateOfOwnership>());
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<CertificateOfOwnership> *)0;
|
||||||
|
if (!have) have = _newCoo(rev.credentialId());
|
||||||
|
if (rev.threshold() > have->revocationThreshold) {
|
||||||
|
have->lastReceived = now;
|
||||||
|
have->revocationThreshold = rev.threshold();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -39,49 +39,30 @@ class Network;
|
||||||
/**
|
/**
|
||||||
* A container for certificates of membership and other network credentials
|
* A container for certificates of membership and other network credentials
|
||||||
*
|
*
|
||||||
* This is kind of analogous to a join table between Peer and Network. It is
|
* This is essentially a relational join between Peer and Network.
|
||||||
* held by the Network object for each participating Peer.
|
|
||||||
*
|
*
|
||||||
* This class is not thread safe. It must be locked externally.
|
* This class is not thread safe. It must be locked externally.
|
||||||
*/
|
*/
|
||||||
class Membership
|
class Membership
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Tags and related state
|
|
||||||
struct _RemoteTag
|
|
||||||
{
|
|
||||||
_RemoteTag() : id(ZT_MEMBERSHIP_CRED_ID_UNUSED),lastReceived(0),revocationThreshold(0) {}
|
|
||||||
// Tag ID (last 32 bits, first 32 bits are set in unused entries to sort them to end)
|
|
||||||
uint64_t id;
|
|
||||||
// Last time we received THEIR tag (with this ID)
|
|
||||||
uint64_t lastReceived;
|
|
||||||
// Revocation blacklist threshold or 0 if none
|
|
||||||
uint64_t revocationThreshold;
|
|
||||||
// THEIR tag
|
|
||||||
Tag tag;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Credentials and related state
|
|
||||||
struct _RemoteCapability
|
|
||||||
{
|
|
||||||
_RemoteCapability() : id(ZT_MEMBERSHIP_CRED_ID_UNUSED),lastReceived(0),revocationThreshold(0) {}
|
|
||||||
// Capability ID (last 32 bits, first 32 bits are set in unused entries to sort them to end)
|
|
||||||
uint64_t id;
|
|
||||||
// Last time we received THEIR capability (with this ID)
|
|
||||||
uint64_t lastReceived;
|
|
||||||
// Revocation blacklist threshold or 0 if none
|
|
||||||
uint64_t revocationThreshold;
|
|
||||||
// THEIR capability
|
|
||||||
Capability cap;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Comparison operator for remote credential entries
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct _RemoteCredentialSorter
|
struct _RemoteCredential
|
||||||
{
|
{
|
||||||
inline bool operator()(const T *a,const T *b) const { return (a->id < b->id); }
|
_RemoteCredential() : id(ZT_MEMBERSHIP_CRED_ID_UNUSED),lastReceived(0),revocationThreshold(0) {}
|
||||||
inline bool operator()(const uint64_t a,const T *b) const { return (a < b->id); }
|
uint64_t id;
|
||||||
inline bool operator()(const T *a,const uint64_t b) const { return (a->id < b); }
|
uint64_t lastReceived; // last time we got this credential
|
||||||
|
uint64_t revocationThreshold; // credentials before this time are invalid
|
||||||
|
T credential;
|
||||||
|
inline bool operator<(const _RemoteCredential &c) const { return (id < c.id); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct _RemoteCredentialComp
|
||||||
|
{
|
||||||
|
inline bool operator()(const _RemoteCredential<T> *a,const _RemoteCredential<T> *b) const { return (a->id < b->id); }
|
||||||
|
inline bool operator()(const uint64_t a,const _RemoteCredential<T> *b) const { return (a < b->id); }
|
||||||
|
inline bool operator()(const _RemoteCredential<T> *a,const uint64_t b) const { return (a->id < b); }
|
||||||
inline bool operator()(const uint64_t a,const uint64_t b) const { return (a < b); }
|
inline bool operator()(const uint64_t a,const uint64_t b) const { return (a < b); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,8 +70,8 @@ private:
|
||||||
struct _LocalCredentialPushState
|
struct _LocalCredentialPushState
|
||||||
{
|
{
|
||||||
_LocalCredentialPushState() : lastPushed(0),id(0) {}
|
_LocalCredentialPushState() : lastPushed(0),id(0) {}
|
||||||
uint64_t lastPushed;
|
uint64_t lastPushed; // last time we sent our own copy of this credential
|
||||||
uint32_t id;
|
uint64_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -117,7 +98,7 @@ public:
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if ((_i != &(_m->_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*_i)->id != ZT_MEMBERSHIP_CRED_ID_UNUSED)) {
|
if ((_i != &(_m->_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*_i)->id != ZT_MEMBERSHIP_CRED_ID_UNUSED)) {
|
||||||
const Capability *tmp = &((*_i)->cap);
|
const Capability *tmp = &((*_i)->credential);
|
||||||
if (_m->_isCredentialTimestampValid(*_c,*tmp,**_i)) {
|
if (_m->_isCredentialTimestampValid(*_c,*tmp,**_i)) {
|
||||||
++_i;
|
++_i;
|
||||||
return tmp;
|
return tmp;
|
||||||
|
@ -131,7 +112,7 @@ public:
|
||||||
private:
|
private:
|
||||||
const Membership *_m;
|
const Membership *_m;
|
||||||
const NetworkConfig *_c;
|
const NetworkConfig *_c;
|
||||||
const _RemoteCapability *const *_i;
|
const _RemoteCredential<Capability> *const *_i;
|
||||||
};
|
};
|
||||||
friend class CapabilityIterator;
|
friend class CapabilityIterator;
|
||||||
|
|
||||||
|
@ -150,7 +131,7 @@ public:
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if ((_i != &(_m->_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*_i)->id != ZT_MEMBERSHIP_CRED_ID_UNUSED)) {
|
if ((_i != &(_m->_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*_i)->id != ZT_MEMBERSHIP_CRED_ID_UNUSED)) {
|
||||||
const Tag *tmp = &((*_i)->tag);
|
const Tag *tmp = &((*_i)->credential);
|
||||||
if (_m->_isCredentialTimestampValid(*_c,*tmp,**_i)) {
|
if (_m->_isCredentialTimestampValid(*_c,*tmp,**_i)) {
|
||||||
++_i;
|
++_i;
|
||||||
return tmp;
|
return tmp;
|
||||||
|
@ -164,7 +145,7 @@ public:
|
||||||
private:
|
private:
|
||||||
const Membership *_m;
|
const Membership *_m;
|
||||||
const NetworkConfig *_c;
|
const NetworkConfig *_c;
|
||||||
const _RemoteTag *const *_i;
|
const _RemoteCredential<Tag> *const *_i;
|
||||||
};
|
};
|
||||||
friend class TagIterator;
|
friend class TagIterator;
|
||||||
|
|
||||||
|
@ -249,12 +230,19 @@ public:
|
||||||
*/
|
*/
|
||||||
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev);
|
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and add a credential if signature is okay and it's otherwise good
|
||||||
|
*/
|
||||||
|
AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_RemoteTag *_newTag(const uint64_t id);
|
_RemoteCredential<Tag> *_newTag(const uint64_t id);
|
||||||
_RemoteCapability *_newCapability(const uint64_t id);
|
_RemoteCredential<Capability> *_newCapability(const uint64_t id);
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *_newCoo(const uint64_t id);
|
||||||
bool _revokeCom(const Revocation &rev);
|
bool _revokeCom(const Revocation &rev);
|
||||||
bool _revokeCap(const Revocation &rev,const uint64_t now);
|
bool _revokeCap(const Revocation &rev,const uint64_t now);
|
||||||
bool _revokeTag(const Revocation &rev,const uint64_t now);
|
bool _revokeTag(const Revocation &rev,const uint64_t now);
|
||||||
|
bool _revokeCoo(const Revocation &rev,const uint64_t now);
|
||||||
|
|
||||||
template<typename C,typename CS>
|
template<typename C,typename CS>
|
||||||
inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &cred,const CS &state) const
|
inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &cred,const CS &state) const
|
||||||
|
@ -275,17 +263,20 @@ private:
|
||||||
// Remote member's latest network COM
|
// Remote member's latest network COM
|
||||||
CertificateOfMembership _com;
|
CertificateOfMembership _com;
|
||||||
|
|
||||||
// Sorted (in ascending order of ID) arrays of pointers to remote tags and capabilities
|
// Sorted (in ascending order of ID) arrays of pointers to remote credentials
|
||||||
_RemoteTag *_remoteTags[ZT_MAX_NETWORK_TAGS];
|
_RemoteCredential<Tag> *_remoteTags[ZT_MAX_NETWORK_TAGS];
|
||||||
_RemoteCapability *_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES];
|
_RemoteCredential<Capability> *_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES];
|
||||||
|
_RemoteCredential<CertificateOfOwnership> *_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
|
||||||
|
|
||||||
// This is the RAM allocated for remote tags and capabilities from which the sorted arrays are populated
|
// This is the RAM allocated for remote credential cache objects
|
||||||
_RemoteTag _tagMem[ZT_MAX_NETWORK_TAGS];
|
_RemoteCredential<Tag> _tagMem[ZT_MAX_NETWORK_TAGS];
|
||||||
_RemoteCapability _capMem[ZT_MAX_NETWORK_CAPABILITIES];
|
_RemoteCredential<Capability> _capMem[ZT_MAX_NETWORK_CAPABILITIES];
|
||||||
|
_RemoteCredential<CertificateOfOwnership> _cooMem[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
|
||||||
|
|
||||||
// Local credential push state tracking
|
// Local credential push state tracking
|
||||||
_LocalCredentialPushState _localTags[ZT_MAX_NETWORK_TAGS];
|
_LocalCredentialPushState _localTags[ZT_MAX_NETWORK_TAGS];
|
||||||
_LocalCredentialPushState _localCaps[ZT_MAX_NETWORK_CAPABILITIES];
|
_LocalCredentialPushState _localCaps[ZT_MAX_NETWORK_CAPABILITIES];
|
||||||
|
_LocalCredentialPushState _localCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -301,6 +301,17 @@ public:
|
||||||
*/
|
*/
|
||||||
Membership::AddCredentialResult addCredential(const Address &sentFrom,const Revocation &rev);
|
Membership::AddCredentialResult addCredential(const Address &sentFrom,const Revocation &rev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a credential and learn it if it passes certificate and other checks
|
||||||
|
*/
|
||||||
|
inline Membership::AddCredentialResult addCredential(const CertificateOfOwnership &coo)
|
||||||
|
{
|
||||||
|
if (coo.networkId() != _id)
|
||||||
|
return Membership::ADD_REJECTED;
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
return _membership(coo.issuedTo()).addCredential(RR,_config,coo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force push credentials (COM, etc.) to a peer now
|
* Force push credentials (COM, etc.) to a peer now
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "NetworkConfig.hpp"
|
#include "NetworkConfig.hpp"
|
||||||
#include "Utils.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -137,6 +136,13 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmp->clear();
|
||||||
|
for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i)
|
||||||
|
this->certificatesOfOwnership[i].serialize(*tmp);
|
||||||
|
if (tmp->size()) {
|
||||||
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
tmp->clear();
|
tmp->clear();
|
||||||
for(unsigned int i=0;i<this->specialistCount;++i)
|
for(unsigned int i=0;i<this->specialistCount;++i)
|
||||||
tmp->append((uint64_t)this->specialists[i]);
|
tmp->append((uint64_t)this->specialists[i]);
|
||||||
|
@ -297,10 +303,23 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
|
||||||
std::sort(&(this->tags[0]),&(this->tags[this->tagCount]));
|
std::sort(&(this->tags[0]),&(this->tags[this->tagCount]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) {
|
||||||
|
unsigned int p = 0;
|
||||||
|
while (p < tmp->size()) {
|
||||||
|
if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP)
|
||||||
|
p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp,p);
|
||||||
|
else {
|
||||||
|
CertificateOfOwnership foo;
|
||||||
|
p += foo.deserialize(*tmp,p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
|
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
|
||||||
unsigned int p = 0;
|
unsigned int p = 0;
|
||||||
while (((p + 8) <= tmp->size())&&(specialistCount < ZT_MAX_NETWORK_SPECIALISTS)) {
|
while ((p + 8) <= tmp->size()) {
|
||||||
this->specialists[this->specialistCount++] = tmp->at<uint64_t>(p);
|
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS)
|
||||||
|
this->specialists[this->specialistCount++] = tmp->at<uint64_t>(p);
|
||||||
p += 8;
|
p += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,12 @@
|
||||||
#include "MulticastGroup.hpp"
|
#include "MulticastGroup.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
#include "CertificateOfMembership.hpp"
|
||||||
|
#include "CertificateOfOwnership.hpp"
|
||||||
#include "Capability.hpp"
|
#include "Capability.hpp"
|
||||||
#include "Tag.hpp"
|
#include "Tag.hpp"
|
||||||
#include "Dictionary.hpp"
|
#include "Dictionary.hpp"
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
|
#include "Utils.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default maximum time delta for COMs, tags, and capabilities
|
* Default maximum time delta for COMs, tags, and capabilities
|
||||||
|
@ -99,7 +101,7 @@
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
// Dictionary capacity needed for max size network config
|
// Dictionary capacity needed for max size network config
|
||||||
#define ZT_NETWORKCONFIG_DICT_CAPACITY (4096 + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS))
|
#define ZT_NETWORKCONFIG_DICT_CAPACITY (1024 + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
|
||||||
|
|
||||||
// Dictionary capacity needed for max size network meta-data
|
// Dictionary capacity needed for max size network meta-data
|
||||||
#define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024
|
#define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024
|
||||||
|
@ -173,6 +175,8 @@ namespace ZeroTier {
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES "CAP"
|
#define ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES "CAP"
|
||||||
// tags (binary blobs)
|
// tags (binary blobs)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_TAGS "TAG"
|
#define ZT_NETWORKCONFIG_DICT_KEY_TAGS "TAG"
|
||||||
|
// tags (binary blobs)
|
||||||
|
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP "COO"
|
||||||
// curve25519 signature
|
// curve25519 signature
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_SIGNATURE "C25519"
|
#define ZT_NETWORKCONFIG_DICT_KEY_SIGNATURE "C25519"
|
||||||
|
|
||||||
|
@ -473,11 +477,6 @@ public:
|
||||||
*/
|
*/
|
||||||
unsigned int staticIpCount;
|
unsigned int staticIpCount;
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of pinned devices (devices with physical address hints)
|
|
||||||
*/
|
|
||||||
unsigned int pinnedCount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of rule table entries
|
* Number of rule table entries
|
||||||
*/
|
*/
|
||||||
|
@ -493,6 +492,11 @@ public:
|
||||||
*/
|
*/
|
||||||
unsigned int tagCount;
|
unsigned int tagCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of certificates of ownership
|
||||||
|
*/
|
||||||
|
unsigned int certificateOfOwnershipCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialist devices
|
* Specialist devices
|
||||||
*
|
*
|
||||||
|
@ -526,6 +530,11 @@ public:
|
||||||
*/
|
*/
|
||||||
Tag tags[ZT_MAX_NETWORK_TAGS];
|
Tag tags[ZT_MAX_NETWORK_TAGS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certificates of ownership for this network member
|
||||||
|
*/
|
||||||
|
CertificateOfOwnership certificatesOfOwnership[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network type (currently just public or private)
|
* Network type (currently just public or private)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -730,6 +730,8 @@ public:
|
||||||
* <[...] one or more serialized Tags>
|
* <[...] one or more serialized Tags>
|
||||||
* <[2] 16-bit number of revocations>
|
* <[2] 16-bit number of revocations>
|
||||||
* <[...] one or more serialized Revocations>
|
* <[...] one or more serialized Revocations>
|
||||||
|
* <[2] 16-bit number of certificates of ownership>
|
||||||
|
* <[...] one or more serialized CertificateOfOwnership>
|
||||||
*
|
*
|
||||||
* This can be sent by anyone at any time to push network credentials.
|
* This can be sent by anyone at any time to push network credentials.
|
||||||
* These will of course only be accepted if they are properly signed.
|
* These will of course only be accepted if they are properly signed.
|
||||||
|
|
|
@ -50,9 +50,10 @@ public:
|
||||||
enum CredentialType
|
enum CredentialType
|
||||||
{
|
{
|
||||||
CREDENTIAL_TYPE_ALL = 0,
|
CREDENTIAL_TYPE_ALL = 0,
|
||||||
CREDENTIAL_TYPE_COM = 1,
|
CREDENTIAL_TYPE_COM = 1, // CertificateOfMembership
|
||||||
CREDENTIAL_TYPE_CAPABILITY = 2,
|
CREDENTIAL_TYPE_CAPABILITY = 2,
|
||||||
CREDENTIAL_TYPE_TAG = 3
|
CREDENTIAL_TYPE_TAG = 3,
|
||||||
|
CREDENTIAL_TYPE_COO = 4 // CertificateOfOwnership
|
||||||
};
|
};
|
||||||
|
|
||||||
Revocation()
|
Revocation()
|
||||||
|
|
|
@ -139,7 +139,8 @@ public:
|
||||||
{
|
{
|
||||||
unsigned int p = startAt;
|
unsigned int p = startAt;
|
||||||
|
|
||||||
// These are the same between Tag and Capability
|
memset(this,0,sizeof(Tag));
|
||||||
|
|
||||||
_networkId = b.template at<uint64_t>(p); p += 8;
|
_networkId = b.template at<uint64_t>(p); p += 8;
|
||||||
_ts = b.template at<uint64_t>(p); p += 8;
|
_ts = b.template at<uint64_t>(p); p += 8;
|
||||||
_id = b.template at<uint32_t>(p); p += 4;
|
_id = b.template at<uint32_t>(p); p += 4;
|
||||||
|
|
|
@ -4,6 +4,7 @@ OBJS=\
|
||||||
node/C25519.o \
|
node/C25519.o \
|
||||||
node/Capability.o \
|
node/Capability.o \
|
||||||
node/CertificateOfMembership.o \
|
node/CertificateOfMembership.o \
|
||||||
|
node/CertificateOfOwnership.o \
|
||||||
node/Cluster.o \
|
node/Cluster.o \
|
||||||
node/Identity.o \
|
node/Identity.o \
|
||||||
node/IncomingPacket.o \
|
node/IncomingPacket.o \
|
||||||
|
|
Loading…
Add table
Reference in a new issue