/// <summary> /// Connect to an SSH server. This method is not designed to be called directly but from /// an <see cref="Maverick.SSH.SSHConnector"/> instance. /// </summary> /// <param name="io">The underlying transport mechanism</param> /// <param name="context">The configuration context for this connection</param> /// <param name="connector">The connector creating this client</param> /// <param name="username">The username for the connection</param> /// <param name="localIdentification">The identification string sent to the server</param> /// <param name="remoteIdentification">The identification string received from the server</param> /// <param name="threaded">Should this connection use an additional thread to buffer messages</param> public void Connect(SSHTransport io, SSHContext context, SSHConnector connector, System.String username, System.String localIdentification, System.String remoteIdentification, bool threaded) { FireEvent(SSHState.CONNECTING); this.context = (SSH2Context)context; this.con = connector; this.io = io; this.threaded = threaded; this.username = username; this.localIdentification = localIdentification; this.remoteIdentification = remoteIdentification; this.transport = new TransportProtocol(io, this); this.transport.StateChange += new TransportProtocolStateChangeEvent(this.OnTransportEvent); this.transport.StartProtocol(); FireEvent(SSHState.CONNECTED); this.connection = new ConnectionProtocol(transport, threaded); this.connection.AddChannelFactory(requestFactory); this.authentication = new AuthenticationProtocol(transport, connection); RequestAuthenticationMethods(); }
internal TransportProtocol(SSHTransport transport, SSHClient client) { this.transport = transport; this.client = client; this.kexqueue = new ArrayList(); this.kexlock = new Object(); }
/// <summary> /// Determine the version of a server. /// </summary> /// <param name="transport">A newly created transport connection</param> /// <returns></returns> public int DetermineVersion(SSHTransport transport) { int version = SelectVersion(GetRemoteIdentification(transport)); try { transport.Close(); } catch (System.IO.IOException) { } return(version); }
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); } }
/// <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); } } }
/// <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="events">A delegate state listener for receiving state change events</param> /// <returns></returns> public SSHClient Connect(SSHTransport transport, System.String username, bool threaded, SSHStateListener events) { return(Connect(transport, username, threaded, null, events)); }
/// <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> /// <returns></returns> public SSHClient Connect(SSHTransport transport, String username, bool threaded) { return(Connect(transport, username, threaded, null, null)); }