protected void ProcessMsgUserInfoResponse(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Read response info. int numResponses = msgReader.ReadInt32(); string[] responses = new string[numResponses]; for (int i = 0; i < numResponses; i++) { responses[i] = Encoding.UTF8.GetString(msgReader.ReadByteString()); } // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserKeyboardInteractiveEventArgs(_lastUserName, responses); if (AuthenticateUserKeyboardInteractive != null) { AuthenticateUserKeyboardInteractive(this, authUserEventArgs); } // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Auth has failed. SendMsgUserAuthFailure(false); break; case AuthenticationResult.RequestMoreInfo: // Request more prompt info from client. RequestPromptInfo(null); break; } }
protected void ProcessMsgUserAuthRequest(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Read auth information. string userName = Encoding.UTF8.GetString(msgReader.ReadByteString()); string serviceName = msgReader.ReadString(); string methodName = msgReader.ReadString(); // Store user name and service name used for this auth. _lastUserName = userName; _lastServiceName = serviceName; // Check if service with specified name exists. if (_client.Services.Count(item => item.Name == serviceName) == 0) { // Service was not found. _client.Disconnect(SshDisconnectReason.ServiceNotAvailable, string.Format( "The service with name {0} is not supported by this server.")); throw new DisconnectedException(); } // Check method of authentication. switch (methodName) { case "none": ProcessMsgUserAuthRequestNone(msgReader); break; case "publickey": ProcessMsgUserAuthRequestPublicKey(msgReader); break; case "password": ProcessMsgUserAuthRequestPassword(msgReader); break; case "hostbased": ProcessMsgUserAuthRequestHostBased(msgReader); break; case "keyboard-interactive": ProcessMsgUserAuthRequestKeyboardInteractive(msgReader); break; default: // Invalid auth method. _client.Disconnect(false); break; } }
public byte[] GetSignature(byte[] signatureData) { using (var dataStream = new MemoryStream(signatureData)) { using (var dataReader = new SshStreamReader(dataStream)) { // Read signature from stream. if (dataReader.ReadString() != this.Name) { throw new CryptographicException( "Signature was not created with this algorithm."); } var signature = dataReader.ReadByteString(); return(signature); } } }
protected void ProcessMsgChannelData(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Read channel number and get channel object. uint channelNum = msgReader.ReadUInt32(); SshChannel channel; try { channel = _channels.SingleOrDefault(item => item.ServerChannel == channelNum); } catch (InvalidOperationException) { return; } // Let channel read data. var data = msgReader.ReadByteString(); channel.ProcessData(data); }
protected void ProcessMsgUserAuthRequestKeyboardInteractive(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) { AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.KeyboardInteractive)); } // Read request information. string language = msgReader.ReadString(); string[] subMethods = Encoding.UTF8.GetString(msgReader.ReadByteString()).Split( new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); // Request prompt info from client. RequestPromptInfo(subMethods); }
protected void ProcessMsgUserInfoResponse(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Read response info. int numResponses = msgReader.ReadInt32(); string[] responses = new string[numResponses]; for (int i = 0; i < numResponses; i++) responses[i] = Encoding.UTF8.GetString(msgReader.ReadByteString()); // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserKeyboardInteractiveEventArgs(_lastUserName, responses); if (AuthenticateUserKeyboardInteractive != null) AuthenticateUserKeyboardInteractive(this, authUserEventArgs); // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Auth has failed. SendMsgUserAuthFailure(false); break; case AuthenticationResult.RequestMoreInfo: // Request more prompt info from client. RequestPromptInfo(null); break; } }
protected void ProcessMsgUserAuthRequestPublicKey(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.PublicKey)); // Read request information. bool isAuthRequest = msgReader.ReadBoolean(); string keyAlgName = msgReader.ReadString(); byte[] keyAndCertsData = msgReader.ReadByteString(); // Try to find public key algorithm. PublicKeyAlgorithm keyAlg = null; try { keyAlg = (PublicKeyAlgorithm)_client.PublicKeyAlgorithms.Single(item => item.Name == keyAlgName).Clone(); } catch (InvalidOperationException) { // Public key algorithm is not supported. SendMsgUserAuthFailure(false); } // Load key and certificats data for algorithm. keyAlg.LoadKeyAndCertificatesData(keyAndCertsData); // Check if request is actual auth request or query of whether specified public key is // acceptable. if (isAuthRequest) { // Read client signature. var signatureData = msgReader.ReadByteString(); var signature = keyAlg.GetSignature(signatureData); // Verify signature. var payloadData = ((MemoryStream)msgReader.BaseStream).ToArray(); if (VerifyPublicKeySignature(keyAlg, payloadData, 0, payloadData.Length - signatureData.Length - 4, signature)) { // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserPublicKeyEventArgs(_lastUserName, keyAlg.ExportPublicKey()); AuthenticateUserPublicKey(this, authUserEventArgs); // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Auth has failed. SendMsgUserAuthFailure(false); break; } } else { // Signature is invalid. SendMsgUserAuthFailure(false); } } else { // Public key is acceptable. SendMsgUserAuthPkOk(keyAlgName, keyAndCertsData); } }
protected void ProcessMsgUserAuthRequestPassword(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.Password)); // Check whether client is changing password. bool changingPassword = msgReader.ReadBoolean(); if (changingPassword) { // Read old and new passwords (in plaintext). string oldPassword = Encoding.UTF8.GetString(msgReader.ReadByteString()); string newPassword = Encoding.UTF8.GetString(msgReader.ReadByteString()); // Raise event to get result of password change request. var changePasswordEventArgs = new ChangePasswordEventArgs(oldPassword, newPassword); if (ChangePassword != null) ChangePassword(this, changePasswordEventArgs); // Check result of password change request. switch (changePasswordEventArgs.Result) { case PasswordChangeResult.Success: // Password change and auth have succeeded. AuthenticateUser(_lastServiceName); break; case PasswordChangeResult.FurtherAuthRequired: // Password change has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case PasswordChangeResult.Failure: // Password change has failed. SendMsgUserAuthFailure(false); break; case PasswordChangeResult.NewPasswordUnacceptable: // Password was not changed. SendMsgUserAuthPasswdChangeReq(changePasswordEventArgs.ReplyPrompt, ""); break; } } else { // Read password (in plaintext). string password = Encoding.UTF8.GetString(msgReader.ReadByteString()); // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserPasswordEventArgs(_lastUserName, password); if (AuthenticateUserPassword != null) AuthenticateUserPassword(this, authUserEventArgs); // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Increment number of failed auth attempts. _failedAuthAttempts++; if (_failedAuthAttempts < this.MaximumAuthAttempts) { // Auth has failed, but allow client to reattempt auth. SendMsgUserAuthFailure(false); } else { // Auth has failed too many times, disconnect. _client.Disconnect(false); throw new DisconnectedException(); } break; case AuthenticationResult.PasswordExpired: // Password change is required. SendMsgUserAuthPasswdChangeReq("The specified password has expired.", ""); break; } } }
protected void ProcessMsgUserAuthRequestKeyboardInteractive(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.KeyboardInteractive)); // Read request information. string language = msgReader.ReadString(); string[] subMethods = Encoding.UTF8.GetString(msgReader.ReadByteString()).Split( new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); // Request prompt info from client. RequestPromptInfo(subMethods); }
protected void ProcessMsgUserAuthRequest(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Read auth information. string userName = Encoding.UTF8.GetString(msgReader.ReadByteString()); string serviceName = msgReader.ReadString(); string methodName = msgReader.ReadString(); // Store user name and service name used for this auth. _lastUserName = userName; _lastServiceName = serviceName; // Check if service with specified name exists. if (_client.Services.Count(item => item.Name == serviceName) == 0) { // Service was not found. _client.Disconnect(SshDisconnectReason.ServiceNotAvailable, string.Format( "The service with name {0} is not supported by this server.")); throw new DisconnectedException(); } // Check method of authentication. switch (methodName) { case "none": ProcessMsgUserAuthRequestNone(msgReader); break; case "publickey": ProcessMsgUserAuthRequestPublicKey(msgReader); break; case "password": ProcessMsgUserAuthRequestPassword(msgReader); break; case "hostbased": ProcessMsgUserAuthRequestHostBased(msgReader); break; case "keyboard-interactive": ProcessMsgUserAuthRequestKeyboardInteractive(msgReader); break; default: // Invalid auth method. _client.Disconnect(false); break; } }
public byte[] GetSignature(byte[] signatureData) { using (var dataStream = new MemoryStream(signatureData)) { using (var dataReader = new SshStreamReader(dataStream)) { // Read signature from stream. if (dataReader.ReadString() != this.Name) throw new CryptographicException( "Signature was not created with this algorithm."); var signature = dataReader.ReadByteString(); return signature; } } }
protected void ProcessMsgChannelExtendedData(SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); // Read channel number and get channel object. uint channelNum = msgReader.ReadUInt32(); SshChannel channel; try { channel = _channels.SingleOrDefault(item => item.ServerChannel == channelNum); } catch (InvalidOperationException) { return; } // Let channel read extended data. var dataType = (SshExtendedDataType)msgReader.ReadUInt32(); var data = msgReader.ReadByteString(); channel.ProcessExtendedData(dataType, data); }
protected internal override void ProcessRequest(string requestType, bool wantReply, SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } switch (requestType) { case "pty-req": // Read information about pseudo-terminal. var termEnvVar = msgReader.ReadString(); var termCharsWidth = msgReader.ReadUInt32(); var termCharsHeight = msgReader.ReadUInt32(); var termPixelsWidth = msgReader.ReadUInt32(); var termPixelsHeight = msgReader.ReadUInt32(); var termModes = ReadTerminalModes(msgReader.ReadByteString()); // Raise event to request pseudo terminal. var pseudoTerminalRequestedEventArgs = new PseudoTerminalRequestedEventArgs(termEnvVar); OnPseudoTerminalRequested(pseudoTerminalRequestedEventArgs); // Check if request to allocate pseudo terminal failed. if (!pseudoTerminalRequestedEventArgs.Success) { break; } _termEnvVar = termEnvVar; _termCharsWidth = termCharsWidth; _termCharsHeight = termCharsHeight; _termPixelsWidth = termPixelsWidth; _termPixelsHeight = termPixelsHeight; _termModes = termModes; // Add TERM to list of environment variables. _envVars.Add("TERM", _termEnvVar); // Raise event, pseudo terminal has been allocated. OnPseudoTerminalAllocated(new EventArgs()); if (wantReply) { _connService.SendMsgChannelSuccess(this); } return; case "env": // Read name and value of environment variable. var varName = msgReader.ReadString(); var varValue = msgReader.ReadString(); // Add variable to list. _envVars.Add(varName, varValue); if (wantReply) { _connService.SendMsgChannelSuccess(this); } return; case "shell": // Start default shell. StartShell(); if (wantReply) { _connService.SendMsgChannelSuccess(this); } return; case "exec": // not implemented break; default: base.ProcessRequest(requestType, wantReply, msgReader); return; } // Request has failed. if (wantReply) { _connService.SendMsgChannelFailure(this); } }
protected void ProcessMsgUserAuthRequestHostBased(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) { AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.HostBased)); } // Read request information. string keyAlgName = msgReader.ReadString(); byte[] keyAndCertsData = msgReader.ReadByteString(); string clientHostName = msgReader.ReadString(); string clientUserName = msgReader.ReadString(); // Try to find public key algorithm. PublicKeyAlgorithm keyAlg = null; try { keyAlg = (PublicKeyAlgorithm)_client.PublicKeyAlgorithms.Single(item => item.Name == keyAlgName).Clone(); } catch (InvalidOperationException) { // Public key algorithm is not supported. SendMsgUserAuthFailure(false); } // Load key and certificats data for algorithm. keyAlg.LoadKeyAndCertificatesData(keyAndCertsData); // Read client signature. var signatureData = msgReader.ReadByteString(); var signature = keyAlg.GetSignature(signatureData); // Verify signature. var payloadData = ((MemoryStream)msgReader.BaseStream).ToArray(); if (VerifyPublicKeySignature(keyAlg, payloadData, 0, payloadData.Length - signatureData.Length - 4, signature)) { // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserHostBasedEventArgs(_lastUserName, clientHostName, clientUserName, keyAlg.ExportPublicKey()); if (AuthenticateUserHostBased != null) { AuthenticateUserHostBased(this, authUserEventArgs); } // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Auth has failed. SendMsgUserAuthFailure(false); break; } } else { // Signature is invalid. SendMsgUserAuthFailure(false); } }
protected void ProcessMsgUserAuthRequestPassword(SshStreamReader msgReader) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } // Raise event to specify requested auth method. if (AuthenticationMethodRequested != null) { AuthenticationMethodRequested(this, new AuthMethodRequestedEventArgs(AuthenticationMethod.Password)); } // Check whether client is changing password. bool changingPassword = msgReader.ReadBoolean(); if (changingPassword) { // Read old and new passwords (in plaintext). string oldPassword = Encoding.UTF8.GetString(msgReader.ReadByteString()); string newPassword = Encoding.UTF8.GetString(msgReader.ReadByteString()); // Raise event to get result of password change request. var changePasswordEventArgs = new ChangePasswordEventArgs(oldPassword, newPassword); if (ChangePassword != null) { ChangePassword(this, changePasswordEventArgs); } // Check result of password change request. switch (changePasswordEventArgs.Result) { case PasswordChangeResult.Success: // Password change and auth have succeeded. AuthenticateUser(_lastServiceName); break; case PasswordChangeResult.FurtherAuthRequired: // Password change has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case PasswordChangeResult.Failure: // Password change has failed. SendMsgUserAuthFailure(false); break; case PasswordChangeResult.NewPasswordUnacceptable: // Password was not changed. SendMsgUserAuthPasswdChangeReq(changePasswordEventArgs.ReplyPrompt, ""); break; } } else { // Read password (in plaintext). string password = Encoding.UTF8.GetString(msgReader.ReadByteString()); // Raise event to get result of auth attempt. var authUserEventArgs = new AuthUserPasswordEventArgs(_lastUserName, password); if (AuthenticateUserPassword != null) { AuthenticateUserPassword(this, authUserEventArgs); } // Check result of auth attempt. switch (authUserEventArgs.Result) { case AuthenticationResult.Success: // Auth has succeeded. AuthenticateUser(_lastServiceName); break; case AuthenticationResult.FurtherAuthRequired: // Auth has succeeded, but further auth is required. SendMsgUserAuthFailure(true); break; case AuthenticationResult.Failure: // Increment number of failed auth attempts. _failedAuthAttempts++; if (_failedAuthAttempts < this.MaximumAuthAttempts) { // Auth has failed, but allow client to reattempt auth. SendMsgUserAuthFailure(false); } else { // Auth has failed too many times, disconnect. _client.Disconnect(false); throw new DisconnectedException(); } break; case AuthenticationResult.PasswordExpired: // Password change is required. SendMsgUserAuthPasswdChangeReq("The specified password has expired.", ""); break; } } }
protected internal override void ProcessRequest(string requestType, bool wantReply, SshStreamReader msgReader) { if (_isDisposed) throw new ObjectDisposedException(this.GetType().FullName); switch (requestType) { case "pty-req": // Read information about pseudo-terminal. var termEnvVar = msgReader.ReadString(); var termCharsWidth = msgReader.ReadUInt32(); var termCharsHeight = msgReader.ReadUInt32(); var termPixelsWidth = msgReader.ReadUInt32(); var termPixelsHeight = msgReader.ReadUInt32(); var termModes = ReadTerminalModes(msgReader.ReadByteString()); // Raise event to request pseudo terminal. var pseudoTerminalRequestedEventArgs = new PseudoTerminalRequestedEventArgs(termEnvVar); OnPseudoTerminalRequested(pseudoTerminalRequestedEventArgs); // Check if request to allocate pseudo terminal failed. if (!pseudoTerminalRequestedEventArgs.Success) break; _termEnvVar = termEnvVar; _termCharsWidth = termCharsWidth; _termCharsHeight = termCharsHeight; _termPixelsWidth = termPixelsWidth; _termPixelsHeight = termPixelsHeight; _termModes = termModes; // Add TERM to list of environment variables. _envVars.Add("TERM", _termEnvVar); // Raise event, pseudo terminal has been allocated. OnPseudoTerminalAllocated(new EventArgs()); if (wantReply) _connService.SendMsgChannelSuccess(this); return; case "env": // Read name and value of environment variable. var varName = msgReader.ReadString(); var varValue = msgReader.ReadString(); // Add variable to list. _envVars.Add(varName, varValue); if (wantReply) _connService.SendMsgChannelSuccess(this); return; case "shell": // Start default shell. StartShell(); if (wantReply) _connService.SendMsgChannelSuccess(this); return; case "exec": // not implemented break; default: base.ProcessRequest(requestType, wantReply, msgReader); return; } // Request has failed. if (wantReply) _connService.SendMsgChannelFailure(this); }