@ -134,6 +134,9 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
break ;
case Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE : {
/* Note: certificates are public so it's safe to push them to anyone
* who asks . We won ' t communicate unless we also get a certificate
* from the remote that agrees . */
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
if ( network ) {
SharedPtr < NetworkConfig > nconf ( network - > config2 ( ) ) ;
@ -170,8 +173,20 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
bool IncomingPacket : : _doHELLO ( const RuntimeEnvironment * RR )
{
/* Note: this is the only packet ever sent in the clear, and it's also
* the only packet that we authenticate via a different path . Authentication
* occurs here and is based on the validity of the identity and the
* integrity of the packet ' s MAC , but it must be done after we check
* the identity since HELLO is a mechanism for learning new identities
* in the first place . */
try {
const unsigned int protoVersion = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION ] ;
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
TRACE ( " dropped HELLO from %s(%s): protocol version too old " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
const unsigned int vMajor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION ] ;
const unsigned int vMinor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION ] ;
const unsigned int vRevision = at < uint16_t > ( ZT_PROTO_VERB_HELLO_IDX_REVISION ) ;
@ -179,6 +194,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
Identity id ;
unsigned int destAddrPtr = id . deserialize ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY ) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY ;
if ( source ( ) ! = id . address ( ) ) {
TRACE ( " dropped HELLO from %s(%s): identity not for sending address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
InetAddress destAddr ;
if ( destAddrPtr < size ( ) ) { // ZeroTier One < 1.0.3 did not include this field
@ -193,16 +212,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
}
}
if ( source ( ) ! = id . address ( ) ) {
TRACE ( " dropped HELLO from %s(%s): identity not for sending address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
TRACE ( " dropped HELLO from %s(%s): protocol version too old " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( id . address ( ) ) ) ;
if ( peer ) {
// We already have an identity with this address -- check for collisions
@ -245,12 +254,14 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
} else {
// We don't already have an identity with this address -- validate and learn it
// Check identity proof of work
if ( ! id . locallyValidate ( ) ) {
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " dropped HELLO from %s(%s): identity invalid " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
// Check packet integrity and authentication
SharedPtr < Peer > newPeer ( new Peer ( RR - > identity , id ) ) ;
if ( ! dearmor ( newPeer - > key ( ) ) ) {
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
@ -554,14 +565,17 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS ] ;
unsigned int comLen = 0 ;
bool comFailed = false ;
if ( ( flags & 0x01 ) ! = 0 ) {
CertificateOfMembership com ;
comLen = com . deserialize ( * this , ZT_PROTO_VERB_EXT_FRAME_IDX_COM ) ;
if ( com . hasRequiredFields ( ) )
network - > validateAndAddMembershipCertificate ( com ) ;
if ( com . hasRequiredFields ( ) ) {
if ( ! network - > validateAndAddMembershipCertificate ( com ) )
comFailed = true ; // technically this check is redundant to isAllowed(), but do it anyway for thoroughness
}
}
if ( ! network - > isAllowed ( peer - > address ( ) ) ) {
if ( ( comFailed ) | | ( ! network - > isAllowed ( peer - > address ( ) ) ) ) {
TRACE ( " dropped EXT_FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , network - > id ( ) ) ;
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
return true ;
@ -647,8 +661,21 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment
ptr + = com . deserialize ( * this , ptr ) ;
if ( com . hasRequiredFields ( ) ) {
SharedPtr < Network > network ( RR - > node - > network ( com . networkId ( ) ) ) ;
if ( network )
network - > validateAndAddMembershipCertificate ( com ) ;
if ( network ) {
if ( network - > validateAndAddMembershipCertificate ( com ) ) {
if ( ( network - > isAllowed ( peer - > address ( ) ) ) & & ( network - > peerNeedsOurMembershipCertificate ( peer - > address ( ) , RR - > node - > now ( ) ) ) ) {
// If peer passed our check and we haven't sent it our cert yet, respond
// and push our cert as well for instant authorization setup.
SharedPtr < NetworkConfig > nconf ( network - > config2 ( ) ) ;
if ( ( nconf ) & & ( nconf - > com ( ) ) ) {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE ) ;
nconf - > com ( ) . serialize ( outp ) ;
outp . armor ( peer - > key ( ) , true ) ;
RR - > node - > putPacket ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
}
}
}
}
}
}
@ -890,24 +917,25 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2 ;
while ( count ) { // if ptr overflows Buffer will throw
// TODO: properly handle blacklisting, support other features... see Packet.hpp.
unsigned int flags = ( * this ) [ ptr + + ] ;
/*int metric = (*this)[ptr++];*/ + + ptr ;
unsigned int extLen = at < uint16_t > ( ptr ) ; ptr + = 2 ;
ptr + = extLen ; // unused right now
unsigned int addrType = ( * this ) [ ptr + + ] ;
unsigned int addrLen = ( * this ) [ ptr + + ] ;
switch ( addrType ) {
case 4 : {
InetAddress a ( field ( ptr , 4 ) , 4 , at < uint16_t > ( ptr + 4 ) ) ;
if ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) {
if ( ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) & & ( Path : : isAddressValidForPath ( a ) ) )
peer - > attemptToContactAt ( RR , a , RR - > node - > now ( ) ) ;
}
} break ;
case 6 : {
InetAddress a ( field ( ptr , 16 ) , 16 , at < uint16_t > ( ptr + 16 ) ) ;
if ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) {
if ( ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) & & ( Path : : isAddressValidForPath ( a ) ) )
peer - > attemptToContactAt ( RR , a , RR - > node - > now ( ) ) ;
}
} break ;
}
ptr + = addrLen ;