1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
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
|