bool PassStatelessPoWfilter(ICcpRemoteEndpoint clientEndpoint, ClientHelloPacket0 packet)// packets processor thread // sends responses { switch (packet.StatelessProofOfWorkType) { case StatelessProofOfWorkType._2019_06: // verify size of PoW data if (packet.StatelessProofOfWorkData.Length < 12 || packet.StatelessProofOfWorkData.Length > 64) { throw new CcpBadPacketException(); } // verify datetime ("period") // return err code if time is wrong, with correct server's UTC time uint receivedTimeSec32; unsafe { fixed(byte *statelessProofOfWorkDataPtr = packet.StatelessProofOfWorkData) { fixed(byte *addressBytesPtr = clientEndpoint.AddressBytes) { receivedTimeSec32 = *((uint *)statelessProofOfWorkDataPtr); if (addressBytesPtr[0] != statelessProofOfWorkDataPtr[4] || addressBytesPtr[1] != statelessProofOfWorkDataPtr[5] || addressBytesPtr[2] != statelessProofOfWorkDataPtr[6] || addressBytesPtr[3] != statelessProofOfWorkDataPtr[7] ) { if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorBadStatelessProofOfWork_BadSourceIp, packet.Cnonce0); } return(false); } } } } var localTimeSec32 = TimeSec32UTC; var diffSec = Math.Abs((int)unchecked (localTimeSec32 - receivedTimeSec32)); if (diffSec > _config.StatelessPoW_MaxClockDifferenceS) { // respond with error "try again with valid clock" - legitimate user has to get valid clock from some time server and synchronize itself with the server if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorBadStatelessProofOfWork_BadClock, packet.Cnonce0); } return(false); } var hash = _cryptoLibrary.GetHashSHA256(packet.OriginalPacketPayload); // calculate hash, considering entire packet data (including stateless PoW result) // verify hash result if (!StatelessPowHashIsOK(hash)) { HandleBadStatelessPowPacket(clientEndpoint); // no response return(false); } // check if hash is unique var dataIsUnique = _recentUniquePowData.TryInputData(hash, localTimeSec32); if (dataIsUnique) { return(true); } else { // respond with error "try again with unique PoW data" if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorTryAgainRightNowWithThisServer, packet.Cnonce0); } return(false); } default: throw new CcpBadPacketException(); } }
/// <summary> /// sends responses /// executed by receiver thread /// </summary> bool PassPow1filter(IPEndPoint requesterEndpoint, RegisterPow1RequestPacket packet) { // verify size of Pow1 data if (packet.ProofOfWork1.Length != 64) { if (Configuration.VisionChannel?.GetAttentionTo(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide) <= AttentionLevel.needsAttention) { Configuration.VisionChannel?.Emit(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide, AttentionLevel.needsAttention, $"pow1 filter rejected request from {requesterEndpoint}: invalid pow1 length"); } return(false); } var localTimeSec32 = Timestamp32S; var timeDifferenceSec = Math.Abs((int)unchecked (localTimeSec32 - packet.Timestamp32S)); if (timeDifferenceSec > Configuration.RegisterPow1_MaxTimeDifferenceS) { if (Configuration.VisionChannel?.GetAttentionTo(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide) <= AttentionLevel.needsAttention) { Configuration.VisionChannel?.Emit(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide, AttentionLevel.needsAttention, $"pow1 filter rejected request from {requesterEndpoint}: invalid timestamp"); } // respond with error "try again with valid clock" - legitimate user has to get valid clock from some time server and synchronize itself with the server if (Configuration.RespondToRegisterPow1Errors) { RespondToRegisterPow1withError(requesterEndpoint, RegisterPow1ResponseStatusCode.rejected_badtimestamp, packet.Pow1RequestId); } return(false); } if (!Pow1IsOK(packet, requesterEndpoint.Address.GetAddressBytes())) { if (Configuration.VisionChannel?.GetAttentionTo(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide) <= AttentionLevel.needsAttention) { Configuration.VisionChannel?.Emit(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide, AttentionLevel.needsAttention, $"pow1 filter rejected request from {requesterEndpoint}: invalid pow1"); } OnReceivedBadRegisterReqPow1(requesterEndpoint); // no response return(false); } if (_recentUniquePow1Data != null) { // check if pow1 data is unique var dataIsUnique = _recentUniquePow1Data.TryInputData(packet.ProofOfWork1, localTimeSec32); if (dataIsUnique) { return(true); } else { if (Configuration.VisionChannel?.GetAttentionTo(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide) <= AttentionLevel.needsAttention) { Configuration.VisionChannel?.Emit(Configuration.VisionChannelSourceId, VisionChannelModuleName_reg_epSide, AttentionLevel.needsAttention, $"pow1 filter rejected request from {requesterEndpoint}: pow1 data is not unique"); } // respond with error "try again with unique PoW data" if (Configuration.RespondToRegisterPow1Errors) { RespondToRegisterPow1withError(requesterEndpoint, RegisterPow1ResponseStatusCode.rejected_tryagainRightNowWithThisServer, packet.Pow1RequestId); } return(false); } } return(true); }