コード例 #1
0
ファイル: TransportProtocol.cs プロジェクト: hst-bridge/BBS
        /// <summary>
        /// Send a message to the remote side of the connection.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="returnPayload">Return the unecrypted payload of this packet.</param>
        public byte[]  SendMessage(SSHPacket packet, bool returnPayload)
        {
            byte[] payload = null;

            lock (this)
            {
                if (currentState == TransportProtocolState.PERFORMING_KEYEXCHANGE &&
                    !IsTransportMessage(packet.MessageID))
                {
                    lock (kexqueue)
                    {
                        kexqueue.Add(packet);
                        return(payload);
                    }
                }


                try
                {
                    int padding = 4;

                    // Compress the payload if necersary

                    /*if (outgoingCompression != null)
                     * {
                     *      msgdata = outgoingCompression.compress(msgdata, 0, msgdata.Length);
                     * }*/

                    // Determine the padding length
                    padding += ((outgoingCipherLength - ((packet.Length + padding) % outgoingCipherLength)) % outgoingCipherLength);

                    packet.MoveToPosition(0);
                    // Write the packet length field
                    packet.WriteUINT32(packet.Length - 4 + padding);
                    // Write the padding length
                    packet.WriteByte((byte)padding);

                    // Now skip back up to the end of the packet
                    packet.MoveToEnd();

                    if (returnPayload)
                    {
                        payload = packet.Payload;
                    }

                    // Create some random data for the padding
                    byte[] pad = new byte[padding];
                    rnd.GetBytes(pad);
                    packet.WriteBytes(pad);


                    // Generate the MAC
                    if (outgoingMac != null)
                    {
                        outgoingMac.Generate(outgoingSequence, packet.Array, 0, packet.Length, packet.Array, packet.Length);
                    }

                    // Perfrom encrpytion
                    if (encryption != null)
                    {
                        encryption.Transform(packet.Array, 0, packet.Array, 0, packet.Length);
                    }

                    packet.Skip(outgoingMacLength);
                    outgoingBytes += packet.Length;

                    // Send!
                    packet.WriteToStream(transport.GetStream());

                    outgoingSequence++;
                    numOutgoingBytesSinceKEX += (uint)packet.Length;
                    numOutgoingSSHPacketsSinceKEX++;

                    ReleaseSSHPacket(packet);

                    if (outgoingSequence > 4294967295)
                    {
                        outgoingSequence = 0;
                    }

                    if (numOutgoingBytesSinceKEX >= MAX_NUM_BYTES_BEFORE_REKEY ||
                        numOutgoingSSHPacketsSinceKEX >= MAX_NUM_PACKETS_BEFORE_REKEY)
                    {
                        SendKeyExchangeInit();
                    }
                }
                catch (System.IO.IOException ex)
                {
                    InternalDisconnect();

                    throw new SSHException("Unexpected termination: " + ex.Message, SSHException.UNEXPECTED_TERMINATION);
                }
                catch (System.ObjectDisposedException ex)
                {
                    InternalDisconnect();

                    throw new SSHException("Unexpected terminaton: " + ex.Message,
                                           SSHException.UNEXPECTED_TERMINATION);
                }
            }

            return(payload);
        }