Beispiel #1
0
        internal System.String GetRemoteIdentification(SSHTransport transport)
        {
            try
            {
                System.String remoteIdentification = "";

                // Now wait for a reply and evaluate the ident string
                System.Text.StringBuilder buffer;
                Stream stream = transport.GetStream();

                int MAX_BUFFER_LENGTH = 255;

                // Look for a string starting with "SSH-"
                while (!remoteIdentification.StartsWith("SSH-"))
                {
                    // Get the next string
                    int ch;
                    buffer = new System.Text.StringBuilder(MAX_BUFFER_LENGTH);
                    while (((ch = stream.ReadByte()) != '\n') &&
                           (buffer.Length < MAX_BUFFER_LENGTH) &&
                           ch > -1)
                    {
                        buffer.Append((char)ch);
                    }

                    if (ch == -1)
                    {
                        throw new SSHException("Failed to read remote identification", SSHException.CONNECT_FAILED);
                    }
                    // Set trimming off any EOL characters
                    remoteIdentification = buffer.ToString().Trim();
                }

                return(remoteIdentification);
            }
            catch (System.Exception ex)
            {
                throw new SSHException(ex.Message, SSHException.CONNECT_FAILED);
            }
        }
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>
        /// Create a new connection to an SSH server. This method takes a newly created <see cref="Maverick.SSH.SSHTransport"/>
        /// instance and performs the initial protocol negotiation to determine which type of client to
        /// create.
        /// </summary>
        /// <param name="transport">The transport layer to use</param>
        /// <param name="username">The name of the user making the connection</param>
        /// <param name="threaded">Should the client buffer input to ensure the smooth running of events. If you do not buffer input
        /// and require the use of state or data events they may not operate correctly as the API will operate in single threaded
        /// mode.</param>
        /// <param name="context">The configuration context to use for the connection</param>
        /// <param name="events">A delegate state listener for receiving state change events</param>
        /// <returns></returns>
        internal SSHClient Connect(SSHTransport transport,
                                   System.String username, bool threaded, SSHContext context, SSHStateListener events)
        {
            System.String localIdentification;
            System.String remoteIdentification = GetRemoteIdentification(transport);
            // Lets try SSH2 first because its a better protocol
            SSHClient client;

            System.Exception lastError       = null;
            bool             pointOfNoReturn = false;

            Stream stream = transport.GetStream();

            if ((ssh2Context != null || (context != null &&
                                         context is SSH2Context)) &&
                (supportedVersions & SSH2) != 0)
            {
                //			Send our identification depending upon which versions we can support
                if ((SelectVersion(remoteIdentification) & SSH2) != 0)
                {
                    try
                    {
                        if (context == null)
                        {
                            context = ssh2Context;
                        }

                        client = (SSHClient) new SSH2Client();
                        localIdentification = "SSH-2.0-" + softwareComments + "\n";
                        pointOfNoReturn     = true;
                        byte[] tempArray = SupportClass.ToByteArray(localIdentification);
                        stream.Write(tempArray, 0, tempArray.Length);

                        client.StateChange += events;
                        // Now get the client to connect using the selected protocol
                        client.Connect(transport,
                                       context,
                                       this,
                                       username,
                                       localIdentification.Trim(),
                                       remoteIdentification,
                                       threaded);
                        return(client);
                    }
                    catch (System.Exception t)
                    {
                        lastError = t;
                    }
                    finally
                    {
                        if (lastError != null && pointOfNoReturn)
                        {
                            if (lastError is SSHException)
                            {
                                throw (SSHException)lastError;
                            }
                            else
                            {
                                throw new SSHException(lastError.Message != null?lastError.Message:lastError.GetType().FullName, SSHException.CONNECT_FAILED);
                            }
                        }
                    }
                }
            }



            try
            {
                transport.Close();
            }
            catch (System.IO.IOException)
            {
            }

            if (lastError == null)
            {
                throw new SSHException("Failed to negotiate a version with the server! " + remoteIdentification, SSHException.CONNECT_FAILED);
            }
            else
            {
                if (lastError is SSHException)
                {
                    throw (SSHException)lastError;
                }
                else
                {
                    throw new SSHException(lastError.Message != null?lastError.Message:lastError.GetType().FullName, SSHException.CONNECT_FAILED);
                }
            }
        }