Exemple #1
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);
                }
            }
        }