diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2019-03-14 14:29:15 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2019-03-14 14:29:15 -0700 |
commit | e03102dbcb4d28cfa54740a8d9824d3c6324d97b (patch) | |
tree | a0da61347f8899b7aa93ab3e754f337151e936d8 | |
parent | 9d7b7c72b2dd769853bea3423321539ab198829e (diff) | |
download | infinitytier-e03102dbcb4d28cfa54740a8d9824d3c6324d97b.tar.gz infinitytier-e03102dbcb4d28cfa54740a8d9824d3c6324d97b.zip |
Clean out some unnecessarily pedantic auth stuff in favor of a simpler way of gating multicast gathers.
-rw-r--r-- | node/IncomingPacket.cpp | 69 | ||||
-rw-r--r-- | node/Multicaster.cpp | 22 | ||||
-rw-r--r-- | node/Multicaster.hpp | 39 | ||||
-rw-r--r-- | node/Network.cpp | 1 | ||||
-rw-r--r-- | node/Network.hpp | 12 | ||||
-rw-r--r-- | node/Node.cpp | 4 | ||||
-rw-r--r-- | node/Node.hpp | 23 | ||||
-rw-r--r-- | node/Switch.cpp | 2 |
8 files changed, 51 insertions, 121 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index c42a6d24..5605d2b9 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -645,8 +645,6 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar _sendErrorNeedCredentials(RR,tPtr,peer,nwid); RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_FRAME,true); } - } else { - _sendErrorNeedCredentials(RR,tPtr,peer,nwid); } peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished,nwid); @@ -757,45 +755,10 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer) { const int64_t now = RR->node->now(); - - uint64_t authOnNetwork[256]; // cache for approved network IDs - unsigned int authOnNetworkCount = 0; - SharedPtr<Network> network; - bool trustEstablished = false; - - // Iterate through 18-byte network,MAC,ADI tuples - for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18) { - const uint64_t nwid = at<uint64_t>(ptr); - - bool auth = false; - for(unsigned int i=0;i<authOnNetworkCount;++i) { - if (nwid == authOnNetwork[i]) { - auth = true; - break; - } - } - if (!auth) { - if ((!network)||(network->id() != nwid)) - network = RR->node->network(nwid); - const bool authOnNet = ((network)&&(network->gate(tPtr,peer))); - if (!authOnNet) - _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - trustEstablished |= authOnNet; - if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) { - auth = true; - if (authOnNetworkCount < 256) // sanity check, packets can't really be this big - authOnNetwork[authOnNetworkCount++] = nwid; - } - } - - if (auth) { - const MulticastGroup group(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)); - RR->mc->add(tPtr,now,nwid,group,peer->address()); - } - } - - peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished,(network) ? network->id() : 0); - + // Packet contains a series of 18-byte network,MAC,ADI tuples + for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18) + RR->mc->add(tPtr,now,at<uint64_t>(ptr),MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address()); + peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,false,0); return true; } @@ -828,7 +791,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t case Membership::ADD_DEFERRED_FOR_WHOIS: return false; } - } else RR->mc->addCredential(tPtr,com,false); + } } } ++p; // skip trailing 0 after COMs if present @@ -982,18 +945,20 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr try { CertificateOfMembership com; com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM); - if (com) { - if (network) - network->addCredential(tPtr,com); - else RR->mc->addCredential(tPtr,com,false); - } + if ((com)&&(network)) + network->addCredential(tPtr,com); } catch ( ... ) {} // discard invalid COMs } - const bool trustEstablished = ((network)&&(network->gate(tPtr,peer))); - if (!trustEstablished) - _sendErrorNeedCredentials(RR,tPtr,peer,nwid); - if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) { + bool trustEstablished = false; + if (network) { + if (network->gate(tPtr,peer)) + trustEstablished = true; + else _sendErrorNeedCredentials(RR,tPtr,peer,nwid); + } + + const int64_t now = RR->node->now(); + if ((gatherLimit > 0)&&((trustEstablished)||(RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())))) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER); outp.append(packetId()); @@ -1003,7 +968,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit); if (gatheredLocally > 0) { outp.armor(peer->key(),true); - _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),now); } } diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index c38e2f02..67e133c0 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -42,8 +42,7 @@ namespace ZeroTier { Multicaster::Multicaster(const RuntimeEnvironment *renv) : RR(renv), - _groups(256), - _gatherAuth(256) + _groups(32) { } @@ -415,25 +414,6 @@ void Multicaster::clean(int64_t now) } } } - - { - Mutex::Lock _l(_gatherAuth_m); - _GatherAuthKey *k = (_GatherAuthKey *)0; - uint64_t *ts = NULL; - Hashtable<_GatherAuthKey,uint64_t>::Iterator i(_gatherAuth); - while (i.next(k,ts)) { - if ((now - *ts) >= ZT_MULTICAST_CREDENTIAL_EXPIRATON) - _gatherAuth.erase(*k); - } - } -} - -void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated) -{ - if ((alreadyValidated)||(com.verify(RR,tPtr) == 0)) { - Mutex::Lock _l(_gatherAuth_m); - _gatherAuth[_GatherAuthKey(com.networkId(),com.issuedTo())] = RR->node->now(); - } } void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member) diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index dd4a4656..2cdcfb82 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -158,33 +158,6 @@ public: */ void clean(int64_t now); - /** - * Add an authorization credential - * - * The Multicaster keeps its own track of when valid credentials of network - * membership are presented. This allows it to control MULTICAST_LIKE - * GATHER authorization for networks this node does not belong to. - * - * @param com Certificate of membership - * @param alreadyValidated If true, COM has already been checked and found to be valid and signed - */ - void addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated); - - /** - * Check authorization for GATHER and LIKE for non-network-members - * - * @param a Address of peer - * @param nwid Network ID - * @param now Current time - * @return True if GATHER and LIKE should be allowed - */ - bool cacheAuthorized(const Address &a,const uint64_t nwid,const int64_t now) const - { - Mutex::Lock _l(_gatherAuth_m); - const uint64_t *p = _gatherAuth.get(_GatherAuthKey(nwid,a)); - return ((p)&&((now - *p) < ZT_MULTICAST_CREDENTIAL_EXPIRATON)); - } - private: struct Key { @@ -226,18 +199,6 @@ private: Hashtable<Multicaster::Key,MulticastGroupStatus> _groups; Mutex _groups_m; - - struct _GatherAuthKey - { - _GatherAuthKey() : member(0),networkId(0) {} - _GatherAuthKey(const uint64_t nwid,const Address &a) : member(a.toInt()),networkId(nwid) {} - inline unsigned long hashCode() const { return (unsigned long)(member ^ networkId); } - inline bool operator==(const _GatherAuthKey &k) const { return ((member == k.member)&&(networkId == k.networkId)); } - uint64_t member; - uint64_t networkId; - }; - Hashtable< _GatherAuthKey,uint64_t > _gatherAuth; - Mutex _gatherAuth_m; }; } // namespace ZeroTier diff --git a/node/Network.cpp b/node/Network.cpp index 31301631..bbef98dd 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1370,7 +1370,6 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Certific const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,com); if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) { m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false); - RR->mc->addCredential(tPtr,com,true); } return result; } diff --git a/node/Network.hpp b/node/Network.hpp index a8c5ea1f..eec016c0 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -291,6 +291,11 @@ public: } /** + * @return True if QoS is in effect for this network + */ + inline bool qosEnabled() { return false; } + + /** * Set a bridge route * * @param mac MAC address of destination @@ -299,13 +304,6 @@ public: void learnBridgeRoute(const MAC &mac,const Address &addr); /** - * Whether QoS is in effect for this network - */ - bool QoSEnabled() { - return false; - } - - /** * Learn a multicast group that is bridged to our tap device * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call diff --git a/node/Node.cpp b/node/Node.cpp index 30c722b2..1a1f903d 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -633,6 +633,10 @@ std::vector<World> Node::moons() const void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) { + _localControllerAuthorizations_m.lock(); + _localControllerAuthorizations[_LocalControllerAuth(nwid,destination)] = now(); + _localControllerAuthorizations_m.unlock(); + if (destination == RR->identity.address()) { SharedPtr<Network> n(network(nwid)); if (!n) return; diff --git a/node/Node.hpp b/node/Node.hpp index 9f223eb5..c3e46deb 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -263,6 +263,16 @@ public: inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; } inline uint8_t getMultipathMode() { return _multipathMode; } + inline bool localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const + { + _localControllerAuthorizations_m.lock(); + const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr)); + _localControllerAuthorizations_m.unlock(); + if (at) + return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3)); + return false; + } + private: RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -276,6 +286,19 @@ private: // Time of last identity verification indexed by InetAddress.rateGateHash() -- used in IncomingPacket::_doHELLO() via rateGateIdentityVerification() int64_t _lastIdentityVerification[16384]; + // Map that remembers if we have recently sent a network config to someone + // querying us as a controller. + struct _LocalControllerAuth + { + uint64_t nwid,address; + _LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {} + inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); } + inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); } + inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); } + }; + Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations; + Mutex _localControllerAuthorizations_m; + Hashtable< uint64_t,SharedPtr<Network> > _networks; Mutex _networks_m; diff --git a/node/Switch.cpp b/node/Switch.cpp index 58979e26..3a4f8276 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -502,7 +502,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const void Switch::aqm_enqueue(void *tPtr, const SharedPtr<Network> &network, Packet &packet,bool encrypt,int qosBucket) { - if(!network->QoSEnabled()) { + if(!network->qosEnabled()) { send(tPtr, packet, encrypt); return; } |