Example #1
0
        /// <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);
        }
Example #2
0
        internal SSHPacket ReadMessage()
        {
            lock (kexlock)
            {
                try
                {
                    SSHPacket packet = GetSSHPacket(false);
                    packet.ReadFromStream(transport.GetStream(), incomingCipherLength);

                    // Mark the current position so we can read more data
                    packet.Mark();
                    packet.MoveToPosition(0);

                    //	  Decrypt the data if we have a valid cipher
                    if (decryption != null)
                    {
                        decryption.Transform(packet.Array, 0, packet.Array, 0, incomingCipherLength);
                    }

                    int msglen = (int)packet.ReadUINT32();
                    int padlen = packet.ReadByte();

                    int remaining = (msglen - (incomingCipherLength - 4));

                    //      Verify that the packet length is good
                    if (remaining < 0)
                    {
                        InternalDisconnect();
                        throw new SSHException("EOF whilst reading message data block", SSHException.UNEXPECTED_TERMINATION);
                    }
                    else if (remaining > packet.Limit - packet.Length)
                    {
                        InternalDisconnect();
                        throw new SSHException("Incoming packet length violates SSH protocol",
                                               SSHException.UNEXPECTED_TERMINATION);
                    }

                    //	Read, decrypt and save the remaining data
                    packet.MoveToMark();

                    packet.ReadFromStream(transport.GetStream(), remaining);

                    if (decryption != null)
                    {
                        decryption.Transform(packet.Array, incomingCipherLength, packet.Array, incomingCipherLength, remaining);
                    }

                    // Tell the packet where the payload ends
                    //packet.PayloadLength = (int)msglen - padlen - 1;

                    if (incomingMac != null)
                    {
                        packet.ReadFromStream(transport.GetStream(), incomingMacLength);

                        // Verify the mac
                        if (!incomingMac.Verify(incomingSequence, packet.Array, 0, incomingCipherLength + remaining,
                                                packet.Array, incomingCipherLength + remaining))
                        {
                            Disconnect("Corrupt Mac on input", DisconnectionReason.MAC_ERROR);
                            throw new SSHException("Corrupt Mac on input", SSHException.PROTOCOL_VIOLATION);
                        }
                    }

                    if (++incomingSequence > 4294967295)
                    {
                        incomingSequence = 0;
                    }


                    incomingBytes += incomingCipherLength + remaining + incomingMacLength;


                    // Uncompress the message payload if necersary

                    /*if (incomingCompression != null)
                     * {
                     *      return incomingCompression.uncompress(payload, 0, payload.Length);
                     * }*/

                    numIncomingBytesSinceKEX += (uint)packet.Length;
                    numIncomingSSHPacketsSinceKEX++;

                    if (numIncomingBytesSinceKEX >= MAX_NUM_BYTES_BEFORE_REKEY ||
                        numIncomingSSHPacketsSinceKEX >= MAX_NUM_PACKETS_BEFORE_REKEY)
                    {
                        SendKeyExchangeInit();
                    }

                    // Get the packet ready for reading
                    packet.MoveToPosition(6);

                    return(packet);
                }
                catch (System.ObjectDisposedException ex)
                {
                    InternalDisconnect();

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

                    throw new SSHException("Unexpected terminaton: "
                                           + (ex.Message != null? ex.Message:ex.GetType().FullName)
                                           + " sequenceNo = " + incomingSequence + " bytesIn = "
                                           + incomingBytes + " bytesOut = " + outgoingBytes,
                                           SSHException.UNEXPECTED_TERMINATION);
                }
            }
        }