Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ require('remote-sshfs').setup{
"/etc/ssh/ssh_config",
-- "/path/to/custom/ssh_config"
},
ssh_known_hosts = vim.fn.expand "$HOME" .. "/.ssh/known_hosts",
-- NOTE: Can define ssh_configs similarly to include all configs in a folder
-- ssh_configs = vim.split(vim.fn.globpath(vim.fn.expand "$HOME" .. "/.ssh/configs", "*"), "\n")
sshfs_args = { -- arguments to pass to the sshfs command
Expand Down Expand Up @@ -291,6 +292,7 @@ Using the full config is quicker if plenary is already managed by your setup, bu
- Password handling: When key-based authentication isn't used, you'll be prompted to enter a password/passphrase, which is piped to `sshfs -o password_stdin`. Ensure your SSH server allows password auth or use an SSH agent.
- Default mount directory: By default, mounts go into `~/.sshfs/<host>/`. Override `mounts.base_dir` in your setup if you'd like a different location.
- Key-based authentication: This plugin relies on your local SSH config and agent for auth. Make sure `ssh-agent` is running and your keys are loaded, or configure `IdentityFile` in your SSH config.
- Known hosts management: If the target host is not already listed in `known_hosts`, the user will be prompted with its fingerprint and given the choice to trust and store it.

## 🌟 Credits

Expand Down
58 changes: 57 additions & 1 deletion lua/remote-sshfs/connections.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local handler = require "remote-sshfs.handler"
local config = {}
local hosts = {}
local ssh_configs = {}
local ssh_known_hosts = nil
local sshfs_args = {}

-- Current connection
Expand All @@ -18,6 +19,7 @@ M.setup = function(opts)
config = opts
utils.setup_sshfs(config)
ssh_configs = config.connections.ssh_configs
ssh_known_hosts = config.connections.ssh_known_hosts
sshfs_args = config.connections.sshfs_args
hosts = utils.parse_hosts_from_configs(ssh_configs)
end
Expand Down Expand Up @@ -131,6 +133,58 @@ M.mount_host = function(host, mount_dir, ask_pass)
-- Mount point
table.insert(cmd, mount_dir)

local function ensure_ssh_host_key(callback)
assert(ssh_known_hosts, "ssh_known_hosts is required")

local hostname = host["HostName"] or host["Name"]

-- Check if host is known
local known_info = vim.fn.system { "ssh-keygen", "-F", hostname, "-f", ssh_known_hosts }
if known_info:find "found" then
print("Host key for " .. hostname .. " already known.")
callback()
return true
end

-- Get fingerprint
local scan = vim.fn.system("ssh-keyscan -t ed25519 " .. hostname .. " 2>/dev/null")
if scan == "" then
vim.notify("Could not get fingerprint for " .. hostname, vim.log.levels.ERROR)
return false
end

local fingerprint = vim.fn.system('echo "' .. scan .. '" | ssh-keygen -lf -')
if fingerprint == "" then
vim.notify("Could not parse fingerprint for " .. hostname, vim.log.levels.ERROR)
return false
end
fingerprint = fingerprint:gsub("\n", "")

local prompt = string.format(
"The authenticity of host '%s' can't be established. %s Add this host key to %s? (y/n)",
hostname,
fingerprint,
ssh_known_hosts
)
vim.schedule(function()
ui.prompt_yes_no(prompt, function(item_short)
ui.clear_prompt()
if item_short == "y" then
local scan_cmd = string.format("ssh-keyscan %s >> %s", hostname, ssh_known_hosts)
local result = vim.fn.system(scan_cmd)
if vim.v.shell_error == 0 then
vim.notify("Host key added for " .. hostname, vim.log.levels.INFO)
callback()
else
vim.notify("Failed to add host key for " .. hostname .. "\n" .. result, vim.log.levels.ERROR)
end
else
vim.notify("Aborted adding host key for " .. hostname, vim.log.levels.WARN)
end
end)
end)
end

local function start_job()
vim.notify("Connecting to host (" .. (host["Name"] or target_host) .. ")...")
local skip_clean = false
Expand Down Expand Up @@ -176,7 +230,9 @@ M.mount_host = function(host, mount_dir, ask_pass)
vim.fn.chansend(id, password .. "\n")
end
end
start_job()
ensure_ssh_host_key(function()
start_job()
end)
end

M.unmount_host = function()
Expand Down
1 change: 1 addition & 0 deletions lua/remote-sshfs/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local default_opts = {
"/etc/ssh/ssh_config",
-- "/path/to/custom/ssh_config"
},
ssh_known_hosts = vim.fn.expand "$HOME" .. "/.ssh/known_hosts",
sshfs_args = {
"-o reconnect",
"-o ConnectTimeout=5",
Expand Down