Beispiel #1
0
        /// <summary>
        /// Process a global message.
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        protected internal override bool ProcessGlobalMessage(SSHPacket packet)
        {
            // We need to filter for any messages that require a response from the
            // connection protocol such as channel open or global requests. These
            // are not handled anywhere else within this implementation because
            // doing so would require a thread to wait.

            try
            {
                switch (packet.MessageID)
                {
                case SSH_MSG_CHANNEL_OPEN:
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_OPEN");
#endif
                    //		  Attempt to open the channel
                    System.String type         = packet.ReadString();
                    int           remoteid     = (int)packet.ReadUINT32();
                    int           remotewindow = (int)packet.ReadUINT32();
                    int           remotepacket = (int)packet.ReadUINT32();
                    byte[]        requestdata  = packet.Available > 0 ? new byte[packet.Available] : null;
                    if (requestdata != null)
                    {
                        packet.ReadBytes(requestdata);
                    }

                    ProcessChannelOpenRequest(type, remoteid, remotewindow, remotepacket, requestdata);
                    return(true);
                }

                case SSH_MSG_GLOBAL_REQUEST:
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_GLOBAL_REQUEST");
#endif

                    // Attempt to process the global request
                    System.String requestname = packet.ReadString();
                    bool          wantreply   = packet.ReadBool();
                    byte[]        requestdata = new byte[packet.Available];
                    packet.ReadBytes(requestdata);

                    // Process the request
                    ProcessGlobalRequest(requestname, wantreply, requestdata);
                    return(true);
                }

                default:
                    return(false);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Beispiel #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);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Opens a channel
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="requestdata"></param>
        public void OpenChannel(SSH2Channel channel, byte[] requestdata)
        {
            lock (this)
            {
                try
                {
                    int channelid = AllocateChannel(channel);

                    if (channelid == -1)
                    {
                        throw new ChannelOpenException("Maximum number of channels exceeded",
                                                       ChannelOpenException.RESOURCE_SHORTAGE);
                    }

                    channel.Init(this, channelid);
                    SSHPacket packet = GetPacket();
                    packet.WriteByte(SSH_MSG_CHANNEL_OPEN);
                    packet.WriteString(channel.Name);
                    packet.WriteUINT32(channel.ChannelID);
                    packet.WriteUINT32(channel.WindowSize);
                    packet.WriteUINT32(channel.PacketSize);
                    if (requestdata != null)
                    {
                        packet.WriteBytes(requestdata);
                    }

#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_OPEN");
                    System.Diagnostics.Trace.WriteLine("Channelid=" + channel.ChannelID);
                    System.Diagnostics.Trace.WriteLine("Name=" + channel.Name);
#endif

                    transport.SendMessage(packet);

                    packet = channel.MessageStore.NextMessage(CHANNEL_OPEN_RESPONSE_MESSAGES);

#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received reply to SSH_MSG_CHANNEL_OPEN");
                    channel.LogMessage(packet);
#endif
                    if (packet.MessageID == SSH_MSG_CHANNEL_OPEN_FAILURE)
                    {
                        FreeChannel(channel);
                        int reason = (int)packet.ReadUINT32();
                        throw new ChannelOpenException(packet.ReadString(), reason);
                    }
                    else
                    {
                        int    remoteid     = (int)packet.ReadUINT32();
                        int    remotewindow = (int)packet.ReadUINT32();
                        int    remotepacket = (int)packet.ReadUINT32();
                        byte[] responsedata = new byte[packet.Available];
                        packet.ReadBytes(responsedata);

                        channel.Open(remoteid, remotewindow, remotepacket, responsedata);

                        return;
                    }
                }
                catch (System.IO.IOException ex)
                {
                    throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
                }
            }
        }