SECURITY_TOKEN CNetServer::GetToken(const NETADDR &Addr) { md5_state_t md5; md5_byte_t digest[16]; SECURITY_TOKEN SecurityToken; md5_init(&md5); md5_append(&md5, (unsigned char*)m_SecurityTokenSeed, sizeof(m_SecurityTokenSeed)); md5_append(&md5, (unsigned char*)&Addr, sizeof(Addr)); md5_finish(&md5, digest); SecurityToken = ToSecurityToken(digest); if (SecurityToken == NET_SECURITY_TOKEN_UNKNOWN || SecurityToken == NET_SECURITY_TOKEN_UNSUPPORTED) SecurityToken = 1; return SecurityToken; }
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken) { if (State() != NET_CONNSTATE_OFFLINE && m_SecurityToken != NET_SECURITY_TOKEN_UNKNOWN && m_SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED) { // supposed to have a valid token in this packet, check it if (pPacket->m_DataSize < (int)sizeof(m_SecurityToken)) return 0; pPacket->m_DataSize -= sizeof(m_SecurityToken); if (m_SecurityToken != ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize])) { if(g_Config.m_Debug) dbg_msg("security", "token mismatch, expected %d got %d", m_SecurityToken, ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize])); return 0; } } int64 Now = time_get(); // check if resend is requested if(pPacket->m_Flags&NET_PACKETFLAG_RESEND) Resend(); // if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL) { int CtrlMsg = pPacket->m_aChunkData[0]; if(CtrlMsg == NET_CTRLMSG_CLOSE) { if(net_addr_comp(&m_PeerAddr, pAddr) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; char Str[128] = {0}; if(pPacket->m_DataSize > 1) { // make sure to sanitize the error string form the other party if(pPacket->m_DataSize < 128) str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize); else str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str)); str_sanitize_strong(Str); } if(!m_BlockCloseMsg) { // set the error string SetError(Str); } if(g_Config.m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; } else { if(State() == NET_CONNSTATE_OFFLINE) { if(CtrlMsg == NET_CTRLMSG_CONNECT) { NETADDR nAddr; mem_copy(&nAddr, pAddr, sizeof(nAddr)); nAddr.port = 0; m_PeerAddr.port = 0; #ifndef FUZZING if(net_addr_comp(&m_PeerAddr, &nAddr) == 0 && time_get() - m_LastUpdateTime < time_freq() * 3) return 0; #endif // send response and init connection Reset(); m_State = NET_CONNSTATE_PENDING; m_PeerAddr = *pAddr; mem_zero(m_ErrorString, sizeof(m_ErrorString)); m_LastSendTime = Now; m_LastRecvTime = Now; m_LastUpdateTime = Now; if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC))) { m_SecurityToken = SecurityToken; if(g_Config.m_Debug) dbg_msg("security", "generated token %d", m_SecurityToken); } else { if(g_Config.m_Debug) dbg_msg("security", "token not supported by client (packet size %d)", pPacket->m_DataSize); m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED; } SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)); if(g_Config.m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } else if(State() == NET_CONNSTATE_CONNECT) { // connection made if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT) { if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC))) { m_SecurityToken = ToSecurityToken(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]); if(g_Config.m_Debug) dbg_msg("security", "got token %d", m_SecurityToken); } else { m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED; if(g_Config.m_Debug) dbg_msg("security", "token not supported by server"); } m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } } } else { if(State() == NET_CONNSTATE_PENDING) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "connecting online"); } } if(State() == NET_CONNSTATE_ONLINE) { m_LastRecvTime = Now; AckChunks(pPacket->m_Ack); } return 1; }