diff --git a/include/ZeroTierCore.h b/include/ZeroTierCore.h index b3921d3b1..d32f691b5 100644 --- a/include/ZeroTierCore.h +++ b/include/ZeroTierCore.h @@ -1867,11 +1867,12 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks( * * @param node Node instance * @param nwid 64-bit ZeroTier network ID + * @param fingerprintHash If non-NULL this is the full fingerprint of the controller * @param uptr An arbitrary pointer to associate with this network (default: NULL) * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr); +ZT_SDK_API enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,const ZT_Fingerprint *controllerFingerprint,void *uptr,void *tptr); /** * Leave a network diff --git a/node/Network.cpp b/node/Network.cpp index a0f3067b3..f7a79cdf4 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -158,7 +158,7 @@ _doZtFilterResult _doZtFilter( case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_WATCH: case ZT_NETWORK_RULE_ACTION_REDIRECT: - if (RR->identity.address() == rules[rn].v.fwd.address) + if (RR->identity.address().toInt() == rules[rn].v.fwd.address) superAccept = true; break; default: @@ -533,7 +533,7 @@ _doZtFilterResult _doZtFilter( const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); -Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr,const NetworkConfig *nconf) : +Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const Fingerprint &controllerFingerprint,void *uptr,const NetworkConfig *nconf) : RR(renv), _uPtr(uptr), _id(nwid), @@ -543,6 +543,9 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u _destroyed(false), _netconfFailure(NETCONF_FAILURE_NONE) { + if (controllerFingerprint) + _controllerFingerprint = controllerFingerprint; + if (nconf) { this->setConfiguration(tPtr,*nconf,false); _lastConfigUpdate = 0; // still want to re-request since it's likely outdated @@ -868,6 +871,15 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr &source,const Buf &chunk,int ptr,int size) { + // If the controller's full fingerprint is known or was explicitly specified on join(), + // require that the controller's identity match. Otherwise learn it. + if (_controllerFingerprint) { + if (source->identity().fingerprint() != _controllerFingerprint) + return 0; + } else { + _controllerFingerprint = source->identity().fingerprint(); + } + return 0; #if 0 if (_destroyed) diff --git a/node/Network.hpp b/node/Network.hpp index 50502e737..15ec936dc 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -67,10 +67,11 @@ public: * @param renv Runtime environment * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param nwid Network ID + * @param controllerFingerprint Initial controller fingerprint if non-NULL * @param uptr Arbitrary pointer used by externally-facing API (for user use) * @param nconf Network config, if known */ - Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr,const NetworkConfig *nconf); + Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const Fingerprint &controllerFingerprint,void *uptr,const NetworkConfig *nconf); ~Network(); @@ -350,6 +351,7 @@ private: const RuntimeEnvironment *const RR; void *_uPtr; const uint64_t _id; + Fingerprint _controllerFingerprint; MAC _mac; // local MAC address bool _portInitialized; diff --git a/node/Node.cpp b/node/Node.cpp index a08b1a8c2..449251821 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -347,7 +347,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int return ZT_RESULT_OK; } -ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr) +ZT_ResultCode Node::join(uint64_t nwid,const ZT_Fingerprint *controllerFingerprint,void *uptr,void *tptr) { RWMutex::Lock l(_networks_m); @@ -382,7 +382,10 @@ try_larger_network_hashtable: nw = &(_networks[(unsigned long)(nwidHashed & newNetworksMask)]); } - nw->set(new Network(RR,tptr,nwid,uptr,(const NetworkConfig *)0)); + Fingerprint fp; + if (controllerFingerprint) + Utils::copy(fp.apiFingerprint(),controllerFingerprint); + nw->set(new Network(RR,tptr,nwid,fp,uptr,(const NetworkConfig *)0)); return ZT_RESULT_OK; } @@ -928,10 +931,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64 } } -enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr) +enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,const ZT_Fingerprint *controllerFingerprint,void *uptr,void *tptr) { try { - return reinterpret_cast(node)->join(nwid,uptr,tptr); + return reinterpret_cast(node)->join(nwid,controllerFingerprint,uptr,tptr); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { diff --git a/node/Node.hpp b/node/Node.hpp index dd30e0e62..872f15f47 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -88,7 +88,7 @@ public: unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline); - ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr); + ZT_ResultCode join(uint64_t nwid,const ZT_Fingerprint *controllerFingerprint,void *uptr,void *tptr); ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr); ZT_ResultCode multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);