RemoteSshdConfig.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. using Renci.SshNet.TestTools.OpenSSH;
  2. namespace Renci.SshNet.IntegrationTests
  3. {
  4. internal sealed class RemoteSshdConfig
  5. {
  6. private const string SshdConfigFilePath = "/etc/ssh/sshd_config";
  7. private static readonly Encoding Utf8NoBom = new UTF8Encoding(false, true);
  8. private readonly RemoteSshd _remoteSshd;
  9. private readonly IConnectionInfoFactory _connectionInfoFactory;
  10. private readonly SshdConfig _config;
  11. public RemoteSshdConfig(RemoteSshd remoteSshd, IConnectionInfoFactory connectionInfoFactory)
  12. {
  13. _remoteSshd = remoteSshd;
  14. _connectionInfoFactory = connectionInfoFactory;
  15. using (var client = new ScpClient(_connectionInfoFactory.Create()))
  16. {
  17. client.Connect();
  18. using (var memoryStream = new MemoryStream())
  19. {
  20. client.Download(SshdConfigFilePath, memoryStream);
  21. memoryStream.Position = 0;
  22. _config = SshdConfig.LoadFrom(memoryStream, Encoding.UTF8);
  23. }
  24. }
  25. }
  26. /// <summary>
  27. /// Specifies whether challenge-response authentication is allowed.
  28. /// </summary>
  29. /// <param name="value"><see langword="true"/> to allow challenge-response authentication.</param>
  30. /// <returns>
  31. /// The current <see cref="RemoteSshdConfig"/> instance.
  32. /// </returns>
  33. public RemoteSshdConfig WithChallengeResponseAuthentication(bool? value)
  34. {
  35. _config.ChallengeResponseAuthentication = value;
  36. return this;
  37. }
  38. /// <summary>
  39. /// Specifies whether to allow keyboard-interactive authentication.
  40. /// </summary>
  41. /// <param name="value"><see langword="true"/> to allow keyboard-interactive authentication.</param>
  42. /// <returns>
  43. /// The current <see cref="RemoteSshdConfig"/> instance.
  44. /// </returns>
  45. public RemoteSshdConfig WithKeyboardInteractiveAuthentication(bool value)
  46. {
  47. _config.KeyboardInteractiveAuthentication = value;
  48. return this;
  49. }
  50. /// <summary>
  51. /// Specifies whether <c>sshd</c> should print /etc/motd when a user logs in interactively.
  52. /// </summary>
  53. /// <param name="value"><see langword="true"/> if <c>sshd</c> should print /etc/motd when a user logs in interactively.</param>
  54. /// <returns>
  55. /// The current <see cref="RemoteSshdConfig"/> instance.
  56. /// </returns>
  57. public RemoteSshdConfig PrintMotd(bool? value = true)
  58. {
  59. _config.PrintMotd = value;
  60. return this;
  61. }
  62. /// <summary>
  63. /// Specifies whether TTY is permitted.
  64. /// </summary>
  65. /// <param name="value"><see langword="true"/> to permit TTY.</param>
  66. /// <returns>
  67. /// The current <see cref="RemoteSshdConfig"/> instance.
  68. /// </returns>
  69. public RemoteSshdConfig PermitTTY(bool? value = true)
  70. {
  71. _config.PermitTTY = value;
  72. return this;
  73. }
  74. /// <summary>
  75. /// Specifies whether TCP forwarding is permitted.
  76. /// </summary>
  77. /// <param name="value"><see langword="true"/> to allow TCP forwarding.</param>
  78. /// <returns>
  79. /// The current <see cref="RemoteSshdConfig"/> instance.
  80. /// </returns>
  81. public RemoteSshdConfig AllowTcpForwarding(bool? value = true)
  82. {
  83. _config.AllowTcpForwarding = value;
  84. return this;
  85. }
  86. public RemoteSshdConfig WithAuthenticationMethods(string user, string authenticationMethods)
  87. {
  88. var sshNetMatch = _config.Matches.Find(m => m.Users.Contains(user));
  89. if (sshNetMatch is null)
  90. {
  91. sshNetMatch = new Match(new[] { user }, Array.Empty<string>());
  92. _config.Matches.Add(sshNetMatch);
  93. }
  94. sshNetMatch.AuthenticationMethods = authenticationMethods;
  95. return this;
  96. }
  97. public RemoteSshdConfig ClearCiphers()
  98. {
  99. _config.Ciphers.Clear();
  100. return this;
  101. }
  102. public RemoteSshdConfig AddCipher(Cipher cipher)
  103. {
  104. _config.Ciphers.Add(cipher);
  105. return this;
  106. }
  107. public RemoteSshdConfig ClearKeyExchangeAlgorithms()
  108. {
  109. _config.KeyExchangeAlgorithms.Clear();
  110. return this;
  111. }
  112. public RemoteSshdConfig AddKeyExchangeAlgorithm(KeyExchangeAlgorithm keyExchangeAlgorithm)
  113. {
  114. _config.KeyExchangeAlgorithms.Add(keyExchangeAlgorithm);
  115. return this;
  116. }
  117. public RemoteSshdConfig ClearPublicKeyAcceptedAlgorithms()
  118. {
  119. _config.PublicKeyAcceptedAlgorithms.Clear();
  120. return this;
  121. }
  122. public RemoteSshdConfig AddPublicKeyAcceptedAlgorithm(PublicKeyAlgorithm publicKeyAlgorithm)
  123. {
  124. _config.PublicKeyAcceptedAlgorithms.Add(publicKeyAlgorithm);
  125. return this;
  126. }
  127. public RemoteSshdConfig ClearMessageAuthenticationCodeAlgorithms()
  128. {
  129. _config.MessageAuthenticationCodeAlgorithms.Clear();
  130. return this;
  131. }
  132. public RemoteSshdConfig AddMessageAuthenticationCodeAlgorithm(MessageAuthenticationCodeAlgorithm messageAuthenticationCodeAlgorithm)
  133. {
  134. _config.MessageAuthenticationCodeAlgorithms.Add(messageAuthenticationCodeAlgorithm);
  135. return this;
  136. }
  137. public RemoteSshdConfig ClearHostKeyAlgorithms()
  138. {
  139. _config.HostKeyAlgorithms.Clear();
  140. return this;
  141. }
  142. public RemoteSshdConfig AddHostKeyAlgorithm(HostKeyAlgorithm hostKeyAlgorithm)
  143. {
  144. _config.HostKeyAlgorithms.Add(hostKeyAlgorithm);
  145. return this;
  146. }
  147. public RemoteSshdConfig ClearSubsystems()
  148. {
  149. _config.Subsystems.Clear();
  150. return this;
  151. }
  152. public RemoteSshdConfig AddSubsystem(Subsystem subsystem)
  153. {
  154. _config.Subsystems.Add(subsystem);
  155. return this;
  156. }
  157. public RemoteSshdConfig WithLogLevel(LogLevel logLevel)
  158. {
  159. _config.LogLevel = logLevel;
  160. return this;
  161. }
  162. public RemoteSshdConfig WithUsePAM(bool usePAM)
  163. {
  164. _config.UsePAM = usePAM;
  165. return this;
  166. }
  167. public RemoteSshdConfig ClearHostKeyFiles()
  168. {
  169. _config.HostKeyFiles.Clear();
  170. return this;
  171. }
  172. public RemoteSshdConfig AddHostKeyFile(string hostKeyFile)
  173. {
  174. _config.HostKeyFiles.Add(hostKeyFile);
  175. return this;
  176. }
  177. public RemoteSshd Update()
  178. {
  179. using (var client = new ScpClient(_connectionInfoFactory.Create()))
  180. {
  181. client.Connect();
  182. using (var memoryStream = new MemoryStream())
  183. using (var sw = new StreamWriter(memoryStream, Utf8NoBom))
  184. {
  185. sw.NewLine = "\n";
  186. _config.SaveTo(sw);
  187. sw.Flush();
  188. memoryStream.Position = 0;
  189. client.Upload(memoryStream, SshdConfigFilePath);
  190. }
  191. }
  192. return _remoteSshd;
  193. }
  194. }
  195. }