71 lines
2.0 KiB
C#
71 lines
2.0 KiB
C#
using Renci.SshNet;
|
|
|
|
namespace McpSsh.Server.Ssh;
|
|
|
|
public interface ISshClientFactory
|
|
{
|
|
SshClient CreateSshClient(SshConnectionRequest request);
|
|
|
|
SftpClient CreateSftpClient(SshConnectionRequest request);
|
|
|
|
ScpClient CreateScpClient(SshConnectionRequest request);
|
|
}
|
|
|
|
public sealed record SshConnectionRequest(
|
|
string Host,
|
|
string Username,
|
|
int Port,
|
|
string? KeyPath,
|
|
string? KeyPassphrase,
|
|
TimeSpan? Timeout = null);
|
|
|
|
public sealed class SshNetClientFactory : ISshClientFactory
|
|
{
|
|
private readonly ISshKeyResolver _keyResolver;
|
|
|
|
public SshNetClientFactory(ISshKeyResolver keyResolver)
|
|
{
|
|
_keyResolver = keyResolver;
|
|
}
|
|
|
|
public SshClient CreateSshClient(SshConnectionRequest request)
|
|
{
|
|
var client = new SshClient(CreateConnectionInfo(request));
|
|
ApplyTimeout(client, request.Timeout);
|
|
return client;
|
|
}
|
|
|
|
public SftpClient CreateSftpClient(SshConnectionRequest request)
|
|
{
|
|
var client = new SftpClient(CreateConnectionInfo(request));
|
|
ApplyTimeout(client, request.Timeout);
|
|
return client;
|
|
}
|
|
|
|
public ScpClient CreateScpClient(SshConnectionRequest request)
|
|
{
|
|
var client = new ScpClient(CreateConnectionInfo(request));
|
|
ApplyTimeout(client, request.Timeout);
|
|
return client;
|
|
}
|
|
|
|
private ConnectionInfo CreateConnectionInfo(SshConnectionRequest request)
|
|
{
|
|
var keyPath = _keyResolver.ResolveKeyPath(request.KeyPath);
|
|
var keyFile = string.IsNullOrEmpty(request.KeyPassphrase)
|
|
? new PrivateKeyFile(keyPath)
|
|
: new PrivateKeyFile(keyPath, request.KeyPassphrase);
|
|
|
|
var auth = new PrivateKeyAuthenticationMethod(request.Username, keyFile);
|
|
return new ConnectionInfo(request.Host, request.Port, request.Username, auth);
|
|
}
|
|
|
|
private static void ApplyTimeout(BaseClient client, TimeSpan? timeout)
|
|
{
|
|
if (timeout is { } value)
|
|
{
|
|
client.ConnectionInfo.Timeout = value;
|
|
}
|
|
}
|
|
}
|