diff options
-rw-r--r-- | openssh-config-html.lsp | 34 | ||||
-rw-r--r-- | openssh-connectedpeers-html.lsp | 31 | ||||
-rw-r--r-- | openssh-controller.lua | 74 | ||||
l---------[-rw-r--r--] | openssh-expert-html.lsp | 17 | ||||
-rw-r--r-- | openssh-model.lua | 201 | ||||
l---------[-rw-r--r--] | openssh-startstop-html.lsp | 24 | ||||
l---------[-rw-r--r--] | openssh-status-html.lsp | 19 |
7 files changed, 112 insertions, 288 deletions
diff --git a/openssh-config-html.lsp b/openssh-config-html.lsp index e76d1a2..6990014 100644 --- a/openssh-config-html.lsp +++ b/openssh-config-html.lsp @@ -1,38 +1,18 @@ -<% local form, viewlibrary, page_info, session = ... +<% local form, viewlibrary, page_info = ... require("viewfunctions") ---[[ -io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>") -io.write(html.cfe_unpack(form)) -io.write("</span>") ---]] %> <% if viewlibrary and viewlibrary.dispatch_component then viewlibrary.dispatch_component("status") end %> -<H1>Configuration</H1> -<H2>Guided Configuration</H2> -<FORM NAME="configuration" ACTION="" METHOD="POST"> -<H3>Settings</H3> -<DL> -<% -local myform = form -local tags = { "Port", "ListenAddress", "PasswordAuthentication", "UseDNS",} -displayinfo(myform,tags) +<H1><%= form.label %></H1> +<% + form.action = page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action + local order = {"Port", "ListenAddress", "PermitRootLogin", "PasswordAuthentication", "UseDNS"} + displayform(form, order) %> -</DL> -<H3>Save</H3> -<DL> -<% -local myform = form -local tags = { "cmdsave",} -displayinfo(myform,tags) -%> -</DL> -</FORM> - -<% if viewlibrary and viewlibrary.dispatch_component and session.permissions[page_info.controller].startstop then +<% if viewlibrary and viewlibrary.dispatch_component then viewlibrary.dispatch_component("startstop") end %> diff --git a/openssh-connectedpeers-html.lsp b/openssh-connectedpeers-html.lsp index 9fdbca8..5657e36 100644 --- a/openssh-connectedpeers-html.lsp +++ b/openssh-connectedpeers-html.lsp @@ -10,34 +10,41 @@ io.write("</span>") <H1>Connected peers</H1> <DL> <% +if #data == 0 then + io.write("No peers found\n") +end local col1="180px" for k,v in pairs(data) do - io.write("<H3>" .. (tostring(v.host) or "unkown") .. "</H3>") + io.write("<H3>" .. v.host) + if v.name and v.name ~= "" then io.write(" - "..v.name) end + io.write("</H3>\n") io.write("<TABLE>") for i=1, v.cnt do io.write("<TR>") if (v.tty[i]) then io.write("<TD WIDTH='20px' STYLE='padding-left:20px;vertical-align:top;'><IMG SRC='/skins/static/tango/16x16/apps/utilities-terminal.png' HEIGHT='16' WIDTH='16'></TD>") - io.write("<TD STYLE='padding-bottom:10px'>") + io.write("<TD STYLE='padding-bottom:10px'>\n") io.write("<TABLE>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session TTY:</TD><TD>".. tostring(v.tty[i]['tty']) .. "</TD></TR>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Started:</TD><TD>".. tostring(v.tty[i]['time']) .. "</TD></TR>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Idle:</TD><TD>".. tostring(v.tty[i]['idle']) .. "</TD></TR>") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session user:</TD><TD>".. v.tty[i].user .. "</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session TTY:</TD><TD>".. v.tty[i].tty .. "</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Started:</TD><TD>".. v.tty[i].time .. "</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Idle:</TD><TD>".. v.tty[i].idle .. "</TD></TR>\n") io.write("</TABLE>") - io.write("</TD>") + io.write("</TD>\n") else io.write("<TD WIDTH='20px' STYLE='padding-left:20px;vertical-align:top;'><IMG SRC='/skins/static/tango/16x16/emblems/emblem-unreadable.png' HEIGHT='16' WIDTH='16'></TD>") - io.write("<TD STYLE='padding-bottom:10px'>") + io.write("<TD STYLE='padding-bottom:10px'>\n") io.write("<TABLE>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session TTY:</TD><TD>No records</TD></TR>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Started:</TD><TD>No records</TD></TR>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Idle:</TD><TD>No records</TD></TR>") - io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Other:</TD><TD>This could be a sshfs session</TD></TR>") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session user:</TD><TD>No records</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session TTY:</TD><TD>No records</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Started:</TD><TD>No records</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Session Idle:</TD><TD>No records</TD></TR>\n") + io.write("<TR><TD WIDTH='"..col1.."' STYLE='font-weight:bold;'>Other:</TD><TD>This could be a sshfs session</TD></TR>\n") io.write("</TABLE>") - io.write("</TD>") + io.write("</TD>\n") end io.write("</TR>") end diff --git a/openssh-controller.lua b/openssh-controller.lua index 30800f5..6a76512 100644 --- a/openssh-controller.lua +++ b/openssh-controller.lua @@ -3,8 +3,6 @@ module(..., package.seeall) -- Load libraries require("controllerfunctions") -local checkboxes = { "PermitRootLogin", "PasswordAuthentication", "UseDNS" } - default_action = "status" function status(self) @@ -12,75 +10,7 @@ function status(self) end function config(self) - local output = {} - local errtxt = {} - local successfuledit - if (self.clientdata.cmdsave) then - local fields = { "Port", "ListenAddress", "PermitRootLogin", "PasswordAuthentication", "UseDNS", } - local newconfig = {} - for _ , v in pairs(fields) do - newconfig[v] = self.clientdata[v] or "" - end - successfuledit, errtxt = self.model.write_config(newconfig) - end - - local config = self.model.read_config() or {} - output.cmdsave = cfe({ - name="cmdsave", - label="Save above changes", - value="Apply", - type="submit", - }) - - output.Port = cfe({ - name="Port", - label="Port", - value=config.Port, - }) - output.ListenAddress = cfe({ - name="ListenAddress", - label="Listen address", - value=config.ListenAddress, - }) - output.PermitRootLogin = cfe({ - name="PermitRootLogin", - label="Permit Root Login", - }) - - output.PasswordAuthentication = cfe({ - name="PasswordAuthentication", - label="Password Authentication", - }) - - output.UseDNS = cfe({ - name="UseDNS", - label="Use DNS", - }) - - -- Display checkboxes checked/unchecked - for k,v in pairs(checkboxes) do - output[v]['value']="yes" - output[v]['type']="checkbox" - if (config[v]) and (string.lower(tostring(config[v] or "")) == "yes") then - output[v]['checked']="yes" - end - end - - -- Display results of previous save action - if (self.clientdata.cmdsave) and not (successfuledit) then - for k,v in pairs(self.clientdata) do - if (output) and (output[k]) and (k) then - output[k]['value'] = self.clientdata[k] - output[k]['errtxt'] = errtxt[k] - end - end - - output.cmdsave.errtxt = "Save action was canceled because there was invalid input." - elseif (self.clientdata.cmdsave) and (successfuledit) then - output.cmdsave.descr = "* Configuration was succesfully saved" - end - - return output + return controllerfunctions.handle_form(self, self.model.read_config, self.model.update_config, self.clientdata, "Save", "Edit Config", "Configuration Saved") end function startstop(self) @@ -94,5 +24,3 @@ end function connectedpeers(self) return self.model.list_conn_peers() end -function welcome(self) -end diff --git a/openssh-expert-html.lsp b/openssh-expert-html.lsp index d349048..207f324 100644..120000 --- a/openssh-expert-html.lsp +++ b/openssh-expert-html.lsp @@ -1,16 +1 @@ -<% local form, viewlibrary, page_info, session = ... %> -<% require("viewfunctions") %> - -<% if viewlibrary and viewlibrary.dispatch_component then - viewlibrary.dispatch_component("status") -end %> - -<% -local pattern = string.gsub(page_info.prefix..page_info.controller, "[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%1") -local func = haserl.loadfile(page_info.viewfile:gsub(pattern..".*$", "/") .. "filedetails-html.lsp") -func(form, viewlibrary, page_info, session) -%> - -<% if viewlibrary and viewlibrary.dispatch_component and session.permissions[page_info.controller].startstop then - viewlibrary.dispatch_component("startstop") -end %> +../expert-html.lsp
\ No newline at end of file diff --git a/openssh-model.lua b/openssh-model.lua index 4df9abd..4aac198 100644 --- a/openssh-model.lua +++ b/openssh-model.lua @@ -4,8 +4,6 @@ module(..., package.seeall) require("modelfunctions") require("validator") require("fs") -require("posix") -require("getopts") -- Set variables local configfile = "/etc/ssh/sshd_config" @@ -14,92 +12,40 @@ local packagename = "openssh-server" local header = "SSH" local path="PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " -local default = { - Port = 22, - ListenAddress = "0.0.0.0", --- PermitRootLogin = true, - PasswordAuthentication = true, - UseDNS = true, -} - -- ################################################################################ -- LOCAL FUNCTIONS -local function parseconfigfile(file) - file = file or "" - local retval = {} - for line in string.gmatch(file, "([^\n]+)\n?") do - line = string.gsub(line, "#.*$", "") - if line and line ~= "" then - table.insert(retval, {}) - for word in string.gmatch(line, "%S+") do - table.insert(retval[#retval], word) - end - end - end - - return retval -end - -- return "Yes" or "No" on true/false or value as string local function config_value(value) if type(value) == "boolean" then if value then - return "Yes" + return "yes" else - return "No" + return "no" end end return tostring(value) end -local function validateconfig(config) +local function validate_config(config) + local success = true - if config.ListenAddress and not validator.is_ipv4(config.ListenAddress) then - return false, { ['ListenAddress'] = "You entered invalid IP", } + if not validator.is_ipv4(config.value.ListenAddress.value) then + config.value.ListenAddress.errtxt = "Invalid IP" + success = false end - - if config.Port and not validator.is_port(config.Port) then - return false, { ['Port'] = "You entered invalid Port", } + if not validator.is_port(config.value.Port.value) then + config.value.Port.value = "Invalid Port" + success = false end - return true + return success, config end + -- ################################################################################ -- PUBLIC FUNCTIONS --- valid keywords and default config - -function read_config() - local conf = {} - local f = io.open(configfile, "r") - local line, key, _, k, v - - if not f then - return nil - end - - -- clone default conf - for k, v in pairs(default) do - conf[k] = v - end - - for line in f:lines() do - line = string.gsub(line, "#.*", "") - for key, _ in pairs(default) do - local k,v = string.match(line, "^("..key..")%s+(.*)") - if k then - conf[k] = v - end - end - end - f:close() - return conf -end - - -function startstop_service(action)require("getopts") - +function startstop_service(action) return modelfunctions.startstop_service(processname, action) end @@ -116,49 +62,61 @@ function setconfigfile(filedetails) return modelfunctions.setfiledetails(filedetails) end -function write_config(config) - local k, v, lines, i,j - local errtxt = {} - local conf = {} +function read_config() + local output = {} + output.Port = cfe({ value=22, label="Port" }) + output.ListenAddress = cfe({ value="0.0.0.0", label="Listen address" }) + output.PermitRootLogin = cfe({ type="boolean", value=true, label="Permit Root Login" }) + output.PasswordAuthentication = cfe({ type="boolean", value=true, label="Password Authentication" }) + output.UseDNS = cfe({ type="boolean", value=true, label="Use DNS" }) + + local config = format.parse_configfile(fs.read_file(configfile)) + if config then + output.Port.value = config.Port or output.Port.value + output.ListenAddress.value = config.ListenAddress or output.ListenAddress.value + output.PermitRootLogin.value = not (config.PermitRootLogin == "no") + output.PasswordAuthentication.value = not (config.PasswordAuthentication == "no") + output.UseDNS.value = not (config.UseDNS == "no") + end + + return cfe({ type="group", value=output, label="OpenSSH Config" }) +end - local validated, errtxt = validateconfig(config) - if not validated then - return false, errtxt - end +function update_config(config) + local success, config = validate_config(config) - -- filter out unsupported keys - for k,v in pairs(default) do - if (config[k] == nil) or (config[k] == "") then - conf[k] = "no" - else - conf[k] = config[k] + if success then + for name,val in pairs(config.value) do + val.line = name.." "..config_value(val.value) end - end - lines = fs.read_file_as_array(configfile) or {} - for i, j in ipairs(lines) do - for k, v in pairs(conf) do - if string.match(j, "^#?"..k.."%s+") then - lines[i] = k .. " " .. config_value(v) - conf[k] = nil + local lines = {} + for line in string.gmatch(fs.read_file(configfile) or "", "([^\n]*)\n?") do + for name,val in pairs(config.value) do + if val.line and string.find(line, "^%s*#?%s*"..name) then + if string.find(line, "^%s*#") then + lines[#lines+1] = val.line + else + line = val.line + end + val.line = nil + end end + lines[#lines+1] = line end - end - -- append config opts to end - for k,v in pairs(conf) do - table.insert(lines, k .. " " .. config_value(v)) + for name,val in pairs(config.value) do + if val.line then + lines[#lines+1] = val.line + val.line = nil + end + end + fs.write_file(configfile, string.gsub(table.concat(lines, "\n"), "\n+$", "")) + else + config.errtxt = "Failed to save config" end - -- write file - posix.mkdir(posix.dirname(configfile)) - local f = io.open(configfile, "w") - for _,i in ipairs(lines) do - f:write(i.."\n") - end - f:close() - - return true + return config end function list_conn_peers() @@ -167,42 +125,47 @@ function list_conn_peers() local ps = {} local who = {} config = read_config() - local f = io.popen( path .. 'netstat -lna | grep ' .. tostring(config.Port) .. ' | grep "ESTABLISHED"' ) + local f = io.popen( path .. 'netstat -lna | grep ":' .. tostring(config.value.Port.value) .. ' " | grep "ESTABLISHED"' ) for line in f:lines() do - local peer = string.match(line, "^%S*%s*%S*%s*%S*%s*%S*%s*(%S*)") - peer = string.match(peer, "(%d*%.%d*%.%d*%.%d*):%d*$") - if (peer) then - if not (netstat[peer]) then netstat[peer] = {cnt=0} end - netstat[peer]['cnt'] = (tonumber(netstat[peer]['cnt']) + 1) + local peer = string.match(line, "^%S+%s+%S+%s+%S+%s+%S+%s+(%S+)") + peer = string.match(peer, "(%d+%.%d+%.%d+%.%d+):%d*$") + if peer then + if not netstat[peer] then + local g = io.popen( path .. "dnsname " .. peer) + local name = g:read("*l") + g:close() + netstat[peer] = {cnt=0, name=name} + end + netstat[peer].cnt = netstat[peer].cnt + 1 end end f:close() local f = io.popen( path .. 'ps | grep "sshd:" | grep -v "grep"' ) for line in f:lines() do - table.insert(ps, string.match(line,".-%@(%S*)$")) + table.insert(ps, string.match(line,"@(%S+)")) end f:close() for peer,v in pairs(netstat) do - if not (netstat[peer]['tty']) then netstat[peer]['tty'] = {} end - local f = io.popen( path .. 'who | grep "' .. tostring(peer) .. '" | egrep "' .. table.concat(ps, "|") .. '"' ) + if not (netstat[peer].tty) then netstat[peer].tty = {} end + local cmd = path .. 'who | egrep "' .. peer + if v.name and v.name ~= "" then cmd = cmd .. '|' .. v.name end + cmd = cmd .. '" | egrep "' .. table.concat(ps, "|") .. '"' + local f = io.popen( cmd ) for line in f:lines() do local user,tty,idle,time = string.match(line, "^(%S*)%s*(%S*)%s*(%S*)%s*(%S*%s*%S*%s*%S*)") - table.insert(netstat[peer]['tty'], { - user=user, - tty=tty, - idle=idle, - time=time, + table.insert(netstat[peer].tty, { + user=user, + tty=tty, + idle=idle, + time=time, }) end f:close() - end - - for k,v in pairs(netstat) do table.insert(output, v) - output[#output]['host'] = k + output[#output]['host'] = peer end return output diff --git a/openssh-startstop-html.lsp b/openssh-startstop-html.lsp index 56404f9..0ea2627 100644..120000 --- a/openssh-startstop-html.lsp +++ b/openssh-startstop-html.lsp @@ -1,23 +1 @@ -<% local data, viewlibrary, page_info = ... %> - -<H1>Management</H1> -<DL> -<form action="<%= page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action %>" method="POST"> -<DT>Program control-panel</DT> -<DD> -<input class="submit" type="submit" name="action" value="Start" <% if data.value.status.value== "Enabled" then io.write("disabled") end %>> -<input class="submit" type="submit" name="action" value="Stop" <% if data.value.status.value== "Disabled" then io.write("disabled") end %>> -<input class="submit" type="submit" name="action" value="Restart" <% if data.value.status.value== "Disabled" then io.write("disabled") end %>> -</DD> -</form> - -<% if data.value.result then %> -<DT>Previous action result</DT> -<DD> -<% if data.value.result.descr then %> -<P CLASS='descr'><%= string.gsub(data.value.result.descr, "\n", "<BR>") %></P> -<% end if data.value.result.errtxt then %> -<P CLASS='error'><%= string.gsub(data.value.result.errtxt, "\n", "<BR>") %></P> -<% end end %> -</DD> -</DL> +../startstop-html.lsp
\ No newline at end of file diff --git a/openssh-status-html.lsp b/openssh-status-html.lsp index c126d2e..b2f8480 100644..120000 --- a/openssh-status-html.lsp +++ b/openssh-status-html.lsp @@ -1,18 +1 @@ -<% local data, viewlibrary, page_info, session = ... -require("viewfunctions") ---[[ -io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>") -io.write(html.cfe_unpack(data)) -io.write("</span>") ---]] -%> - -<H1>System Info</H1> -<DL> -<% -displayitem(data.value.status) -displayitem(data.value.version) -displayitem(data.value.autostart) -%> -</DL> - +../status-html.lsp
\ No newline at end of file |