示例#1
0
 private void WriteCreditStruct(SafeMemFile memfile, CreditStruct creditStruct)
 {
     memfile.WriteUInt32(creditStruct.nUploadedLo);      // uploaded TO him
     memfile.WriteUInt32(creditStruct.nDownloadedLo);    // downloaded from him
     memfile.WriteUInt32(creditStruct.nLastSeen);
     memfile.WriteUInt32(creditStruct.nUploadedHi);      // upload high 32
     memfile.WriteUInt32(creditStruct.nDownloadedHi);    // download high 32
     memfile.WriteUInt16(creditStruct.nReserved3);
     memfile.WriteUInt8(creditStruct.nKeySize);
     memfile.Write(creditStruct.abySecureIdent);
 }
示例#2
0
        public void KeepConnectionAlive()
        {
            uint dwServerKeepAliveTimeout = MuleApplication.Instance.Preference.ServerKeepAliveTimeout;

            if (dwServerKeepAliveTimeout > 0 &&
                IsConnected &&
                connectedSocket_ != null &&
                connectedSocket_.ConnectionState == ConnectionStateEnum.CS_CONNECTED &&
                MpdUtilities.GetTickCount() - connectedSocket_.LastTransmission >= dwServerKeepAliveTimeout)
            {
                // "Ping" the server if the TCP connection was not used for the specified interval with
                // an empty publish files packet . recommended by lugdunummaster himself!
                SafeMemFile files = MpdObjectManager.CreateSafeMemFile(4);
                files.WriteUInt32(0); // nr. of files
                Packet packet = MuleApplication.Instance.NetworkObjectManager.CreatePacket(files);
                packet.OperationCode = OperationCodeEnum.OP_OFFERFILES;
                MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                connectedSocket_.SendPacket(packet, true);
            }
        }
示例#3
0
        protected void SaveList()
        {
            lastSaved_ = MpdUtilities.GetTickCount();

            string name =
                System.IO.Path.Combine(MuleApplication.Instance.Preference.GetMuleDirectory(Mule.Preference.DefaultDirectoryEnum.EMULE_CONFIGDIR),
                                       CLIENTS_MET_FILENAME);

            try
            {
                using (FileStream file = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    int         count   = clients_.Count;
                    SafeMemFile memfile =
                        MpdObjectManager.CreateSafeMemFile(count * (16 + 5 * 4 + 1 * 2 + 1 + CreditStruct.MAXPUBKEYSIZE));

                    memfile.WriteUInt8((byte)VersionsEnum.CREDITFILE_VERSION);
                    Dictionary <MapCKey, ClientCredits> .Enumerator pos = clients_.GetEnumerator();
                    count = 0;
                    while (pos.MoveNext())
                    {
                        ClientCredits cur_credit = pos.Current.Value;
                        if (cur_credit.GetUploadedTotal() != 0 || cur_credit.GetDownloadedTotal() != 0)
                        {
                            WriteCreditStruct(memfile, cur_credit.DataStruct);
                            count++;
                        }
                    }

                    memfile.WriteUInt32((uint)count);
                    file.Write(memfile.Buffer, 0, (int)memfile.Length);
                    file.Flush();
                    file.Close();
                    memfile.Close();
                }
            }
            catch (Exception error)
            {
                MpdUtilities.DebugLogError(error);
            }
        }
示例#4
0
        public void ConnectionEstablished(Mule.Network.ServerSocket sender)
        {
            if (!IsConnecting)
            {
                // we are already IsConnected to another server
                DestroySocket(sender);
                return;
            }

            InitLocalIP();
            if (sender.ConnectionState == ConnectionStateEnum.CS_WAITFORLOGIN)
            {
                ED2KServer pServer =
                    MuleApplication.Instance.ServerList.GetServerByAddress(sender.CurrentServer.Address,
                                                                           sender.CurrentServer.Port);
                if (pServer != null)
                {
                    pServer.ResetFailedCount();
                }

                // Send login packet
                SafeMemFile data = MpdObjectManager.CreateSafeMemFile(256);
                data.WriteHash16(MuleApplication.Instance.Preference.UserHash);
                data.WriteUInt32(ClientID);
                data.WriteUInt16(MuleApplication.Instance.Preference.Port);

                uint tagcount = 4;
                data.WriteUInt32(tagcount);

                Tag tagName = MpdObjectManager.CreateTag(TagTypeEnum.CT_NAME,
                                                         MuleApplication.Instance.Preference.UserNick);
                tagName.WriteTagToFile(data);

                Tag tagVersion = MpdObjectManager.CreateTag(TagTypeEnum.CT_VERSION, VersionsEnum.EDONKEYVERSION);
                tagVersion.WriteTagToFile(data);

                ServerFlagsEnum dwCryptFlags = 0;
                if (MuleApplication.Instance.Preference.IsClientCryptLayerSupported)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_SUPPORTCRYPT;
                }
                if (MuleApplication.Instance.Preference.IsClientCryptLayerRequested)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_REQUESTCRYPT;
                }
                if (MuleApplication.Instance.Preference.IsClientCryptLayerRequired)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_REQUIRECRYPT;
                }

                Tag tagFlags = MpdObjectManager.CreateTag(TagTypeEnum.CT_SERVER_FLAGS,
                                                          ServerFlagsEnum.SRVCAP_ZLIB | ServerFlagsEnum.SRVCAP_NEWTAGS |
                                                          ServerFlagsEnum.SRVCAP_LARGEFILES |
                                                          ServerFlagsEnum.SRVCAP_UNICODE | dwCryptFlags);

                tagFlags.WriteTagToFile(data);

                // eMule Version (14-Mar-2004: requested by lugdunummaster (need for LowID clients which have no chance
                // to send an Hello packet to the server during the callback test))
                Tag tagMuleVersion = MpdObjectManager.CreateTag(TagTypeEnum.CT_EMULE_VERSION,
                                                                (MuleApplication.Instance.Version.Major << 17) |
                                                                (MuleApplication.Instance.Version.Minor << 10) |
                                                                (MuleApplication.Instance.Version.Build << 7));
                tagMuleVersion.WriteTagToFile(data);

                Packet packet = MuleApplication.Instance.NetworkObjectManager.CreatePacket(data);
                packet.OperationCode = OperationCodeEnum.OP_LOGINREQUEST;
                MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                SendPacket(packet, true, sender);
            }
            else if (sender.ConnectionState == ConnectionStateEnum.CS_CONNECTED)
            {
                MuleApplication.Instance.Statistics.Reconnects++;
                MuleApplication.Instance.Statistics.ServerConnectTime = MpdUtilities.GetTickCount();
                IsConnected      = true;
                connectedSocket_ = sender;
                StopConnectionTry();
                MuleApplication.Instance.SharedFiles.ClearED2KPublishInfo();
                MuleApplication.Instance.SharedFiles.SendListToServer();

                if (MuleApplication.Instance.Preference.DoesAddServersFromServer)
                {
                    Packet packet =
                        MuleApplication.Instance.NetworkObjectManager.CreatePacket(
                            OperationCodeEnum.OP_GETSERVERLIST, 0);
                    MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                    SendPacket(packet, true);
                }
            }
        }
示例#5
0
        private void StartNegotiation(bool bOutgoing)
        {
            if (!bOutgoing)
            {
                negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_RANDOMPART;
                streamCryptState_   = StreamCryptStateEnum.ECS_NEGOTIATING;
                receiveBytesWanted_ = 4;
            }
            else if (streamCryptState_ == StreamCryptStateEnum.ECS_PENDING)
            {
                SafeMemFile fileRequest = MpdObjectManager.CreateSafeMemFile(29);
                byte        bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker();
                fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker);
                fileRequest.WriteUInt32(randomKeyPart_);
                fileRequest.WriteUInt32(MuleConstants.MAGICVALUE_SYNC);
                byte bySupportedEncryptionMethod = Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION); // we do not support any further encryption in this version
                fileRequest.WriteUInt8(bySupportedEncryptionMethod);
                fileRequest.WriteUInt8(bySupportedEncryptionMethod);                                      // so we also prefer this one
                byte byPadding = Convert.ToByte(MpdUtilities.GetRandomUInt8() %
                                                (MuleApplication.Instance.Preference.CryptTCPPaddingLength + 1));
                fileRequest.WriteUInt8(byPadding);
                for (int i = 0; i < byPadding; i++)
                {
                    fileRequest.WriteUInt8(MpdUtilities.GetRandomUInt8());
                }

                negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTB_MAGICVALUE;
                streamCryptState_   = StreamCryptStateEnum.ECS_NEGOTIATING;
                receiveBytesWanted_ = 4;

                SendNegotiatingData(fileRequest.Buffer, (uint)fileRequest.Length, 5);
            }
            else if (streamCryptState_ == StreamCryptStateEnum.ECS_PENDING_SERVER)
            {
                SafeMemFile fileRequest = MpdObjectManager.CreateSafeMemFile(113);
                byte        bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker();
                fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker);

                cryptDHA_.genRandomBits((int)MuleConstants.DHAGREEMENT_A_BITS, new Random()); // our random a
                BigInteger cryptDHPrime =
                    new BigInteger(dh768_p_, (int)MuleConstants.PRIMESIZE_BYTES);             // our fixed prime
                // calculate g^a % p
                BigInteger cryptDHGexpAmodP =
                    new BigInteger(2).modPow(cryptDHA_, cryptDHPrime);

                // put the result into a buffer
                byte[] aBuffer = new byte[MuleConstants.PRIMESIZE_BYTES];
                Array.Copy(cryptDHGexpAmodP.getBytes(), aBuffer, MuleConstants.PRIMESIZE_BYTES);

                fileRequest.Write(aBuffer);
                byte byPadding = (byte)(MpdUtilities.GetRandomUInt8() % 16); // add random padding
                fileRequest.WriteUInt8(byPadding);
                for (int i = 0; i < byPadding; i++)
                {
                    fileRequest.WriteUInt8(MpdUtilities.GetRandomUInt8());
                }

                negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_DHANSWER;
                streamCryptState_   = StreamCryptStateEnum.ECS_NEGOTIATING;
                receiveBytesWanted_ = 96;

                SendNegotiatingData(fileRequest.Buffer, (uint)fileRequest.Length, (uint)fileRequest.Length);
            }
            else
            {
                Debug.Assert(false);
                streamCryptState_ = StreamCryptStateEnum.ECS_NONE;
                return;
            }
        }
示例#6
0
        private int Negotiate(byte[] pBuffer, int offset, int nLen)
        {
            int nRead = 0;

            Debug.Assert(receiveBytesWanted_ > 0);
            try
            {
                while (negotiatingState_ != NegotiatingStateEnum.ONS_COMPLETE && receiveBytesWanted_ > 0)
                {
                    if (receiveBytesWanted_ > 512)
                    {
                        Debug.Assert(false);
                        return(0);
                    }

                    if (fiReceiveBuffer_ == null)
                    {
                        byte[] pReceiveBuffer = new byte[512]; // use a fixed size buffer
                        fiReceiveBuffer_ = MpdObjectManager.CreateSafeMemFile(pReceiveBuffer);
                    }
                    int nToRead = Math.Min(Convert.ToInt32(nLen) - nRead, Convert.ToInt32(receiveBytesWanted_));
                    fiReceiveBuffer_.Write(pBuffer, nRead, nToRead);
                    nRead += nToRead;
                    receiveBytesWanted_ -= Convert.ToUInt32(nToRead);
                    if (receiveBytesWanted_ > 0)
                    {
                        return(nRead);
                    }
                    uint nCurrentBytesLen = (uint)fiReceiveBuffer_.Position;

                    if (negotiatingState_ != NegotiatingStateEnum.ONS_BASIC_CLIENTA_RANDOMPART &&
                        negotiatingState_ != NegotiatingStateEnum.ONS_BASIC_SERVER_DHANSWER)
                    { // don't have the keys yet
                        byte[] pCryptBuffer = fiReceiveBuffer_.Buffer;
                        MuleUtilities.RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, rc4ReceiveKey_);
                    }
                    fiReceiveBuffer_.SeekToBegin();

                    switch (negotiatingState_)
                    {
                    case NegotiatingStateEnum.ONS_NONE:     // would be a bug
                        Debug.Assert(false);
                        return(0);

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_RANDOMPART:
                    {
                        Debug.Assert(rc4ReceiveKey_ == null);

                        byte[] achKeyData = new byte[21];
                        MpdUtilities.Md4Cpy(achKeyData, MuleApplication.Instance.Preference.UserHash);
                        achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_REQUESTER);
                        fiReceiveBuffer_.Read(achKeyData, 17, 4);         // random key part sent from remote client

                        MD5 md5 = MD5.Create();
                        rc4ReceiveKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);
                        achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_SERVER);
                        rc4SendKey_    =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);

                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_MAGICVALUE;
                        receiveBytesWanted_ = 4;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_MAGICVALUE:
                    {
                        uint dwValue = fiReceiveBuffer_.ReadUInt32();
                        if (dwValue == MuleConstants.MAGICVALUE_SYNC)
                        {
                            // yup, the one or the other way it worked, this is an encrypted stream
                            //DEBUG_ONLY( MpdUtilities.DebugLog(("Received proper magic value, clientIP: %s"), DbgGetIPString()) );
                            // set the receiver key
                            negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_METHODTAGSPADLEN;
                            receiveBytesWanted_ = 3;
                        }
                        else
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_METHODTAGSPADLEN:
                        DbgByEncryptionSupported = fiReceiveBuffer_.ReadUInt8();
                        DbgByEncryptionRequested = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionRequested != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), DbgByEncryptionRequested);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING;
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING;
                        }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING:
                    {
                        // ignore the random bytes, send the response, set status complete
                        SafeMemFile fileResponse = MpdObjectManager.CreateSafeMemFile(26);
                        fileResponse.WriteUInt32(MuleConstants.MAGICVALUE_SYNC);
                        byte bySelectedEncryptionMethod = Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION);         // we do not support any further encryption in this version, so no need to look which the other client preferred
                        fileResponse.WriteUInt8(bySelectedEncryptionMethod);

                        IPEndPoint remoteEp = RemoteEndPoint as IPEndPoint;

                        byte byPaddingLen =
                            MuleApplication.Instance.ServerConnect.AwaitingTestFromIP(BitConverter.ToUInt32(remoteEp.Address.GetAddressBytes(), 0))
                                        ? Convert.ToByte(16) :
                            Convert.ToByte(MuleApplication.Instance.Preference.CryptTCPPaddingLength + 1);
                        byte byPadding = Convert.ToByte(MpdUtilities.GetRandomUInt8() % byPaddingLen);

                        fileResponse.WriteUInt8(byPadding);
                        for (int i = 0; i < byPadding; i++)
                        {
                            fileResponse.WriteUInt8(MpdUtilities.GetRandomUInt8());
                        }
                        SendNegotiatingData(fileResponse.Buffer, (uint)fileResponse.Length);
                        negotiatingState_ = NegotiatingStateEnum.ONS_COMPLETE;
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        //DEBUG_ONLY( MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) );
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_MAGICVALUE:
                    {
                        if (fiReceiveBuffer_.ReadUInt32() != MuleConstants.MAGICVALUE_SYNC)
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTB_METHODTAGSPADLEN;
                        receiveBytesWanted_ = 2;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_METHODTAGSPADLEN:
                    {
                        DbgByEncryptionMethodSet = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionMethodSet != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"),
                                                       DbgGetIPString(), DbgByEncryptionMethodSet);
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING;
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING;
                        }
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING:
                        // ignore the random bytes, the handshake is complete
                        negotiatingState_ = NegotiatingStateEnum.ONS_COMPLETE;
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        //DEBUG_ONLY( MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) );
                        break;

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_DHANSWER:
                    {
                        Debug.Assert(cryptDHA_ != new BigInteger(0));
                        byte[] aBuffer = new byte[MuleConstants.PRIMESIZE_BYTES + 1];
                        fiReceiveBuffer_.Read(aBuffer, 0, Convert.ToInt32(MuleConstants.PRIMESIZE_BYTES));
                        BigInteger cryptDHAnswer =
                            new BigInteger(aBuffer, (int)MuleConstants.PRIMESIZE_BYTES);
                        BigInteger cryptDHPrime =
                            new BigInteger(dh768_p_, (int)MuleConstants.PRIMESIZE_BYTES);          // our fixed prime
                        BigInteger cryptResult =
                            cryptDHAnswer.modPow(cryptDHA_, cryptDHPrime);

                        cryptDHA_ = 0;
                        Array.Clear(aBuffer, 0, aBuffer.Length);

                        // create the keys
                        Array.Copy(cryptResult.getBytes(), aBuffer, MuleConstants.PRIMESIZE_BYTES);
                        aBuffer[MuleConstants.PRIMESIZE_BYTES] = Convert.ToByte(MuleConstants.MAGICVALUE_REQUESTER);
                        MD5 md5 = MD5.Create();

                        rc4SendKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(aBuffer), 16);
                        aBuffer[MuleConstants.PRIMESIZE_BYTES] = Convert.ToByte(MuleConstants.MAGICVALUE_SERVER);
                        rc4ReceiveKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(aBuffer), 16);

                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_MAGICVALUE;
                        receiveBytesWanted_ = 4;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_MAGICVALUE:
                    {
                        uint dwValue = fiReceiveBuffer_.ReadUInt32();
                        if (dwValue == MuleConstants.MAGICVALUE_SYNC)
                        {
                            // yup, the one or the other way it worked, this is an encrypted stream
                            MpdUtilities.DebugLog(("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString());
                            // set the receiver key
                            negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_METHODTAGSPADLEN;
                            receiveBytesWanted_ = 3;
                        }
                        else
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_METHODTAGSPADLEN:
                        DbgByEncryptionSupported = fiReceiveBuffer_.ReadUInt8();
                        DbgByEncryptionRequested = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionRequested != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), DbgByEncryptionRequested);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING;
                        if (receiveBytesWanted_ > 16)
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), receiveBytesWanted_);
                        }
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING;
                        }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING:
                    {
                        // ignore the random bytes (they are decrypted already), send the response, set status complete
                        SafeMemFile fileResponse = MpdObjectManager.CreateSafeMemFile(26);
                        fileResponse.WriteUInt32(MuleConstants.MAGICVALUE_SYNC);
                        byte bySelectedEncryptionMethod =
                            Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION);         // we do not support any further encryption in this version, so no need to look which the other client preferred
                        fileResponse.WriteUInt8(bySelectedEncryptionMethod);
                        byte byPadding = (byte)(MpdUtilities.GetRandomUInt8() % 16);
                        fileResponse.WriteUInt8(byPadding);
                        for (int i = 0; i < byPadding; i++)
                        {
                            fileResponse.WriteUInt8(MpdUtilities.GetRandomUInt8());
                        }

                        negotiatingState_ = NegotiatingStateEnum.ONS_BASIC_SERVER_DELAYEDSENDING;
                        SendNegotiatingData(fileResponse.Buffer, (uint)fileResponse.Length, 0, true);         // don't actually send it right now, store it in our sendbuffer
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString());
                        break;
                    }

                    default:
                        Debug.Assert(false);
                        break;
                    }
                    fiReceiveBuffer_.SeekToBegin();
                }

                fiReceiveBuffer_ = null;
                return(nRead);
            }
            catch (Exception)
            {
                Debug.Assert(false);
                OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                fiReceiveBuffer_ = null;
                return(-1);
            }
        }