mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-21 10:01:46 +00:00
More fixes to legacy support, and to a potential issue on quit.
This commit is contained in:
parent
023cac4ebb
commit
42d644a57e
@ -554,6 +554,8 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
|
|||||||
const unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME + frameLen);
|
const unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME + frameLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
if (origin == RR->identity.address())
|
||||||
|
return true;
|
||||||
Mutex::Lock _l(p5MulticastDedupBuffer_m);
|
Mutex::Lock _l(p5MulticastDedupBuffer_m);
|
||||||
if (!p5MulticastDedupBufferPtr) {
|
if (!p5MulticastDedupBufferPtr) {
|
||||||
memset(p5MulticastDedupBuffer,0,sizeof(p5MulticastDedupBuffer));
|
memset(p5MulticastDedupBuffer,0,sizeof(p5MulticastDedupBuffer));
|
||||||
@ -566,6 +568,32 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
|
|||||||
p5MulticastDedupBuffer[p5MulticastDedupBufferPtr++ % 1024] = guid;
|
p5MulticastDedupBuffer[p5MulticastDedupBufferPtr++ % 1024] = guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedPtr<Network> network(RR->nc->network(nwid));
|
||||||
|
if (network) {
|
||||||
|
if ((flags & ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE) != 0) {
|
||||||
|
CertificateOfMembership com;
|
||||||
|
com.deserialize(*this,ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 + signatureLen);
|
||||||
|
if (com.hasRequiredFields())
|
||||||
|
network->addMembershipCertificate(com,false);
|
||||||
|
}
|
||||||
|
if (!network->isAllowed(origin)) {
|
||||||
|
SharedPtr<Peer> originPeer(RR->topology->getPeer(origin));
|
||||||
|
if (originPeer)
|
||||||
|
_sendErrorNeedCertificate(RR,originPeer,nwid);
|
||||||
|
} else if ((frameLen > 0)&&(frameLen <= 2800)) {
|
||||||
|
if (!dest.mac().isMulticast())
|
||||||
|
return true;
|
||||||
|
if ((!sourceMac)||(sourceMac.isMulticast())||(sourceMac == network->mac()))
|
||||||
|
return true;
|
||||||
|
if (sourceMac != MAC(origin,nwid)) {
|
||||||
|
if (network->permitsBridging(origin)) {
|
||||||
|
network->learnBridgeRoute(sourceMac,origin);
|
||||||
|
} else return true;
|
||||||
|
}
|
||||||
|
network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_P5_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
|
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_P5_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
|
||||||
|
|
||||||
if (RR->topology->amSupernode()) {
|
if (RR->topology->amSupernode()) {
|
||||||
@ -577,12 +605,14 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
|
|||||||
const unsigned int limit = 128; // use a fairly generous limit since we want legacy peers to always work until they go away
|
const unsigned int limit = 128; // use a fairly generous limit since we want legacy peers to always work until they go away
|
||||||
|
|
||||||
std::vector<Address> members(RR->mc->getMembers(nwid,dest,limit));
|
std::vector<Address> members(RR->mc->getMembers(nwid,dest,limit));
|
||||||
|
SharedPtr<Peer> lpp;
|
||||||
|
|
||||||
setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff);
|
setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff);
|
||||||
setSource(RR->identity.address());
|
setSource(RR->identity.address());
|
||||||
compress();
|
compress();
|
||||||
for(std::vector<Address>::iterator lp(members.begin());lp!=members.end();++lp) {
|
for(std::vector<Address>::iterator lp(members.begin());lp!=members.end();++lp) {
|
||||||
SharedPtr<Peer> lpp(RR->topology->getPeer(*lp));
|
if (!senderIsLegacy)
|
||||||
|
lpp = RR->topology->getPeer(*lp);
|
||||||
if ( (*lp != origin) && (*lp != peer->address()) && ((senderIsLegacy) || (!lpp) || (lpp->remoteVersionMajor() < 1)) ) {
|
if ( (*lp != origin) && (*lp != peer->address()) && ((senderIsLegacy) || (!lpp) || (lpp->remoteVersionMajor() < 1)) ) {
|
||||||
newInitializationVector();
|
newInitializationVector();
|
||||||
setDestination(*lp);
|
setDestination(*lp);
|
||||||
@ -605,35 +635,6 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
|
|||||||
sn->send(RR,data(),size(),Utils::now());
|
sn->send(RR,data(),size(),Utils::now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Network> network(RR->nc->network(nwid));
|
|
||||||
if (network) {
|
|
||||||
if ((flags & ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE)) {
|
|
||||||
CertificateOfMembership com;
|
|
||||||
com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 + signatureLen);
|
|
||||||
if (com.hasRequiredFields())
|
|
||||||
network->addMembershipCertificate(com,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!network->isAllowed(origin)) {
|
|
||||||
_sendErrorNeedCertificate(RR,peer,network->id());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((frameLen > 0)&&(frameLen <= 2800)) {
|
|
||||||
if (!dest.mac().isMulticast())
|
|
||||||
return true;
|
|
||||||
if ((!sourceMac)||(sourceMac.isMulticast())||(sourceMac == network->mac()))
|
|
||||||
return true;
|
|
||||||
if (sourceMac != MAC(origin,network->id())) {
|
|
||||||
if (network->permitsBridging(origin)) {
|
|
||||||
network->learnBridgeRoute(sourceMac,origin);
|
|
||||||
} else return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
TRACE("dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
|
TRACE("dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
|
@ -270,8 +270,7 @@ void Multicaster::send(
|
|||||||
outp.append((uint16_t)0xffff); // do not forward
|
outp.append((uint16_t)0xffff); // do not forward
|
||||||
outp.append((unsigned char)0,320 + 1024); // empty queue and bloom filter
|
outp.append((unsigned char)0,320 + 1024); // empty queue and bloom filter
|
||||||
|
|
||||||
unsigned int signedPortionStart = outp.size();
|
outp.append((unsigned char)((com) ? ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE : 0));
|
||||||
outp.append((unsigned char)0);
|
|
||||||
outp.append((uint64_t)nwid);
|
outp.append((uint64_t)nwid);
|
||||||
outp.append((uint16_t)0);
|
outp.append((uint16_t)0);
|
||||||
outp.append((unsigned char)0);
|
outp.append((unsigned char)0);
|
||||||
@ -286,9 +285,9 @@ void Multicaster::send(
|
|||||||
outp.append((uint16_t)etherType);
|
outp.append((uint16_t)etherType);
|
||||||
outp.append((uint16_t)len);
|
outp.append((uint16_t)len);
|
||||||
outp.append(data,len);
|
outp.append(data,len);
|
||||||
unsigned int signedPortionLen = outp.size() - signedPortionStart;
|
unsigned int signedPortionLen = outp.size() - ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION;
|
||||||
|
|
||||||
C25519::Signature sig(RR->identity.sign(outp.field(signedPortionStart,signedPortionLen),signedPortionLen));
|
C25519::Signature sig(RR->identity.sign(outp.field(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPortionLen),signedPortionLen));
|
||||||
|
|
||||||
outp.append((uint16_t)sig.size());
|
outp.append((uint16_t)sig.size());
|
||||||
outp.append(sig.data,sig.size());
|
outp.append(sig.data,sig.size());
|
||||||
|
@ -310,25 +310,31 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!forceAccept) {
|
if (!forceAccept) {
|
||||||
if (cert.signedBy() != controller())
|
if (cert.signedBy() != controller()) {
|
||||||
|
LOG("rejected network membership certificate for %.16llx signed by %s: signer not a controller of this network",(unsigned long long)_id,cert.signedBy().toString().c_str());
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> signer(RR->topology->getPeer(cert.signedBy()));
|
SharedPtr<Peer> signer(RR->topology->getPeer(cert.signedBy()));
|
||||||
if (!signer)
|
|
||||||
return; // we should already have done a WHOIS on this peer, since this is our netconf master
|
if (!signer) {
|
||||||
if (!cert.verify(signer->identity()))
|
// This would be rather odd, since this is our netconf master... could happen
|
||||||
|
// if we get packets before we've gotten config.
|
||||||
|
RR->sw->requestWhois(cert.signedBy());
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cert.verify(signer->identity())) {
|
||||||
|
LOG("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
|
||||||
// We go ahead and accept certs provisionally even if _isOpen is true, since
|
|
||||||
// that might be changed in short order if the user is fiddling in the UI.
|
|
||||||
|
|
||||||
CertificateOfMembership &old = _membershipCertificates[cert.issuedTo()];
|
CertificateOfMembership &old = _membershipCertificates[cert.issuedTo()];
|
||||||
if (cert.timestamp() >= old.timestamp()) {
|
if (cert.timestamp() >= old.timestamp())
|
||||||
//TRACE("got new certificate for %s on network %.16llx",cert.issuedTo().toString().c_str(),cert.networkId());
|
|
||||||
old = cert;
|
old = cert;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now)
|
bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now)
|
||||||
@ -632,6 +638,7 @@ void Network::_dumpMembershipCerts()
|
|||||||
FILE *mcdb = fopen(mcdbPath.c_str(),"wb");
|
FILE *mcdb = fopen(mcdbPath.c_str(),"wb");
|
||||||
if (!mcdb)
|
if (!mcdb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fwrite("ZTMCD0",6,1,mcdb) != 1) {
|
if (fwrite("ZTMCD0",6,1,mcdb) != 1) {
|
||||||
fclose(mcdb);
|
fclose(mcdb);
|
||||||
Utils::rm(mcdbPath);
|
Utils::rm(mcdbPath);
|
||||||
@ -639,29 +646,14 @@ void Network::_dumpMembershipCerts()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(std::map<Address,CertificateOfMembership>::iterator c=(_membershipCertificates.begin());c!=_membershipCertificates.end();++c) {
|
for(std::map<Address,CertificateOfMembership>::iterator c=(_membershipCertificates.begin());c!=_membershipCertificates.end();++c) {
|
||||||
try {
|
buf.clear();
|
||||||
c->second.serialize(buf);
|
c->second.serialize(buf);
|
||||||
if (buf.size() >= (ZT_NETWORK_CERT_WRITE_BUF_SIZE / 2)) {
|
if (buf.size() > 0) {
|
||||||
if (fwrite(buf.data(),buf.size(),1,mcdb) != 1) {
|
if (fwrite(buf.data(),buf.size(),1,mcdb) != 1) {
|
||||||
fclose(mcdb);
|
fclose(mcdb);
|
||||||
Utils::rm(mcdbPath);
|
Utils::rm(mcdbPath);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
buf.clear();
|
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
|
||||||
// Sanity check... no cert will ever be big enough to overflow buf
|
|
||||||
fclose(mcdb);
|
|
||||||
Utils::rm(mcdbPath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf.size()) {
|
|
||||||
if (fwrite(buf.data(),buf.size(),1,mcdb) != 1) {
|
|
||||||
fclose(mcdb);
|
|
||||||
Utils::rm(mcdbPath);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user