summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-11-25 19:27:55 +0000
committerTed Trask <ttrask01@yahoo.com>2008-11-25 19:27:55 +0000
commit3459e6bf19a13f35e419b0adabf8c3456a0a5025 (patch)
tree9330301f44a88ee2f3cb8b5d0271204294aa99c6
parent99b9d1c5e938d818ca3e78a1f37d6a80da4b88f1 (diff)
downloadacf-openvpn-3459e6bf19a13f35e419b0adabf8c3456a0a5025.tar.bz2
acf-openvpn-3459e6bf19a13f35e419b0adabf8c3456a0a5025.tar.xz
Rewrite of openvpn to use cfes and new style. Added ability to edit/create/delete configs. Combined three view functions into one. Added a new status and moved old status to listconfigs. Still needs work, including ability to start/stop/restart.v0.3.0
git-svn-id: svn://svn.alpinelinux.org/acf/openvpn/trunk@1611 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r--Makefile2
-rw-r--r--openvpn-clientconfig-html.lsp70
-rw-r--r--openvpn-controller.lua62
l---------openvpn-createconfig-html.lsp1
l---------openvpn-editconfig-html.lsp1
-rw-r--r--openvpn-listconfigs-html.lsp51
-rw-r--r--openvpn-logfile-html.lsp13
-rw-r--r--openvpn-model.lua274
-rw-r--r--openvpn-peminfo-html.lsp40
-rw-r--r--openvpn-serverconfig-html.lsp72
l---------[-rw-r--r--]openvpn-status-html.lsp38
-rw-r--r--openvpn-statusinfo-html.lsp19
-rw-r--r--openvpn-unknownconfig-html.lsp29
-rw-r--r--openvpn-viewconfig-html.lsp82
-rw-r--r--openvpn.menu1
-rw-r--r--openvpn.roles6
16 files changed, 300 insertions, 461 deletions
diff --git a/Makefile b/Makefile
index c692274..f1019ec 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
APP_NAME=openvpn
PACKAGE=acf-$(APP_NAME)
-VERSION=0.2.6
+VERSION=0.3.0
APP_DIST= \
openvpn* \
diff --git a/openvpn-clientconfig-html.lsp b/openvpn-clientconfig-html.lsp
deleted file mode 100644
index 1aa2bc3..0000000
--- a/openvpn-clientconfig-html.lsp
+++ /dev/null
@@ -1,70 +0,0 @@
-<% local view = ... %>
-<html>
-<body>
-<h1>Client config '<%= view.config.name %>'</h1>
-
-<h2>Client settings</h2>
-
-<dt>Mode</dt>
-<dd>client</dd>
-
-<dt>User device</dt>
-<dd><%= view.config.dev %></dd>
-
-<dt>Remote server</dt>
-<dd><%= view.config.remote %>:<%= view.config.remoteport %> (<%= view.config.proto %>)</dd>
-
-<dt>Logfile</dt>
-<dd><% if ( view.config.log ) then %><%= html.link{value = view.url .. "/logfile?name=" .. view.config.linkname , label=view.config.log } %><% else %>Syslog<% end %> (Verbosity level: <%= view.config.verb %>)</dd>
-
-<dt>View/Modify configfile</dt>
-<dd><%= html.link{value = view.url .. "/unknown_config?name=" .. view.config.linkname , label=view.config.name } %></dd>
-
-<% --[[ %>
-<h3>Client properties</h3>
-
-<dt>Common name</dt>
-<dd>xxx</dd>
-
-<dt>Virtual address</dt>
-<dd>xxx.xxx.xxx.xxx</dd>
-
-<dt>Real address</dt>
-<dd>xxx.xxx.xxx.xxx:xxxx</dd>
-
-<% --]] %>
-
-<h2>Startup options</h2>
-
-<dt>Process running</dt>
-<dd><input type="checkbox" disabled <% if (view.config.status_isrunning ~= "") then io.write("checked='yes'") end %>></dd>
-
-<h2>Certificate files</h2>
-
-<% if (view.config.ca) then %>
-<dt>CA Certificate</dt>
-<dd><%= view.config.ca %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.ca , label=view.config.ca } %></dd>
-<% end %>
-
-<% if (view.config.cert) then %>
-<dt>Client Certificate</dt>
-<dd><%= view.config.cert %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.cert , label=view.config.cert } %></dd>
-<% end %>
-
-<% if (view.config.key) then %>
-<dt>Client Private Key</dt>
-<dd><%= view.config.key %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.key , label=view.config.key } %></dd>
-<% end %>
-
-<% if (view.config.tls) then %>
-<dt>TLS Authentication</dt>
-<dd><%= view.config.tls %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.tls , label=view.config.tls } %></dd>
-<% end %>
-
-<% if (view.config.crl) then %>
-<dt>CRL Verify File</dt>
-<dd><%= view.config.crl %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.crl , label=view.config.crl } %> (client side)</dd>
-<% end %>
-
-</body>
-</html>
diff --git a/openvpn-controller.lua b/openvpn-controller.lua
index 54a28e2..047e7df 100644
--- a/openvpn-controller.lua
+++ b/openvpn-controller.lua
@@ -1,63 +1,37 @@
--- the hostname controller
-
module (..., package.seeall)
+require("controllerfunctions")
+
default_action = "status"
status = function (self)
- -- FIXME: If return 1 rows go direct to that config-page
- return ( {conflistfiles = self.model:get_conflist(), url = self.conf.script .. self.conf.prefix .. self.conf.controller, version = self.model:openvpn_version()} )
+ return self.model.getstatus()
+end
+
+listconfigs = function (self)
+ return self.model.get_conflist()
end
+editconfig = function (self)
+ return controllerfunctions.handle_form(self, function() return self.model.get_filecontent(self.clientdata.name) end, self.model.update_filecontent, self.clientdata, "Save", "Edit Config File", "Config File Saved")
+end
-serverconfig = function (self)
- local configname = self.clientdata.name or ""
- return ( {config = self.model:get_config(configname), url = self.conf.script .. self.conf.prefix .. self.conf.controller} )
+createconfig = function ( self )
+ return controllerfunctions.handle_form(self, self.model.create_new_config, self.model.create_config, self.clientdata, "Create", "Create new config", "New config Created")
end
-clientconfig = function (self)
- local configname = self.clientdata.name or ""
- return ( {config = self.model:get_config(configname), url = self.conf.script .. self.conf.prefix .. self.conf.controller} )
+deleteconfig = function(self)
+ return self:redirect_to_referrer(self.model.delete_config(self.clientdata.name))
end
-peminfo = function (self)
+viewconfig = function(self)
+ return self.model.get_config(self.clientdata.name)
end
statusinfo = function (self)
- local configname = self.clientdata.name or ""
- return ( {clientlist = self.model:clientlist(configname), url = self.conf.script .. self.conf.prefix .. self.conf.controller} )
-end
-
-unknownconfig = function (self)
- local filename = self.clientdata.name or ""
- local filecontent = self.clientdata.modifications or ""
-
----[[
- if ( filecontent ~= "") then
- local me = ( {configfilecontent = self.model:update_filecontent(filename,filecontent), url = self.conf.script .. self.conf.prefix .. self.conf.controller } )
- if ( me.configfilecontent == nil ) then
- redirect(self)
- else
- return me
- end
- else
----[=[
- local me = ( {configfilecontent = self.model:get_filecontent(filename), url = self.conf.script .. self.conf.prefix .. self.conf.controller } )
- if ( me.configfilecontent == nil ) then
- redirect(self)
- else
- return me
- end
---]=]
--- return ( {configfilecontent = self.model:get_filecontent(filename), url = self.conf.script .. self.conf.prefix .. self.conf.controller} )
-
- end
---]]
-
+ return self.model.getclientinfo(self.clientdata.name)
end
logfile = function (self)
- local configname = self.clientdata.name or ""
- -- FIXME: If return 0 rows, goto read
- return ( {logfilecontent = self.model:get_logfile(configname), url = self.conf.script .. self.conf.prefix .. self.conf.controller } )
+ return self.model.get_logfile(self.clientdata.name)
end
diff --git a/openvpn-createconfig-html.lsp b/openvpn-createconfig-html.lsp
new file mode 120000
index 0000000..4b6b762
--- /dev/null
+++ b/openvpn-createconfig-html.lsp
@@ -0,0 +1 @@
+../form-html.lsp \ No newline at end of file
diff --git a/openvpn-editconfig-html.lsp b/openvpn-editconfig-html.lsp
new file mode 120000
index 0000000..15b1930
--- /dev/null
+++ b/openvpn-editconfig-html.lsp
@@ -0,0 +1 @@
+../filedetails-html.lsp \ No newline at end of file
diff --git a/openvpn-listconfigs-html.lsp b/openvpn-listconfigs-html.lsp
new file mode 100644
index 0000000..1e67f4b
--- /dev/null
+++ b/openvpn-listconfigs-html.lsp
@@ -0,0 +1,51 @@
+<% local view, viewlibrary, page_info, session = ... %>
+<% require("viewfunctions") %>
+
+<% displaycommandresults({"editconfig", "deleteconfig"}, session) %>
+<% displaycommandresults({"createconfig"}, session, true) %>
+
+<% if viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("status")
+end %>
+
+<H2>Available configs</H2>
+<TABLE>
+ <TR style="background:#eee;font-weight:bold;vertical-align:top;">
+ <TD class="header">Actions</TD>
+ <TD class="header">Config</TD>
+ <TD class="header">Type</TD>
+ <TD class="header">Status</TD>
+ <TD class="header">Connected<BR>Clients</TD>
+ </TR>
+
+<% for i,config in ipairs(view.value) do %>
+ <TR >
+ <TD>
+ <%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/viewconfig?name=" .. config.name, label="View " } %>
+ <% if session.permissions.openvpn.editconfig then %>
+ <%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/editconfig?name=" .. config.name.."&redir="..page_info.orig_action, label="Expert " } %>
+ <% end %>
+ <% if session.permissions.openvpn.deleteconfig then %>
+ <%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/deleteconfig?name=" .. config.name.."&redir="..page_info.orig_action, label="Delete " } %>
+ <% end %>
+ </TD>
+ <TD><%= string.gsub(config.name, "^.*/", "") %></TD>
+ <TD <% if config.errtxt then io.write('class="error"') end %>><%= config.type %></TD>
+ <TD><%= config.status %></TD>
+ <TD><% if ( config.type == "server" ) then %><% if ( config.clients > 0 ) then %><%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/status_info?name=" .. config.name, label = config.clients } %><% else %><%= config.clients %><% end %><% end %></TD>
+ </TR>
+ <% if config.errtxt then %>
+ <TR class="error"><TD colspan=5><%= config.errtxt %></TD></TR>
+ <% end %>
+<% end %>
+
+<% if (#view.value == 0) then %>
+ <TR>
+ <TD colspan=3>(No existing config-files)</TD>
+ </TR>
+<% end %>
+</TABLE>
+
+<% if viewlibrary.dispatch_component and session.permissions.openvpn.createconfig then
+ viewlibrary.dispatch_component("createconfig")
+end %>
diff --git a/openvpn-logfile-html.lsp b/openvpn-logfile-html.lsp
index 22ebabe..7271147 100644
--- a/openvpn-logfile-html.lsp
+++ b/openvpn-logfile-html.lsp
@@ -1,8 +1,7 @@
-<% local view = ... %>
-<html>
-<body>
-<h1>Logfile '<%= view.logfilecontent.name %>'</h1>
-<textarea name=""><%= view.logfilecontent.value %></textarea>
+<% local data, viewlibrary = ...
+require("viewfunctions")
+%>
-</body>
-</html>
+<% if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("alpine-baselayout/logfiles/view", {name=data.value})
+end %>
diff --git a/openvpn-model.lua b/openvpn-model.lua
index 26e2874..304b155 100644
--- a/openvpn-model.lua
+++ b/openvpn-model.lua
@@ -1,46 +1,36 @@
module (..., package.seeall)
+require ("modelfunctions")
require ("posix")
require ("format")
require ("fs")
require ("processinfo")
+require ("validator")
+require ("date")
+local processname = "openvpn"
+local packagename = "openvpn"
local baseurl = "/etc/openvpn/"
--- no initializer in model - use controller.init for that
-
-- ################################################################################
-- LOCAL FUNCTIONS
-local function file_info ( path )
- require("posix")
- local filedetails = posix.stat(path)
- filedetails["owner"]=rawget((posix.getpasswd(filedetails["uid"])),"name")
- filedetails["group"]=rawget((posix.getgroup(filedetails["gid"])),"name")
- filedetails["atimelong"]=os.date("%c", filedetails["atime"])
- filedetails["mtimelong"]=os.date("%c", filedetails["mtime"])
- filedetails["longname"]=path
- filedetails["name"]=basename(path)
- filedetails["size"]=filedetails["size"] .. " bytes"
- return filedetails
-end
local function config_content( f )
local config = {}
- config.name = baseurl .. f
- local conf_file = fs.read_file_as_array ( config.name )
- for i=1,table.maxn(conf_file) do
- local l = conf_file[i]
- -- Filter out commented lines
- if not string.find ( l, "^[;#].*" ) then
- local a,b = string.match ( l, "^%s*(%S+)%s*(%S*).*$" )
- if (a) then
- config[string.lower(a)]=b
- end
- if (a == "remote") then
- config["remoteport"]=string.match ( l, "^%s*%S+%s+%S+%s+(%S*)" )
- end
+ local lines = format.parse_linesandwords(fs.read_file(f) or "", "[#;]")
+ -- there can be multiple entries
+ for i,linetable in ipairs(lines) do
+ if config[linetable[1]] then
+ config[linetable[1]] = config[linetable[1]] .. "\n" .. (table.concat(linetable, " ", 2) or "")
+ else
+ config[linetable[1]] = table.concat(linetable, " ", 2) or ""
end
end
+
+ config.name = f
+ if config.remote then
+ config.remoteport = string.match ( config.remote, "^%S+%s+(%S*)" )
+ end
if not ( config.log ) then
config.log = config["log-append"]
end
@@ -50,13 +40,12 @@ local function config_content( f )
if not ( config["local"] ) then
config["local"] = "0.0.0.0"
end
- config["linkname"]=basename(f)
return config
end
local is_running = function( process, parameters )
- local retval = ""
+ local retval = "Stopped"
-- local tst = ""
-- local pidofsx, error = io.popen("pidof " .. process ,r)
-- local pidofs = string.gsub(pidofsx:read("*a"), "\n", "")
@@ -65,7 +54,7 @@ local is_running = function( process, parameters )
local i,v
for i,v in ipairs(processinfo.pidof(process) or {}) do
local path = string.gsub("/proc/".. v .. "/cmdline", "%s", "")
- local f,err = io.open(path,r)
+ local f = io.open(path,r)
local file_resultx = f:read("*a")
local file_result = string.match(file_resultx, parameters)
f:close()
@@ -76,77 +65,62 @@ local is_running = function( process, parameters )
return retval
end
-local function check_valid_config ( f )
- config.err = ""
+local function check_valid_config (config)
+ config.errtxt = nil
if not (config.client) or not (config.ca) or not (config.cert) or not (config.key) or not (config.dev) or not (config.proto) or not (config.remote) then
- config.type = nil
- config.err = ""
+ config.errtxt = ""
if not (config.ca) then
- config.err = config.err .. "Check CA; "
+ config.errtxt = config.errtxt .. "Check CA; "
end
if not (config.cert) then
- config.err = config.err .. "Check CERT; "
+ config.errtxt = config.errtxt .. "Check CERT; "
end
if not (config.key) then
- config.err = config.err .. "Check KEY; "
+ config.errtxt = config.errtxt .. "Check KEY; "
end
if not (config.dev) then
- config.err = config.err .. "Check DEV; "
+ config.errtxt = config.errtxt .. "Check DEV; "
end
if not (config.proto) then
- config.err = config.err .. "Check PROTO; "
+ config.errtxt = config.errtxt .. "Check PROTO; "
end
if (config.client) or not (config.ca) or not (config.cert) or not (config.key) or not (config.dev) or not (config.proto) or not (config.port) then
config.type = nil
else
config.type = "server"
- config.err = ""
+ config.errtxt = nil
end
else
config.type = "client"
- config.err = ""
+ config.errtxt = nil
end
if not (config.type) then config.type = "unknown" end
- return config.type, config.err
+ return config.type, config.errtxt
end
local function list_conffiles()
local configfiles = {}
- local config = {}
- local files , errstr, errno = posix.dir ( baseurl )
- if files then
- for k,v in ipairs(files) do
- if string.match (v, "^.*conf$") then
- table.insert ( configfiles, cfe{ name = v } )
- end
- end
- return configfiles
+ for file in fs.find(".*%.conf", baseurl) do
+ configfiles[#configfiles+1] = file
end
+ return configfiles
end
--- ################################################################################
--- PUBLIC FUNCTIONS
-
-function clientlist( self, path )
- local libdate = require("date")
+local function clientlist( statusfile )
local clientlist = {}
local routinglist = {}
local datechange = {}
local list = {}
- local f = ""
- local clientlst = nil
- local routinglst = nil
- if ( path ) then
- config = config_content ( path )
- end
- if (config.status) then
- local f = fs.read_file_as_array( config.status )
+ if (statusfile) then
+ local f = fs.read_file_as_array( statusfile )
+ local clientlst = false
+ local routinglst = false
if ( f ) then
for k,v in ipairs(f) do
local col = format.string_to_table(v, ",")
if ( col[1] == "ROUTING TABLE" ) or ( col[1] == "GLOBAL STATS" ) then
- clientlst = nil
- routinglst = nil
+ clientlst = false
+ routinglst = false
end
if ( clientlst ) then
table.insert(clientlist, { CN=col[1],
@@ -163,7 +137,7 @@ function clientlist( self, path )
if (col[4]) then
local month,day,hour,min,sec,year = string.match(col[4],"^%S+%s+(%S+)%s+(%S+)%s+(%d%d):(%d%d):(%d%d)%s+(%S+)")
table.insert(datechange, { year=year,
- month=libdate.abr_month_num(month),
+ month=date.abr_month_num(month),
day=day,
hour=hour,
min=min,
@@ -171,10 +145,10 @@ function clientlist( self, path )
end
end
if ( col[1] == "Virtual Address" ) then
- routinglst = "YES"
+ routinglst = true
end
if ( col[1] == "Common Name" ) then
- clientlst = "YES"
+ clientlst = true
end
end
@@ -188,10 +162,9 @@ function clientlist( self, path )
end
end
end
- connclients = table.maxn(clientlist)
- if ( connclients > 0 ) then
- -- FIXME: If possible, use lib/date.lua instead of the following code.
- local lastdatechange = libdate.date_to_seconds(datechange)
+ local lastdatechangetxt, lastdatechangediff
+ if ( #clientlist > 0 ) then
+ local lastdatechange = date.date_to_seconds(datechange)
lastdatechangetxt = os.date("%c", lastdatechange[#lastdatechange])
lastdatechangediff = os.time() - os.date(lastdatechange[table.maxn(lastdatechange)])
if (lastdatechangediff > 60) then
@@ -200,95 +173,102 @@ function clientlist( self, path )
lastdatechangediff = lastdatechangediff .. " sec"
end
end
- return list, connclients, lastdatechangetxt, lastdatechangediff
+ return list, #clientlist, lastdatechangetxt, lastdatechangediff
end
-function openvpn_version()
- local f,error = io.popen("/usr/sbin/openvpn --version")
- openvpnversion = f:read("*l")
- f:close()
- if not (openvpnversion) then
- openvpnversion = "Not installed!"
- end
- return openvpnversion
-end
+-- ################################################################################
+-- PUBLIC FUNCTIONS
-function get_config ( self, f )
- local path = basename(f)
- local configresult = {}
- config = nil
- config = config_content ( path )
- local clientlist, client_count, client_lastupdate, client_lastdatechangediff = clientlist ()
- local status_isrunning = is_running ("openvpn", path)
- if (client_lastupdate == nil) then
- config["client_lastupdate"] = "?"
- else
- config["client_lastupdate"]=client_lastupdate
- end
- if (client_lastupdate == nil) then
- config["client_lastdatechangediff"] = "? min"
- else
- config["client_lastdatechangediff"]=client_lastdatechangediff
- end
- config["client_count"]=client_count
- config["status_isrunning"]=status_isrunning
- configresult = config
- return configresult
+function getstatus()
+ return modelfunctions.getstatus(processname, packagename, "OpenVPN Status")
end
-function update_filecontent (self, f, modifications)
- name = basename(f)
- path = baseurl .. name
- local available_files = list_conffiles()
- for k,v in pairs(available_files) do
- if ( available_files[k].name == name ) then
- local file = io.open( path, "w+" )
- local file_result,err = file:write(format.dostounix(modifications))
- file:close()
- if (err ~= nil) then
- local filedetails = get_config(name)
- file_content = {name=name, value=file_result, filedetails=filedetails, err=err}
- end
- end
- end
- return file_content
+function getclientinfo(f)
+ local config = config_content(f)
+ return cfe({ type="structure", value=clientlist(config.status), label="Client info" })
end
-function get_logfile( self, path)
- config = config_content ( path )
- local logfilecontent = fs.read_file ( config.log )
- if not (logfilecontent) then
- logfilecontent = "File is empty or missing!"
+function get_config(f)
+ local config = config_content(f)
+ check_valid_config(config)
+ if config.type == "server" then
+ local clientlist, client_count, client_lastupdate, client_lastdatechangediff = clientlist(config.status)
+ config["client_lastupdate"] = client_lastupdate or "?"
+ config["client_lastdatechangediff"] = client_lastdatechangediff or "? min"
+ config["client_count"] = client_count or 0
end
- return ( { name = config.log, value = logfilecontent } )
+ config["status_isrunning"] = is_running ("openvpn", basename(f))
+ return cfe({ type="structure", value=config, label="OpenVPN Config" })
end
-function get_filecontent( self, f)
- local path = basename(f)
- local configresult = {}
- config = config_content ( path )
- local file = io.open( config.name )
- local file_result = file:read("*a") or "unknown"
- file:close()
- local conf_type, err = check_valid_config ( path )
- local filedetails = file_info( config.name )
- file_content = cfe{name=config.name, value=file_result, type=conf_type, filedetails=filedetails}
- return file_content
+function get_logfile(f)
+ local config = config_content(f)
+ return cfe({ value=config.log or "", label="Config file" })
end
function get_conflist ()
local configlist = {}
- for k,v in pairs(list_conffiles() or {}) do
- config = config_content ( v.name )
- local conf_type, err = check_valid_config ( v.name )
- local isrunning = is_running ("openvpn", v.name)
- local clientlist, connclients = clientlist ()
- table.insert ( configlist, cfe{ name = v.name, type = conf_type, err = err, status = isrunning, clients = connclients } )
+ for i,file in ipairs(list_conffiles()) do
+ config = config_content ( file )
+ local conf_type, errtxt = check_valid_config(config)
+ local isrunning = is_running ("openvpn", basename(file))
+ local clientlist, connclients = clientlist (config.status)
+ table.insert ( configlist, { name = file, type = conf_type, errtxt = errtxt, status = isrunning, clients = connclients } )
end
- local countconfigs = table.maxn(configlist)
- return configlist, countconfigs
+ return cfe({ type="structure", value=configlist, label="Configuration List" })
+end
+
+function get_filecontent(f)
+ --FIXME validate
+ return modelfunctions.getfiledetails(f, list_conffiles())
end
-get = function (self)
- return list_conffiles()
+
+function update_filecontent(filedetails)
+ --FIXME validate
+ return modelfunctions.setfiledetails(filedetails, list_conffiles())
+end
+
+function create_new_config()
+ config = {
+ name = cfe({ label="File Name" }),
+ }
+
+ return cfe({ type="group", value=config, label="Config" })
end
+function create_config(config)
+ local success = true
+ local path = config.value.name.value
+ if not string.find(path, "/") then
+ path = baseurl .. path
+ end
+
+ if not validator.is_valid_filename(path, baseurl) then
+ success = false
+ config.value.name.errtxt = "Invalid path"
+ elseif posix.stat(path) then
+ success = false
+ config.value.name.errtxt = "File already exists"
+ end
+
+ if success then
+ if not posix.stat(baseurl) then posix.mkdir(baseurl) end
+ fs.create_file(path)
+ else
+ config.errtxt = "Failed to create config"
+ end
+
+ return config
+end
+
+function delete_config(name)
+ local cmdresult = cfe({ label="Delete config result", errtxt="Failed to delete config - not found" })
+
+ if validator.is_valid_filename(name, baseurl) and fs.is_file(name) then
+ os.remove(name)
+ cmdresult.value = "Config Deleted"
+ cmdresult.errtxt = nil
+ end
+
+ return cmdresult
+end
diff --git a/openvpn-peminfo-html.lsp b/openvpn-peminfo-html.lsp
deleted file mode 100644
index 070399f..0000000
--- a/openvpn-peminfo-html.lsp
+++ /dev/null
@@ -1,40 +0,0 @@
-<% local view = ... %>
-<html>
-<body>
-<h1>Certificate Info 'xxx.conf'</h1>
-<h2>General</h2>
-
-<dt>Serial</dt>
-<dd>xxx</dd>
-
-<dt>Common name</dt>
-<dd>xxx</dd>
-
-<dt>Country</dt>
-<dd>xxx</dd>
-
-<dt>State or Province</dt>
-<dd>xxx</dd>
-
-<dt>City</dt>
-<dd>xxx</dd>
-
-<dt>Company</dt>
-<dd>xxx</dd>
-
-<dt>Departement II</dt>
-<dd>xxx</dd>
-
-<dt>e-mail</dt>
-<dd>xxx</dd>
-
-<dt>Status</dt>
-<dd>xxx</dd>
-
-<h2>Certificate Details</h2>
-
-<textarea></textarea>
-
-
-</body>
-</html>
diff --git a/openvpn-serverconfig-html.lsp b/openvpn-serverconfig-html.lsp
deleted file mode 100644
index fad78dc..0000000
--- a/openvpn-serverconfig-html.lsp
+++ /dev/null
@@ -1,72 +0,0 @@
-<% local view = ... %>
-<html>
-<body>
-<h1>Server config '<%= view.config.name %>'</h1>
-
-<h2>Server settings</h2>
-
-<dt>Mode</dt>
-<dd>server</dd>
-
-<dt>User device</dt>
-<dd><%= view.config.dev %></dd>
-
-<dt>Listens on</dt>
-<dd><%= view.config["local"] %>:<%= view.config.port %> (<%= view.config.proto %>)</dd>
-
-<dt>Logfile</dt>
-<dd><% if ( view.config.log ) then %><%= html.link{value = view.url .. "/logfile?name=" .. view.config.linkname , label=view.config.log } %><% else %>Syslog<% end %> (Verbosity level: <%= view.config.verb %>)</dd>
-
-<dt>View/Modify configfile</dt>
-<dd><%= html.link{value = view.url .. "/unknown_config?name=" .. view.config.linkname , label=view.config.name } %></dd>
-
-<h3>Connected clients status</h3>
-
-<dt>Last status was recorded</dt>
-<dd><%= view.config.client_lastupdate %> (This was <b><%= view.config.client_lastdatechangediff %></b> ago)</dd>
-
-<dt>Maximum clients</dt>
-<dd><%= view.config["max-clients"] %></dd>
-
-<dt>Connected clients</dt>
-<dd><% if ( view.config.client_count > 0 ) then %><%= html.link{value = view.url .. "/status_info?name=" .. view.config.linkname , label=view.config.client_count } %><% else %><%= view.config.client_count %><% end %></dd>
-
-<h2>Startup options</h2>
-
-<dt>Process running</dt>
-<dd><input type="checkbox" disabled <% if (view.config.status_isrunning ~= "") then io.write("checked='yes'") end %>></dd>
-
-<h2>Certificate files</h2>
-
-<% if (view.config.dh) then %>
-<dt>DH</dt>
-<dd><%= view.config.dh %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.dh , label=view.config.dh } %></dd>
-<% end %>
-
-<% if (view.config.ca) then %>
-<dt>CA Certificate</dt>
-<dd><%= view.config.ca %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.ca , label=view.config.ca } %></dd>
-<% end %>
-
-<% if (view.config.cert) then %>
-<dt>Server Certificate</dt>
-<dd><%= view.config.cert %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.cert , label=view.config.cert } %></dd>
-<% end %>
-
-<% if (view.config.key) then %>
-<dt>Server Private Key</dt>
-<dd><%= view.config.key %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.key , label=view.config.key } %></dd>
-<% end %>
-
-<% if (view.config.tls) then %>
-<dt>TLS Authentication</dt>
-<dd><%= view.config.tls %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.tls , label=view.config.tls } %></dd>
-<% end %>
-
-<% if (view.config.crl) then %>
-<dt>CRL Verify File</dt>
-<dd><%= view.config.crl %><% -- html.link{value = view.url .. "/pem_info?name=" .. view.config.crl , label=view.config.crl } %></dd>
-<% end %>
-
-</body>
-</html>
diff --git a/openvpn-status-html.lsp b/openvpn-status-html.lsp
index 8cbe657..b2f8480 100644..120000
--- a/openvpn-status-html.lsp
+++ b/openvpn-status-html.lsp
@@ -1,37 +1 @@
-<% local view = ... %>
-<h1>SYSTEM INFO</h1>
-
-<dl>
-<dt>Program version</dt>
-<DD><%= view.version %></DD>
-</dl>
-
-<H2>PROGRAM SPECIFIC OPTIONS/INFORMATION</H2>
-
-<H3>Available configs (Click on config-name to see details)</H3>
-<TABLE>
- <TR style="background:#eee;font-weight:bold;vertical-align:top;">
- <TD class="header">Config</TD>
- <TD class="header">Type</TD>
- <TD class="header">Status</TD>
- <TD class="header">Connected<BR>Clients</TD>
- <TD class="header">Notes</TD>
- </TR>
-
-<% for i = 1, table.maxn(view.conflistfiles) do %>
- <TR >
- <TD><%= html.link{value = view.url .. "/" .. view.conflistfiles[i].type .. "_config?name=" .. view.conflistfiles[i].name , label=view.conflistfiles[i].name } %></TD>
- <TD><%= view.conflistfiles[i].type %></TD>
- <TD><%= view.conflistfiles[i].status %></TD>
- <TD><% if ( view.conflistfiles[i].type == "server" ) then %><% if ( view.conflistfiles[i].clients > 0 ) then %><%= html.link{value = view.url .. "/status_info?name=" .. view.conflistfiles[i].name , label=view.conflistfiles[i].clients } %><% else %><%= view.conflistfiles[i].clients %><% end %><% end %></TD>
- <TD style="color:red"><i><%= view.conflistfiles[i].err %></i></TD>
- </TR>
-<% end %>
-
-<% if (#view.conflistfiles == 0) then %>
- <TR>
- <TD colspan=3>(No existing config-files)</TD>
- </TR>
-<% end %>
-</TABLE>
-
+../status-html.lsp \ No newline at end of file
diff --git a/openvpn-statusinfo-html.lsp b/openvpn-statusinfo-html.lsp
index 000000f..e6f85b5 100644
--- a/openvpn-statusinfo-html.lsp
+++ b/openvpn-statusinfo-html.lsp
@@ -1,6 +1,5 @@
<% local view = ... %>
-<html>
-<body>
+
<h1>Status</h1>
<h2>Connected clients</h2>
@@ -12,19 +11,17 @@
<TD>Bytes<BR>Received</TD>
<TD>Bytes<BR>Sent</TD>
</TR>
-<% for i = 1, table.maxn(view.clientlist) do %>
+<% for i in ipairs(view.value) do %>
<TR>
- <TD><%= view.clientlist[i].CN %></TD>
- <TD><%= view.clientlist[i].VIRTADDR %></TD>
- <TD><%= view.clientlist[i].REALADDR %></TD>
- <TD><%= view.clientlist[i].BYTESRCV %></TD>
- <TD><%= view.clientlist[i].BYTESSND %></TD>
+ <TD><%= view.value[i].CN %></TD>
+ <TD><%= view.value[i].VIRTADDR %></TD>
+ <TD><%= view.value[i].REALADDR %></TD>
+ <TD><%= view.value[i].BYTESRCV %></TD>
+ <TD><%= view.value[i].BYTESSND %></TD>
</TR>
<TR>
- <TD COLSPAN=5 style="border-bottom: 1px solid #ccc;"><%= view.clientlist[i].CONN %></TD>
+ <TD COLSPAN=5 style="border-bottom: 1px solid #ccc;"><%= view.value[i].CONN %></TD>
</TR>
<% end %>
</TABLE>
-</body>
-</html>
diff --git a/openvpn-unknownconfig-html.lsp b/openvpn-unknownconfig-html.lsp
deleted file mode 100644
index ab37bfc..0000000
--- a/openvpn-unknownconfig-html.lsp
+++ /dev/null
@@ -1,29 +0,0 @@
-<% local view = ... %>
-<html>
-<body>
-<h1>Configuration file '<%= view.configfilecontent.name %>'</h1>
-
-<h2>Details</h2>
-
-<dt>File name</dt>
-<dd><%= view.configfilecontent.filedetails.longname %></dd>
-
-<dt>File size</dt>
-<dd><%= view.configfilecontent.filedetails.size %></dd>
-
-<dt>Last modified</dt>
-<dd><%= view.configfilecontent.filedetails.mtimelong %></dd>
-
-<dt>This config looks like a</dt>
-<dd><a href="<%= view.url %>/<%= view.configfilecontent.type %>_config?name=<%= view.configfilecontent.name %>"><%= view.configfilecontent.type %></a> config</a></dd>
-
-<h2>Content</h2>
-
-<form name="myform" action="" method="POST">
-<input name="name" type="hidden" value="<%= view.configfilecontent.name %>">
-<textarea name="modifications"><%= view.configfilecontent.value %></textarea>
-
-<input type="submit" name="cmd" class="submit" value="update"></form>
-
-</body>
-</html>
diff --git a/openvpn-viewconfig-html.lsp b/openvpn-viewconfig-html.lsp
new file mode 100644
index 0000000..1cdfa8d
--- /dev/null
+++ b/openvpn-viewconfig-html.lsp
@@ -0,0 +1,82 @@
+<% local view, viewlibrary, page_info, session = ... %>
+<% require("format") %>
+<% local shortname = string.gsub(view.value.name, "^.*/", "") %>
+
+<h1><%= format.cap_begin_word(view.value.type) %> config '<%= shortname %>'</h1>
+
+<h2><%= format.cap_begin_word(view.value.type) %> settings</h2>
+<dl>
+<dt>Mode</dt>
+<dd><%= view.value.type %></dd>
+
+<dt>User device</dt>
+<dd><%= view.value.dev %></dd>
+
+<% if view.value.type == "server" then %>
+<dt>Listens on</dt>
+<dd><%= view.value["local"] %>:<%= view.value.port %> (<%= view.value.proto %>)</dd>
+<% end %>
+
+<% if view.value.type == "client" then %>
+<dt>Remote server</dt>
+<dd><% if string.find(view.value.remote, "%s") then io.write((string.gsub(view.value.remote, "%s+", ":"))) else io.write(view.value.remote .. (view.value.rport or view.value.port or "1194")) end %> (<%= view.value.proto %>)</dd>
+<% end %>
+
+<dt>Logfile</dt>
+<dd><% if ( view.value.log ) then %><%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/logfile?name=" .. view.value.name, label=view.value.log } %><% else %>Syslog<% end %> (Verbosity level: <%= view.value.verb %>)</dd>
+</dl>
+
+<% if view.value.type == "server" then %>
+<h3>Connected clients status</h3>
+<dl>
+<dt>Last status was recorded</dt>
+<dd><%= view.value.client_lastupdate %> (This was <b><%= view.value.client_lastdatechangediff %></b> ago)</dd>
+
+<dt>Maximum clients</dt>
+<dd><%= view.value["max-clients"] %></dd>
+
+<dt>Connected clients</dt>
+<dd><% if ( view.value.client_count > 0 ) then %><%= html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/status_info?name=" .. view.value.name , label=view.value.client_count } %><% else %><%= view.value.client_count %><% end %></dd>
+</dl>
+<% end %>
+
+<h2>Startup options</h2>
+<dl>
+<dt>Process status</dt>
+<dd><%= view.value.status_isrunning %></dd>
+</dl>
+
+<% if view.value.dh or view.value.ca or view.value.cert or view.value.key or view.value.tls or view.value.crl then %>
+<h2>Certificate files</h2>
+<dl>
+<% if (view.value.dh) then %>
+<dt>DH</dt>
+<dd><%= view.value.dh %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.dh , label=view.value.dh } %></dd>
+<% end %>
+
+<% if (view.value.ca) then %>
+<dt>CA Certificate</dt>
+<dd><%= view.value.ca %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.ca , label=view.value.ca } %></dd>
+<% end %>
+
+<% if (view.value.cert) then %>
+<dt>Certificate</dt>
+<dd><%= view.value.cert %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.cert , label=view.value.cert } %></dd>
+<% end %>
+
+<% if (view.value.key) then %>
+<dt>Private Key</dt>
+<dd><%= view.value.key %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.key , label=view.value.key } %></dd>
+<% end %>
+
+<% if (view.value.tls) then %>
+<dt>TLS Authentication</dt>
+<dd><%= view.value.tls %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.tls , label=view.value.tls } %></dd>
+<% end %>
+
+<% if (view.value.crl) then %>
+<dt>CRL Verify File</dt>
+<dd><%= view.value.crl %><% -- html.link{value = page_info.script .. page_info.prefix .. page_info.controller .. "/pem_info?name=" .. view.value.crl , label=view.value.crl } %></dd>
+<% end %>
+</dl>
+<% end %>
diff --git a/openvpn.menu b/openvpn.menu
index bfcbefa..be042b4 100644
--- a/openvpn.menu
+++ b/openvpn.menu
@@ -1,2 +1,3 @@
#CAT GROUP/DESC TAB ACTION
Networking 40OpenVPN Status status
+Networking 40OpenVPN Config listconfigs
diff --git a/openvpn.roles b/openvpn.roles
index 43ef507..a5cdc7e 100644
--- a/openvpn.roles
+++ b/openvpn.roles
@@ -1,3 +1,3 @@
-USER=openvpn:status,openvpn:statusinfo,openvpn:logfile
-EDITOR=openvpn:serverconfig,openvpn:clientconfig,openvpn:peminfo,openvpn:unknownconfig
-ADMIN=openvpn:status,openvpn:statusinfo,openvpn:logfile,openvpn:serverconfig,openvpn:clientconfig,openvpn:peminfo,openvpn:unknownconfig
+USER=openvpn:status,openvpn:statusinfo,openvpn:logfile,openvpn:listconfigs,openvpn:viewconfig
+EXPERT=openvpn:editconfig,openvpn:createconfig,openvpn:deleteconfig
+ADMIN=openvpn:status,openvpn:statusinfo,openvpn:logfile,openvpn:listconfigs,openvpn:viewconfig,openvpn:editconfig,openvpn:createconfig,openvpn:deleteconfig