diff options
author | Ted Trask <ttrask01@yahoo.com> | 2012-11-06 23:02:06 +0000 |
---|---|---|
committer | Ted Trask <ttrask01@yahoo.com> | 2012-11-06 23:02:06 +0000 |
commit | 7e68058a731feeb17dd6a609acb26bb68ba06ff8 (patch) | |
tree | 2a97796627bdb7906e00e146ffa5d42feeaa6a6b | |
download | acf-awall-7e68058a731feeb17dd6a609acb26bb68ba06ff8.tar.bz2 acf-awall-7e68058a731feeb17dd6a609acb26bb68ba06ff8.tar.xz |
First cut at awall ACFv0.0.1
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | awall-controller.lua | 39 | ||||
l--------- | awall-editpolicy-html.lsp | 1 | ||||
-rw-r--r-- | awall-listpolicies-html.lsp | 51 | ||||
-rw-r--r-- | awall-model.lua | 275 | ||||
l--------- | awall-status-html.lsp | 1 | ||||
l--------- | awall-viewpolicy-html.lsp | 1 | ||||
-rw-r--r-- | awall.menu | 4 | ||||
-rw-r--r-- | awall.roles | 3 | ||||
-rw-r--r-- | config.mk | 10 |
11 files changed, 430 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aee4a0a --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +APP_NAME=awall +PACKAGE=acf-$(APP_NAME) +VERSION=0.0.1 + +APP_DIST=\ + awall* \ + + +EXTRA_DIST=README Makefile config.mk + +DISTFILES=$(APP_DIST) $(EXTRA_DIST) + +TAR=tar + +P=$(PACKAGE)-$(VERSION) +tarball=$(P).tar.bz2 +install_dir=$(DESTDIR)/$(appdir)/$(APP_NAME) + +all: +clean: + rm -rf $(tarball) $(P) + +dist: $(tarball) + +install: + mkdir -p "$(install_dir)" + cp -a $(APP_DIST) "$(install_dir)" + +$(tarball): $(DISTFILES) + rm -rf $(P) + mkdir -p $(P) + cp -a $(DISTFILES) $(P) + $(TAR) -jcf $@ $(P) + rm -rf $(P) + +# target that creates a tar package, unpacks is and install from package +dist-install: $(tarball) + $(TAR) -jxf $(tarball) + $(MAKE) -C $(P) install DESTDIR=$(DESTDIR) + rm -rf $(P) + +include config.mk + +.PHONY: all clean dist install dist-install @@ -0,0 +1 @@ +ACF for ppp diff --git a/awall-controller.lua b/awall-controller.lua new file mode 100644 index 0000000..9fa56a1 --- /dev/null +++ b/awall-controller.lua @@ -0,0 +1,39 @@ +module(..., package.seeall) + +default_action = "status" + +function status(self) + return self.model.getstatus() +end + +function startstop(self) + return self.handle_form(self, self.model.get_startstop, self.model.startstop_service, self.clientdata) +end + +function listpolicies(self) + return self.model.list_policies() +end + +function viewpolicy(self) + return self.model.read_policyfile(self, clientdata) +end + +function createpolicy(self) + return self.handle_form(self, self.model.get_newpolicy, self.model.create_policy, self.clientdata, "Create", "Create New Policy File", "Policy File Created") +end + +function deletepolicy(self) + return self.handle_form(self, self.model.get_delete_policy, self.model.delete_policy, self.clientdata, "Delete", "Delete Policy File", "Policy File Deleted") +end + +function editpolicy(self) + return self.handle_form(self, self.model.get_policyfile, self.model.update_policyfile, self.clientdata, "Save", "Edit Policy", "Policy File Saved") +end + +function enablepolicy(self) + return self.handle_form(self, self.model.get_enablepolicy, self.model.enable_policy, self.clientdata, "Enable", "Enable Policy", "Policy Enabled") +end + +function disablepolicy(self) + return self.handle_form(self, self.model.get_enablepolicy, self.model.disable_policy, self.clientdata, "Disable", "Disable Policy", "Policy Disabled") +end diff --git a/awall-editpolicy-html.lsp b/awall-editpolicy-html.lsp new file mode 120000 index 0000000..15b1930 --- /dev/null +++ b/awall-editpolicy-html.lsp @@ -0,0 +1 @@ +../filedetails-html.lsp
\ No newline at end of file diff --git a/awall-listpolicies-html.lsp b/awall-listpolicies-html.lsp new file mode 100644 index 0000000..1d807e9 --- /dev/null +++ b/awall-listpolicies-html.lsp @@ -0,0 +1,51 @@ +<% local form, viewlibrary, page_info, session = ... +require("htmlviewfunctions") +html = require("acf.html") +%> + +<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery-latest.js"></script> +<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery.tablesorter.js"></script> +<script type="text/javascript"> + $(document).ready(function() { + $(".deletepolicy").click(function(){ return confirm("Are you sure you want to delete this policy?")}); + }); +</script> + +<% htmlviewfunctions.displaycommandresults({"deletepolicy", "editpolicy", "viewpolicy", "enablepolicy", "disablepolicy", "startstop"}, session) %> +<% htmlviewfunctions.displaycommandresults({"createpolicy"}, session, true) %> + +<h1>Policies</h1> +<DL> +<% if form.errtxt then %><P CLASS='error'><%= string.gsub(html.html_escape(form.errtxt), "\n", "<BR>") %></P><% end %> +<TABLE> + <TR style="background:#eee;font-weight:bold;"> + <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Action</TD> + <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Status</TD> + <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Name</TD> + <TD style="white-space:nowrap;text-align:left;" class="header">Description</TD> + </TR> +<% for i,pol in ipairs(form.value) do %> + <TR> + <TD style="padding-right:20px;white-space:nowrap;"> + <% + if viewlibrary.check_permission("deletepolicy") and pol.editable and pol.status ~= "enabled" and pol.status ~= "required" then io.write(html.link{value = "deletepolicy?submit=true&filename=" .. pol.filename, label="Delete ", class="deletepolicy" }) end + if viewlibrary.check_permission("editpolicy") and pol.editable then io.write(html.link{value = "editpolicy?filename=" .. pol.filename.."&redir="..page_info.orig_action, label="Edit " }) end + if viewlibrary.check_permission("viewpolicy") and not pol.editable and pol.filename then io.write(html.link{value = "viewpolicy?filename=" .. pol.filename.."&redir="..page_info.orig_action, label="View " }) end + if viewlibrary.check_permission("enablepolicy") and (pol.status == "disabled" or pol.status == "required") then io.write(html.link{value = "enablepolicy?submit=true&name=" .. pol.name, label="Enable " }) end + if viewlibrary.check_permission("disablepolicy") and pol.status == "enabled" then io.write(html.link{value = "disablepolicy?submit=true&name=" .. pol.name, label="Disable " }) end + %> + </TD> + <TD style="white-space:nowrap;" width="90%"><%= html.html_escape(string.gsub(pol.status or "", "^%l", string.upper)) %></TD> + <TD style="white-space:nowrap;" width="90%"><%= html.html_escape(pol.name) %></TD> + <TD style="white-space:nowrap;" width="90%"><%= html.html_escape(pol.description) %></TD> + </TR> +<% end %> +</TABLE></DL> + +<% if viewlibrary and viewlibrary.dispatch_component and viewlibrary.check_permission("createpolicy") then + viewlibrary.dispatch_component("createpolicy") +end %> + +<% if viewlibrary and viewlibrary.dispatch_component and viewlibrary.check_permission("startstop") then + viewlibrary.dispatch_component("startstop") +end %> 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 diff --git a/awall-status-html.lsp b/awall-status-html.lsp new file mode 120000 index 0000000..b2f8480 --- /dev/null +++ b/awall-status-html.lsp @@ -0,0 +1 @@ +../status-html.lsp
\ No newline at end of file diff --git a/awall-viewpolicy-html.lsp b/awall-viewpolicy-html.lsp new file mode 120000 index 0000000..15b1930 --- /dev/null +++ b/awall-viewpolicy-html.lsp @@ -0,0 +1 @@ +../filedetails-html.lsp
\ No newline at end of file diff --git a/awall.menu b/awall.menu new file mode 100644 index 0000000..dc4ccb3 --- /dev/null +++ b/awall.menu @@ -0,0 +1,4 @@ +#CAT GROUP/DESC TAB ACTION +Networking 25Alpine_Wall Status status +Networking 25Alpine_Wall Policies listpolicies +Networking 25Alpine_Wall Expert expert diff --git a/awall.roles b/awall.roles new file mode 100644 index 0000000..c6ee6a0 --- /dev/null +++ b/awall.roles @@ -0,0 +1,3 @@ +USER=awall:status,awall:startstop +EXPERT=awall:listpolicies,awall:createpolicy,awall:deletepolicy,awall:editpolicy,awall:viewpolicy,awall:enablepolicy,awall:disablepolicy +ADMIN=awall:status,awall:startstop,awall:listpolicies,awall:createpolicy,awall:deletepolicy,awall:editpolicy,awall:viewpolicy,awall:enablepolicy,awall:disablepolicy diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..45f4d21 --- /dev/null +++ b/config.mk @@ -0,0 +1,10 @@ +prefix=/usr +datadir=${prefix}/share +sysconfdir=${prefix}/etc +localstatedir=${prefix}/var +acfdir=${datadir}/acf +wwwdir=${acfdir}/www +cgibindir=${acfdir}/cgi-bin +appdir=${acfdir}/app +acflibdir=${acfdir}/lib +sessionsdir=${localstatedir}/lib/acf/sessions |