diff options
Diffstat (limited to 'node/PacketDecoder.cpp')
-rw-r--r-- | node/PacketDecoder.cpp | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 2efa7cf9..f65e4167 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -189,16 +189,16 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) return true; } + // Do we already have this peer? SharedPtr<Peer> peer(_r->topology->getPeer(id.address())); if (peer) { + // Check to make sure this isn't a colliding identity (different key, + // but same address). The odds are spectacularly low but it could happen. + // Could also be a sign of someone doing something nasty. if (peer->identity() != id) { - // Sorry, someone beat you to that address. What are the odds? - // Well actually they're around two in 2^40. You should play - // the lottery. unsigned char key[ZT_PEER_SECRET_KEY_LENGTH]; if (_r->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) { TRACE("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str()); - Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); outp.append((unsigned char)Packet::VERB_HELLO); outp.append(packetId()); @@ -209,7 +209,26 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) return true; } // else continue and send OK since we already know thee... } else { - // Learn a new peer + // If we don't have a peer record on file, check the identity cache (if + // we have one) to see if we have a cached identity. Then check that for + // collision before adding a new peer. + Identity alreadyHaveCachedId(_r->topology->getIdentity(id.address())); + if ((alreadyHaveCachedId)&&(id != alreadyHaveCachedId)) { + unsigned char key[ZT_PEER_SECRET_KEY_LENGTH]; + if (_r->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) { + TRACE("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str()); + Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); + outp.append((unsigned char)Packet::VERB_HELLO); + outp.append(packetId()); + outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); + outp.armor(key,true); + _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + } + return true; + } + + // Learn a new peer if it's new. This also adds it to the identity + // cache if that's enabled. peer = _r->topology->addPeer(SharedPtr<Peer>(new Peer(_r->identity,id))); } |