summaryrefslogtreecommitdiffstats
path: root/shorewall-model.lua
blob: 7dee572029e1cf6c5d6890e83dc7fe044fbc1c02 (plain)
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
module(..., package.seeall)

-- Load libraries
require("fs")
require("procps")
require("getopts")
require("format")
require("daemoncontrol")
require("validator")
require("processinfo")

-- Set variables
local configfile = "/etc/shorewall/shorewall.conf"
local processname = "shorewall"
local packagename = "shorewall"
local baseurl = "/etc/shorewall/"
local config = {}

-- ################################################################################
-- LOCAL FUNCTIONS

local function getloglevels()
	local loglevels = {}
	for i=1,8 do
		table.insert(loglevels,i)
	end
	return loglevels
end

local function getdetails()
	local f,error = io.popen("/sbin/shorewall status")
	local fake = f:read("*l")
	local fake = f:read("*l")
	local programstatus = f:read("*l") or ""
	local programstate = f:read("*l") or ""
	f:close()
	local f,error = io.popen("/sbin/shorewall version")
	local programversion = "shorewall-" .. f:read("*l")
	f:close()
	return programversion,programstatus,programstate
end

local function read_config(file)
	local path = baseurl .. file
	if not (fs.is_file(path)) then
		return {}
	end
	local filecontent = fs.read_file_as_array(path)
	local output = {}
	for k,v in pairs(filecontent) do
		if not string.find ( v, "^[;#].*" ) then
			table.insert(output, v)
		end
	end
	return output
end

---[[
local function addremove_config( addremove, file, value, orgvalue )
	filepath = baseurl .. file
	local cmdoutput

	-- Check if we are about to change a valid filename
	local isvalidfile
	for k,v in pairs(getfilelist()) do
		isvalidfile = true
		if (v.value == filepath) then
			break
		end
		isvalidfile = false
	end
	if not (fs.is_file(filepath)) or not (isvalidfile) then
		return false, cfe({ 
			name="model:addremove_config()", 
			errtxt="'" .. filepath .. "' is not a valid file!",
			})
	end

	if not (type(value) == "table") then
		return false, cfe({ 
			name="model:addremove_config()", 
			errtxt="Value should come as an array!",
			})
	end		

	local filecontentarray = fs.read_file_as_array(filepath)

	if (addremove == "delete" ) then
		local modifyrow
		local orgrecordtable = {}
		for word in string.gmatch(orgvalue, "%S+") do
			table.insert(orgrecordtable, word)
		end
		for i=1, #filecontentarray do
			local recordtable = {}
			for word in string.gmatch(filecontentarray[i], "%S+") do
				table.insert(recordtable, word)
			end

			if (table.concat(recordtable) == table.concat(orgrecordtable)) then
				modifyrow = i
			end
		end

		if (tonumber(modifyrow)) then
			table.remove(filecontentarray, modifyrow)
			fs.write_file(filepath, table.concat(filecontentarray, "\n"))
			return true, cfe({ 
				name="model:addremove_config()", 
				descr="* Record was successfully deleted!",
				})
		else
			return false, cfe({ 
				name="model:addremove_config()", 
				errtxt="Record was not deleted!",
				})
		end

	elseif (addremove == "add" ) then
		--Check if such record already exists
		for k,v in pairs(filecontentarray) do
			if not string.find ( v, "^[;#].*" ) then
				local recordtable = {}
				for word in string.gmatch(v, "%S+") do
					table.insert(recordtable, word)
				end
				if (table.concat(recordtable) == table.concat(value)) then
					return false, cfe({ 
						name="model:addremove_config()", 
						errtxt="The config already holds this kind of config!",
						})
				end
			end
		end

		table.insert(filecontentarray, (#filecontentarray), table.concat(value, "\t"))
		fs.write_file(filepath, table.concat(filecontentarray, "\n"))
		return true, cfe({ 
			name="model:addremove_config()", 
			descr="* Record was successfully added!",
			})

	elseif (addremove == "modify" ) then
		local modifyrow
		local orgrecordtable = {}
		for word in string.gmatch(orgvalue, "%S+") do
			table.insert(orgrecordtable, word)
		end
		for i=1, #filecontentarray do
			local recordtable = {}
			for word in string.gmatch(filecontentarray[i], "%S+") do
				table.insert(recordtable, word)
			end

			if (table.concat(recordtable) == table.concat(orgrecordtable)) then
				modifyrow = i
			end
		end

		if (tonumber(modifyrow)) then
			table.remove(filecontentarray, modifyrow)
			table.insert(filecontentarray, modifyrow, table.concat(value, "\t"))
			fs.write_file(filepath, table.concat(filecontentarray, "\n"))
			return true, cfe({ 
				name="model:addremove_config()", 
				descr="* Record was successfully modified!",
				})
		else
			return false, cfe({ 
				name="model:addremove_config()", 
				errtxt="Record was not modified!",
				})
		end

	else
		return false, cfe({ 
				name="model:addremove_config()", 
				errtxt="Wrong usage of this function! Available options are [add|delete|modify]. You chose '" .. addremove .. "'",
				})
	end

	return false, cfe({ 
			name="model:addremove_config()", 
			errtxt="Something went wrong!",
			debug=value,
			})
end
--]]


-- ################################################################################
-- PUBLIC FUNCTIONS

function modify_config(self, addremove, file, value, orgvalue )
	return addremove_config(addremove, file, value, orgvalue )
end

-- action should be a CFE
function startstop_service ( self, action )
	local cmd = action.value
	local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, cmd)
	action.descr=cmdmessage
	action.errtxt=cmderror
	-- Reporting back (true|false, the original acition)
	return cmdresult,action

end

function getconfig()
	local config = {}

	config.params = cfe({ 
		name = "params",
		label="List of parameters",
		type="select",
		option=read_config("params"),
		 })
	config.params.size=#config.params.option + 1

	config.interfaces = cfe({ 
		name = "interfaces",
		label="List of interfaces",
		type="select",
		option=read_config("interfaces"),
		 })
	config.interfaces.size=#config.interfaces.option + 1

	config.zones = cfe({ 
		name = "zones",
		label="List of zones",
		type="select",
		option=read_config("zones"),
		 })
	config.zones.size=#config.zones.option + 1

	config.policy = cfe({ 
		name = "policy",
		label="List of policy",
		type="select",
		option=read_config("policy"),
		 })
	config.policy.size=#config.policy.option + 1

	config.rules = cfe({ 
		name = "rules",
		label="List of rules",
		type="select",
		option=read_config("rules"),
		 })
	config.rules.size=#config.rules.option + 1

	return config

end

function getstatus()
	local status = {}

	local value, errtxt = processinfo.package_version(packagename)
	status.version = cfe({ name = "version",
		label="Program version",
		value=value,
		errtxt=errtxt,
		 })

	local programversion,programstatus,programstate = getdetails()
	status.status = cfe({ name="status",
		label="Program status",
		value=programstatus,
		})

	status.state = cfe({ name="state",
		label="Program reports",
		value=programstate,
		})

	local autostart_sequense, autostart_errtxt = processinfo.process_botsequence(processname)
	status.autostart = cfe({ name="autostart",
		label="Autostart sequence",
		value=autostart_sequense,
		errtxt=autostart_errtxt,
		})

	return status
end

function configcheck ()
	local check = {}
	local f,err = io.popen("/bin/echo -n '>> Check starts at: ';/bin/date; /bin/echo; /etc/init.d/shorewall check; /bin/echo; /bin/echo -n '>> Check stops at: '; /bin/date;")
	local checkresult = f:read("*a")
	f:close()
	check.checkresult = cfe({ name = "checkresult",
		type="longtext",
		label="Result of checking config",
		value=checkresult,
		 })
	return check
end

function get_defined_zones ()
	local output = {}
	for k,v in pairs(read_config("zones")) do
		table.insert(output, string.match(v, "^%s*(%S*)"))
	end
	return output
end

function getlogfile ()
	local logfile = {}
	local cmdaction = "grep Shorewall /var/log/messages"
	local f, error = io.popen(cmdaction ,r)
	local checkresult = f:read("*a")
	f:close()
	logfile.checkresult = cfe({ name = "checkresult",
		type="longtext",
		label="Result of logfiles",
		value=checkresult,
		 })
	logfile.filename = cfe({ 
		name="filename",
		label="File name",
		value=cmdaction,
		})
	return logfile
end

function getfilelist ()
	local filepath = baseurl
	local listed_files = {}

	local k,v
	for name in posix.files(filepath) do
		if not string.match(name, "^%.") and not string.match(name, "^Makefile") then
			local filedetails = fs.stat(filepath .. name)
			table.insert ( listed_files , cfe({name=name, value=filepath .. name, mtime=filedetails.mtime, size=filedetails.size,}) )
		end
	end

	table.sort(listed_files, function (a,b) return (a.name < b.name) end )

	return listed_files
end

function getfiledetails(self,search)
	local file = {}
	local path = nil
	--Validate filename
	local available_files = getfilelist()
	for k,v in pairs(available_files) do
		if ( tostring(available_files[k]["value"]) == tostring(search.value) ) then
			path = tostring(search.value)
		end
	end
	if not (path) or (path == "") then
		file["filename"] = search
		file["filename"]["label"] = "File name"
		file["filename"]["errtxt"] = "Invalid path!"
		return file
	end

	local filedetails = fs.stat(path)
	file["filename"] = cfe({ 
		name="filename",
		label="File name",
		value=path,
		})
	file["filesize"] = cfe({ 
		name="filesize",
		label="File size",
		value=filedetails.size,
		})
	file["mtime"] = cfe({ 
		name="mtime",
		label="File name",
		value=filedetails.mtime,
		})
	file["filecontent"] = cfe({ 
		type="longtext",
		name="filecontent",
		label="File content",
		value=fs.read_file(path),
		})

	return file
end

-- modifications should be a CFE
function updatefilecontent (self, filetochange)
	local path = nil
	--Validate filename
	local available_files = getfilelist()
	for k,v in pairs(available_files) do
		if ( tostring(available_files[k]["value"]) == tostring(filetochange.name) ) then
			path = tostring(filetochange.name)
		end
	end
	if not (path) then
		filetochange.errtxt = "Invalid path!"
		return filetochange
	end

	local file_result,err = fs.write_file(path, format.dostounix(filetochange.value))
	return file_result, err
end