From 2dac09e436f254663a7ca5db3501468248192f7f Mon Sep 17 00:00:00 2001 From: Ted Trask Date: Wed, 21 Jan 2009 22:04:37 +0000 Subject: Added escapespecialcharacters to format.lua to escape shell special characters. Reviewed all calls to io.popen and os.execute to escape special characters. Fixed file uploads in openssl and ipsectools with viewfunctions.lua. Tried to fix openssl renew when subject contains special characters, but not done yet. git-svn-id: svn://svn.alpinelinux.org/acf/openssl/trunk@1687 ab2d0c66-481e-0410-8bed-d214d4d58bed --- openssl-model.lua | 114 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 49 deletions(-) (limited to 'openssl-model.lua') diff --git a/openssl-model.lua b/openssl-model.lua index 470d9ba..2f4120c 100644 --- a/openssl-model.lua +++ b/openssl-model.lua @@ -105,13 +105,16 @@ local create_subject_string = function(values, ignorevalues) name = name:gsub(".*%.", "") -- remove the "0." from the front if (short_names[name] or reverseshorts[name]) and value.value and value.value ~= "" then name = short_names[name] or name - outstr[#outstr + 1] = name .. "=" .. value.value:gsub("[/=]", "\\%1") -- escape characters + -- escape characters + outstr[#outstr + 1] = name .. "=" .. format.escapespecialcharacters(value.value):gsub("[=]", "\\%1") end end + -- now do the ones with no short names (and not ignored) for name,value in pairs(values.value) do name = name:gsub(".*%.", "") -- remove the "0." from the front if not reverseignore[name] and not short_names[name] and not reverseshorts[name] and value.value and value.value ~= "" then - outstr[#outstr + 1] = name .. "=" .. value.value:gsub("[/=]", "\\%1") -- escape characters + -- escape characters + outstr[#outstr + 1] = format.escapespecialcharacters(name) .. "=" .. format.escapespecialcharacters(value.value):gsub("[=]", "\\%1") end end return "/"..table.concat(outstr, "/") @@ -186,11 +189,11 @@ end local copyca = function(cacert, cakey) config = config or format.parse_ini_file(fs.read_file(configfile) or "") local certpath = getconfigentry(config.ca.default_ca, "certificate") - local cmd = "cp "..cacert.." "..certpath + local cmd = "cp "..format.escapespecialcharacters(cacert).." "..format.escapespecialcharacters(certpath) local f = io.popen(cmd) f:close() local keypath = getconfigentry(config.ca.default_ca, "private_key") - local cmd = "cp "..cakey.." "..keypath + local cmd = "cp "..format.escapespecialcharacters(cakey).." "..format.escapespecialcharacters(keypath) local f = io.popen(cmd) f:close() end @@ -273,7 +276,7 @@ getstatus = function() if not fs.is_file(cacert.value) then cacert.errtxt="File not found" else - local cmd = path .. "openssl x509 -in "..cacert.value.." -noout -text" + local cmd = path .. "openssl x509 -in "..format.escapespecialcharacters(cacert.value).." -noout -text" local f = io.popen(cmd) cacertcontents.value = f:read("*a") f:close() @@ -412,7 +415,7 @@ submitrequest = function(defaults, user) end fs.write_file(reqname..".cfg", fileval) - local cmd = path .. "openssl req -nodes -new -config "..reqname..".cfg -keyout "..reqname..".pem -out "..reqname..".csr -subj '"..subject.."' 2>&1" + local cmd = path .. "openssl req -nodes -new -config "..format.escapespecialcharacters(reqname)..".cfg -keyout "..format.escapespecialcharacters(reqname)..".pem -out "..format.escapespecialcharacters(reqname)..'.csr -subj "'..subject..'" 2>&1' local f = io.popen(cmd) local cmdresult = f:read("*a") f:close() @@ -421,11 +424,12 @@ submitrequest = function(defaults, user) local keyfilestats = posix.stat(reqname..".pem") if not certfilestats or certfilestats.size == 0 or not keyfilestats or keyfilestats.size == 0 then success = false - cmd = "rm "..reqname..".*" + cmd = "rm "..format.escapespecialcharacters(reqname)..".*" f = io.popen(cmd) f:close() else fs.write_file(reqname..".pwd", defaults.value.password.value) + fs.write_file(reqname..".sbj", subject) end end @@ -439,7 +443,7 @@ end listrequests = function(user) user = user or "*" local list={} - local fh = io.popen("find " .. requestdir .. " -name "..user..".*.csr -maxdepth 1") + local fh = io.popen("find " .. format.escapespecialcharacters(requestdir) .. " -name "..format.escapespecialcharacters(user)..".*.csr -maxdepth 1") for x in fh:lines() do local name = basename(x,".csr") local a,b,c = string.match(name, "([^%.]*)%.([^%.]*)%.([^%.]*)") @@ -450,7 +454,7 @@ end viewrequest = function(request) local reqpath = requestdir .. request - local cmd = path .. "openssl req -in "..reqpath..".csr -text -noout" + local cmd = path .. "openssl req -in "..format.escapespecialcharacters(reqpath)..".csr -text -noout" local f = io.popen(cmd) local cmdresult = f:read("*a") f:close() @@ -473,7 +477,7 @@ approverequest = function(request) local certname = certdir..request.."."..serial -- Now, sign the certificate - local cmd = path .. "openssl ca -config "..configfile.." -in "..reqpath..".csr -out "..certname..".crt -name "..certtype.." -batch 2>&1" + local cmd = path .. "openssl ca -config "..configfile.." -in "..format.escapespecialcharacters(reqpath)..".csr -out "..format.escapespecialcharacters(certname)..".crt -name "..format.escapespecialcharacters(certtype).." -batch 2>&1" local f = io.popen(cmd) cmdresult.value = f:read("*a") f:close() @@ -482,7 +486,7 @@ approverequest = function(request) local filestats = posix.stat(certname..".crt") if filestats and filestats.size > 0 then -- We're wrapping up the key, the cert, and the CA cert (and whatever came with it) - cmd = path .. "openssl pkcs12 -export -inkey "..reqpath..".pem -in "..certname..".crt -out "..certname..".pfx -passout file:"..reqpath..".pwd -certfile "..getconfigentry(certtype, "certificate").." 2>&1" + cmd = path .. "openssl pkcs12 -export -inkey "..format.escapespecialcharacters(reqpath)..".pem -in "..format.escapespecialcharacters(certname)..".crt -out "..format.escapespecialcharacters(certname)..".pfx -passout file:"..format.escapespecialcharacters(reqpath)..".pwd -certfile "..format.escapespecialcharacters(getconfigentry(certtype, "certificate")).." 2>&1" f = io.popen(cmd) local newcmdresult = f:read("*a") f:close() @@ -492,21 +496,24 @@ approverequest = function(request) -- Finally, remove the request filestats = posix.stat(certname..".pfx") if filestats and filestats.size > 0 then - cmd = "cp "..reqpath..".pwd "..certname..".pwd" + cmd = "cp "..format.escapespecialcharacters(reqpath)..".pwd "..format.escapespecialcharacters(certname)..".pwd" f = io.popen(cmd) f:close() - cmd = "cp "..reqpath..".pem "..certname..".pem" + cmd = "cp "..format.escapespecialcharacters(reqpath)..".sbj "..format.escapespecialcharacters(certname)..".sbj" f = io.popen(cmd) f:close() - cmd = "cp "..reqpath..".cfg "..certname..".cfg" + cmd = "cp "..format.escapespecialcharacters(reqpath)..".pem "..format.escapespecialcharacters(certname)..".pem" f = io.popen(cmd) f:close() - cmd = "rm "..reqpath..".*" + cmd = "cp "..format.escapespecialcharacters(reqpath)..".cfg "..format.escapespecialcharacters(certname)..".cfg" + f = io.popen(cmd) + f:close() + cmd = "rm "..format.escapespecialcharacters(reqpath)..".*" f = io.popen(cmd) f:close() else -- or failed, remove the cert - cmd = "rm "..certname..".*" + cmd = "rm "..format.escapespecialcharacters(certname)..".*" f = io.popen(cmd) f:close() end @@ -519,7 +526,7 @@ deleterequest = function(request, user) if (not fs.is_file(requestdir..request..".csr")) or (not string.find(request, "^"..user.."%.")) then return cfe({ value="Request not found", label="Delete result" }) end - cmd = "rm "..requestdir..request..".*" + cmd = "rm "..requestdir..format.escapespecialcharacters(request)..".*" f = io.popen(cmd) f:close() return cfe({ value="Request deleted", label="Delete result" }) @@ -528,11 +535,11 @@ end listcerts = function(user) user = user or "*" local list={} - local fh = io.popen("find " .. certdir .. " -name "..user..".*.pfx -maxdepth 1") + local fh = io.popen("find " .. certdir .. " -name "..format.escapespecialcharacters(user)..".*.pfx -maxdepth 1") for x in fh:lines() do local name = basename(x,".pfx") local a,b,c,d = string.match(name, "([^%.]*)%.([^%.]*)%.([^%.]*).([^%.]*)") - local cmd = path .. "openssl x509 -in "..certdir..name..".crt -noout -enddate" + local cmd = path .. "openssl x509 -in "..certdir..format.escapespecialcharacters(name)..".crt -noout -enddate" local f = io.popen(cmd) local enddate = f:read("*a") enddate = string.match(enddate, "notAfter=(.*)") @@ -553,7 +560,7 @@ listcerts = function(user) end viewcert = function(cert) - local cmd = path .. "openssl x509 -in "..certdir..cert..".crt -noout -text" + local cmd = path .. "openssl x509 -in "..certdir..format.escapespecialcharacters(cert)..".crt -noout -text" local f = io.popen(cmd) local cmdresult = f:read("*a") f:close() @@ -570,7 +577,7 @@ end revokecert = function(cert) local cmdresult = cfe({ label="Revoke result" }) - local cmd = path .. "openssl ca -config "..configfile.." -revoke "..certdir .. cert..".crt -batch 2>&1" + local cmd = path .. "openssl ca -config "..configfile.." -revoke "..certdir .. format.escapespecialcharacters(cert)..".crt -batch 2>&1" local f = io.popen(cmd) cmdresult.value = f:read("*a") f:close() @@ -579,7 +586,7 @@ end deletecert = function(cert) -- The certificate will still be in the ca directories and index.txt, just not available for web interface - cmd = "rm "..certdir..cert..".*" + cmd = "rm "..certdir..format.escapespecialcharacters(cert)..".*" f = io.popen(cmd) f:close() return cfe({ value="Certificate deleted", label="Delete result" }) @@ -597,23 +604,22 @@ renewcert = function(cert, approve) if success then -- Submit the request - -- First, get the subject - local cmd = path .. "openssl x509 -in "..certdir..cert..".crt -noout -subject" - local f = io.popen(cmd) - local subject = f:read("*a") - subject = string.match(subject, "subject= ([^\n]*)") + -- First, put the subject, config file and password in place + cmd = "cp "..certdir..format.escapespecialcharacters(cert)..".pwd "..format.escapespecialcharacters(reqname)..".pwd" + f = io.popen(cmd) f:close() - - -- Next, put the key and password in place - cmd = "cp "..certdir..cert..".pwd "..reqname..".pwd" + cmd = "cp "..certdir..format.escapespecialcharacters(cert)..".sbj "..format.escapespecialcharacters(reqname)..".sbj" f = io.popen(cmd) f:close() - cmd = "cp "..certdir..cert..".cfg "..reqname..".cfg" + cmd = "cp "..certdir..format.escapespecialcharacters(cert)..".cfg "..format.escapespecialcharacters(reqname)..".cfg" f = io.popen(cmd) f:close() - -- Next, submit the request - cmd = path .. "openssl req -nodes -new -config "..reqname..".cfg -keyout "..reqname..".pem -out "..reqname..".csr -subj '"..subject.."' 2>&1" + -- Next, get the subject (removing the /n inserted by fs.write_file) + local subject = string.gsub(fs.read_file(reqname..".sbj") or "", "\n", "") + + -- Next, submit the request (new key) + cmd = path .. "openssl req -nodes -new -config "..format.escapespecialcharacters(reqname)..".cfg -keyout "..format.escapespecialcharacters(reqname)..".pem -out "..format.escapespecialcharacters(reqname)..'.csr -subj "'..subject..'" 2>&1' f = io.popen(cmd) cmdresult = f:read("*a") f:close() @@ -621,7 +627,7 @@ renewcert = function(cert, approve) if not filestats or filestats.size == 0 then cmdresult = "Failed to submit request\n"..cmdresult success = false - cmd = "rm "..reqname..".*" + cmd = "rm "..format.escapespecialcharacters(reqname)..".*" f = io.popen(cmd) f:close() else @@ -680,19 +686,25 @@ putca = function(newca) -- Trying to upload a cert/key -- The way haserl works, ca contains the temporary file name -- First, get the cert - local cmd = path .. "openssl pkcs12 -in "..newca.value.ca.value.." -out "..newca.value.ca.value.."cert.pem -password pass:"..newca.value.password.value.." -nokeys 2>&1" - local f = io.popen(cmd) - local cmdresult = f:read("*a") - f:close() - local filestats = posix.stat(newca.value.ca.value.."cert.pem") - if not filestats or filestats.size == 0 then - newca.value.ca.errtxt = "Could not open certificate\n"..cmdresult + local cmd, f, cmdresult + if validator.is_valid_filename(newca.value.ca.value, "/tmp/") and fs.is_file(newca.value.ca.value) then + cmd = path .. "openssl pkcs12 -in "..format.escapespecialcharacters(newca.value.ca.value).." -out "..format.escapespecialcharacters(newca.value.ca.value).."cert.pem -password pass:"..format.escapespecialcharacters(newca.value.password.value).." -nokeys 2>&1" + f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + local filestats = posix.stat(newca.value.ca.value.."cert.pem") + if not filestats or filestats.size == 0 then + newca.value.ca.errtxt = "Could not open certificate\n"..cmdresult + success = false + end + else + newca.value.ca.errtxt = "Invalid certificate" success = false end - -- Since -cacerts doesn't seem to work, we have to check to make sure we got a CA + -- Check to make sure we got a CA cert if success then - cmd = path .. "openssl x509 -in "..newca.value.ca.value.."cert.pem -noout -text" + cmd = path .. "openssl x509 -in "..format.escapespecialcharacters(newca.value.ca.value).."cert.pem -noout -text" f = io.popen(cmd) cmdresult = f:read("*a") f:close() @@ -704,7 +716,7 @@ putca = function(newca) -- Now, get the key if success then - cmd = path .. "openssl pkcs12 -in "..newca.value.ca.value.." -out "..newca.value.ca.value.."key.pem -password pass:"..newca.value.password.value.." -nocerts -nodes 2>&1" + cmd = path .. "openssl pkcs12 -in "..format.escapespecialcharacters(newca.value.ca.value).." -out "..format.escapespecialcharacters(newca.value.ca.value).."key.pem -password pass:"..format.escapespecialcharacters(newca.value.password.value).." -nocerts -nodes 2>&1" f = io.popen(cmd) cmdresult = f:read("*a") f:close() @@ -723,10 +735,14 @@ putca = function(newca) end -- Delete the temporary files - cmd = "rm "..newca.value.ca.value.."*" - f = io.popen(cmd) - f:close() - + if validator.is_valid_filename(newca.value.ca.value, "/tmp/") and fs.is_file(newca.value.ca.value) then + cmd = "rm "..format.escapespecialcharacters(newca.value.ca.value) + f = io.popen(cmd.."cert.pem") + f:close() + f = io.popen(cmd.."key.pem") + f:close() + end + -- Clear the values newca.value.ca.value = "" newca.value.password.value = "" @@ -752,7 +768,7 @@ generateca = function(defaults) if success then -- Submit the request local subject = create_subject_string(defaults, {"days"}) - local cmd = path .. "openssl req -x509 -nodes -new -config "..configfile.." -keyout /tmp/cakey.pem -out /tmp/cacert.pem -subj '"..subject.."' -days "..defaults.value.days.value.." 2>&1" + local cmd = path .. "openssl req -x509 -nodes -new -config "..configfile..' -keyout /tmp/cakey.pem -out /tmp/cacert.pem -subj "'..subject..'" -days '..format.escapespecialcharacters(defaults.value.days.value).." 2>&1" local f = io.popen(cmd) local cmdresult = f:read("*a") f:close() -- cgit v1.2.3