Safety upgrades to code

This commit is contained in:
Adam Ierymenko 2019-08-28 10:34:32 -07:00
parent 1977b9b764
commit 59ee0cfe88
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
9 changed files with 196 additions and 191 deletions

View File

@ -38,6 +38,7 @@ set(core_headers
RingBuffer.hpp RingBuffer.hpp
RuntimeEnvironment.hpp RuntimeEnvironment.hpp
Salsa20.hpp Salsa20.hpp
ScopedPtr.hpp
SelfAwareness.hpp SelfAwareness.hpp
SHA512.hpp SHA512.hpp
SharedPtr.hpp SharedPtr.hpp

View File

@ -21,6 +21,7 @@
#include "Revocation.hpp" #include "Revocation.hpp"
#include "Switch.hpp" #include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "ScopedPtr.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -37,10 +38,9 @@ static inline Credential::VerifyResult _credVerify(const RuntimeEnvironment *con
return Credential::VERIFY_NEED_IDENTITY; return Credential::VERIFY_NEED_IDENTITY;
} }
try { try {
Buffer<(sizeof(CRED) + 64)> *const tmp = new Buffer<(sizeof(CRED) + 64)>(); ScopedPtr< Buffer<(sizeof(CRED) + 64)> > tmp(new Buffer<(sizeof(CRED) + 64)>());
credential.serialize(*tmp,true); credential.serialize(*tmp,true);
const Credential::VerifyResult result = (id.verify(tmp->data(),tmp->size(),credential.signature(),credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE); const Credential::VerifyResult result = (id.verify(tmp->data(),tmp->size(),credential.signature(),credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE);
delete tmp;
return result; return result;
} catch ( ... ) {} } catch ( ... ) {}
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;

View File

@ -21,6 +21,7 @@
#include "Buffer.hpp" #include "Buffer.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Str.hpp" #include "Str.hpp"
#include "ScopedPtr.hpp"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
@ -101,14 +102,12 @@ public:
} else { } else {
_signedBy = signingId; _signedBy = signingId;
} }
Buffer<65536> *tmp = new Buffer<65536>();
try { try {
ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
serialize(*tmp,true); serialize(*tmp,true);
_signatureLength = signingId.sign(tmp->data(),tmp->size(),_signature,ZT_SIGNATURE_BUFFER_SIZE); _signatureLength = signingId.sign(tmp->data(),tmp->size(),_signature,ZT_SIGNATURE_BUFFER_SIZE);
delete tmp;
return (_signatureLength > 0); return (_signatureLength > 0);
} catch ( ... ) { } catch ( ... ) {
delete tmp;
return false; return false;
} }
} }
@ -120,15 +119,12 @@ public:
{ {
if ((_signatureLength == 0)||(_signatureLength > sizeof(_signature))) if ((_signatureLength == 0)||(_signatureLength > sizeof(_signature)))
return false; return false;
Buffer<65536> *tmp = nullptr;
try { try {
tmp = new Buffer<65536>(); ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
serialize(*tmp,true); serialize(*tmp,true);
const bool ok = (_signedBy) ? _signedBy.verify(tmp->data(),tmp->size(),_signature,_signatureLength) : _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength); const bool ok = (_signedBy) ? _signedBy.verify(tmp->data(),tmp->size(),_signature,_signatureLength) : _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength);
delete tmp;
return ok; return ok;
} catch ( ... ) { } catch ( ... ) {
if (tmp) delete tmp;
return false; return false;
} }
} }
@ -150,7 +146,7 @@ public:
uint8_t s384[48]; uint8_t s384[48];
char enc[256]; char enc[256];
Buffer<65536> *const tmp = new Buffer<65536>(); ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
serialize(*tmp,false); serialize(*tmp,false);
SHA384(s384,tmp->data(),tmp->size()); SHA384(s384,tmp->data(),tmp->size());
ECC384ECDSASign(p384SigningKeyPrivate,s384,((uint8_t *)tmp->unsafeData()) + tmp->size()); ECC384ECDSASign(p384SigningKeyPrivate,s384,((uint8_t *)tmp->unsafeData()) + tmp->size());
@ -172,7 +168,6 @@ public:
++txtRecNo; ++txtRecNo;
} }
delete tmp;
return txtRecords; return txtRecords;
} }
@ -192,7 +187,6 @@ public:
inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
{ {
uint8_t dec[256],s384[48]; uint8_t dec[256],s384[48];
Buffer<65536> *tmp = nullptr;
try { try {
std::vector<Str> txtRecords; std::vector<Str> txtRecords;
while (start != end) { while (start != end) {
@ -206,26 +200,22 @@ public:
return false; return false;
std::sort(txtRecords.begin(),txtRecords.end()); std::sort(txtRecords.begin(),txtRecords.end());
tmp = new Buffer<65536>(); ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i) for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i)
tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec))); tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec)));
if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) { if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) {
delete tmp;
return false; return false;
} }
SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE); SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE);
if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) { if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) {
delete tmp;
return false; return false;
} }
deserialize(*tmp,0); deserialize(*tmp,0);
delete tmp;
return verify(); return verify();
} catch ( ... ) { } catch ( ... ) {
if (tmp) delete tmp;
return false; return false;
} }
} }

View File

@ -31,6 +31,7 @@
#include "Node.hpp" #include "Node.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include "ScopedPtr.hpp"
#include <set> #include <set>
@ -561,22 +562,20 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
tmp[0] = nwid; tmp[1] = 0; tmp[0] = nwid; tmp[1] = 0;
bool got = false; bool got = false;
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dict = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>(); ScopedPtr< Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> > dict(new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>());
try { try {
int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1); int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1);
if (n > 1) { if (n > 1) {
NetworkConfig *nconf = new NetworkConfig();
try { try {
ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
if (nconf->fromDictionary(*dict)) { if (nconf->fromDictionary(*dict)) {
this->setConfiguration(tPtr,*nconf,false); this->setConfiguration(tPtr,*nconf,false);
_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated _lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated
got = true; got = true;
} }
} catch ( ... ) {} } catch ( ... ) {}
delete nconf;
} }
} catch ( ... ) {} } catch ( ... ) {}
delete dict;
if (!got) if (!got)
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1); RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1);
@ -856,7 +855,6 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
const unsigned int chunkLen = chunk.at<uint16_t>(ptr); ptr += 2; const unsigned int chunkLen = chunk.at<uint16_t>(ptr); ptr += 2;
const void *chunkData = chunk.field(ptr,chunkLen); ptr += chunkLen; const void *chunkData = chunk.field(ptr,chunkLen); ptr += chunkLen;
NetworkConfig *nc = (NetworkConfig *)0;
uint64_t configUpdateId; uint64_t configUpdateId;
{ {
Mutex::Lock l1(_config_l); Mutex::Lock l1(_config_l);
@ -953,27 +951,16 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
if (c->haveBytes == totalLength) { if (c->haveBytes == totalLength) {
c->data.unsafeData()[c->haveBytes] = (char)0; // ensure null terminated c->data.unsafeData()[c->haveBytes] = (char)0; // ensure null terminated
nc = new NetworkConfig(); ScopedPtr<NetworkConfig> nc(new NetworkConfig());
try { try {
if (!nc->fromDictionary(c->data)) { if (nc->fromDictionary(c->data)) {
delete nc; this->setConfiguration(tPtr,*nc,true);
nc = (NetworkConfig *)0; return configUpdateId;
} }
} catch ( ... ) { } catch ( ... ) {}
delete nc;
nc = (NetworkConfig *)0;
}
} }
} }
if (nc) {
this->setConfiguration(tPtr,*nc,true);
delete nc;
return configUpdateId;
} else {
return 0;
}
return 0; return 0;
} }
@ -1007,15 +994,14 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
_portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); _portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
if (saveToDisk) { if (saveToDisk) {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *const d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try { try {
ScopedPtr< Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> > d(new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>());
if (nconf.toDictionary(*d,false)) { if (nconf.toDictionary(*d,false)) {
uint64_t tmp[2]; uint64_t tmp[2];
tmp[0] = _id; tmp[1] = 0; tmp[0] = _id; tmp[1] = 0;
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d->data(),d->sizeBytes()); RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d->data(),d->sizeBytes());
} }
} catch ( ... ) {} } catch ( ... ) {}
delete d;
} }
return 2; // OK and configuration has changed return 2; // OK and configuration has changed
@ -1120,7 +1106,7 @@ void Network::_requestConfiguration(void *tPtr)
const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff); const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff);
const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff); const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff);
if (endPortRange >= startPortRange) { if (endPortRange >= startPortRange) {
NetworkConfig *const nconf = new NetworkConfig(); ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
nconf->networkId = _id; nconf->networkId = _id;
nconf->timestamp = RR->node->now(); nconf->timestamp = RR->node->now();
@ -1182,7 +1168,6 @@ void Network::_requestConfiguration(void *tPtr)
nconf->name[15] = (char)0; nconf->name[15] = (char)0;
this->setConfiguration(tPtr,*nconf,false); this->setConfiguration(tPtr,*nconf,false);
delete nconf;
} else { } else {
this->setNotFound(); this->setNotFound();
} }
@ -1200,7 +1185,7 @@ void Network::_requestConfiguration(void *tPtr)
char v4ascii[24]; char v4ascii[24];
Utils::decimal(ipv4[0],v4ascii); Utils::decimal(ipv4[0],v4ascii);
NetworkConfig *const nconf = new NetworkConfig(); ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
nconf->networkId = _id; nconf->networkId = _id;
nconf->timestamp = RR->node->now(); nconf->timestamp = RR->node->now();
@ -1241,32 +1226,31 @@ void Network::_requestConfiguration(void *tPtr)
nconf->name[nn++] = (char)0; nconf->name[nn++] = (char)0;
this->setConfiguration(tPtr,*nconf,false); this->setConfiguration(tPtr,*nconf,false);
delete nconf;
} }
return; return;
} }
const Address ctrl(controller()); const Address ctrl(controller());
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd; ScopedPtr< Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> > rmd(new Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY>());
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR,(uint64_t)ZT_VENDOR_ZEROTIER); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR,(uint64_t)ZT_VENDOR_ZEROTIER);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MAJOR); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MAJOR);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MINOR); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MINOR);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,(uint64_t)ZEROTIER_ONE_VERSION_REVISION); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,(uint64_t)ZEROTIER_ONE_VERSION_REVISION);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES,(uint64_t)ZT_MAX_NETWORK_RULES); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES,(uint64_t)ZT_MAX_NETWORK_RULES);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_CAPABILITIES,(uint64_t)ZT_MAX_NETWORK_CAPABILITIES); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_CAPABILITIES,(uint64_t)ZT_MAX_NETWORK_CAPABILITIES);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES,(uint64_t)ZT_MAX_CAPABILITY_RULES); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES,(uint64_t)ZT_MAX_CAPABILITY_RULES);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION); rmd->add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION);
RR->t->networkConfigRequestSent(tPtr,*this,ctrl); RR->t->networkConfigRequestSent(tPtr,*this,ctrl);
if (ctrl == RR->identity.address()) { if (ctrl == RR->identity.address()) {
if (RR->localNetworkController) { if (RR->localNetworkController) {
RR->localNetworkController->request(_id,InetAddress(),0xffffffffffffffffULL,RR->identity,rmd); RR->localNetworkController->request(_id,InetAddress(),0xffffffffffffffffULL,RR->identity,*rmd);
} else { } else {
this->setNotFound(); this->setNotFound();
} }
@ -1275,9 +1259,9 @@ void Network::_requestConfiguration(void *tPtr)
Packet outp(ctrl,RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); Packet outp(ctrl,RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)_id); outp.append((uint64_t)_id);
const unsigned int rmdSize = rmd.sizeBytes(); const unsigned int rmdSize = rmd->sizeBytes();
outp.append((uint16_t)rmdSize); outp.append((uint16_t)rmdSize);
outp.append((const void *)rmd.data(),rmdSize); outp.append((const void *)rmd->data(),rmdSize);
if (_config) { if (_config) {
outp.append((uint64_t)_config.revision); outp.append((uint64_t)_config.revision);
outp.append((uint64_t)_config.timestamp); outp.append((uint64_t)_config.timestamp);
@ -1373,7 +1357,7 @@ void Network::_announceMulticastGroups(void *tPtr,bool force)
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups) void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
{ {
// Assumes _myMulticastGroups_l and _memberships_l are locked // Assumes _myMulticastGroups_l and _memberships_l are locked
Packet *const outp = new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); ScopedPtr<Packet> outp(new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE));
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
@ -1392,8 +1376,6 @@ void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const st
outp->compress(); outp->compress();
RR->sw->send(tPtr,*outp,true); RR->sw->send(tPtr,*outp,true);
} }
delete outp;
} }
std::vector<MulticastGroup> Network::_allMulticastGroups() const std::vector<MulticastGroup> Network::_allMulticastGroups() const

View File

@ -16,99 +16,93 @@
#include <algorithm> #include <algorithm>
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "ScopedPtr.hpp"
namespace ZeroTier { namespace ZeroTier {
bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const
{ {
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];
try { d.clear();
d.clear();
// Try to put the more human-readable fields first // Try to put the more human-readable fields first
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) return false;
// Then add binary blobs // Then add binary blobs
if (this->com) {
tmp->clear();
this->com.serialize(*tmp);
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) return false;
}
if (this->com) {
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->capabilityCount;++i) this->com.serialize(*tmp);
this->capabilities[i].serialize(*tmp); if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) return false;
if (tmp->size()) { }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->capabilityCount;++i)
this->capabilities[i].serialize(*tmp);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->tagCount;++i)
this->tags[i].serialize(*tmp);
if (tmp->size()) {
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();
for(unsigned int i=0;i<this->specialistCount;++i)
tmp->append((uint64_t)this->specialists[i]);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->routeCount;++i) {
reinterpret_cast<const InetAddress *>(&(this->routes[i].target))->serialize(*tmp);
reinterpret_cast<const InetAddress *>(&(this->routes[i].via))->serialize(*tmp);
tmp->append((uint16_t)this->routes[i].flags);
tmp->append((uint16_t)this->routes[i].metric);
}
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->staticIpCount;++i)
this->staticIps[i].serialize(*tmp);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) return false;
}
if (this->ruleCount) {
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->tagCount;++i) Capability::serializeRules(*tmp,rules,ruleCount);
this->tags[i].serialize(*tmp);
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*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();
for(unsigned int i=0;i<this->specialistCount;++i)
tmp->append((uint64_t)this->specialists[i]);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->routeCount;++i) {
reinterpret_cast<const InetAddress *>(&(this->routes[i].target))->serialize(*tmp);
reinterpret_cast<const InetAddress *>(&(this->routes[i].via))->serialize(*tmp);
tmp->append((uint16_t)this->routes[i].flags);
tmp->append((uint16_t)this->routes[i].metric);
}
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) return false;
}
tmp->clear();
for(unsigned int i=0;i<this->staticIpCount;++i)
this->staticIps[i].serialize(*tmp);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) return false;
}
if (this->ruleCount) {
tmp->clear();
Capability::serializeRules(*tmp,rules,ruleCount);
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) return false;
}
}
delete tmp;
} catch ( ... ) {
delete tmp;
throw;
} }
return true; return true;
@ -117,25 +111,21 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d) bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d)
{ {
static const NetworkConfig NIL_NC; static const NetworkConfig NIL_NC;
Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> *const tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>(); ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
try { try {
*this = NIL_NC; *this = NIL_NC;
// Fields that are always present, new or old // Fields that are always present, new or old
this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,0); this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,0);
if (!this->networkId) { if (!this->networkId)
delete tmp;
return false; return false;
}
this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,0); this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,0);
this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,0); this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,0);
this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0); this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0);
this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0); this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
if (!this->issuedTo) { if (!this->issuedTo)
delete tmp;
return false; return false;
}
this->remoteTraceTarget = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET); this->remoteTraceTarget = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET);
this->remoteTraceLevel = (Trace::Level)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL); this->remoteTraceLevel = (Trace::Level)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL);
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0); this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
@ -148,7 +138,6 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
this->mtu = ZT_MAX_MTU; this->mtu = ZT_MAX_MTU;
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) { if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) {
delete tmp;
return false; return false;
} else { } else {
// Otherwise we can use the new fields // Otherwise we can use the new fields
@ -228,10 +217,8 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
} }
} }
delete tmp;
return true; return true;
} catch ( ... ) { } catch ( ... ) {
delete tmp;
return false; return false;
} }
} }

View File

@ -86,7 +86,7 @@ namespace ZeroTier {
#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)) #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 2048 #define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 8192
// Network config version // Network config version
#define ZT_NETWORKCONFIG_VERSION 7 #define ZT_NETWORKCONFIG_VERSION 7

View File

@ -32,6 +32,7 @@
#include "SelfAwareness.hpp" #include "SelfAwareness.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include "ScopedPtr.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -558,47 +559,41 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
if (!n) return; if (!n) return;
n->setConfiguration((void *)0,nc,true); n->setConfiguration((void *)0,nc,true);
} else { } else {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>(); ScopedPtr< Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> > dconf(new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>());
try { if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) { uint64_t configUpdateId = Utils::random();
uint64_t configUpdateId = Utils::random(); if (!configUpdateId) ++configUpdateId;
if (!configUpdateId) ++configUpdateId;
const unsigned int totalSize = dconf->sizeBytes(); const unsigned int totalSize = dconf->sizeBytes();
unsigned int chunkIndex = 0; unsigned int chunkIndex = 0;
while (chunkIndex < totalSize) { while (chunkIndex < totalSize) {
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256))); const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG); Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
if (requestPacketId) { if (requestPacketId) {
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append(requestPacketId); outp.append(requestPacketId);
}
const unsigned int sigStart = outp.size();
outp.append(nwid);
outp.append((uint16_t)chunkLen);
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
outp.append((uint8_t)0); // no flags
outp.append((uint64_t)configUpdateId);
outp.append((uint32_t)totalSize);
outp.append((uint32_t)chunkIndex);
uint8_t sig[256];
const unsigned int siglen = RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart,sig,sizeof(sig));
outp.append((uint8_t)1);
outp.append((uint16_t)siglen);
outp.append(sig,siglen);
outp.compress();
RR->sw->send((void *)0,outp,true);
chunkIndex += chunkLen;
} }
const unsigned int sigStart = outp.size();
outp.append(nwid);
outp.append((uint16_t)chunkLen);
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
outp.append((uint8_t)0); // no flags
outp.append((uint64_t)configUpdateId);
outp.append((uint32_t)totalSize);
outp.append((uint32_t)chunkIndex);
uint8_t sig[256];
const unsigned int siglen = RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart,sig,sizeof(sig));
outp.append((uint8_t)1);
outp.append((uint16_t)siglen);
outp.append(sig,siglen);
outp.compress();
RR->sw->send((void *)0,outp,true);
chunkIndex += chunkLen;
} }
delete dconf;
} catch ( ... ) {
delete dconf;
throw;
} }
} }
} }

View File

@ -22,6 +22,7 @@
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "RingBuffer.hpp" #include "RingBuffer.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "ScopedPtr.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -173,7 +174,7 @@ void Peer::received(
if (pathsToPush.size() > 0) { if (pathsToPush.size() > 0) {
std::vector<InetAddress>::const_iterator p(pathsToPush.begin()); std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
while (p != pathsToPush.end()) { while (p != pathsToPush.end()) {
Packet *const outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); ScopedPtr<Packet> outp(new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS));
outp->addSize(2); // leave room for count outp->addSize(2); // leave room for count
unsigned int count = 0; unsigned int count = 0;
while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) { while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) {
@ -205,7 +206,6 @@ void Peer::received(
outp->armor(_key,true); outp->armor(_key,true);
path->send(RR,tPtr,outp->data(),outp->size(),now); path->send(RR,tPtr,outp->data(),outp->size(),now);
} }
delete outp;
} }
} }
} }

50
node/ScopedPtr.hpp Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c)2019 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: 2023-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.
*/
/****/
#ifndef ZT_SCOPEDPTR_HPP
#define ZT_SCOPEDPTR_HPP
#include "Constants.hpp"
namespace ZeroTier {
/**
* Simple scoped pointer
*
* This is used in the core to avoid requiring C++11 and because auto_ptr is weird.
*/
template<typename T>
class ScopedPtr
{
public:
ZT_ALWAYS_INLINE ScopedPtr(T *const p) : _p(p) {}
ZT_ALWAYS_INLINE ~ScopedPtr() { delete _p; }
ZT_ALWAYS_INLINE T *operator->() const { return _p; }
ZT_ALWAYS_INLINE T &operator*() const { return *_p; }
ZT_ALWAYS_INLINE operator bool() const { return (_p != (T *)0); }
ZT_ALWAYS_INLINE T *ptr() const { return _p; }
ZT_ALWAYS_INLINE bool operator==(const ScopedPtr &p) const { return (_p == p._p); }
ZT_ALWAYS_INLINE bool operator!=(const ScopedPtr &p) const { return (_p != p._p); }
ZT_ALWAYS_INLINE bool operator==(T *const p) const { return (_p == p); }
ZT_ALWAYS_INLINE bool operator!=(T *const p) const { return (_p != p); }
private:
ZT_ALWAYS_INLINE ScopedPtr() {}
T *const _p;
};
} // namespace ZeroTier
#endif