/// <param name="waitNhaFromNeighborNullable">is used to verify NPACK.NeighborHMAC</param>
        internal async Task <NeighborPeerAckPacket> OptionallySendUdpRequestAsync_Retransmit_WaitForNeighborPeerAck(string completionActionVisibleId, byte[] requestPacketDataNullable, IPEndPoint responderEndpoint,
                                                                                                                    RequestP2pSequenceNumber16 reqP2pSeq16, ConnectionToNeighbor waitNhaFromNeighborNullable = null, Action <BinaryWriter> npaRequestFieldsForNeighborHmacNullable = null)
        {
            var npaScanner = NeighborPeerAckPacket.GetScanner(reqP2pSeq16, waitNhaFromNeighborNullable, npaRequestFieldsForNeighborHmacNullable);

            if (WriteToLog_udp_deepDetail_enabled)
            {
                WriteToLog_udp_deepDetail($"waiting for NPACK, scanner: {MiscProcedures.ByteArrayToString(npaScanner.ResponseFirstBytes)} npaSeq={reqP2pSeq16}");
            }
            var nextHopResponsePacketData = await SendUdpRequestAsync_Retransmit(
                new PendingLowLevelUdpRequest(completionActionVisibleId, responderEndpoint,
                                              npaScanner,
                                              DateTimeNowUtc, Configuration.UdpLowLevelRequests_ExpirationTimeoutS,
                                              requestPacketDataNullable,
                                              Configuration.UdpLowLevelRequests_InitialRetransmissionTimeoutS, Configuration.UdpLowLevelRequests_RetransmissionTimeoutIncrement
                                              ));

            if (nextHopResponsePacketData == null)
            {
                string desc = "no NPACK response to DRP request '";
                if (requestPacketDataNullable != null)
                {
                    desc += (PacketTypes)requestPacketDataNullable[0];
                }
                desc += $"' - timeout expired ({Configuration.UdpLowLevelRequests_ExpirationTimeoutS}s) completionAction={completionActionVisibleId}";
                if (waitNhaFromNeighborNullable != null)
                {
                    desc += $", neighbor={waitNhaFromNeighborNullable}";
                }
                throw new DrpTimeoutException(desc);
            }

            var nextHopResponsePacket = new NeighborPeerAckPacket(nextHopResponsePacketData);

            if (nextHopResponsePacket.ResponseCode != ResponseOrFailureCode.accepted)
            {
                if (WriteToLog_udp_deepDetail_enabled)
                {
                    WriteToLog_udp_deepDetail($"got NPACK with {nextHopResponsePacket.ResponseCode} throwing exception");
                }
                throw new RequestRejectedException(nextHopResponsePacket.ResponseCode);
            }
            return(nextHopResponsePacket);
        }
        /// <summary>
        /// is executed by engine thread
        /// </summary>
        /// <returns>
        /// true if the response is linked to request, and the packet is processed
        /// </returns>
        bool PendingUdpRequests_ProcessPacket(IPEndPoint responderEndpoint, byte[] udpData, DateTime receivedAtUtc)
        {
            using var tracker = CreateTracker("PendingUdpRequests_ProcessPacket");
            tracker.Details   = $"count={_pendingLowLevelUdpRequests.Count}";

            // todo optimize this by storing pending requests indexed
            for (var item = _pendingLowLevelUdpRequests.First; item != null; item = item.Next)
            {
                var request = item.Value;

                if (WriteToLog_udp_deepDetail_enabled)
                {
                    WriteToLog_udp_deepDetail($"matching to pending request... responderEndpoint={responderEndpoint}, " +
                                              $"udpData={MiscProcedures.ByteArrayToString(udpData)} ({(PacketTypes)udpData[0]}) " +
                                              $"hash={MiscProcedures.GetArrayHashCodeString(udpData)}, " +
                                              $"request={request}"
                                              // + $" ResponseScanner.ResponseFirstBytes={MiscProcedures.ByteArrayToString(request.ResponseScanner.ResponseFirstBytes)}"
                                              );
                }

                try
                {
                    if (request.ResponderEndpoint.Equals(responderEndpoint) && request.ResponseScanner.Scan(this, udpData))
                    {
                        tracker.Details += $"; completed {request.CompletionActionVisibleId}";
                        _pendingLowLevelUdpRequests.Remove(item);
                        request.ResponseReceivedAtUtc = receivedAtUtc;
                        tracker.Dispose();
                        using (var tr2 = CreateTracker(request.CompletionActionVisibleId))
                            request.TaskCompletionSource.SetResult(udpData);
                        return(true);
                    }
                }
                catch (Exception exc)
                {
                    HandleExceptionInEngineThread(exc);
                }
            }

            //  WriteToLog_udp_detail($"match to pending request was not found for packet from {responderEndpoint}, udpData={MiscProcedures.ByteArrayToString(udpData)}");

            return(false);
        }
Beispiel #3
0
 public override string ToString() => MiscProcedures.ByteArrayToString(Ed25519publicKey);
Beispiel #4
0
 public override string ToString() => MiscProcedures.ByteArrayToString(hmacSha256);
Beispiel #5
0
        void IDrpRegisteredPeerApp.OnReceivedInvite(RegistrationId remoteRegistrationId, byte[] contactInvitationToken, out UserId remoteUserIdNullable, out UserCertificate localUserCertificateWithPrivateKey, out bool autoReply)
        {
            remoteUserIdNullable = null;

            var contact = GetUnconfirmedContactByToken(contactInvitationToken);

            if (contact == null)
            {
                _userAppEngine.WriteToLog_needsAtttention($"unconfirmed contact was not found by contactInvitationToken={MiscProcedures.ByteArrayToString(contactInvitationToken)}");
                autoReply = false;
                localUserCertificateWithPrivateKey = null;
            }
            else
            {
                _userAppEngine.WriteToLog_higherLevelDetail($"unconfirmed contact '{contact.UserAliasID}' was found by contactInvitationToken={MiscProcedures.ByteArrayToString(contactInvitationToken)}");
                autoReply = true;
                localUserCertificateWithPrivateKey = User.LocalUserCertificate;
                localUserCertificateWithPrivateKey.AssertHasPrivateKey();
                localUserCertificateWithPrivateKey.AssertIsValidNow(_userAppEngine.Engine.CryptoLibrary, User.UserID, _userAppEngine.Engine.DateTimeNowUtc);
            }
        }
Beispiel #6
0
        const ushort Magic16_ipv4_requesterToResponder = 0xBFA4; // is used to validate decrypted data

        //   IAuthenticatedEncryptor Encryptor;
        //   IAuthenticatedDecryptor Decryptor;

        /// <summary>
        /// initializes SharedAuthKeyForHMAC
        /// </summary>
        public void InitializeP2pStream(RegisterRequestPacket req, RegisterAck1Packet ack1, RegisterAck2Packet ack2)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(ToString());
            }

            _req  = req;
            _ack1 = ack1;
            _ack2 = ack2;

            var ms = new MemoryStream();

            using (var writer = new BinaryWriter(ms))
            {
                req.GetSharedSignedFields(writer, true);
                ack1.GetSharedSignedFields(writer, true, true);
                ack2.GetSharedSignedFields(writer, false, true);
                //  var iv = cryptoLibrary.GetHashSHA256(ms.ToArray()); // todo use for p2p  encryption

                ms.Write(SharedDhSecret, 0, SharedDhSecret.Length);

                SharedAuthKeyForNeighborHMAC = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp

                if (_engine.WriteToLog_p2p_detail_enabled)
                {
                    _engine.WriteToLog_p2p_detail2(this, $"initialized P2P stream: SharedAuthKeyForHMAC={MiscProcedures.ByteArrayToString(SharedAuthKeyForNeighborHMAC)}", req);
                }
                //Encryptor = cryptoLibrary.CreateAesEncyptor(iv, aesKey);
                //Decryptor = cryptoLibrary.CreateAesDecyptor(iv, aesKey);
            }
        }
 public override string ToString() => $"{RequesterEndpoint}-{MiscProcedures.ByteArrayToString(RequestData)}";
 public override string ToString() => $"key={RequestKey}: {MiscProcedures.ByteArrayToString(ResponseUdpPayloadData)}";
        public Func <byte[], bool> OptionalFilter;             // verifies NPACK.NeighborHMAC, ignores invalid HMACs // returns false to ignore the processed response packet

        public bool Scan(DrpPeerEngine engine, byte[] udpData) // may throw parser exception
        {
            if (!MiscProcedures.EqualByteArrayHeader(ResponseFirstBytes, udpData, IgnoredByteAtOffset1))
            {
                if (engine.WriteToLog_udp_deepDetail_enabled)
                {
                    engine.WriteToLog_udp_deepDetail($"packet does not match to ResponseFirstBytes={MiscProcedures.ByteArrayToString(ResponseFirstBytes)} ({(PacketTypes)ResponseFirstBytes[0]}) udpData={MiscProcedures.ByteArrayToString(udpData)} ({(PacketTypes)udpData[0]})"
                                                     );
                }
                return(false);
            }
            if (OptionalFilter != null)
            {
                if (!OptionalFilter(udpData))
                {
                    //if (engine.WriteToLog_udp_deepDetail_enabled)
                    engine.WriteToLog_udp_lightPain($"packet did not pass OptionalFilter");
                    return(false);
                }
            }
            return(true);
        }