示例#1
0
        /// <summary>
        /// generates new snonce0 object
        /// resets state when necessary
        /// </summary>
        public Snonce0State GenerateOrGetExistingSnonce0(uint timeSec32UTC, ICcpRemoteEndpoint clientEndpoint)
        {
            if (timeSec32UTC > _nextPeriodSwitchTimeSec32UTC || _currentPeriodStates.Count > _config.Snonce0TableMaxSize)
            { // switch tables
                _previousPeriodStates         = _currentPeriodStates;
                _currentPeriodStates          = new Dictionary <ICcpRemoteEndpoint, Snonce0State>();
                _nextPeriodSwitchTimeSec32UTC = timeSec32UTC + _config.Snonce0TablePeriodSec;
            }

            var existingSnonce0 = TryGetSnonce0(clientEndpoint);

            if (existingSnonce0 != null)
            {
                return(existingSnonce0);
            }

            var r = new Snonce0State
            {
                Snonce0 = new byte[ServerHelloPacket0.Snonce0SupportedSize]
            };

            _rnd.NextBytes(r.Snonce0);
            _currentPeriodStates.Add(clientEndpoint, r);
            return(r);
        }
示例#2
0
        void RespondToHello0(ICcpRemoteEndpoint clientEndpoint, ServerHello0Status status, byte[] cnonce0)
        {
            var response = new ServerHelloPacket0 {
                Status = status, Cnonce0 = cnonce0
            };
            var responseBytes = response.Encode();

            _ccpTransport.SendPacket(clientEndpoint, responseBytes);
        }
示例#3
0
 public Snonce0State TryGetSnonce0(ICcpRemoteEndpoint clientEndpoint)
 {
     if (_currentPeriodStates.TryGetValue(clientEndpoint, out var r))
     {
         return(r);
     }
     if (_previousPeriodStates.TryGetValue(clientEndpoint, out r))
     {
         return(r);
     }
     return(null);
 }
示例#4
0
 void ICcpTransportUser.ProcessPacket(ICcpRemoteEndpoint remoteEndpoint, byte[] data) // receiver thread(s)
 {
     lock (_packetsToProcess)
     {
         if (_packetsToProcess.Count > _config.PacketProcessingQueueMaxCount)
         {
             OnPacketProcessingQueueOverloaded();
             return;
         }
         _packetsToProcess.Enqueue(new ReceivedPacket {
             ClientEndpoint = remoteEndpoint, Data = data
         });
     }
 }
示例#5
0
        void ProcessClientHello1(ICcpRemoteEndpoint clientEndpoint, BinaryReader reader, byte[] payloadData) // packets processor thread
        {
            var snonce0 = _snonce0Table.TryGetSnonce0(clientEndpoint);

            if (snonce0 == null)
            {
                HandleBadSnonce0(clientEndpoint);
                return;
            }

            var packet = new ClientHelloPacket1(reader, payloadData);

            // check snonce0
            if (!MiscProcedures.EqualByteArrays(packet.Snonce0, snonce0.Snonce0))
            {
                HandleBadSnonce0(clientEndpoint);
                return;
            }

            ///check stateful PoW result
            var hash = _cryptoLibrary.GetHashSHA256(packet.OriginalPacketPayload);

            // calculate hash, considering entire packet data (including stateful PoW result)
            // verify hash result
            if (!StatefulPowHashIsOK(hash))
            {
                HandleBadStatefulPowPacket(clientEndpoint);
                // no response
                return;
            }

            // questionable:    hello1IPlimit table:  limit number of requests  per 1 minute from every IPv4 block: max 100? requests per 1 minute from 1 block
            //   ------------ possible attack on hello1IPlimit  table???


            var response = new ServerHelloPacket1 {
                Status = ServerHello1Status.OKready, Cnonce1 = packet.StatefulProofOfWorkResponseData
            };
            var responseBytes = response.Encode();

            _ccpTransport.SendPacket(clientEndpoint, responseBytes);
        }
示例#6
0
        void ProcessClientHello0(ICcpRemoteEndpoint clientEndpoint, BinaryReader reader, byte[] payloadData) // packets processor thread
        {
            var packet = new ClientHelloPacket0(reader, payloadData);

            if (!PassStatelessPoWfilter(clientEndpoint, packet))
            {
                return;
            }

            // create snonce0 state
            var snonce0 = _snonce0Table.GenerateOrGetExistingSnonce0(TimeSec32UTC, clientEndpoint);

            var response = new ServerHelloPacket0
            {
                Cnonce0 = packet.Cnonce0,
                Snonce0 = snonce0.Snonce0,
                Status  = ServerHello0Status.OK,
                StatefulProofOfWorkType = StatefulProofOfWorkType._2019_06
            };
            var responseBytes = response.Encode();

            _ccpTransport.SendPacket(clientEndpoint, responseBytes);
        }
示例#7
0
        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();
            }
        }
示例#8
0
 void HandleBadStatefulPowPacket(ICcpRemoteEndpoint remoteEndpoint)
 {
     //todo
 }
示例#9
0
 void HandleBadSnonce0(ICcpRemoteEndpoint remoteEndpoint)
 {//todo
 }
示例#10
0
 /// <summary>
 /// possibly but not neccessarily malformed, because it created an exception
 /// </summary>
 void HandleMalformedPacket(ICcpRemoteEndpoint remoteEndpoint)
 {
     //todo
 }
示例#11
0
        void ICcpTransport.SendPacket(ICcpRemoteEndpoint remoteEndpoint, byte[] data)
        {
            var ep = (CcpUdpRemoteEndpoint)remoteEndpoint;

            _socket.Send(data, data.Length, ep.Endpoint);
        }