-
-
Save denandz/d09ffe67e468baa5609cc6975848d960 to your computer and use it in GitHub Desktop.
Additional logging and attack functionality for ZeroTier security testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp | |
index 10cb0863..cb4b01f0 100644 | |
--- a/node/CertificateOfMembership.cpp | |
+++ b/node/CertificateOfMembership.cpp | |
@@ -150,17 +150,22 @@ void CertificateOfMembership::fromString(const char *s) | |
bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const | |
{ | |
+ fprintf(stderr,"CertificateOfMembership::agreesWith\n"); | |
unsigned int myidx = 0; | |
unsigned int otheridx = 0; | |
- if ((_qualifierCount == 0)||(other._qualifierCount == 0)) | |
+ if ((_qualifierCount == 0)||(other._qualifierCount == 0)){ | |
+ fprintf(stderr,"CertificateOfMembership::agreesWith no qualifiers %u %u\n", _qualifierCount, other._qualifierCount); | |
return false; | |
+ } | |
while (myidx < _qualifierCount) { | |
// Fail if we're at the end of other, since this means the field is | |
// missing. | |
- if (otheridx >= other._qualifierCount) | |
+ if (otheridx >= other._qualifierCount){ | |
+ fprintf(stderr,"CertificateOfMembership::agreesWith otheridx >= other._qualifierCount\n"); | |
return false; | |
+ } | |
// Seek to corresponding tuple in other, ignoring tuples that | |
// we may not have. If we run off the end of other, the tuple is | |
@@ -206,8 +211,10 @@ bool CertificateOfMembership::sign(const Identity &with) | |
int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const | |
{ | |
- if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) | |
- return -1; | |
+ if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)){ | |
+ fprintf(stderr,"CertificateOfMembership::verify - not signed by network controller\n"); | |
+ return -1; | |
+} | |
const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); | |
if (!id) { | |
@@ -222,7 +229,13 @@ int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) con | |
buf[ptr++] = Utils::hton(_qualifiers[i].value); | |
buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta); | |
} | |
- return (id.verify(buf,ptr * sizeof(uint64_t),_signature) ? 0 : -1); | |
+ int ret = (id.verify(buf,ptr * sizeof(uint64_t),_signature) ? 0 : -1); | |
+ if(ret == 0){ | |
+ fprintf(stderr,"CertificateOfMembership::verify - id.verify succeeded\n"); | |
+ } else { | |
+ fprintf(stderr,"CertificateOfMembership::verify - id.verify failed\n"); | |
+ } | |
+ | |
+ return ret; | |
} | |
- | |
} // namespace ZeroTier | |
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp | |
index d1f0f51d..81da02e4 100644 | |
--- a/node/IncomingPacket.cpp | |
+++ b/node/IncomingPacket.cpp | |
@@ -43,6 +43,7 @@ namespace ZeroTier { | |
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t flowId) | |
{ | |
const Address sourceAddress(source()); | |
+ fprintf(stderr,"IncomingPacket::tryDecode()\n"); | |
try { | |
// Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear) | |
@@ -139,6 +140,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
switch(errorCode) { | |
case Packet::ERROR_OBJ_NOT_FOUND: | |
+ fprintf(stderr,"_doERROR - ERROR_OBJ_NOT_FOUND\n"); | |
// Object not found, currently only meaningful from network controllers. | |
if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { | |
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); | |
@@ -148,6 +150,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
break; | |
case Packet::ERROR_UNSUPPORTED_OPERATION: | |
+ fprintf(stderr,"_doERROR - ERROR_UNSUPPORTED_OPERATION\n"); | |
// This can be sent in response to any operation, though right now we only | |
// consider it meaningful from network controllers. This would indicate | |
// that the queried node does not support acting as a controller. | |
@@ -159,12 +162,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
break; | |
case Packet::ERROR_IDENTITY_COLLISION: | |
+ fprintf(stderr,"_doERROR - ERROR_IDENTITY_COLLISION\n"); | |
// FIXME: for federation this will need a payload with a signature or something. | |
if (RR->topology->isUpstream(peer->identity())) | |
RR->node->postEvent(tPtr,ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION); | |
break; | |
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: { | |
+ fprintf(stderr,"_doERROR - ERROR_NEED_MEMBERSHIP_CERTIFICATE\n"); | |
// Peers can send this in response to frames if they do not have a recent enough COM from us | |
networkId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); | |
const SharedPtr<Network> network(RR->node->network(networkId)); | |
@@ -174,6 +179,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
} break; | |
case Packet::ERROR_NETWORK_ACCESS_DENIED_: { | |
+ fprintf(stderr,"_doERROR - ERROR_NETWORK_ACCESS_DENIED_\n"); | |
// Network controller: network access denied. | |
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); | |
if ((network)&&(network->controller() == peer->address())) | |
@@ -181,6 +187,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
} break; | |
case Packet::ERROR_UNWANTED_MULTICAST: { | |
+ fprintf(stderr,"_doERROR - ERROR_UNWANTED_MULTICAST\n"); | |
// Members of networks can use this error to indicate that they no longer | |
// want to receive multicasts on a given channel. | |
networkId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); | |
@@ -510,6 +517,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP | |
} break; | |
case Packet::VERB_WHOIS: | |
+ fprintf(stderr, "_doOK() Handling WHOIS Reply\n"); | |
if (RR->topology->isUpstream(peer->identity())) { | |
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); | |
RR->sw->doAnythingWaitingForPeer(tPtr,RR->topology->addPeer(tPtr,SharedPtr<Peer>(new Peer(RR,RR->identity,id)))); | |
@@ -726,8 +734,11 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar | |
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID); | |
const SharedPtr<Network> network(RR->node->network(nwid)); | |
bool trustEstablished = false; | |
+ fprintf(stderr,"IncomingPacket::doFRAME()\n"); | |
if (network) { | |
+ fprintf(stderr,"IncomingPacket::doFRAME() - passed network id check\n"); | |
if (network->gate(tPtr,peer)) { | |
+ fprintf(stderr,"IncomingPacket::doFRAME() - passed network gate check\n"); | |
trustEstablished = true; | |
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) { | |
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); | |
@@ -889,25 +900,34 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t | |
bool trustEstablished = false; | |
SharedPtr<Network> network; | |
+ | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS\n"); | |
+ | |
unsigned int p = ZT_PACKET_IDX_PAYLOAD; | |
while ((p < size())&&((*this)[p] != 0)) { | |
p += com.deserialize(*this,p); | |
if (com) { | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS: got com: %s\n", com.toString().c_str()); | |
network = RR->node->network(com.networkId()); | |
if (network) { | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS: calling addCredential()\n"); | |
switch (network->addCredential(tPtr,com)) { | |
case Membership::ADD_REJECTED: | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS REJECTED\n"); | |
break; | |
case Membership::ADD_ACCEPTED_NEW: | |
case Membership::ADD_ACCEPTED_REDUNDANT: | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS TRUSTED\n"); | |
trustEstablished = true; | |
break; | |
case Membership::ADD_DEFERRED_FOR_WHOIS: | |
+ fprintf(stderr, "_doNETWORK_CREDENTIALS DEFERRED FOR WHOIS\n"); | |
return false; | |
} | |
} | |
} | |
} | |
+ | |
++p; // skip trailing 0 after COMs if present | |
if (p < size()) { // older ZeroTier versions do not send capabilities, tags, or revocations | |
diff --git a/node/Membership.cpp b/node/Membership.cpp | |
index 4f829ecb..08c272b9 100644 | |
--- a/node/Membership.cpp | |
+++ b/node/Membership.cpp | |
@@ -104,28 +104,36 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i | |
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com) | |
{ | |
+ fprintf(stderr, "Membership:addCredenital\n"); | |
const int64_t newts = com.timestamp(); | |
if (newts <= _comRevocationThreshold) { | |
+ fprintf(stderr, "Membership:addCredenital: revoked\n"); | |
RR->t->credentialRejected(tPtr,com,"revoked"); | |
return ADD_REJECTED; | |
} | |
const int64_t oldts = _com.timestamp(); | |
if (newts < oldts) { | |
+ fprintf(stderr, "Membership:addCredenital: old\n"); | |
RR->t->credentialRejected(tPtr,com,"old"); | |
return ADD_REJECTED; | |
} | |
- if ((newts == oldts)&&(_com == com)) | |
+ if ((newts == oldts)&&(_com == com)){ | |
+ fprintf(stderr, "Membership:addCredenital: redundant\n"); | |
return ADD_ACCEPTED_REDUNDANT; | |
+ } | |
switch(com.verify(RR,tPtr)) { | |
default: | |
+ fprintf(stderr, "Membership:addCredenital: rejected by verify()\n"); | |
RR->t->credentialRejected(tPtr,com,"invalid"); | |
return ADD_REJECTED; | |
case 0: | |
+ fprintf(stderr, "Membership:addCredenital: accepted\n"); | |
_com = com; | |
return ADD_ACCEPTED_NEW; | |
case 1: | |
+ fprintf(stderr, "Membership:addCredenital: deferred for whois\n"); | |
return ADD_DEFERRED_FOR_WHOIS; | |
} | |
} | |
diff --git a/node/Membership.hpp b/node/Membership.hpp | |
index 47698771..2e4313c0 100644 | |
--- a/node/Membership.hpp | |
+++ b/node/Membership.hpp | |
@@ -95,8 +95,13 @@ public: | |
*/ | |
inline bool isAllowedOnNetwork(const NetworkConfig &nconf) const | |
{ | |
+ fprintf(stderr, "isAllowedOnNetwork\n"); | |
if (nconf.isPublic()) return true; | |
- if (_com.timestamp() <= _comRevocationThreshold) return false; | |
+ fprintf(stderr, "isAllowedOnNetwork _com.timestamp() %ld _comRevocationThreshold %ld\n", _com.timestamp(), _comRevocationThreshold); | |
+ if (_com.timestamp() <= _comRevocationThreshold){ | |
+ fprintf(stderr, "isAllowedOnNetwork - revoked\n"); | |
+ return false; | |
+ } | |
return nconf.com.agreesWith(_com); | |
} | |
diff --git a/node/Network.cpp b/node/Network.cpp | |
index 914c96bc..54f2d290 100644 | |
--- a/node/Network.cpp | |
+++ b/node/Network.cpp | |
@@ -1221,14 +1221,21 @@ void Network::requestConfiguration(void *tPtr) | |
bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) | |
{ | |
+ fprintf(stderr,"Network::gate\n"); | |
const int64_t now = RR->node->now(); | |
Mutex::Lock _l(_lock); | |
try { | |
if (_config) { | |
+ fprintf(stderr,"Network::gate got _config\n"); | |
Membership *m = _memberships.get(peer->address()); | |
+ if(m){ | |
+ fprintf(stderr, "Network::gate got m\n"); | |
+ } | |
if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config))) ) { | |
- if (!m) | |
+ fprintf(stderr,"Network::gate m is allowed on network\n"); | |
+ if (!m){ | |
m = &(_membership(peer->address())); | |
+ } | |
if (m->multicastLikeGate(now)) { | |
_announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups()); | |
} | |
@@ -1324,8 +1331,12 @@ void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int | |
Membership::AddCredentialResult Network::addCredential(void *tPtr,const CertificateOfMembership &com) | |
{ | |
- if (com.networkId() != _id) | |
+ fprintf(stderr,"Network::addCredential: %s\n", com.toString().c_str()); | |
+ if (com.networkId() != _id){ | |
+ fprintf(stderr,"Network::addCredential: ADD_REJECTED\n"); | |
return Membership::ADD_REJECTED; | |
+ } | |
+ | |
Mutex::Lock _l(_lock); | |
return _membership(com.issuedTo()).addCredential(RR,tPtr,_config,com); | |
} | |
diff --git a/node/Network.hpp b/node/Network.hpp | |
index b20d8b66..27a7b194 100644 | |
--- a/node/Network.hpp | |
+++ b/node/Network.hpp | |
@@ -352,6 +352,9 @@ public: | |
inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now) | |
{ | |
Mutex::Lock _l(_lock); | |
+ char tmp[32]; | |
+ to.toString(tmp); | |
+ fprintf(stderr, "pushCredentialsNow to %s\n", tmp); | |
_membership(to).pushCredentials(RR,tPtr,now,to,_config); | |
} | |
diff --git a/node/Node.hpp b/node/Node.hpp | |
index 2bbd3b47..630ceb97 100644 | |
--- a/node/Node.hpp | |
+++ b/node/Node.hpp | |
@@ -63,6 +63,10 @@ public: | |
// Public API Functions ---------------------------------------------------- | |
+ RuntimeEnvironment * getRuntime(){ | |
+ return RR; | |
+ } | |
+ | |
ZT_ResultCode processWirePacket( | |
void *tptr, | |
int64_t now, | |
diff --git a/node/Switch.cpp b/node/Switch.cpp | |
index b2040455..3f0ba77e 100644 | |
--- a/node/Switch.cpp | |
+++ b/node/Switch.cpp | |
@@ -866,6 +866,9 @@ void Switch::send(void *tPtr,Packet &packet,bool encrypt,int32_t flowId) | |
void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr) | |
{ | |
+ char tmp[1024]; | |
+ addr.toString(tmp); | |
+ fprintf(stderr,"requestWhois for: %s\n", tmp); | |
if (addr == RR->identity.address()) | |
return; | |
diff --git a/one.cpp b/one.cpp | |
index 06278174..b695568d 100644 | |
--- a/one.cpp | |
+++ b/one.cpp | |
@@ -2035,6 +2035,7 @@ public: | |
returnValue = 1; | |
break; | |
case OneService::ONE_IDENTITY_COLLISION: { | |
+ fprintf(stderr,"COLLISION DETECTED\n"); | |
delete zt1Service; | |
zt1Service = (OneService *)0; | |
std::string oldid; | |
diff --git a/service/OneService.cpp b/service/OneService.cpp | |
index 6f75dbdf..79c7f1f4 100644 | |
--- a/service/OneService.cpp | |
+++ b/service/OneService.cpp | |
@@ -41,6 +41,8 @@ | |
#include "../node/SHA512.hpp" | |
#include "../node/Bond.hpp" | |
#include "../node/Peer.hpp" | |
+#include "../node/Topology.hpp" | |
+#include "../node/Switch.hpp" | |
#include "../osdep/Phy.hpp" | |
#include "../osdep/OSUtils.hpp" | |
@@ -1416,6 +1418,85 @@ public: | |
} else scode = 404; | |
_node->freeQueryResult((void *)pl); | |
} else scode = 500; | |
+ } else if (ps[0] == "dowhois") { | |
+ char tmp[2048]; | |
+ memset(tmp, 0x00, sizeof(tmp)); | |
+ if (ps.size() == 2) { | |
+ uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); | |
+ Address targetaddress = Address(wantp); | |
+ | |
+ RuntimeEnvironment * RR = _node->getRuntime(); | |
+ | |
+ targetaddress.toString(tmp); | |
+ RR->sw->requestWhois(0x0,OSUtils::now(),targetaddress); | |
+ | |
+ snprintf(tmp, sizeof(tmp), "WHOIS sent"); | |
+ } | |
+ else { | |
+ OSUtils::ztsnprintf(tmp,sizeof(tmp),"Please supply address to WHOIS"); | |
+ | |
+ } | |
+ | |
+ res["res"] = tmp; | |
+ scode = 501; | |
+ } else if (ps[0] == "domembershiperror") { | |
+ char tmp[2048]; | |
+ memset(tmp, 0x00, sizeof(tmp)); | |
+ if (ps.size() == 3) { | |
+ uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); | |
+ uint64_t network = Utils::hexStrToU64(ps[2].c_str()); | |
+ Address targetaddress = Address(wantp); | |
+ uint64_t pid = 0x43210; // garbage pid | |
+ | |
+ RuntimeEnvironment * RR = _node->getRuntime(); | |
+ | |
+ Packet outp(targetaddress,RR->identity.address(),Packet::VERB_ERROR); | |
+ outp.append((uint8_t)Packet::VERB_HELLO); | |
+ outp.append((uint64_t)pid); | |
+ outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); | |
+ outp.append(network); | |
+ RR->sw->send(0x0, outp, true); | |
+ snprintf(tmp, sizeof(tmp), "Error sent to 0x%lx for network 0x%lx", wantp, network); | |
+ } | |
+ else { | |
+ OSUtils::ztsnprintf(tmp,sizeof(tmp),"Please supply peer and network address to send ERRORs to"); | |
+ } | |
+ | |
+ res["res"] = tmp; | |
+ scode = 501; | |
+ } else if (ps[0] == "doframe") { | |
+ char tmp[2048]; | |
+ memset(tmp, 0x00, sizeof(tmp)); | |
+ if (ps.size() == 3) { | |
+ /*unsigned char arp[] = { | |
+ 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x52, 0x54, 0x00, 0xc1, | |
+ 0xc1, 0x88, 0xc0, 0xa8, 0x7a, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
+ 0xc0, 0xa8, 0x7a, 0x01 | |
+ }; | |
+ unsigned int arp_len = 28;*/ | |
+ unsigned char arp[] = { 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42}; | |
+ unsigned int arp_len = 8; | |
+ | |
+ uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); | |
+ uint64_t network = Utils::hexStrToU64(ps[2].c_str()); | |
+ Address targetaddress = Address(wantp); | |
+ | |
+ RuntimeEnvironment * RR = _node->getRuntime(); | |
+ | |
+ Packet outp(targetaddress,RR->identity.address(),Packet::VERB_FRAME); | |
+ outp.append(network); | |
+ outp.append((uint16_t)ZT_ETHERTYPE_ARP); | |
+ outp.append(arp,arp_len); | |
+ | |
+ RR->sw->send(0x0, outp, true); | |
+ snprintf(tmp, sizeof(tmp), "Frame sent"); | |
+ } | |
+ else { | |
+ OSUtils::ztsnprintf(tmp,sizeof(tmp),"Please supply peer and network address for doframe"); | |
+ } | |
+ | |
+ res["res"] = tmp; | |
+ scode = 501; | |
} else if (ps[0] == "bonds") { | |
ZT_PeerList *pl = _node->peers(); | |
if (pl) { | |
@@ -1555,6 +1636,30 @@ public: | |
} else scode = 500; | |
} else scode = 404; | |
+ } else if (ps[0] == "sendcom") { | |
+ char tmp[2048]; | |
+ memset(tmp, 0x00, sizeof(tmp)); | |
+ if (ps.size() == 3) { | |
+ uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); | |
+ Address targetaddress = Address(wantp); | |
+ | |
+ CertificateOfMembership com; | |
+ com.fromString(body.c_str()); | |
+ RuntimeEnvironment * RR = _node->getRuntime(); | |
+ | |
+ Packet outp(targetaddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); | |
+ com.serialize(outp); | |
+ outp.append((uint8_t)0x00); | |
+ RR->sw->send(0x0, outp, true); | |
+ | |
+ snprintf(tmp, sizeof(tmp), "COM sent"); | |
+ } | |
+ else { | |
+ OSUtils::ztsnprintf(tmp,sizeof(tmp),"Please supply target peer address and COM string in the POST body."); | |
+ } | |
+ | |
+ res["res"] = tmp; | |
+ scode = 501; | |
} else { | |
if (_controller) | |
scode = _controller->handleControlPlaneHttpPOST(std::vector<std::string>(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment