Example #1
0
        private KeyValuePair<TransferBuffer, Packet> GetPacketToSend()
        {
            if (m_outgoing_packets.Count == 0)
            {
                throw (new Exception("[SecurityAPI::GetPacketToSend] No packets are avaliable to send."));
            }

            Packet packet = m_outgoing_packets[0];
            m_outgoing_packets.RemoveAt(0);

            if (packet.Massive)
            {
                ushort parts = 0;

                PacketWriter final = new PacketWriter();
                PacketWriter final_data = new PacketWriter();

                byte[] input_data = packet.GetBytes();
                PacketReader input_reader = new PacketReader(input_data);

                TransferBuffer workspace = new TransferBuffer(4089, 0, (int)input_data.Length);

                while (workspace.Size > 0)
                {
                    PacketWriter part_data = new PacketWriter();

                    int cur_size = workspace.Size > 4089 ? 4089 : workspace.Size; // Max buffer size is 4kb for the client

                    part_data.Write((byte)0); // Data flag

                    part_data.Write(input_data, workspace.Offset, cur_size);

                    workspace.Offset += cur_size;
                    workspace.Size -= cur_size; // Update the size

                    final_data.Write(FormatPacket(0x600D, part_data.GetBytes(), false));

                    ++parts; // Track how many parts there are
                }

                // Write the final header packet to the front of the packet
                PacketWriter final_header = new PacketWriter();
                final_header.Write((byte)1); // Header flag
                final_header.Write((short)parts);
                final_header.Write(packet.Opcode);
                final.Write(FormatPacket(0x600D, final_header.GetBytes(), false));

                // Finish the large packet of all the data
                final.Write(final_data.GetBytes());

                // Return the collated data
                byte[] raw_bytes = final.GetBytes();
                packet.Lock();
                return new KeyValuePair<TransferBuffer, Packet>(new TransferBuffer(raw_bytes, 0, raw_bytes.Length, true), packet);
            }
            else
            {
                bool encrypted = packet.Encrypted;
                if (!m_client_security)
                {
                    if (m_enc_opcodes.Contains(packet.Opcode))
                    {
                        encrypted = true;
                    }
                }
                byte[] raw_bytes = FormatPacket(packet.Opcode, packet.GetBytes(), encrypted);
                packet.Lock();
                return new KeyValuePair<TransferBuffer, Packet>(new TransferBuffer(raw_bytes, 0, raw_bytes.Length, true), packet);
            }
        }
Example #2
0
        private byte[] FormatPacket(ushort opcode, byte[] data, bool encrypted)
        {
            // Sanity check
            if (data.Length >= 0x8000)
            {
                throw (new Exception("[SecurityAPI::FormatPacket] Payload is too large!"));
            }

            ushort data_length = (ushort)data.Length;

            // Add the packet header to the start of the data
            PacketWriter writer = new PacketWriter();
            writer.Write(data_length); // packet size
            writer.Write(opcode); // packet opcode
            writer.Write((ushort)0); // packet security bytes
            writer.Write(data);
            writer.Flush();

            // Determine if we need to mark the packet size as encrypted
            if (encrypted && (m_security_flags.blowfish == 1 || (m_security_flags.security_bytes == 1 && m_security_flags.blowfish == 0)))
            {
                long seek_index = writer.BaseStream.Seek(0, SeekOrigin.Current);

                ushort packet_size = (ushort)(data_length | 0x8000);

                writer.BaseStream.Seek(0, SeekOrigin.Begin);
                writer.Write((ushort)packet_size);
                writer.Flush();

                writer.BaseStream.Seek(seek_index, SeekOrigin.Begin);
            }

            // Only need to stamp bytes if this is a clientless object
            if (m_client_security == false && m_security_flags.security_bytes == 1)
            {
                long seek_index = writer.BaseStream.Seek(0, SeekOrigin.Current);

                byte sb1 = GenerateCountByte(true);
                writer.BaseStream.Seek(4, SeekOrigin.Begin);
                writer.Write(sb1);
                writer.Flush();

                byte sb2 = GenerateCheckByte(writer.GetBytes());
                writer.BaseStream.Seek(5, SeekOrigin.Begin);
                writer.Write(sb2);
                writer.Flush();

                writer.BaseStream.Seek(seek_index, SeekOrigin.Begin);
            }

            // If the packet should be physically encrypted, return an encrypted version of it
            if (encrypted && m_security_flags.blowfish == 1)
            {
                byte[] raw_data = writer.GetBytes();
                byte[] encrypted_data = m_blowfish.Encode(raw_data, 2, raw_data.Length - 2);

                writer.BaseStream.Seek(2, SeekOrigin.Begin);

                writer.Write(encrypted_data);
                writer.Flush();
            }
            else
            {
                // Determine if we need to unmark the packet size from being encrypted but not physically encrypted
                if (encrypted && (m_security_flags.security_bytes == 1 && m_security_flags.blowfish == 0))
                {
                    long seek_index = writer.BaseStream.Seek(0, SeekOrigin.Current);

                    writer.BaseStream.Seek(0, SeekOrigin.Begin);
                    writer.Write((ushort)data_length);
                    writer.Flush();

                    writer.BaseStream.Seek(seek_index, SeekOrigin.Begin);
                }
            }

            // Return the final data
            return writer.GetBytes();
        }