mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-30 09:48:54 +00:00
Improve security posture by eliminating non-const data() accessor from Buffer.
This commit is contained in:
parent
e8c5495b61
commit
e53d208ea4
@ -163,11 +163,13 @@ public:
|
|||||||
return ((unsigned char *)_b)[i];
|
return ((unsigned char *)_b)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *data() throw() { return (unsigned char *)_b; }
|
|
||||||
const unsigned char *data() const throw() { return (const unsigned char *)_b; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safe way to get a pointer to a field from data() with bounds checking
|
* Get a raw pointer to a field with bounds checking
|
||||||
|
*
|
||||||
|
* This isn't perfectly safe in that the caller could still overflow
|
||||||
|
* the pointer, but its use provides both a sanity check and
|
||||||
|
* documentation / reminder to the calling code to treat the returned
|
||||||
|
* pointer as being of size [l].
|
||||||
*
|
*
|
||||||
* @param i Index of field in buffer
|
* @param i Index of field in buffer
|
||||||
* @param l Length of field in bytes
|
* @param l Length of field in bytes
|
||||||
@ -304,8 +306,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Increment size and return pointer to field of specified size
|
* Increment size and return pointer to field of specified size
|
||||||
*
|
*
|
||||||
* The memory isn't actually written, so this is a shortcut for a multi-step
|
* Nothing is actually written to the memory. This is a shortcut
|
||||||
* process involving getting the current pointer and adding size.
|
* for addSize() followed by field() to reference the previous
|
||||||
|
* position and the new size.
|
||||||
*
|
*
|
||||||
* @param l Length of field to append
|
* @param l Length of field to append
|
||||||
* @return Pointer to beginning of appended field of length 'l'
|
* @return Pointer to beginning of appended field of length 'l'
|
||||||
@ -352,6 +355,22 @@ public:
|
|||||||
_l = i;
|
_l = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move everything after 'at' to the buffer's front and truncate
|
||||||
|
*
|
||||||
|
* @param at Truncate before this position
|
||||||
|
* @throw std::out_of_range Position is beyond size of buffer
|
||||||
|
*/
|
||||||
|
inline void behead(const unsigned int at)
|
||||||
|
throw(std::out_of_range)
|
||||||
|
{
|
||||||
|
if (!at)
|
||||||
|
return;
|
||||||
|
if (at > _l)
|
||||||
|
throw std::out_of_range("Buffer: behead() beyond capacity");
|
||||||
|
::memmove(_b,_b + at,_l -= at);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set buffer data length to zero
|
* Set buffer data length to zero
|
||||||
*/
|
*/
|
||||||
@ -388,6 +407,11 @@ public:
|
|||||||
Utils::burn(_b,sizeof(_b));
|
Utils::burn(_b,sizeof(_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Constant pointer to data in buffer
|
||||||
|
*/
|
||||||
|
inline const void *data() const throw() { return _b; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Size of data in buffer
|
* @return Size of data in buffer
|
||||||
*/
|
*/
|
||||||
|
@ -46,50 +46,56 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
|
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
|
||||||
{
|
{
|
||||||
if ((!encrypted())&&(verb() == Packet::VERB_HELLO)) {
|
try {
|
||||||
// Unencrypted HELLOs are handled here since they are used to
|
if ((!encrypted())&&(verb() == Packet::VERB_HELLO)) {
|
||||||
// populate our identity cache in the first place. _doHELLO() is special
|
// Unencrypted HELLOs are handled here since they are used to
|
||||||
// in that it contains its own authentication logic.
|
// populate our identity cache in the first place. _doHELLO() is special
|
||||||
//TRACE("<< HELLO from %s(%s) (normal unencrypted HELLO)",source().toString().c_str(),_remoteAddress.toString().c_str());
|
// in that it contains its own authentication logic.
|
||||||
return _doHELLO(RR);
|
return _doHELLO(RR);
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr<Peer> peer = RR->topology->getPeer(source());
|
|
||||||
if (peer) {
|
|
||||||
if (!dearmor(peer->key())) {
|
|
||||||
TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",source().toString().c_str(),_remoteAddress.toString().c_str(),size());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!uncompress()) {
|
|
||||||
TRACE("dropped packet from %s(%s), compressed data invalid",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TRACE("<< %s from %s(%s)",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str());
|
SharedPtr<Peer> peer = RR->topology->getPeer(source());
|
||||||
|
if (peer) {
|
||||||
switch(verb()) {
|
if (!dearmor(peer->key())) {
|
||||||
//case Packet::VERB_NOP:
|
TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",source().toString().c_str(),_remoteAddress.toString().c_str(),size());
|
||||||
default: // ignore unknown verbs, but if they pass auth check they are still valid
|
|
||||||
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP,Utils::now());
|
|
||||||
return true;
|
return true;
|
||||||
case Packet::VERB_HELLO: return _doHELLO(RR);
|
}
|
||||||
case Packet::VERB_ERROR: return _doERROR(RR,peer);
|
if (!uncompress()) {
|
||||||
case Packet::VERB_OK: return _doOK(RR,peer);
|
TRACE("dropped packet from %s(%s), compressed data invalid",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
case Packet::VERB_WHOIS: return _doWHOIS(RR,peer);
|
return true;
|
||||||
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,peer);
|
}
|
||||||
case Packet::VERB_FRAME: return _doFRAME(RR,peer);
|
|
||||||
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
|
//TRACE("<< %s from %s(%s)",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
case Packet::VERB_P5_MULTICAST_FRAME: return _doP5_MULTICAST_FRAME(RR,peer);
|
|
||||||
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
|
switch(verb()) {
|
||||||
case Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE: return _doNETWORK_MEMBERSHIP_CERTIFICATE(RR,peer);
|
//case Packet::VERB_NOP:
|
||||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
|
default: // ignore unknown verbs, but if they pass auth check they are "received"
|
||||||
case Packet::VERB_NETWORK_CONFIG_REFRESH: return _doNETWORK_CONFIG_REFRESH(RR,peer);
|
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP,Utils::now());
|
||||||
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
|
return true;
|
||||||
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
|
case Packet::VERB_HELLO: return _doHELLO(RR);
|
||||||
|
case Packet::VERB_ERROR: return _doERROR(RR,peer);
|
||||||
|
case Packet::VERB_OK: return _doOK(RR,peer);
|
||||||
|
case Packet::VERB_WHOIS: return _doWHOIS(RR,peer);
|
||||||
|
case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,peer);
|
||||||
|
case Packet::VERB_FRAME: return _doFRAME(RR,peer);
|
||||||
|
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
|
||||||
|
case Packet::VERB_P5_MULTICAST_FRAME: return _doP5_MULTICAST_FRAME(RR,peer);
|
||||||
|
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
|
||||||
|
case Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE: return _doNETWORK_MEMBERSHIP_CERTIFICATE(RR,peer);
|
||||||
|
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
|
||||||
|
case Packet::VERB_NETWORK_CONFIG_REFRESH: return _doNETWORK_CONFIG_REFRESH(RR,peer);
|
||||||
|
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
|
||||||
|
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RR->sw->requestWhois(source());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} catch ( ... ) {
|
||||||
RR->sw->requestWhois(source());
|
// Exceptions are more informatively caught in _do...() handlers but
|
||||||
return false;
|
// this outer try/catch will catch anything else odd.
|
||||||
|
TRACE("dropped ??? from %s(%s): unexpected exception in tryDecode()",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +436,8 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
network->tapPut(MAC(peer->address(),network->id()),network->mac(),etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
|
unsigned int payloadLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
|
||||||
|
network->tapPut(MAC(peer->address(),network->id()),network->mac(),etherType,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now());
|
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now());
|
||||||
|
@ -505,7 +505,7 @@ void Network::_restoreState()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read most recent multicast cert dump
|
// Read most recent membership cert dump
|
||||||
if ((_config)&&(!_config->isPublic())&&(Utils::fileExists(mcdbPath.c_str()))) {
|
if ((_config)&&(!_config->isPublic())&&(Utils::fileExists(mcdbPath.c_str()))) {
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
@ -519,7 +519,7 @@ void Network::_restoreState()
|
|||||||
if ((fread(magic,6,1,mcdb) == 1)&&(!memcmp("ZTMCD0",magic,6))) {
|
if ((fread(magic,6,1,mcdb) == 1)&&(!memcmp("ZTMCD0",magic,6))) {
|
||||||
long rlen = 0;
|
long rlen = 0;
|
||||||
do {
|
do {
|
||||||
long rlen = (long)fread(buf.data() + buf.size(),1,ZT_NETWORK_CERT_WRITE_BUF_SIZE - buf.size(),mcdb);
|
long rlen = (long)fread(const_cast<char *>(static_cast<const char *>(buf.data())) + buf.size(),1,ZT_NETWORK_CERT_WRITE_BUF_SIZE - buf.size(),mcdb);
|
||||||
if (rlen < 0) rlen = 0;
|
if (rlen < 0) rlen = 0;
|
||||||
buf.setSize(buf.size() + (unsigned int)rlen);
|
buf.setSize(buf.size() + (unsigned int)rlen);
|
||||||
unsigned int ptr = 0;
|
unsigned int ptr = 0;
|
||||||
@ -528,10 +528,7 @@ void Network::_restoreState()
|
|||||||
if (com.issuedTo())
|
if (com.issuedTo())
|
||||||
_membershipCertificates[com.issuedTo()] = com;
|
_membershipCertificates[com.issuedTo()] = com;
|
||||||
}
|
}
|
||||||
if (ptr) {
|
buf.behead(ptr);
|
||||||
memmove(buf.data(),buf.data() + ptr,buf.size() - ptr);
|
|
||||||
buf.setSize(buf.size() - ptr);
|
|
||||||
}
|
|
||||||
} while (rlen > 0);
|
} while (rlen > 0);
|
||||||
fclose(mcdb);
|
fclose(mcdb);
|
||||||
} else {
|
} else {
|
||||||
|
@ -383,13 +383,13 @@ public:
|
|||||||
setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH);
|
setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH);
|
||||||
|
|
||||||
// NOTE: this copies both the IV/packet ID and the destination address.
|
// NOTE: this copies both the IV/packet ID and the destination address.
|
||||||
memcpy(field(ZT_PACKET_FRAGMENT_IDX_PACKET_ID,13),p.data() + ZT_PACKET_IDX_IV,13);
|
memcpy(field(ZT_PACKET_FRAGMENT_IDX_PACKET_ID,13),field(ZT_PACKET_IDX_IV,13),13);
|
||||||
|
|
||||||
(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] = ZT_PACKET_FRAGMENT_INDICATOR;
|
(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] = ZT_PACKET_FRAGMENT_INDICATOR;
|
||||||
(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO] = (char)(((fragTotal & 0xf) << 4) | (fragNo & 0xf));
|
(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO] = (char)(((fragTotal & 0xf) << 4) | (fragNo & 0xf));
|
||||||
(*this)[ZT_PACKET_FRAGMENT_IDX_HOPS] = 0;
|
(*this)[ZT_PACKET_FRAGMENT_IDX_HOPS] = 0;
|
||||||
|
|
||||||
memcpy(field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD,fragLen),p.data() + fragStart,fragLen);
|
memcpy(field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD,fragLen),field(fragStart,fragLen),fragLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,7 +356,7 @@ void Topology::_loadPeers()
|
|||||||
if ((fread(magic,5,1,pd) == 1)&&(!memcmp("ZTPD0",magic,5))) {
|
if ((fread(magic,5,1,pd) == 1)&&(!memcmp("ZTPD0",magic,5))) {
|
||||||
long rlen = 0;
|
long rlen = 0;
|
||||||
do {
|
do {
|
||||||
long rlen = (long)fread(buf.data() + buf.size(),1,ZT_PEER_WRITE_BUF_SIZE - buf.size(),pd);
|
long rlen = (long)fread(const_cast<char *>(static_cast<const char *>(buf.data())) + buf.size(),1,ZT_PEER_WRITE_BUF_SIZE - buf.size(),pd);
|
||||||
if (rlen < 0) rlen = 0;
|
if (rlen < 0) rlen = 0;
|
||||||
buf.setSize(buf.size() + (unsigned int)rlen);
|
buf.setSize(buf.size() + (unsigned int)rlen);
|
||||||
unsigned int ptr = 0;
|
unsigned int ptr = 0;
|
||||||
@ -366,10 +366,7 @@ void Topology::_loadPeers()
|
|||||||
_activePeers[p->address()] = p;
|
_activePeers[p->address()] = p;
|
||||||
saveIdentity(p->identity());
|
saveIdentity(p->identity());
|
||||||
}
|
}
|
||||||
if (ptr) {
|
buf.behead(ptr);
|
||||||
memmove(buf.data(),buf.data() + ptr,buf.size() - ptr);
|
|
||||||
buf.setSize(buf.size() - ptr);
|
|
||||||
}
|
|
||||||
} while (rlen > 0);
|
} while (rlen > 0);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user