using Renci.SshNet.TestTools.OpenSSH; namespace Renci.SshNet.IntegrationTests { internal sealed class RemoteSshdConfig { private const string SshdConfigFilePath = "/etc/ssh/sshd_config"; private static readonly Encoding Utf8NoBom = new UTF8Encoding(false, true); private readonly RemoteSshd _remoteSshd; private readonly IConnectionInfoFactory _connectionInfoFactory; private readonly SshdConfig _config; public RemoteSshdConfig(RemoteSshd remoteSshd, IConnectionInfoFactory connectionInfoFactory) { _remoteSshd = remoteSshd; _connectionInfoFactory = connectionInfoFactory; using (var client = new ScpClient(_connectionInfoFactory.Create())) { client.Connect(); using (var memoryStream = new MemoryStream()) { client.Download(SshdConfigFilePath, memoryStream); memoryStream.Position = 0; _config = SshdConfig.LoadFrom(memoryStream, Encoding.UTF8); } } } /// /// Specifies whether challenge-response authentication is allowed. /// /// to allow challenge-response authentication. /// /// The current instance. /// public RemoteSshdConfig WithChallengeResponseAuthentication(bool? value) { _config.ChallengeResponseAuthentication = value; return this; } /// /// Specifies whether to allow keyboard-interactive authentication. /// /// to allow keyboard-interactive authentication. /// /// The current instance. /// public RemoteSshdConfig WithKeyboardInteractiveAuthentication(bool value) { _config.KeyboardInteractiveAuthentication = value; return this; } /// /// Specifies whether sshd should print /etc/motd when a user logs in interactively. /// /// if sshd should print /etc/motd when a user logs in interactively. /// /// The current instance. /// public RemoteSshdConfig PrintMotd(bool? value = true) { _config.PrintMotd = value; return this; } /// /// Specifies whether TTY is permitted. /// /// to permit TTY. /// /// The current instance. /// public RemoteSshdConfig PermitTTY(bool? value = true) { _config.PermitTTY = value; return this; } /// /// Specifies whether TCP forwarding is permitted. /// /// to allow TCP forwarding. /// /// The current instance. /// public RemoteSshdConfig AllowTcpForwarding(bool? value = true) { _config.AllowTcpForwarding = value; return this; } public RemoteSshdConfig WithAuthenticationMethods(string user, string authenticationMethods) { var sshNetMatch = _config.Matches.Find(m => m.Users.Contains(user)); if (sshNetMatch is null) { sshNetMatch = new Match(new[] { user }, Array.Empty()); _config.Matches.Add(sshNetMatch); } sshNetMatch.AuthenticationMethods = authenticationMethods; return this; } public RemoteSshdConfig ClearCiphers() { _config.Ciphers.Clear(); return this; } public RemoteSshdConfig AddCipher(Cipher cipher) { _config.Ciphers.Add(cipher); return this; } public RemoteSshdConfig ClearKeyExchangeAlgorithms() { _config.KeyExchangeAlgorithms.Clear(); return this; } public RemoteSshdConfig AddKeyExchangeAlgorithm(KeyExchangeAlgorithm keyExchangeAlgorithm) { _config.KeyExchangeAlgorithms.Add(keyExchangeAlgorithm); return this; } public RemoteSshdConfig ClearPublicKeyAcceptedAlgorithms() { _config.PublicKeyAcceptedAlgorithms.Clear(); return this; } public RemoteSshdConfig AddPublicKeyAcceptedAlgorithm(PublicKeyAlgorithm publicKeyAlgorithm) { _config.PublicKeyAcceptedAlgorithms.Add(publicKeyAlgorithm); return this; } public RemoteSshdConfig ClearMessageAuthenticationCodeAlgorithms() { _config.MessageAuthenticationCodeAlgorithms.Clear(); return this; } public RemoteSshdConfig AddMessageAuthenticationCodeAlgorithm(MessageAuthenticationCodeAlgorithm messageAuthenticationCodeAlgorithm) { _config.MessageAuthenticationCodeAlgorithms.Add(messageAuthenticationCodeAlgorithm); return this; } public RemoteSshdConfig ClearHostKeyAlgorithms() { _config.HostKeyAlgorithms.Clear(); return this; } public RemoteSshdConfig AddHostKeyAlgorithm(HostKeyAlgorithm hostKeyAlgorithm) { _config.HostKeyAlgorithms.Add(hostKeyAlgorithm); return this; } public RemoteSshdConfig ClearSubsystems() { _config.Subsystems.Clear(); return this; } public RemoteSshdConfig AddSubsystem(Subsystem subsystem) { _config.Subsystems.Add(subsystem); return this; } public RemoteSshdConfig WithLogLevel(LogLevel logLevel) { _config.LogLevel = logLevel; return this; } public RemoteSshdConfig WithUsePAM(bool usePAM) { _config.UsePAM = usePAM; return this; } public RemoteSshdConfig ClearHostKeyFiles() { _config.HostKeyFiles.Clear(); return this; } public RemoteSshdConfig AddHostKeyFile(string hostKeyFile) { _config.HostKeyFiles.Add(hostKeyFile); return this; } public RemoteSshd Update() { using (var client = new ScpClient(_connectionInfoFactory.Create())) { client.Connect(); using (var memoryStream = new MemoryStream()) using (var sw = new StreamWriter(memoryStream, Utf8NoBom)) { sw.NewLine = "\n"; _config.SaveTo(sw); sw.Flush(); memoryStream.Position = 0; client.Upload(memoryStream, SshdConfigFilePath); } } return _remoteSshd; } } }