Example #1
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);
            }
        }
Example #2
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();
            }
        }
Example #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;
            }
        /// <summary>
        /// Attempts an authentication using the public/private key pair.
        /// </summary>
        /// <param name="authentication"></param>
        /// <param name="serviceName"></param>
        public void Authenticate(AuthenticationProtocol authentication,
                                 String serviceName)
        {
            ByteBuffer baw = new ByteBuffer();

            baw.WriteBinaryString(authentication.SessionIdentifier);
            baw.Write(AuthenticationProtocol.SSH_MSG_USERAUTH_REQUEST);
            baw.WriteString(Username);
            baw.WriteString(serviceName);
            baw.WriteString("publickey");
            baw.WriteBool(!VerifyOnly);

            byte[] encoded;
            String algorithm;

            baw.WriteString(algorithm     = KeyPair.PublicKey.Algorithm);
            baw.WriteBinaryString(encoded = KeyPair.PublicKey.GetEncoded());

            ByteBuffer baw2 = new ByteBuffer();

            // Generate the authentication request
            baw2.WriteBool(!VerifyOnly);
            baw2.WriteString(algorithm);
            baw2.WriteBinaryString(encoded);

            if (!VerifyOnly)
            {
                byte[] signature = KeyPair.PrivateKey.Sign(baw.ToByteArray());

                // Format the signature correctly
                ByteBuffer sig = new ByteBuffer();
                sig.WriteString(algorithm);
                sig.WriteBinaryString(signature);
                baw2.WriteBinaryString(sig.ToByteArray());
            }

            authentication.SendRequest(Username,
                                       serviceName,
                                       "publickey",
                                       baw2.ToByteArray());

            SSHPacket packet = authentication.ReadMessage();

            if (packet.MessageID == SSH_MSG_USERAUTH_PK_OK)
            {
                throw new SSH2AuthenticationResult(AuthenticationResult.PUBLIC_KEY_ACCEPTABLE, "");
            }
            else
            {
                authentication.connection.transport.Disconnect("Unexpected message " + packet.MessageID + " received",
                                                               DisconnectionReason.PROTOCOL_ERROR);

                throw new SSHException("Unexpected message "
                                       + packet.MessageID
                                       + " received",
                                       SSHException.PROTOCOL_VIOLATION);
            }
        }
Example #5
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);
            }
        }
Example #6
0
        internal void  ProcessGlobalRequest(System.String requestname, bool wantreply, byte[] requestdata)
        {
#if DEBUG
            System.Diagnostics.Trace.WriteLine("Processing global request " + requestname);
#endif
            try
            {
                bool          success = false;
                GlobalRequest request = new GlobalRequest(requestname, requestdata);
                if (requesthandlers.ContainsKey(requestname))
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Found handler for request " + requestname);
#endif
                    success = ((GlobalRequestHandler)requesthandlers[requestname]).ProcessGlobalRequest(request);
                }
#if DEBUG
                else
                {
                    System.Diagnostics.Trace.WriteLine("Cannot find handler for request " + requestname);
                }
#endif
                if (wantreply)
                {
                    SSHPacket packet = GetPacket();

                    if (success)
                    {
                        packet.WriteByte(SSH_MSG_REQUEST_SUCCESS);
                        if (request.Data != null)
                        {
                            packet.WriteBytes(requestdata);
                        }

#if DEBUG
                        System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_REQUEST_SUCCESS");
#endif
                        transport.SendMessage(packet);
                    }
                    else
                    {
                        // Return a response
                        packet.WriteByte(SSH_MSG_REQUEST_FAILURE);
#if DEBUG
                        System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_REQUEST_FAILURE");
#endif

                        transport.SendMessage(packet);
                    }
                }
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Example #7
0
            public bool WantsNotification(SSHPacket msg)
            {
                switch (msg.MessageID)
                {
                case SSH_MSG_CHANNEL_CLOSE:
                    return(true);

                default:
                    return(false);
                }
            }
Example #8
0
            public bool WantsNotification(SSHPacket msg)
            {
                switch (msg.MessageID)
                {
                case SSH_MSG_REQUEST_SUCCESS:
                case SSH_MSG_REQUEST_FAILURE:
                    return(true);

                default:
                    return(false);
                }
            }
Example #9
0
            public bool WantsNotification(SSHPacket msg)
            {
                switch (msg.MessageID)
                {
                case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
                case SSH_MSG_CHANNEL_OPEN_FAILURE:
                    return(true);

                default:
                    return(false);
                }
            }
Example #10
0
        /// <summary>
        /// Attempts to authenticate the user using their password.
        /// </summary>
        /// <param name="authentication"></param>
        /// <param name="servicename"></param>
        public void Authenticate(AuthenticationProtocol authentication,
                                 String servicename)
        {
            try
            {
                if (Username == null || Password == null)
                {
                    throw new SSHException("Username or password not set!",
                                           SSHException.BAD_API_USAGE);
                }

                if (passwordChangeRequired && newpassword == null)
                {
                    throw new SSHException("You must set a new password!",
                                           SSHException.BAD_API_USAGE);
                }

                ByteBuffer buf = new ByteBuffer();
                buf.WriteBool(passwordChangeRequired);
                buf.WriteString(Password);
                if (passwordChangeRequired)
                {
                    buf.WriteString(newpassword);
                }
                authentication.SendRequest(Username,
                                           servicename,
                                           "password",
                                           buf.ToByteArray());

                // We need to read the response since we may have password change.
                SSHPacket packet = authentication.ReadMessage();

                if (packet.MessageID != SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
                {
                    authentication.transport.Disconnect(
                        "Unexpected message received",
                        DisconnectionReason.PROTOCOL_ERROR);
                    throw new SSHException(
                              "Unexpected response from Authentication Protocol",
                              SSHException.PROTOCOL_VIOLATION);
                }

                passwordChangeRequired = true;
                throw new SSH2AuthenticationResult(AuthenticationResult.FAILED, "");
            }
            catch (IOException ex)
            {
                throw new SSHException(ex.Message,
                                       SSHException.INTERNAL_ERROR);
            }
        }
Example #11
0
        /// <summary>
        /// Sends a global request.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="wantreply"></param>
        /// <returns></returns>
        public bool SendGlobalRequest(GlobalRequest request, bool wantreply)
        {
            try
            {
                SSHPacket packet = GetPacket();
                packet.WriteByte(SSH_MSG_GLOBAL_REQUEST);
                packet.WriteString(request.Name);
                packet.WriteBool(wantreply);
                if (request.Data != null)
                {
                    packet.WriteBytes(request.Data);
                }

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_GLOBAL_REQUEST");
                System.Diagnostics.Trace.WriteLine(request.Name);
#endif
                SendMessage(packet);

                if (wantreply)
                {
                    packet = GlobalMessages.NextMessage(GLOBAL_REQUEST_MESSAGES);
                    if (packet.MessageID == SSH_MSG_REQUEST_SUCCESS)
                    {
                        if (packet.Available > 1)
                        {
                            byte[] tmp = new byte[packet.Available];
                            packet.ReadBytes(tmp);
                            request.Data = tmp;
                        }
                        else
                        {
                            request.Data = null;
                        }
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(true);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Example #12
0
        /// <summary>
        /// Process a channel request
        /// </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>
        protected internal virtual void ChannelRequest(String requesttype, bool wantreply, byte[] requestdata)
        {
            if (wantreply)
            {
                SSHPacket packet = connection.GetPacket();
                packet.WriteByte(SSH_MSG_CHANNEL_FAILURE);

#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_CHANNEL_FAILURE");
                System.Diagnostics.Trace.WriteLine("Channelid=" + ChannelID);
#endif
                connection.SendMessage(packet);
            }
        }
Example #13
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);
                }
            }
        }
Example #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="serverId"></param>
        /// <param name="clientKexInit"></param>
        /// <param name="serverKexInit"></param>
        public override void PerformClientExchange(String clientId,
                                                   String serverId,
                                                   byte[] clientKexInit,
                                                   byte[] serverKexInit)
        {
            this.clientId      = clientId;
            this.serverId      = serverId;
            this.clientKexInit = clientKexInit;
            this.serverKexInit = serverKexInit;

            BigInteger q = p.subtract(BigInteger.ONE).divide(g);

            do
            {
                x = new BigInteger(p.bitLength(), new RNGCryptoServiceProvider());
            }while((x.compareTo(BigInteger.ONE) < 0) &&
                   (x.compareTo(q) > 0));

            e = g.modPow(x, p);

            if (e.compareTo(BigInteger.ONE) < 0 ||
                e.compareTo(p.subtract(BigInteger.ONE)) > 0)
            {
                throw new SSHException("Key exchange failed to generate e value", SSHException.INTERNAL_ERROR);
            }

            SSHPacket packet = transport.GetSSHPacket(true);

            packet.WriteByte(SSH_MSG_KEXDH_INIT);
            packet.WriteBigInteger(e);

            transport.SendMessage(packet);

            packet = transport.NextMessage();

            if (packet.MessageID != SSH_MSG_KEXDH_REPLY)
            {
                throw new SSHException("Expected SSH_MSG_KEXDH_REPLY but got message id "
                                       + packet.MessageID, SSHException.KEY_EXCHANGE_FAILED);
            }

            hostKey   = packet.ReadBinaryString();
            f         = packet.ReadBigInteger();
            signature = packet.ReadBinaryString();

            secret = f.modPow(x, p);

            CalculateExchangeHash();
        }
Example #15
0
        internal void StartService(String serviceName)
        {
            SSHPacket packet = GetSSHPacket(true);

            packet.WriteByte(SSH_MSG_SERVICE_REQUEST);
            packet.WriteString(serviceName);

#if DEBUG
            System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_SERVICE_REQUEST");
            System.Diagnostics.Trace.WriteLine(serviceName);
#endif
            SendMessage(packet);

            do
            {
                packet = ReadMessage();
            }while(ProcessMessage(packet) || packet.MessageID != SSH_MSG_SERVICE_ACCEPT);
        }
Example #16
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);
            }
        }
Example #17
0
        internal bool ProcessMessage(SSHPacket packet)
        {
            try
            {
                switch (packet.MessageID)
                {
                case SSH_MSG_USERAUTH_FAILURE:
                {
                    String auths = packet.ReadString();

                    throw new SSH2AuthenticationResult(
                              packet.ReadBool()
                                                        ? AuthenticationResult.FURTHER_AUTHENTICATION_REQUIRED
                                                        : AuthenticationResult.FAILED,
                              auths);
                }

                case SSH_MSG_USERAUTH_SUCCESS:
                {
                    connection.Start();
                    throw new SSH2AuthenticationResult(AuthenticationResult.COMPLETE, "");
                }

                case SSH_MSG_USERAUTH_BANNER:
                {
                    if (((SSH2Context)transport.Context).Banner != null)
                    {
                        ((SSH2Context)transport.Context).Banner.DisplayBanner(packet.ReadString());
                    }
                    return(true);
                }

                default:
                    return(false);
                }
            }
            catch (IOException ex)
            {
                throw new SSHException(ex.Message,
                                       SSHException.INTERNAL_ERROR);
            }
        }
Example #18
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);
            }
        }
Example #19
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);
                }
            }
        }
Example #20
0
            /// <summary>
            /// Write data to the SSH stream.
            /// </summary>
            /// <param name="buf">The destination byte array.</param>
            /// <param name="offset">The offset to start taking data for writing.</param>
            /// <param name="len">The number of bytes to write.</param>
            public override void Write(byte[] buf, int offset, int len)
            {
                int write;

                do
                {
                    if (outputEOF)
                    {
                        throw new SSHException("The channel is EOF", SSHException.CHANNEL_FAILURE);
                    }

                    if (channel.IsClosed)
                    {
                        throw new SSHException("The channel is closed!", SSHException.CHANNEL_FAILURE);
                    }

                    if (channel.remotewindow.available() <= 0)
                    {
                        SSHPacket packet = channel.ProcessMessages(WINDOW_ADJUST_MESSAGES);
                    }

                    write = channel.remotewindow.available() < channel.remotewindow.PacketSize
                                                          ? (channel.remotewindow.available() < len
                                                                        ? channel.remotewindow.available():len)
                                                                        : (channel.remotewindow.PacketSize < len?channel.remotewindow.PacketSize:len);

                    if (write > 0)
                    {
                        channel.SendChannelData(buf, offset, write);
                        channel.remotewindow.consume(write);
                        len    -= write;
                        offset += write;
                    }
                }while (len > 0);

                channel.FireOutputListenerEvent(buf, offset, len);
            }
Example #21
0
 /// <summary>
 /// Send an authentication request. This method will be called from the <see cref="Maverick.SSH2.SSH2AuthenticationClient.Authenticate"/>
 /// method to initiate the authentication proceedure.
 /// </summary>
 /// <param name="username"></param>
 /// <param name="servicename"></param>
 /// <param name="methodname"></param>
 /// <param name="requestdata"></param>
 public void SendRequest(String username,
                         String servicename,
                         String methodname,
                         byte[] requestdata)
 {
     try
     {
         SSHPacket packet = transport.GetSSHPacket(true);
         packet.WriteByte(SSH_MSG_USERAUTH_REQUEST);
         packet.WriteString(username);
         packet.WriteString(servicename);
         packet.WriteString(methodname);
         if (requestdata != null)
         {
             packet.WriteBytes(requestdata);
         }
         transport.SendMessage(packet);
     }
     catch (IOException ex)
     {
         throw new SSHException(ex.Message,
                                SSHException.INTERNAL_ERROR);
     }
 }
Example #22
0
        /// <summary>
        /// Processes a channel message.
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        protected internal override bool ProcessChannelMessage(SSHChannelMessage msg)
        {
            try
            {
#if DEBUG
                LogMessage(msg);
#endif
                switch (msg.MessageID)
                {
                case SSH_MSG_CHANNEL_REQUEST:
                {
                    String requesttype = msg.ReadString();
                    bool   wantreply   = msg.ReadBool();
                    byte[] requestdata = new byte[msg.Available];
                    msg.ReadBytes(requestdata);
                    ChannelRequest(requesttype, wantreply, requestdata);
                    return(true);
                }

                case SSH_MSG_CHANNEL_DATA:
                {
                    int count = (int)SSHPacket.ReadInt(msg.Payload, 5);
                    if (autoConsumeInput)
                    {
                        localwindow.consume(count);
                        if (localwindow.available() <= stream.buffer.Length / 2 && !IsClosed)
                        {
                            AdjustWindow(stream.buffer.Length - localwindow.available());
                        }
                    }

                    // Fire the input listener event
                    FireInputListenerEvent(msg.Payload, 9, count);

                    return(autoConsumeInput);
                }

                case SSH_MSG_CHANNEL_EXTENDED_DATA:
                {
                    int type  = (int)SSHPacket.ReadInt(msg.Payload, 5);
                    int count = (int)SSHPacket.ReadInt(msg.Payload, 9);


                    if (autoConsumeInput)
                    {
                        localwindow.consume(count);
                        if (localwindow.available() <= stream.buffer.Length / 2 && !IsClosed)
                        {
                            AdjustWindow(stream.buffer.Length - localwindow.available());
                        }
                    }

                    FireErrorStreamListenerEvent(type, msg.Payload, 13, count);

                    return(autoConsumeInput);
                }


                case SSH_MSG_CHANNEL_CLOSE:
                {
                    remoteClosed = true;
                    CheckCloseStatus(true);
                    return(false);
                }

                case SSH_MSG_CHANNEL_EOF:
                {
                    FireEvent(this, ChannelState.REMOTE_EOF);
                    ChannelEOF();
                    return(false);
                }

                default:
                    return(false);
                }
            }
            catch (System.IO.IOException ex)
            {
                throw new SSHException(ex.Message, SSHException.INTERNAL_ERROR);
            }
        }
Example #23
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 #24
0
 /// <summary>
 /// Send a message to the remote side of the connection.
 /// </summary>
 /// <param name="packet"></param>
 public byte[]  SendMessage(SSHPacket packet)
 {
     return(SendMessage(packet, false));
 }
Example #25
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);
                }
            }
        }
Example #26
0
 internal void ReleaseSSHPacket(SSHPacket packet)
 {
     // TODO: Add the packet back into the pool
 }
Example #27
0
        internal void PerformKeyExchange(SSHPacket packet)
        {
            lock (kexlock)
            {
                if (localkex == null)
                {
                    SendKeyExchangeInit();
                }

                SSH2Context context = (SSH2Context)client.Context;

                currentState = TransportProtocolState.PERFORMING_KEYEXCHANGE;

                remotekex = packet.Payload;

                // Ignore the cookie
                packet.Skip(16);

                String remoteKeyExchanges = packet.ReadString();
                String remotePublicKeys   = packet.ReadString();
                String remoteCiphersCS    = packet.ReadString();
                String remoteCiphersSC    = packet.ReadString();
                String remoteHMacCS       = packet.ReadString();
                String remoteHMacSC       = packet.ReadString();


                String cipherCS = SelectNegotiatedComponent(context.SupportedCiphers.List(
                                                                context.PreferredCipherCS), remoteCiphersCS);

                String cipherSC = SelectNegotiatedComponent(context.SupportedCiphers.List(
                                                                context.PreferredCipherSC), remoteCiphersSC);

                Cipher encryption = (Cipher)context.SupportedCiphers.GetInstance(cipherCS);

                Cipher decryption = (Cipher)context.SupportedCiphers.GetInstance(cipherSC);

                String macCS = SelectNegotiatedComponent(context.SupportedMACs.List(
                                                             context.PreferredMacCS), remoteHMacCS);

                String macSC = SelectNegotiatedComponent(context.SupportedMACs.List(
                                                             context.PreferredMacSC), remoteHMacSC);

                SSH2Hmac outgoingMac = (SSH2Hmac)context.SupportedMACs.GetInstance(macCS);

                SSH2Hmac incomingMac = (SSH2Hmac)context.SupportedMACs.GetInstance(macSC);

                // Ignore compression and languages as were not interested in that atm

                // Create a Key Exchange instance
                String kex = SelectNegotiatedComponent(context.SupportedKeyExchanges.List(
                                                           context.PreferredKeyExchange), remoteKeyExchanges);

                String publickey = SelectNegotiatedComponent(context.SupportedPublicKeys.List(
                                                                 context.PreferredPublicKey), remotePublicKeys);

#if DEBUG
                // Output the local settings
                System.Diagnostics.Trace.WriteLine("Local Key exchange settings follow:");
                System.Diagnostics.Trace.WriteLine("Key exchange: " + context.SupportedKeyExchanges.List(
                                                       context.PreferredKeyExchange));
                System.Diagnostics.Trace.WriteLine("Public keys : " + context.SupportedPublicKeys.List(
                                                       context.PreferredPublicKey));
                System.Diagnostics.Trace.WriteLine("Ciphers client->server: " + context.SupportedCiphers.List(
                                                       context.PreferredCipherCS));
                System.Diagnostics.Trace.WriteLine("Ciphers server->client: " + context.SupportedCiphers.List(
                                                       context.PreferredCipherSC));
                System.Diagnostics.Trace.WriteLine("HMAC client->server: " + context.SupportedMACs.List(
                                                       context.PreferredMacCS));
                System.Diagnostics.Trace.WriteLine("HMAC server->client: " + context.SupportedMACs.List(
                                                       context.PreferredMacSC));

                // Output the remote settings
                System.Diagnostics.Trace.WriteLine("Remote Key exchange settings follow:");
                System.Diagnostics.Trace.WriteLine("Key exchange: " + remoteKeyExchanges);
                System.Diagnostics.Trace.WriteLine("Public keys : " + remotePublicKeys);
                System.Diagnostics.Trace.WriteLine("Ciphers client->server: " + remoteCiphersCS);
                System.Diagnostics.Trace.WriteLine("Ciphers server->client: " + remoteCiphersSC);
                System.Diagnostics.Trace.WriteLine("HMAC client->server: " + remoteHMacCS);
                System.Diagnostics.Trace.WriteLine("HMAC server->client: " + remoteHMacSC);

                // Output the selected settigns
                System.Diagnostics.Trace.WriteLine("Selected kex exchange: " + kex);
                System.Diagnostics.Trace.WriteLine("Selected public key: " + publickey);
                System.Diagnostics.Trace.WriteLine("Selected cipher client->server: " + cipherCS);
                System.Diagnostics.Trace.WriteLine("Selected cipher server->client: " + cipherSC);
                System.Diagnostics.Trace.WriteLine("Selected HMAC client->server: " + macCS);
                System.Diagnostics.Trace.WriteLine("Selected HMAC server->client: " + macSC);
#endif
                keyexchange = (SSH2KeyExchange)context.SupportedKeyExchanges.GetInstance(kex);

                keyexchange.Init(this);

                // Perform the key exchange
                keyexchange.PerformClientExchange(client.LocalIdentification,
                                                  client.RemoteIdentification,
                                                  localkex,
                                                  remotekex);

                SSHPublicKey hostkey = (SSHPublicKey)context.SupportedPublicKeys.GetInstance(publickey);

                hostkey.Init(keyexchange.HostKey, 0, keyexchange.HostKey.Length);

                if (context.KnownHosts != null)
                {
                    if (!context.KnownHosts.VerifyHost(transport.Hostname, hostkey))
                    {
                        Disconnect("Host key not accepted", DisconnectionReason.HOST_KEY_NOT_VERIFIABLE);
                        throw new SSHException("The host key was not accepted",
                                               SSHException.CANCELLED_CONNECTION);
                    }
                }

                if (!hostkey.VerifySignature(keyexchange.Signature,
                                             keyexchange.ExchangeHash))
                {
                    Disconnect("The host key signature is invalid",
                               DisconnectionReason.HOST_KEY_NOT_VERIFIABLE);
                    throw new SSHException("The host key signature is invalid",
                                           SSHException.PROTOCOL_VIOLATION);
                }

                if (sessionIdentifier == null)
                {
                    sessionIdentifier = keyexchange.ExchangeHash;
                }

                packet = GetSSHPacket(true);
                packet.WriteByte(SSH_MSG_NEWKEYS);
#if DEBUG
                System.Diagnostics.Trace.WriteLine("Sending SSH_MSG_NEWKEYS");
#endif
                SendMessage(packet);


                encryption.Init(Cipher.ENCRYPT_MODE,
                                MakeSSHKey('A'),
                                MakeSSHKey('C'));

                outgoingCipherLength = encryption.BlockSize;

                outgoingMac.Init(MakeSSHKey('E'));
                outgoingMacLength = outgoingMac.MacLength;

                this.encryption  = encryption;
                this.outgoingMac = outgoingMac;

                do
                {
                    packet = ReadMessage();

                    // Process the transport protocol message, must only be
                    // SSH_MSH_INGORE, SSH_MSG_DEBUG, SSH_MSG_DISCONNECT or SSH_MSG_NEWKEYS
                    if (!ProcessMessage(packet))
                    {
                        Disconnect("Invalid message received during key exchange",
                                   DisconnectionReason.PROTOCOL_ERROR);
                        throw new SSHException(
                                  "Invalid message received during key exchange",
                                  SSHException.PROTOCOL_VIOLATION);
                    }
                }while(packet.MessageID != SSH_MSG_NEWKEYS);

                // Put the incoming components into use
                decryption.Init(Cipher.DECRYPT_MODE,
                                MakeSSHKey('B'),
                                MakeSSHKey('D'));
                incomingCipherLength = decryption.BlockSize;

                incomingMac.Init(MakeSSHKey('F'));
                incomingMacLength = incomingMac.MacLength;

                this.decryption  = decryption;
                this.incomingMac = incomingMac;
                //this.incomingCompression = incomingCompression;

                currentState = TransportProtocolState.CONNECTED;

                FireStateChange(TransportProtocolState.CONNECTED);

                lock (kexqueue)
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Sending queued messages");
#endif
                    for (System.Collections.IEnumerator e = kexqueue.GetEnumerator(); e.MoveNext();)
                    {
                        SendMessage((SSHPacket)e.Current);
                    }

                    kexqueue.Clear();
                }

                // Clean up and reset any parameters
                localkex  = null;
                remotekex = null;
            }
        }
Example #28
0
        internal bool ProcessMessage(SSHPacket packet)
        {
            try
            {
                if (packet.Length < 1)
                {
                    Disconnect("Invalid message received", DisconnectionReason.PROTOCOL_ERROR);
                    throw new SSHException("Invalid transport protocol message", SSHException.INTERNAL_ERROR);
                }

                switch (packet.MessageID)
                {
                case SSH_MSG_DISCONNECT:
                {
                    packet.ReadInt();
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_DISCONNECT: " + packet.ReadString());
#endif
                    InternalDisconnect();
                    throw new SSHException(packet.ReadString(), SSHException.REMOTE_HOST_DISCONNECTED);
                }

                case SSH_MSG_IGNORE:
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_IGNORE");
#endif
                    return(true);
                }

                case SSH_MSG_DEBUG:
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_DEBUG");
                    packet.Skip(1);
                    System.Diagnostics.Trace.WriteLine(packet.ReadString());
#endif
                    return(true);
                }

                case SSH_MSG_NEWKEYS:
                {
                    // This lightweight implemention ignores these messages
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_NEWKEYS");
#endif
                    return(true);
                }

                case SSH_MSG_KEX_INIT:
                {
#if DEBUG
                    System.Diagnostics.Trace.WriteLine("Received SSH_MSG_KEX_INIT");
#endif
                    if (remotekex != null)
                    {
                        Disconnect("Key exchange already in progress!",
                                   DisconnectionReason.PROTOCOL_ERROR);
                        throw new SSHException("Key exchange already in progress!", SSHException.PROTOCOL_VIOLATION);
                    }

                    PerformKeyExchange(packet);

                    return(true);
                }

                default:
                {
                    // Not a transport protocol message
                    return(false);
                }
                }
            }
            catch (System.IO.IOException ex1)
            {
                throw new SSHException(ex1.Message, SSHException.INTERNAL_ERROR);
            }
        }
Example #29
0
        internal void LogMessage(SSHPacket packet)
        {
            switch (packet.MessageID)
            {
            case SSH_MSG_CHANNEL_OPEN_FAILURE:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_OPEN_FAILURE for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_CLOSE:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_CLOSE for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_EOF:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_EOF for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_REQUEST:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_REQUEST for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_SUCCESS:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_SUCCESS for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_FAILURE:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_FAILURE for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_WINDOW_ADJUST:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_WINDOW_ADJUST for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_DATA:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_DATA for channel id " + ChannelID);
                return;
            }

            case SSH_MSG_CHANNEL_EXTENDED_DATA:
            {
                System.Diagnostics.Trace.WriteLine("Received SSH_MSG_CHANNEL_EXTENDED_DATA for channel id " + ChannelID);
                return;
            }
            }
        }
Example #30
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);
            }
        }