From 3424c10a7a9cadc4697951b259d70fc26f56b197 Mon Sep 17 00:00:00 2001 From: Ted Trask Date: Thu, 19 Nov 2009 16:26:08 +0000 Subject: Major changes to only handle one config and add cert processing. --- openvpn-model.lua | 216 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 124 insertions(+), 92 deletions(-) (limited to 'openvpn-model.lua') diff --git a/openvpn-model.lua b/openvpn-model.lua index 7468a01..70de3c8 100644 --- a/openvpn-model.lua +++ b/openvpn-model.lua @@ -10,8 +10,11 @@ require ("date") local processname = "openvpn" local packagename = "openvpn" +local configfile = "/etc/openvpn/openvpn.conf" local baseurl = "/etc/openvpn/" +local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " + -- ################################################################################ -- LOCAL FUNCTIONS @@ -43,22 +46,6 @@ local function config_content( f ) return config end - -local is_running = function( process, parameters ) - local retval = "Stopped" - for i,v in ipairs(processinfo.pidof(process) or {}) do - local path = string.gsub("/proc/".. v .. "/cmdline", "%s", "") - local f = io.open(path,r) - local file_resultx = f:read("*a") - local file_result = string.match(file_resultx, parameters) - f:close() - if ( file_result ) then - retval = "Running" - end - end - return retval -end - 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 @@ -92,16 +79,6 @@ local function check_valid_config (config) return config.type, config.errtxt end -local function list_conffiles() - local configfiles = {} - for file in fs.find(".*conf", baseurl) do - if fs.is_file(file) then - configfiles[#configfiles+1] = file - end - end - return configfiles -end - local function clientlist( statusfile ) local clientlist = {} local routinglist = {} @@ -176,19 +153,20 @@ end -- PUBLIC FUNCTIONS function getstatus() - local status = modelfunctions.getstatus(processname, packagename, "OpenVPN Status") - status.value.autostart = nil - status.value.status = nil - return status + return modelfunctions.getstatus(processname, packagename, "OpenVPN Status") end -function getclientinfo(f) - local config = config_content(f) +function startstop_service(action) + return modelfunctions.startstop_service(processname, action) +end + +function getclientinfo() + local config = config_content(configfile) return cfe({ type="structure", value=clientlist(config.status), label="Client info" }) end -function get_config(f) - local config = config_content(f) +function get_config() + local config = config_content(configfile) check_valid_config(config) if config.type == "server" then local clientlist, client_count, client_lastupdate, client_lastdatechangediff = clientlist(config.status) @@ -196,95 +174,149 @@ function get_config(f) config["client_lastdatechangediff"] = client_lastdatechangediff or "? min" config["client_count"] = client_count or 0 end - config["status_isrunning"] = is_running ("openvpn", basename(f)) return cfe({ type="structure", value=config, label="OpenVPN Config" }) end 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 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 - return cfe({ type="structure", value=configlist, label="Configuration List" }) + local config = config_content(configfile) + return cfe({ value=config.log or "", label="Log file" }) end -function get_filecontent(f) +function get_filecontent() --FIXME validate - return modelfunctions.getfiledetails(f, list_conffiles()) + return modelfunctions.getfiledetails(configfile) end function update_filecontent(filedetails) --FIXME validate - return modelfunctions.setfiledetails(filedetails, list_conffiles()) + return modelfunctions.setfiledetails(filedetails, {configfile}) end -function create_new_config() - config = { - name = cfe({ label="File Name", descr="File name should end with \".conf\"" }), - } +function list_certs() + local list = {} + for file in fs.find(".*%.pem", baseurl) do + list[#list+1] = basename(file) + end + return cfe({ type="list", value=list, label="OpenVPN Certificates" }) +end - return cfe({ type="group", value=config, label="Config" }) +function delete_cert(certname) + local list = list_certs() + local retval = cfe({ label="Delete Certificate result", errtxt="Invalid cert name" }) + for i,cert in ipairs(list.value) do + if cert == certname then + os.remove(baseurl..certname) + retval.value = "Certificate deleted" + retval.errtxt = nil + break + end + end + return retval end -function create_config(config) +function new_upload_cert() + local value = {} + value.cert = cfe({ type="raw", value=0, label="Certificate", descr='File must be a password protected ".pfx" file' }) + value.password = cfe({ label="Certificate Password" }) + value.name = cfe({ label="Certificate Local Name" }) + return cfe({ type="group", value=value }) +end + +function upload_cert(newcert) local success = true - local path = config.value.name.value - if not string.find(path, "/") then - path = baseurl .. path + -- Trying to upload a cert/key + -- The way haserl works, cert contains the temporary file name + -- First, get the cert + local cmd, f, cmdresult + if validator.is_valid_filename(newcert.value.cert.value, "/tmp/") and fs.is_file(newcert.value.cert.value) then + cmd = path .. "openssl pkcs12 -in "..format.escapespecialcharacters(newcert.value.cert.value).." -out "..format.escapespecialcharacters(newcert.value.cert.value).."cert.pem -password pass:"..format.escapespecialcharacters(newcert.value.password.value).." -nokeys -clcerts 2>&1" + f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + local filestats = posix.stat(newcert.value.cert.value.."cert.pem") + if not filestats or filestats.size == 0 then + newcert.value.cert.errtxt = "Could not open certificate\n"..cmdresult + success = false + end + else + newcert.value.cert.errtxt = "Invalid certificate" + success = false end - if not validator.is_valid_filename(path, baseurl) then - success = false - config.value.name.errtxt = "Invalid path" - elseif posix.stat(path) then + -- Now, get the key and the ca certs + if success then + cmd = path .. "openssl pkcs12 -in "..format.escapespecialcharacters(newcert.value.cert.value).." -out "..format.escapespecialcharacters(newcert.value.cert.value).."key.pem -password pass:"..format.escapespecialcharacters(newcert.value.password.value).." -nocerts -nodes 2>&1" + f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + filestats = posix.stat(newcert.value.cert.value.."key.pem") + if not filestats or filestats.size == 0 then + newcert.value.cert.errtxt = "Could not find key\n"..cmdresult + success = false + end + + cmd = path .. "openssl pkcs12 -in "..format.escapespecialcharacters(newcert.value.cert.value).." -out "..format.escapespecialcharacters(newcert.value.cert.value).."ca.pem -password pass:"..format.escapespecialcharacters(newcert.value.password.value).." -nokeys -cacerts 2>&1" + f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + filestats = posix.stat(newcert.value.cert.value.."ca.pem") + if not filestats or filestats.size == 0 then + newcert.value.cert.errtxt = "Could not find CA certs\n"..cmdresult + success = false + end + end + + if newcert.value.name.value == "" then + newcert.value.name.errtxt = "Cannot be blank" success = false - config.value.name.errtxt = "File already exists" - elseif not string.match(path,".*%.conf") then + elseif posix.stat(baseurl..newcert.value.name.value.."-cert.pem") or posix.stat(baseurl..newcert.value.name.value.."-key.pem") or posix.stat(baseurl..newcert.value.name.value.."-ca.pem") then + newcert.value.name.errtxt = "Certificate of this name already exists" success = false - config.value.name.errtxt = "Filename must end with '.conf'" end if success then - fs.create_file(path) + if not posix.stat(baseurl) then + posix.mkdir(baseurl) + end + -- copy the keys + fs.move_file(newcert.value.cert.value.."cert.pem", baseurl..newcert.value.name.value.."-cert.pem") + fs.move_file(newcert.value.cert.value.."key.pem", baseurl..newcert.value.name.value.."-key.pem") + fs.move_file(newcert.value.cert.value.."ca.pem", baseurl..newcert.value.name.value.."-ca.pem") + posix.chmod(baseurl..newcert.value.name.value.."-key.pem", "rw-------") else - config.errtxt = "Failed to create config" + newcert.errtxt = "Failed to upload certificate" 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 + -- Delete the temporary files + if validator.is_valid_filename(newcert.value.cert.value, "/tmp/") and fs.is_file(newcert.value.cert.value) then + os.remove(newcert.value.cert.value.."cert.pem") + os.remove(newcert.value.cert.value.."key.pem") + os.remove(newcert.value.cert.value.."ca.pem") end - return cmdresult + return newcert end -function startstop_service(action,service) - if (service ~= "openvpn") then - if ( fs.is_file(baseurl .. service .. ".conf") ) then - service = "openvpn." .. tostring(service) - if not ( fs.is_file("/etc/init.d/" .. service ) ) then - -- Create missing symlinks - posix.link("/etc/init.d/openvpn","/etc/init.d/" .. service, true) - end - else - return nil +view_cert = function(certname) + local list = list_certs() + local cmdresult = "Invalid cert name" + for i,cert in ipairs(list.value) do + if cert == certname or certname == (baseurl .. cert) then + local cmd = path .. "openssl x509 -in "..baseurl..format.escapespecialcharacters(cert).." -noout -text" + local f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + cmdresult = cmdresult .. "Content:\n" .. (fs.read_file(baseurl..cert) or "") end end - return modelfunctions.startstop_service(service, action) + return cfe({ type="table", value={name=certname, value=cmdresult}, label="Certificate" }) +end + +generate_dh_params = function() + local cmd = path .. "openssl dhparam -out /etc/openvpn/dh1024.pem 1024 2>&1" + f = io.popen(cmd) + local cmdresult = f:read("*a") + f:close() + + return cfe({ value=cmdresult, label="Generate Diffie Hellman parameters result" }) end -- cgit v1.2.3