Esempio n. 1
0
        /// <summary>
        /// Disconnect the SSH transport protocol.
        /// </summary>
        /// <param name="disconnectReason">A descriptive reason for the disconnection.</param>
        /// <param name="reason">The SSH reason code.</param>
        public void Disconnect(String disconnectReason, DisconnectionReason reason)
        {
            try
            {
                this.disconnectReason = disconnectReason;
                SSHPacket packet = GetSSHPacket(true);
                packet.WriteByte(SSH_MSG_DISCONNECT);
                packet.WriteUINT32((int)reason);
                packet.WriteString(disconnectReason);
                packet.WriteString("");

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_DISCONNECT");
                System.Diagnostics.Trace.WriteLine(disconnectReason);
#endif
                SendMessage(packet);
            }
            catch
            {
            }
            finally
            {
                InternalDisconnect();
            }
        }
Esempio n. 2
0
        internal void  SendChannelData(byte[] buf, int offset, int len)
        {
            try
            {
                if (state != CHANNEL_OPEN)
                {
                    throw new SSHException("The channel is closed", SSHException.CHANNEL_FAILURE);
                }

                if (len > 0)
                {
                    SSHPacket packet = connection.GetPacket();
                    packet.WriteByte((System.Byte)SSH_MSG_CHANNEL_DATA);
                    packet.WriteUINT32(remoteid);
                    packet.WriteBinaryString(buf, offset, len);

#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_DATA");
                    System.Diagnostics.Trace.WriteLine("Channelid=" + ChannelID);
#endif
                    connection.SendMessage(packet);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Esempio n. 3
0
            /// <summary>
            /// Close down the output side of the stream.
            /// </summary>
            /// <remarks>
            /// This method sends an SSH_MSG_CHANNEL_EOF message to the remote side.
            /// </remarks>
            public override void CloseOutput()
            {
                if (!channel.IsClosed && !outputEOF && !channel.closing && !channel.remoteClosed)
                {
                    SSHPacket packet = channel.connection.GetPacket();
                    packet.WriteByte(SSH_MSG_CHANNEL_EOF);
                    packet.WriteUINT32(channel.remoteid);

                    try
                    {
#if DEBUG
                        System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_EOF");
                        System.Diagnostics.Trace.WriteLine("Channelid=" + channel.ChannelID);
#endif
                        channel.connection.SendMessage(packet);
                    }
                    finally
                    {
                        outputEOF = true;
                        channel.FireEvent(channel, ChannelState.LOCAL_EOF);
                    }
                }

                outputEOF = true;
            }
Esempio n. 4
0
        internal void AdjustWindow(int increment)
        {
            try
            {
                SSHPacket packet = connection.GetPacket();
                packet.WriteByte((System.Byte)SSH_MSG_WINDOW_ADJUST);
                packet.WriteUINT32(remoteid);
                packet.WriteUINT32(increment);

                localwindow.adjust(increment);

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_WINDOW_ADJUST");
                System.Diagnostics.Trace.WriteLine("Channelid=" + ChannelID);
#endif
                connection.SendMessage(packet);
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Sends a close message to the remote side without waiting for a reply
        /// </summary>
        public override void SendAsyncClose()
        {
            bool performClose = false;

            lock (this)
            {
                if (!closing)
                {
                    performClose = closing = true;
                }
            }

            if (state == CHANNEL_OPEN && performClose)
            {
                try
                {
                    // Close the ChannelOutputStream
                    stream.Close();

                    // Send our close message
                    SSHPacket packet = connection.GetPacket();
                    packet.WriteByte((System.Byte)SSH_MSG_CHANNEL_CLOSE);
                    packet.WriteUINT32(remoteid);

                    try
                    {
#if DEBUG
                        System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_CLOSE");
                        System.Diagnostics.Trace.WriteLine("Channelid=" + ChannelID);
#endif
                        connection.SendMessage(packet);
                    }
                    catch (SSHException)
                    {
                    }
                }
                catch (System.IO.EndOfStreamException)
                {
                    // Ignore this is the message store informing of close/eof
                }
                catch (System.IO.IOException ex)
                {
                    // IO Error during close so the connection has dropped
                    connection.SignalClosingState();
                    connection.transport.Disconnect("IOException during channel close: " + ex.Message,
                                                    DisconnectionReason.CONNECTION_LOST);
                }
            }
        }
Esempio n. 6
0
        internal void  SendKeyExchangeInit()
        {
            try
            {
                FireStateChange(TransportProtocolState.PERFORMING_KEYEXCHANGE);

                numIncomingBytesSinceKEX      = 0;
                numIncomingSSHPacketsSinceKEX = 0;
                numOutgoingBytesSinceKEX      = 0;
                numOutgoingSSHPacketsSinceKEX = 0;

                currentState = TransportProtocolState.PERFORMING_KEYEXCHANGE;

                SSHPacket packet = GetSSHPacket(true);

                SSH2Context transportContext = (SSH2Context)client.Context;
                byte[]      cookie           = new byte[16];
                rnd.GetBytes(cookie);
                packet.WriteByte((byte)SSH_MSG_KEX_INIT);
                packet.WriteBytes(cookie);
                packet.WriteString("diffie-hellman-group1-sha1");
                packet.WriteString(transportContext.SupportedPublicKeys.List(transportContext.PreferredPublicKey));
                packet.WriteString(transportContext.SupportedCiphers.List(transportContext.PreferredCipherCS));
                packet.WriteString(transportContext.SupportedCiphers.List(transportContext.PreferredCipherSC));
                packet.WriteString(transportContext.SupportedMACs.List(transportContext.PreferredMacCS));
                packet.WriteString(transportContext.SupportedMACs.List(transportContext.PreferredMacSC));
                packet.WriteString("none");
                packet.WriteString("none");
                packet.WriteString("");
                packet.WriteString("");
                packet.WriteByte((byte)0);
                packet.WriteUINT32(0);

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_KEX_INIT");
#endif

                localkex = SendMessage(packet, true);
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Sends a channel request. Many channels have extensions that are specific to that particular
        /// channel type, an example of which is requesting a pseudo terminal from an interactive session.
        /// </summary>
        /// <param name="requesttype">the name of the request, for example "pty-req"</param>
        /// <param name="wantreply">specifies whether the remote side should send a success/failure message</param>
        /// <param name="requestdata">the request data</param>
        /// <returns></returns>
        public bool SendRequest(System.String requesttype, bool wantreply, byte[] requestdata)
        {
            lock (this)
            {
                try
                {
                    SSHPacket packet = connection.GetPacket();
                    packet.WriteByte((System.Byte)SSH_MSG_CHANNEL_REQUEST);
                    packet.WriteUINT32(remoteid);
                    packet.WriteString(requesttype);
                    packet.WriteBool(wantreply);
                    if (requestdata != null)
                    {
                        packet.WriteBytes(requestdata);
                    }

#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_REQUEST " + requesttype);
                    System.Diagnostics.Trace.WriteLine("Channelid=" + ChannelID);
#endif
                    connection.SendMessage(packet);

                    bool result = false;

                    if (wantreply)
                    {
                        packet = ProcessMessages(CHANNEL_REQUEST_MESSAGES);
                        return(packet.MessageID == SSH_MSG_CHANNEL_SUCCESS);
                    }

                    return(result);
                }
                catch (System.IO.IOException ex)
                {
                    throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
                }
            }
        }
Esempio n. 8
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);
        }
Esempio n. 9
0
        /// <summary>
        /// Process a channel open request.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="remoteid"></param>
        /// <param name="remotewindow"></param>
        /// <param name="remotepacket"></param>
        /// <param name="requestdata"></param>
        internal void  ProcessChannelOpenRequest(System.String type, int remoteid, int remotewindow, int remotepacket, byte[] requestdata)
        {
            try
            {
                SSHPacket packet = GetPacket();

                if (channelfactories.ContainsKey(type))
                {
                    try
                    {
                        SSH2Channel channel = ((ChannelFactory)channelfactories[type]).CreateChannel(type, requestdata);

                        // Allocate a channel
                        int localid = AllocateChannel(channel);

                        if (localid > -1)
                        {
                            try
                            {
                                channel.Init(this, localid);
                                byte[] responsedata = channel.Create();
                                packet.WriteByte(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
                                packet.WriteUINT32(remoteid);
                                packet.WriteUINT32(localid);
                                packet.WriteUINT32(channel.WindowSize);
                                packet.WriteUINT32(channel.PacketSize);
                                if (responsedata != null)
                                {
                                    packet.WriteBytes(requestdata);
                                }

#if DEBUG
                                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
                                System.Diagnostics.Trace.WriteLine("Channelid=" + localid);
                                System.Diagnostics.Trace.WriteLine("Remoteid=" + remoteid);
#endif
                                transport.SendMessage(packet);

                                channel.Open(remoteid, remotewindow, remotepacket);

                                return;
                            }
                            catch (SSHException ex)
                            {
#if DEBUG
                                System.Diagnostics.Trace.WriteLine("Exception occured whilst opening channel");
                                System.Diagnostics.Trace.WriteLine(ex.StackTrace);
#endif
                                packet.WriteByte(SSH_MSG_CHANNEL_OPEN_FAILURE);
                                packet.WriteUINT32(remoteid);
                                packet.WriteUINT32(ChannelOpenException.CONNECT_FAILED);
                                packet.WriteString(ex.Message);
                                packet.WriteString("");
                            }
                        }
                        else
                        {
#if DEBUG
                            System.Diagnostics.Trace.WriteLine("Maximum allowable open channel limit of " + MaximumNumChannels + " exceeded!");
#endif
                            packet.WriteByte(SSH_MSG_CHANNEL_OPEN_FAILURE);
                            packet.WriteUINT32(remoteid);
                            packet.WriteUINT32(ChannelOpenException.RESOURCE_SHORTAGE);
                            packet.WriteString("Maximum allowable open channel limit of " + MaximumNumChannels + " exceeded!");
                            packet.WriteString("");
                        }
                    }
                    catch (ChannelOpenException ex)
                    {
#if DEBUG
                        System.Diagnostics.Trace.WriteLine("Channel open exception occured whilst opening channel");
                        System.Diagnostics.Trace.WriteLine(ex.StackTrace);
#endif
                        packet.WriteByte(SSH_MSG_CHANNEL_OPEN_FAILURE);
                        packet.WriteUINT32(remoteid);
                        packet.WriteUINT32(ex.Reason);
                        packet.WriteString(ex.Message);
                        packet.WriteString("");
                    }
                }
                else
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine(type + " is not a supported channel type");
#endif
                    packet.WriteByte(SSH_MSG_CHANNEL_OPEN_FAILURE);
                    packet.WriteUINT32(remoteid);
                    packet.WriteUINT32(ChannelOpenException.UNKNOWN_CHANNEL_TYPE);
                    packet.WriteString(type + " is not a supported channel type!");
                    packet.WriteString("");
                }

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_OPEN_FAILURE");
                System.Diagnostics.Trace.WriteLine("Remoteid=" + remoteid);
                System.Diagnostics.Trace.WriteLine("Name=" + type);
#endif
                transport.SendMessage(packet);
            }
            catch (System.IO.IOException ex1)
            {
                throw new SSHException(ex1.Message, SSHException.INTERNAL_ERROR);
            }
        }
Esempio n. 10
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);
                }
            }
        }