diff options
Diffstat (limited to 'node/PacketDecoder.cpp')
| -rw-r--r-- | node/PacketDecoder.cpp | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 43ac8c29..956cb642 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -436,7 +436,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared unsigned char *const bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM); // These fields don't -- they're signed by the original sender - // const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS]; + const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS]; const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); const uint16_t bloomNonce = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE); const unsigned int prefixBits = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS]; @@ -450,6 +450,27 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared const unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen); const unsigned char *const signature = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2,signatureLen); + SharedPtr<Network> network(_r->nc->network(nwid)); + + // Grab, verify, and learn certificate if any -- provided we are a member of this network + // Note: we can do this before verification of the actual packet, since the certificate + // has its own separate signature. + if (((flags & ZT_PROTO_VERB_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE))&&(network)) { + CertificateOfMembership originCom(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 + signatureLen); + Address signedBy(originCom.signedBy()); + if ((originCom.networkId() == nwid)&&(signedBy == network->controller())) { + SharedPtr<Peer> signingPeer(_r->topology->getPeer(signedBy)); + if (!signingPeer) { + // Technically this shouldn't happen, but handle it anyway... + _r->sw->requestWhois(signedBy); + _step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP; // causes processing to come back here + return false; + } else if (originCom.verify(signingPeer->identity())) { + network->addMembershipCertificate(originCom); + } + } + } + // Check multicast signature to verify original sender const unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + frameLen; if (!originPeer->identity().verify(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen,signature,signatureLen)) { @@ -490,7 +511,6 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared #endif unsigned int maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH; - SharedPtr<Network> network(_r->nc->network(nwid)); if ((origin == _r->identity.address())||(_r->mc->deduplicate(nwid,guid))) { // Ordinary nodes will drop duplicates. Supernodes keep propagating @@ -660,12 +680,6 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared while (newFifoPtr != newFifoEnd) *(newFifoPtr++) = (unsigned char)0; - // If we're forwarding a packet within a private network that we are - // a member of, also propagate our cert if needed. This propagates - // it to everyone including people who will receive this multicast. - if (network) - network->pushMembershipCertificate(newFifo,sizeof(newFifo),false,Utils::now()); - // First element in newFifo[] is next hop Address nextHop(newFifo,ZT_ADDRESS_LENGTH); if ((!nextHop)&&(!_r->topology->amSupernode())) { |
