A bunch of comments and cleanup, including some to yesterday's direct path pushing changes. Move path viability check to one place, and stop trying to use link-local addresses since they are not reliable.

This commit is contained in:
Adam Ierymenko 2015-07-07 08:54:48 -07:00
parent f398952a6c
commit c863ff3f02
7 changed files with 111 additions and 60 deletions

View file

@ -134,6 +134,9 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
break;
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
/* Note: certificates are public so it's safe to push them to anyone
* who asks. We won't communicate unless we also get a certificate
* from the remote that agrees. */
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if (network) {
SharedPtr<NetworkConfig> nconf(network->config2());
@ -170,8 +173,20 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
{
/* Note: this is the only packet ever sent in the clear, and it's also
* the only packet that we authenticate via a different path. Authentication
* occurs here and is based on the validity of the identity and the
* integrity of the packet's MAC, but it must be done after we check
* the identity since HELLO is a mechanism for learning new identities
* in the first place. */
try {
const unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION];
if (protoVersion < ZT_PROTO_VERSION_MIN) {
TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION];
const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
@ -179,6 +194,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
Identity id;
unsigned int destAddrPtr = id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY;
if (source() != id.address()) {
TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
InetAddress destAddr;
if (destAddrPtr < size()) { // ZeroTier One < 1.0.3 did not include this field
@ -193,16 +212,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
}
}
if (source() != id.address()) {
TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
if (protoVersion < ZT_PROTO_VERSION_MIN) {
TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
if (peer) {
// We already have an identity with this address -- check for collisions
@ -245,12 +254,14 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
} else {
// We don't already have an identity with this address -- validate and learn it
// Check identity proof of work
if (!id.locallyValidate()) {
RR->node->postEvent(ZT1_EVENT_AUTHENTICATION_FAILURE,(const void *)&_remoteAddress);
TRACE("dropped HELLO from %s(%s): identity invalid",id.address().toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
// Check packet integrity and authentication
SharedPtr<Peer> newPeer(new Peer(RR->identity,id));
if (!dearmor(newPeer->key())) {
RR->node->postEvent(ZT1_EVENT_AUTHENTICATION_FAILURE,(const void *)&_remoteAddress);
@ -554,14 +565,17 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
const unsigned int flags = (*this)[ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS];
unsigned int comLen = 0;
bool comFailed = false;
if ((flags & 0x01) != 0) {
CertificateOfMembership com;
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
if (com.hasRequiredFields())
network->validateAndAddMembershipCertificate(com);
if (com.hasRequiredFields()) {
if (!network->validateAndAddMembershipCertificate(com))
comFailed = true; // technically this check is redundant to isAllowed(), but do it anyway for thoroughness
}
}
if (!network->isAllowed(peer->address())) {
if ((comFailed)||(!network->isAllowed(peer->address()))) {
TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
_sendErrorNeedCertificate(RR,peer,network->id());
return true;
@ -647,8 +661,21 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment
ptr += com.deserialize(*this,ptr);
if (com.hasRequiredFields()) {
SharedPtr<Network> network(RR->node->network(com.networkId()));
if (network)
network->validateAndAddMembershipCertificate(com);
if (network) {
if (network->validateAndAddMembershipCertificate(com)) {
if ((network->isAllowed(peer->address()))&&(network->peerNeedsOurMembershipCertificate(peer->address(),RR->node->now()))) {
// If peer passed our check and we haven't sent it our cert yet, respond
// and push our cert as well for instant authorization setup.
SharedPtr<NetworkConfig> nconf(network->config2());
if ((nconf)&&(nconf->com())) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
nconf->com().serialize(outp);
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
}
}
}
}
}
}
@ -890,24 +917,25 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2;
while (count) { // if ptr overflows Buffer will throw
// TODO: properly handle blacklisting, support other features... see Packet.hpp.
unsigned int flags = (*this)[ptr++];
/*int metric = (*this)[ptr++];*/ ++ptr;
unsigned int extLen = at<uint16_t>(ptr); ptr += 2;
ptr += extLen; // unused right now
unsigned int addrType = (*this)[ptr++];
unsigned int addrLen = (*this)[ptr++];
switch(addrType) {
case 4: {
InetAddress a(field(ptr,4),4,at<uint16_t>(ptr + 4));
if ((flags & (0x01 | 0x02)) == 0) {
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) )
peer->attemptToContactAt(RR,a,RR->node->now());
}
} break;
case 6: {
InetAddress a(field(ptr,16),16,at<uint16_t>(ptr + 16));
if ((flags & (0x01 | 0x02)) == 0) {
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) )
peer->attemptToContactAt(RR,a,RR->node->now());
}
} break;
}
ptr += addrLen;