[feat] Integrated Dropbear SSH server (#3842)

* Add a menu item to start an ssh server

* Add blank login option
pull/3947/head
onde2rock 6 years ago committed by Frans de Jonge
parent fbd549bcfd
commit c0e80461ff

@ -100,8 +100,8 @@ common_settings.night_mode = {
}
common_settings.network = {
text = _("Network"),
sub_item_table = NetworkMgr:getMenuTable()
}
NetworkMgr:getMenuTable(common_settings)
common_settings.screen = {
text = _("Screen"),

@ -33,6 +33,15 @@ local order = {
"time",
-- end common settings
},
network = {
"network_wifi",
"network_proxy",
"network_restore",
"network_info",
"network_before_wifi_action",
"----------------------------",
"ssh",
},
tools = {
"calibre_wireless_connection",
"evernote",

@ -52,6 +52,15 @@ local order = {
"djvu_render_mode",
"status_bar",
},
network = {
"network_wifi",
"network_proxy",
"network_restore",
"network_info",
"network_before_wifi_action",
"----------------------------",
"ssh",
},
tools = {
"read_timer",
"calibre_wireless_connection",

@ -244,14 +244,12 @@ function NetworkMgr:getBeforeWifiActionMenuTable()
}
end
function NetworkMgr:getMenuTable()
return {
self:getWifiMenuTable(),
self:getProxyMenuTable(),
self:getRestoreMenuTable(),
self:getInfoMenuTable(),
self:getBeforeWifiActionMenuTable(),
}
function NetworkMgr:getMenuTable(common_settings)
common_settings.network_wifi = self:getWifiMenuTable()
common_settings.network_proxy = self:getProxyMenuTable()
common_settings.network_restore = self:getRestoreMenuTable()
common_settings.network_info = self:getInfoMenuTable()
common_settings.network_before_wifi_action = self:getBeforeWifiActionMenuTable()
end
function NetworkMgr:showNetworkMenu(complete_callback)

@ -0,0 +1,158 @@
local DataStorage = require("datastorage")
local Device = require("device")
local InfoMessage = require("ui/widget/infomessage") -- luacheck:ignore
local InputDialog = require("ui/widget/inputdialog")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
-- This plugin use a patched dropbear that add two things :
-- the -n option to allow login without password
-- read the keyfile from the relative path: settings/SSH/authorized_keys
local path = DataStorage:getFullDataDir()
if not util.pathExists("dropbearmulti") then
return { disabled = true, }
end
local SSH = WidgetContainer:new{
name = 'SSH',
is_doc_only = false,
}
function SSH:init()
self.SSH_port = G_reader_settings:readSetting("SSH_port") or "2222"
self.allow_no_password = false
self.ui.menu:registerToMainMenu(self)
end
function SSH:start()
local cmd = string.format("%s %s %s %s%s %s %s %s",
"./dropbearmulti dropbear",
"-E", "-r ", path, "/settings/SSH/dropbear_rsa_host_key",
"-p", self.SSH_port,
"-P /tmp/dropbear_koreader.pid")
if self.allow_no_password then
cmd = string.format("%s %s", cmd, "-n")
end
if os.execute("command -v iptables") then
os.execute(string.format("%s %s %s",
"iptables -A INPUT -p tcp --dport", self.SSH_port,
"-m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT"))
os.execute(string.format("%s %s %s",
"iptables -A OUTPUT -p tcp --sport", self.SSH_port,
"-m conntrack --ctstate ESTABLISHED -j ACCEPT"))
end
-- An SSH/telnet server of course needs to be able to manipulate pseudoterminals...
-- Some Kobo don't have this, so we check it on every platfrom, it can't hurt.
os.execute([[if [ ! -d "/dev/pts" ] ; then
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
fi]])
if not util.pathExists(path.."/settings/SSH/") then
os.execute("mkdir "..path.."/settings/SSH")
end
if not util.pathExists(path.."/settings/SSH/dropbear_rsa_host_key") then
os.execute("./dropbearmulti dropbearkey -t rsa -f "..path.."/settings/SSH/dropbear_rsa_host_key")
end
logger.dbg("[Network] Launching SSH server : ", cmd)
if os.execute(cmd) == 0 then
local info = InfoMessage:new{
timeout = 5,
text = string.format("%s %s \n %s",
_("SSH port: "), self.SSH_port,
Device.retrieveNetworkInfo and Device:retrieveNetworkInfo() or _("Could not retrieve network info.")),
}
UIManager:show(info)
else
local info = InfoMessage:new{
timeout = 5,
text = _("Error"),
}
UIManager:show(info)
end
end
function SSH:isRunning()
return util.pathExists("/tmp/dropbear_koreader.pid")
end
function SSH:stop()
os.execute("cat /tmp/dropbear_koreader.pid | xargs kill")
end
function SSH:show_port_dialog()
self.port_dialog = InputDialog:new{
title = _("Choose SSH port"),
input = self.SSH_port,
input_type = "number",
input_hint = self.SSH_port,
buttons = {
{
{
text = _("Cancel"),
callback = function()
UIManager:close(self.port_dialog)
end,
},
{
text = _("Save"),
is_enter_default = true,
callback = function()
local value = tonumber(self.port_dialog:getInputText())
if value then
self.SSH_port = value
G_reader_settings:saveSetting("SSH_port", self.SSH_port)
UIManager:close(self.port_dialog)
end
end
},
},
},
}
UIManager:show(self.port_dialog)
self.port_dialog:onShowKeyboard()
end
function SSH:addToMainMenu(menu_items)
menu_items.ssh = {
text = _("SSH server"),
sub_item_table = {
{
text = _("Start SSH server"),
callback = function() return self:start() end,
enabled_func = function() return not self:isRunning() end,
},
{
text = _("Stop SSH server"),
callback = self.stop,
enabled_func = self.isRunning,
},
{
text = _("Change SSH port"),
enabled_func = function() return not self:isRunning() end,
callback = function() return self:show_port_dialog() end,
},
{
text = _("Login without password (DANGEROUS)"),
checked_func = function() return self.allow_no_password end,
enabled_func = function() return not self:isRunning() end,
callback = function() self.allow_no_password = not self.allow_no_password end,
},
{
text = _("SSH public key"),
callback = function()
local info = InfoMessage:new{
timeout = 60,
text = _("Put your public SSH keys in "..path.."/settings/SSH/authorized_keys"),
}
UIManager:show(info)
end,
},
}
}
end
return SSH
Loading…
Cancel
Save