| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 | 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);                }            }        }        /// <summary>        /// Specifies whether challenge-response authentication is allowed.        /// </summary>        /// <param name="value"><see langword="true"/> to allow challenge-response authentication.</param>        /// <returns>        /// The current <see cref="RemoteSshdConfig"/> instance.        /// </returns>        public RemoteSshdConfig WithChallengeResponseAuthentication(bool? value)        {            _config.ChallengeResponseAuthentication = value;            return this;        }        /// <summary>        /// Specifies whether to allow keyboard-interactive authentication.        /// </summary>        /// <param name="value"><see langword="true"/> to allow keyboard-interactive authentication.</param>        /// <returns>        /// The current <see cref="RemoteSshdConfig"/> instance.        /// </returns>        public RemoteSshdConfig WithKeyboardInteractiveAuthentication(bool value)        {            _config.KeyboardInteractiveAuthentication = value;            return this;        }        /// <summary>        /// Specifies whether <c>sshd</c> should print /etc/motd when a user logs in interactively.        /// </summary>        /// <param name="value"><see langword="true"/> if <c>sshd</c> should print /etc/motd when a user logs in interactively.</param>        /// <returns>        /// The current <see cref="RemoteSshdConfig"/> instance.        /// </returns>        public RemoteSshdConfig PrintMotd(bool? value = true)        {            _config.PrintMotd = value;            return this;        }        /// <summary>        /// Specifies whether TTY is permitted.        /// </summary>        /// <param name="value"><see langword="true"/> to permit TTY.</param>        /// <returns>        /// The current <see cref="RemoteSshdConfig"/> instance.        /// </returns>        public RemoteSshdConfig PermitTTY(bool? value = true)        {            _config.PermitTTY = value;            return this;        }        /// <summary>        /// Specifies whether TCP forwarding is permitted.        /// </summary>        /// <param name="value"><see langword="true"/> to allow TCP forwarding.</param>        /// <returns>        /// The current <see cref="RemoteSshdConfig"/> instance.        /// </returns>        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<string>());                _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 RemoteSshdConfig WithHostKeyCertificate(string hostKeyCertificate)        {            _config.HostCertificate = hostKeyCertificate;            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;        }    }}
 |