summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-08-20 19:02:16 +0000
committerTed Trask <ttrask01@yahoo.com>2008-08-20 19:02:16 +0000
commit8730ef0997957b46d392b981913d8934373e980a (patch)
treeb9cd2e28088756e1441e76790242a5890c14b945
parent4f7c42c67f5e22295d178b924861f150c35132c0 (diff)
downloadacf-tcpproxy-8730ef0997957b46d392b981913d8934373e980a.tar.bz2
acf-tcpproxy-8730ef0997957b46d392b981913d8934373e980a.tar.xz
Modified tcpproxy to add in SMTP proxy support. Entries are directly edited, this still has to be improved.
git-svn-id: svn://svn.alpinelinux.org/acf/tcpproxy/trunk@1388 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r--tcpproxy-controller.lua32
l---------tcpproxy-createsmtpfile-html.lsp1
-rw-r--r--tcpproxy-editsmtpentry-html.lsp11
l---------tcpproxy-editsmtpfile-html.lsp1
-rw-r--r--tcpproxy-listsmtpentries-html.lsp29
-rw-r--r--tcpproxy-listsmtpfiles-html.lsp32
-rw-r--r--tcpproxy-model.lua240
-rw-r--r--tcpproxy-smtpstatus-html.lsp15
-rw-r--r--tcpproxy.menu1
-rw-r--r--tcpproxy.roles6
10 files changed, 366 insertions, 2 deletions
diff --git a/tcpproxy-controller.lua b/tcpproxy-controller.lua
index 45044e0..802f1de 100644
--- a/tcpproxy-controller.lua
+++ b/tcpproxy-controller.lua
@@ -16,3 +16,35 @@ end
function expert(self)
return controllerfunctions.handle_form(self, self.model.getconfigfile, self.model.setconfigfile, self.clientdata, "Save", "Edit Config", "Configuration Saved")
end
+
+function smtpstatus(self)
+ return self.model.getsmtpstatus()
+end
+
+function listsmtpentries(self)
+ return self.model.listsmtpentries(self)
+end
+
+function editsmtpentry(self)
+ return controllerfunctions.handle_form(self, function() return self.model.readsmtpentry(self.clientdata.ipaddr) end, self.model.updatesmtpentry, self.clientdata, "Save", "Edit SMTP Proxy Entry", "SMTP Proxy Entry Saved" )
+end
+
+function delsmtpentry(self)
+ return self:redirect_to_referrer(self.model.delsmtpentry(self.clientdata.ipaddr))
+end
+
+function listsmtpfiles(self)
+ return self.model.listsmtpfiles(self)
+end
+
+function createsmtpfile(self)
+ return controllerfunctions.handle_form(self, self.model.getnewsmtpfile, self.model.createsmtpfile, self.clientdata, "Create", "Create New SMTP Proxy File", "SMTP Proxy File Created")
+end
+
+function editsmtpfile(self)
+ return controllerfunctions.handle_form(self, function() return self.model.readsmtpfile(self.clientdata.filename) end, self.model.updatesmtpfile, self.clientdata, "Save", "Edit SMTP Proxy File", "SMTP Proxy File Saved" )
+end
+
+function delsmtpfile(self)
+ return self:redirect_to_referrer(self.model.delsmtpfile(self.clientdata.filename))
+end
diff --git a/tcpproxy-createsmtpfile-html.lsp b/tcpproxy-createsmtpfile-html.lsp
new file mode 120000
index 0000000..4b6b762
--- /dev/null
+++ b/tcpproxy-createsmtpfile-html.lsp
@@ -0,0 +1 @@
+../form-html.lsp \ No newline at end of file
diff --git a/tcpproxy-editsmtpentry-html.lsp b/tcpproxy-editsmtpentry-html.lsp
new file mode 100644
index 0000000..61579d4
--- /dev/null
+++ b/tcpproxy-editsmtpentry-html.lsp
@@ -0,0 +1,11 @@
+<% local form, viewlibrary, page_info = ...
+require("viewfunctions")
+%>
+
+<H1><%= form.label %></H1>
+<%
+ form.action = page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action
+ form.value.ipaddr.contenteditable = false
+ local order = {"ipaddr"}
+ displayform(form, order)
+%>
diff --git a/tcpproxy-editsmtpfile-html.lsp b/tcpproxy-editsmtpfile-html.lsp
new file mode 120000
index 0000000..15b1930
--- /dev/null
+++ b/tcpproxy-editsmtpfile-html.lsp
@@ -0,0 +1 @@
+../filedetails-html.lsp \ No newline at end of file
diff --git a/tcpproxy-listsmtpentries-html.lsp b/tcpproxy-listsmtpentries-html.lsp
new file mode 100644
index 0000000..7cfa651
--- /dev/null
+++ b/tcpproxy-listsmtpentries-html.lsp
@@ -0,0 +1,29 @@
+<% local view, viewlibrary, page_info, session = ...
+require("viewfunctions")
+%>
+
+<% displaycommandresults({"delsmtpentry"}, session) %>
+
+<H1>Interface Entries</H1>
+<DL>
+<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">Interface</TD>
+ <TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">IP Address</TD>
+ <TD style="white-space:nowrap;text-align:left;" class="header">Command Entry</TD>
+ </TR>
+<% for i,interface in ipairs(view.value) do %>
+ <TR>
+ <TD style="padding-right:20px;white-space:nowrap;">
+ <%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/editsmtpentry?ipaddr="..(interface.ipaddr or interface.interface), label="Edit "} %>
+ <%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/delsmtpentry?ipaddr="..(interface.ipaddr or interface.interface), label="Delete "} %>
+ </TD>
+ <TD style="padding-right:20px;white-space:nowrap;"><%= interface.interface or "" %></TD>
+ <TD style="padding-right:20px;white-space:nowrap;"><%= interface.ipaddr or "" %></TD>
+ <TD style="white-space:nowrap;"><%= interface.cmd or "" %></TD>
+ </TR>
+<% end %>
+</TABLE>
+
+</DL>
diff --git a/tcpproxy-listsmtpfiles-html.lsp b/tcpproxy-listsmtpfiles-html.lsp
new file mode 100644
index 0000000..753857b
--- /dev/null
+++ b/tcpproxy-listsmtpfiles-html.lsp
@@ -0,0 +1,32 @@
+<% local view, viewlibrary, page_info, session = ...
+require("viewfunctions")
+%>
+
+<% displaycommandresults({"delsmtpfile"}, session) %>
+
+<H1>Files</H1>
+<DL>
+<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="white-space:nowrap;text-align:left;" class="header">File</TD>
+ </TR>
+<% for i,file in ipairs(view.value) do %>
+ <TR>
+ <TD style="padding-right:20px;white-space:nowrap;">
+ <%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/editsmtpfile?filename="..file, label="Edit "} %>
+ <%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/delsmtpfile?filename="..file, label="Delete "} %>
+ </TD>
+ <TD style="white-space:nowrap;"><%= file %></TD>
+ </TR>
+<% end %>
+</TABLE>
+</DL>
+
+<% if viewlibrary and viewlibrary.dispatch_component then
+ local createform = viewlibrary.dispatch_component("createsmtpfile", nil, true) %>
+<H2><%= createform.label %></H2>
+<%
+ createform.action = page_info.script .. page_info.prefix .. page_info.controller .. "/createsmtpfile"
+ displayform(createform)
+end %>
diff --git a/tcpproxy-model.lua b/tcpproxy-model.lua
index 57bb845..b1caf83 100644
--- a/tcpproxy-model.lua
+++ b/tcpproxy-model.lua
@@ -2,15 +2,39 @@ module(..., package.seeall)
-- Load libraries
require("modelfunctions")
+require("validator")
+require("fs")
+require("posix")
-- Set variables
local configfile = "/etc/tcpproxy.conf"
local processname = "tcpproxy"
local packagename = "tcpproxy"
+local smtppackagename = "rxmtp"
+local smtpdirectory = "/etc/rxmtp/"
+
+local keywords = { "standalone", "port", "interface", "rotate", "server", "uid", "gid", "user", "exec", "acp", "logname", "setenv", "timeout", "writefile" }
+local config
-- ################################################################################
-- LOCAL FUNCTIONS
+local function parseconfigfile(file)
+ file = file or ""
+ local retval = {}
+ for line in string.gmatch(file, "([^\n]+)\n?") do
+ line = string.gsub(line, "#.*$", "")
+ if line and line ~= "" then
+ table.insert(retval, {})
+ for word in string.gmatch(line, "%S+") do
+ table.insert(retval[#retval], word)
+ end
+ end
+ end
+
+ return retval
+end
+
-- ################################################################################
-- PUBLIC FUNCTIONS
@@ -30,3 +54,219 @@ function setconfigfile(filedetails)
filedetails.value.filename.value = configfile
return modelfunctions.setfiledetails(filedetails)
end
+
+local function getsmtpconfig(config)
+ -- parse the TCP proxy config file for smtp entries
+ local retval = {}
+ local port25 = false
+ local currentint
+ for i,entry in ipairs(config) do
+ if entry[1] == "port" then
+ if entry[2] == "25" then
+ port25 = true
+ currentint = nil
+ else
+ port25 = false
+ currentint = nil
+ end
+ elseif port25 then
+ if entry[1] == "interface" then
+ currentint = entry[2]
+ elseif entry[1] == "exec" and string.find(entry[2], "rxmtp$") then
+ if currentint then
+ table.insert(retval, {ipaddr=currentint, cmd=table.concat(entry, " ", 2)})
+ else
+ -- bad config - exec command without interface
+ end
+ end
+ end
+ end
+
+ return retval
+end
+
+local function setsmtpcmd(ipaddr, cmd)
+ if cmd then cmd = "exec "..cmd end
+ local file = fs.read_file(configfile)
+ local inport25 = false
+ local ininterface = false
+ local done = false
+ local lines = {}
+ for line in string.gmatch(file, "([^\n]*)\n?") do
+ if not done then
+ if ininterface and string.find(line, "^%s*exec%s") then
+ -- We found the line, replace it
+ line = cmd
+ done = true
+ elseif ininterface and string.find(line, "^%s*interface%s") then
+ -- We're leaving the interface and we haven't written line yet
+ if cmd then
+ if string.find(lines[#lines], "^%s*$") then lines[#lines] = nil end
+ lines[#lines + 1] = "exec "..cmd
+ lines[#lines + 1] = ""
+ end
+ done = true
+ elseif inport25 and string.find(line, "^%s*interface%s+"..ipaddr) then
+ ininterface = true
+ elseif inport25 and string.find(line, "^%s*port%s") then
+ -- we're leaving port 25 and we haven't written line yet
+ if cmd then
+ lines[#lines + 1] = "interface "..ipaddr
+ lines[#lines + 1] = "exec "..cmd
+ lines[#lines + 1] = ""
+ end
+ done = true
+ elseif string.find(line, "^%s*port%s+25") then
+ inport25 = true
+ end
+ end
+ lines[#lines + 1] = line
+ end
+ if not done and cmd then
+ if not inport25 then lines[#lines + 1] = "port 25" end
+ if not ininterface then lines[#lines + 1] = "interface "..ipaddr end
+ lines[#lines + 1] = "exec "..cmd
+ end
+
+ fs.write_file(configfile, table.concat(lines, "\n"))
+end
+
+function getsmtpstatus()
+ local value, errtxt = processinfo.package_version(smtppackagename)
+ local version = cfe({ value=value, label="Program version" })
+ return cfe({ type="group", value={version=version, entries=entries}, label="SMTP Proxy Status" })
+end
+
+function listsmtpentries(self)
+ local entries = cfe({ type="structure", value={}, label="SMTP Command Entries" })
+ if self then
+ local interfacescontroller = self:new("alpine-baselayout/interfaces")
+ local interfaces = interfacescontroller.model:get_addresses()
+ interfacescontroller:destroy()
+ -- add in entries for interfaces (w/o ipaddr)
+ local interface
+ for i,entry in ipairs(interfaces.value) do
+ if interface ~= entry.interface then
+ interface = entry.interface
+ table.insert(entries.value, {interface=interface})
+ end
+ table.insert(entries.value, entry)
+ end
+ end
+
+ local reverseaddress = {}
+ for i,int in ipairs(entries.value) do reverseaddress[int.ipaddr or int.interface] = i end
+
+ config = config or parseconfigfile(fs.read_file(configfile))
+ local smtpconfig = getsmtpconfig(config)
+ for i,int in ipairs(smtpconfig) do
+ local pos = reverseaddress[int.ipaddr]
+ if pos then
+ entries.value[pos].cmd = int.cmd
+ else
+ if not validator.is_ipv4(int.ipaddr) then
+ int.interface = int.ipaddr
+ int.ipaddr = nil
+ end
+ table.insert(entries.value, int)
+ end
+ end
+
+ return entries
+end
+
+function readsmtpentry(ipaddr)
+ config = config or parseconfigfile(fs.read_file(configfile))
+ local smtpconfig = getsmtpconfig(config)
+ local exec = ""
+ for i,entry in ipairs(smtpconfig) do
+ if entry.ipaddr == ipaddr then
+ exec = entry.cmd
+ break
+ end
+ end
+
+ local ipaddrcfe = cfe({ value=ipaddr, label="Interface / IP Address" })
+ local execcfe = cfe({ value=exec, label="Command" })
+ return cfe({ type="group", value={exec=execcfe, ipaddr=ipaddrcfe}, label="SMTP Proxy Entry" })
+end
+
+function updatesmtpentry(entry)
+ -- validate?
+ setsmtpcmd(entry.value.ipaddr.value, entry.value.exec.value)
+ return entry
+end
+
+function delsmtpentry(ipaddr)
+ setsmtpcmd(ipaddr, nil)
+ return cfe({ value="Deleted SMTP Proxy Entry", label="Delete SMTP Entry result" })
+end
+
+function listsmtpfiles()
+ local retval = cfe({ type="list", value={}, label="SMTP Proxy Files" })
+ if not fs.is_dir(smtpdirectory) then posix.mkdir(smtpdirectory) end
+ for file in posix.files(smtpdirectory) do
+ if fs.is_file(smtpdirectory .. file) then
+ table.insert(retval.value, smtpdirectory .. file)
+ end
+ end
+ return retval
+end
+
+function getnewsmtpfile()
+ local filename = cfe({ label="File Name", descr="Must be in "..smtpdirectory })
+ return cfe({ type="group", value={filename=filename}, label="SMTP Proxy File" })
+end
+
+function createsmtpfile(filedetails)
+ local success = true
+
+ if not validator.is_valid_filename(filedetails.value.filename.value, smtpdirectory) then
+ success = false
+ filedetails.value.filename.errtxt = "Invalid filename"
+ else
+ if not fs.is_dir(smtpdirectory) then posix.mkdir(smtpdirectory) end
+ if posix.stat(filedetails.value.filename.value) then
+ success = false
+ filedetails.value.filename.errtxt = "Filename already exists"
+ end
+ end
+
+ if success then
+ fs.create_file(filedetails.value.filename.value)
+ else
+ filedetails.errtxt = "Failed to Create File"
+ end
+
+ return filedetails
+end
+
+function readsmtpfile(filename)
+ if validator.is_valid_filename(filename, smtpdirectory) and fs.is_file(filename) then
+ return modelfunctions.getfiledetails(filename)
+ end
+ local retval = modelfunctions.getfiledetails("")
+ retval.value.filename.value = filename
+ return retval
+end
+
+function updatesmtpfile(filedetails)
+ if validator.is_valid_filename(filedetails.value.filename.value, smtpdirectory) and fs.is_file(filedetails.value.filename.value) then
+ return modelfunctions.setfiledetails(filedetails)
+ end
+ filedetails.value.filename.errtxt = "Invalid Filename"
+ filedetails.errtxt = "Failed to set file"
+ return filedetails
+end
+
+function delsmtpfile(filename)
+ local retval = cfe({ value="Deleted SMTP Proxy File", label="Delete SMTP File result" })
+ if validator.is_valid_filename(filename, smtpdirectory) and fs.is_file(filename) then
+ os.remove(filename)
+ else
+ retval.value = "Failed to delete SMTP Proxy File - invalid filename"
+ end
+
+ return retval
+end
+
diff --git a/tcpproxy-smtpstatus-html.lsp b/tcpproxy-smtpstatus-html.lsp
new file mode 100644
index 0000000..c639424
--- /dev/null
+++ b/tcpproxy-smtpstatus-html.lsp
@@ -0,0 +1,15 @@
+<% local view, viewlibrary, page_info, session = ...
+require("viewfunctions")
+%>
+
+<% displaycommandresults({"delsmtpentry", "delsmtpfile"}, session) %>
+
+<H1>SMTP Proxy Status</H1>
+<DL>
+<% displayitem(view.value.version) %>
+</DL>
+
+<% if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("listsmtpentries")
+ viewlibrary.dispatch_component("listsmtpfiles")
+end %>
diff --git a/tcpproxy.menu b/tcpproxy.menu
index 0f68d61..da4fdc1 100644
--- a/tcpproxy.menu
+++ b/tcpproxy.menu
@@ -1,3 +1,4 @@
#CAT GROUP/DESC TAB ACTION
Networking 35TCP_Proxy Status status
+Networking 35TCP_Proxy SMTP_Proxy smtpstatus
Networking 35TCP_Proxy Expert expert
diff --git a/tcpproxy.roles b/tcpproxy.roles
index 9b40383..803e033 100644
--- a/tcpproxy.roles
+++ b/tcpproxy.roles
@@ -1,2 +1,4 @@
-READ=tcpproxy:status
-UPDATE=tcpproxy:startstop,tcpproxy:expert
+READ=tcpproxy:status,tcpproxy:smtpstatus,tcpproxy:listsmtpentries,tcpproxy:listsmtpfiles
+UPDATE=tcpproxy:startstop,tcpproxy:expert,tcpproxy:editsmtpentry,tcpproxy:editsmtpfile
+DELETE=tcpproxy:delsmtpentry,tcpproxy:delsmtpfile
+CREATE=tcpproxy:createsmtpfile