using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Common; using Renci.SshNet.Messages; namespace Renci.SshNet { /// /// Provides connection information when password authentication method is used /// public partial class PasswordConnectionInfo : ConnectionInfo, IDisposable { private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false); private Exception _exception; private RequestMessage _requestMessage; private string _password; /// /// Gets connection name /// public override string Name { get { return this._requestMessage.MethodName; } } /// /// Occurs when user's password has expired and needs to be changed. /// public event EventHandler PasswordExpired; /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. /// Connection password. public PasswordConnectionInfo(string host, string username, string password) : this(host, 22, username, password) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection port. /// Connection username. /// Connection password. /// is null. /// is invalid, or is null or contains whitespace characters. /// is not within and . public PasswordConnectionInfo(string host, int port, string username, string password) : this(host, port, username, password, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// The port. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. public PasswordConnectionInfo(string host, int port, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort) : this(host, port, username, password, proxyType, proxyHost, proxyPort, string.Empty, string.Empty) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// The port. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. /// The proxy username. public PasswordConnectionInfo(string host, int port, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername) : this(host, port, username, password, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort) : this(host, 22, username, password, proxyType, proxyHost, proxyPort, string.Empty, string.Empty) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. /// The proxy username. public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername) : this(host, 22, username, password, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. /// The proxy username. /// The proxy password. public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword) : this(host, 22, username, password, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// The port. /// Connection username. /// Connection password. /// Type of the proxy. /// The proxy host. /// The proxy port. /// The proxy username. /// The proxy password. public PasswordConnectionInfo(string host, int port, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword) : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword) { if (password == null) throw new ArgumentNullException("password"); this._password = password; this._requestMessage = new RequestMessagePassword(ServiceName.Connection, this.Username, password); } /// /// Called when connection needs to be authenticated. /// protected override void OnAuthenticate() { this.Session.RegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ"); this.SendMessage(this._requestMessage); this.WaitHandle(this._authenticationCompleted); if (this._exception != null) { throw this._exception; } } /// /// Handles the UserAuthenticationSuccessMessageReceived event of the session. /// /// The source of the event. /// The event data. protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e) { base.Session_UserAuthenticationSuccessMessageReceived(sender, e); this._authenticationCompleted.Set(); } /// /// Handles the UserAuthenticationFailureReceived event of the session. /// /// The source of the event. /// The event data. protected override void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e) { base.Session_UserAuthenticationFailureReceived(sender, e); this._authenticationCompleted.Set(); } /// /// Handles the MessageReceived event of the session. /// /// The source of the event. /// The event data. protected override void Session_MessageReceived(object sender, MessageEventArgs e) { base.Session_MessageReceived(sender, e); if (e.Message is PasswordChangeRequiredMessage) { this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ"); this.ExecuteThread(() => { try { var eventArgs = new AuthenticationPasswordChangeEventArgs(this.Username); // Raise an event to allow user to supply a new password if (this.PasswordExpired != null) { this.PasswordExpired(this, eventArgs); } // Send new authentication request with new password this.SendMessage(new RequestMessagePassword(ServiceName.Connection, this.Username, this._password, eventArgs.NewPassword)); } catch (Exception exp) { this._exception = exp; this._authenticationCompleted.Set(); } }); } } partial void ExecuteThread(Action action); #region IDisposable Members private bool isDisposed = false; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this.isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. if (this._authenticationCompleted != null) { this._authenticationCompleted.Dispose(); this._authenticationCompleted = null; } } // Note disposing has been done. isDisposed = true; } } /// /// Releases unmanaged resources and performs other cleanup operations before the /// is reclaimed by garbage collection. /// ~PasswordConnectionInfo() { // Do not re-create Dispose clean-up code here. // Calling Dispose(false) is optimal in terms of // readability and maintainability. Dispose(false); } #endregion } }