From 7e68058a731feeb17dd6a609acb26bb68ba06ff8 Mon Sep 17 00:00:00 2001 From: Ted Trask Date: Tue, 6 Nov 2012 23:02:06 +0000 Subject: First cut at awall ACF --- awall-model.lua | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 awall-model.lua (limited to 'awall-model.lua') diff --git a/awall-model.lua b/awall-model.lua new file mode 100644 index 0000000..7e79813 --- /dev/null +++ b/awall-model.lua @@ -0,0 +1,275 @@ +module(..., package.seeall) + +-- Load libraries +require("posix") +require("json") +require("modelfunctions") +processinfo = require("acf.processinfo") +fs = require("acf.fs") +--validator = require("acf.validator") + +-- Set variables +local packagename = "awall" + +local etcpath = "/etc/awall/" +local etcoptionalpath = "/etc/awall/optional/" +local usrpath = "/usr/share/awall/mandatory/" +local usroptionalpath = "/usr/share/awall/optional/" + +local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " + +-- ################################################################################ +-- LOCAL FUNCTIONS + +local findfiles = function(where) + local files = {} + for d in posix.files(where) do + if string.find(d, "%.json$") then + if fs.is_file(where .. d) and string.find(d, "%.json$") then + files[#files+1] = where..d + elseif fs.is_link(where .. d) then + -- awall will use links, but we want to drop the links from /etc/awall/ to one of the optional dirs + -- because those are the ones handled by enable/disable + local link = posix.dirname(posix.readlink(where..d) or "").."/" +logevent("link = "..link) + if where == etcpath and (string.find(link, "^"..etcoptionalpath.."$") or string.find(link, "^"..usroptionalpath.."$")) then + -- do nothing + else + files[#files+1] = where..d + end + + end + end + end + return files +end + +local validatefiledetails = function(filedetails) + local success = true + local res, err = pcall(function() + local jsonoutput, count = json.decode(filedetails.value.filecontent.value) + end) + if not res and err then + success = false + end + + if not success then + filedetails.value.filecontent.errtxt = "Invalid json code\n"..(err or "") + end + return success, filedetails +end + +local validateeditablefile = function(filename) + -- get/setfiledetails only work for files (not links), this prevents editing/deleting the enable links + local dir = posix.dirname(filename or "").."/" + if fs.is_file(filename) and string.find(filename, "%.json$") and (dir==etcpath or dir==etcoptionalpath) then + return true + else + return false + end +end + +-- ################################################################################ +-- PUBLIC FUNCTIONS + +function getstatus() + local status = {} + + local value, errtxt = processinfo.package_version(packagename) + status.version = cfe({ + label="Program version", + value=value, + errtxt=errtxt, + name=packagename + }) + + return cfe({ type="group", value=status, label="AWall Status" }) +end + +function get_startstop(self, clientdata) + local actions = {"Verify", "Translate", "Activate"} + return cfe({ type="group", label="Management", value={}, option=actions }) +end + +function startstop_service(self, startstop, action) + if not action then + startstop.errtxt = "Invalid Action" + else + local cmd + if action == "Verify" then + cmd = path.."awall translate -V 2>&1" + elseif action == "Translate" then + cmd = path.."awall translate 2>&1" + else + cmd = path.."awall activate -f 2>&1" + end + local f = io.popen(cmd) + startstop.descr = f:read("*a") + f:close() + end + return startstop +end + +function list_policies() + -- core-router disabled BSN core router + local policies = {} + local reversepolicies = {} + local errtxt + local cmd = path.."awall list 2>&1" + local f = io.popen(cmd) + for l in f:lines() do + local a,b,c = string.match(l, "(%S+)%s+(%S+)%s*(.*)") + if a and a == "/usr/bin/lua:" then + errtxt = b.." "..c + break + end + if a then + policies[#policies+1] = {name=a, status=b, description=c} + reversepolicies[a] = #policies + end + end + f:close() + -- Since awall seems to crash (and not give results) when there is any error + -- Let's show the actual files too + local addfiles = function(files, editable, mandatory) + for i,d in ipairs(files) do + local name = string.match(d, "([^/]*)%.json$") + if reversepolicies[name] then + policies[reversepolicies[name]].filename = d + policies[reversepolicies[name]].editable = editable + if mandatory then policies[reversepolicies[name]].status = "mandatory" end + else + policies[#policies+1] = {name=name, filename=d, editable=editable} + if mandatory then policies[#policies].status = "mandatory" end + reversepolicies[name] = #policies + end + end + end + + local files = findfiles(usroptionalpath) + addfiles(files, false, false) + files = findfiles(etcoptionalpath) + addfiles(files, true, false) + files = findfiles(usrpath) + addfiles(files, false, true) + files = findfiles(etcpath) + addfiles(files, true, true) + + table.sort(policies, function(a,b) return a.name < b.name end) + + return cfe({ type="list", value=policies, label="Policies", errtxt=errtxt }) +end + +function get_newpolicy() + local newpolicy = {} + newpolicy.name = cfe({ label="Name", seq=1 }) + newpolicy.optional = cfe({ type="boolean", label="Optional", seq=2 }) + return cfe({ type="group", value=newpolicy, label="New Policy" }) +end + +function create_policy(self, newpolicy) + local success = true + local name = newpolicy.value.name.value + + if name == "" then + newpolicy.value.name.errtxt = "Invalid name" + success = false + else + local policies = list_policies() + for i,pol in ipairs(policies.value) do + if pol.name == newpolicy.value.name.value then + newpolicy.value.name.errtxt = "Name already exists" + success = false + break + end + end + end + + if success then + local path + if newpolicy.value.optional.value then + path = etcoptionalpath + else + path = etcpath + end + path = path..name..".json" + if posix.stat(path) then + newpolicy.value.name.errtxt = path.." already exists" + success = false + else + fs.write_file(path, "{}") + end + end + + if not success then + newpolicy.errtxt = "Failed to create policy file" + end + + return newpolicy +end + +function get_delete_policy(self, clientdata) + retval = {} + retval.filename = cfe({ value=clientdata.filename or "", label="File Name" }) + return cfe({ type="group", value=retval, label="Delete Policy File" }) +end + +function delete_policy(self, delpolicy) + if validateeditablefile(delpolicy.value.filename.value) then + os.remove(delpolicy.value.filename.value) + else + delpolicy.errtxt = "Failed to delete policy" + delpolicy.value.filename.errtxt="Policy not found" + end + + return delpolicy +end + +function read_policyfile(self, clientdata) + -- Can read from all 4 locations + return modelfunctions.getfiledetails(clientdata.filename, function(filename) + local dir = posix.dirname(filename or "").."/" + if string.find(filename, "%.json$") and (dir==etcpath or dir==etcoptionalpath or dir==usrpath or dir==usroptionalpath) then + return true + else + return false + end + end) +end + +function get_policyfile(self, clientdata) + -- Can only get (for editing) from /etc/ locations + return modelfunctions.getfiledetails(clientdata.filename, validateeditablefile) +end + +function update_policyfile(self, filedetails) + return modelfunctions.setfiledetails(self, filedetails, validateeditablefile, validatefiledetails) +end + +function get_enablepolicy(self, clientdata) + local policy = {} + policy.name = cfe({ value=clientdata.name or "", label="Name", seq=1 }) + return cfe({ type="group", value=policy, label="Policy" }) +end + +function enable_policy(self, enable) + local cmd = path.."awall enable "..format.escapespecialcharacters(enable.value.name.value).." 2>&1" + local f = io.popen(cmd) + local result = f:read("*a") + f:close() + if result ~= "" then + enable.errtxt = result + end + return enable +end + +function disable_policy(self, disable) + local cmd = path.."awall disable "..format.escapespecialcharacters(disable.value.name.value).." 2>&1" + local f = io.popen(cmd) + local result = f:read("*a") + f:close() + if result ~= "" then + disable.errtxt = result + end + return disable +end -- cgit v1.2.3