module(..., package.seeall) -- Load libraries require("modelfunctions") require("validator") require("fs") -- Set variables local configfile = "/etc/ssh/sshd_config" local processname = "sshd" local packagename = "openssh-server" local header = "SSH" local path="PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " -- ################################################################################ -- LOCAL FUNCTIONS -- 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" else return "no" end end return tostring(value) end local function validate_config(config) local success = true if not validator.is_ipv4(config.value.ListenAddress.value) then config.value.ListenAddress.errtxt = "Invalid IP" success = false end if not validator.is_port(config.value.Port.value) then config.value.Port.value = "Invalid Port" success = false end return success, config end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, header .. " status") end function getconfigfile() return modelfunctions.getfiledetails(configfile) end function setconfigfile(filedetails) filedetails.value.filename.value = configfile return modelfunctions.setfiledetails(filedetails) end 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 function update_config(config) local success, config = validate_config(config) if success then for name,val in pairs(config.value) do val.line = name.." "..config_value(val.value) end 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 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 return config end function list_conn_peers() local output = {} local netstat = {} local ps = {} local who = {} config = read_config() 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 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+)")) end f:close() for peer,v in pairs(netstat) do 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, }) end f:close() table.insert(output, v) output[#output]['host'] = peer end return output end