local auxlib = require"openssl.auxlib" local pkey = require "openssl.pkey" local x509_csr = require"_openssl.x509.csr" local x509_altname = require"openssl.x509.altname" local x509_name = require"openssl.x509.name" local _basename = arg and arg[0] and arg[0]:match"([^/]+)$" or "UNKNOWN" local function cluck(fmt, ...) io.stderr:write(_basename, ": ", string.format(fmt, ...), "\n") end local function croak(fmt, ...) io.stderr:write(_basename, ": ", string.format(fmt, ...), "\n") os.exit(1) end local function OK() cluck("OK") return true end local _testno = 0 local function testnames(altnames, expected) local matched = {} _testno = _testno + 1 for type,data in auxlib.pairs(altnames) do local found for i,e in ipairs(expected) do if not matched[i] and e.type == type and e.data == data then cluck("expected match #%d.%d found (%s=%s)", _testno, i, type,data) matched[i] = true found = true end end if not found then return false, string.format("extra name in test #%d (%s=%s)", _testno, type, data) end end for i,e in ipairs(expected) do if not matched[i] then return false, string.format("expected match #%d.%d not found (%s=%s)", _testno, i, e.type, e.data) end end return true end local function checknames(altnames, expected) local ok, why = testnames(altnames, expected) if not ok then croak(why or "UNKNOWN") end return true end key = pkey.new({ bits = 4096 }) data = [[ -----BEGIN CERTIFICATE REQUEST----- MIIFQjCCAyoCAQAwUzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1OMRQwEgYDVQQH DAtNaW5uZWFwb2xpczEhMB8GA1UECwwYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4sXzE3GQtpFKiuGe389k MB0OaGXQxiI/yl6zm9PyYWe5aMpx1THDVhkWXemDVkduEqtLfa8GSNT0ps3BPdTx qxNwZ3J9xiVfNZZYO5ZSxs1g32M1lw20wIezLpbQ1ggyt01o9VTQDY6kA+D0G87B 4FtIZxVaXM2z5HVaGYyivxAygDukDsO+RU0NC9mYOfAP4rt/u/xp8LsW0b4aIFqx gPcBZj92B+Wi2B4sKSe1m5kMfmh+e8v981hbY7V8FUMebB63iRGF6GU4kjXiMMW6 gSoc+usq9li8VxjxPngql9pyLqFIa/2gW0c9sKKB2X9tB0nmudjAUrjZjHZEDlNr yx15JHhEIT31yP9xGQpy5H+jBldp/shqaV4Alsou9Hn9W71ap7VHOWLrIcaZGKTn CVSSYPygn4Rm8Cgwbv5mP6G+SqGHAFqirEysAARUFxsjBLlkNaVFOA38l2cufH8n 1NE/B4iOG/ETvQDR/aKrbyKKo2k/hO941h3J9pwJcCikE0NsRcH6WAm8ifJ0Zd/q u8fqI8g9mYPbMWy11+njnfNOVFVhNOmM1/ZM66ac9zgGYncaHu4UzYnvWw75tDbF vA+oIJlcxBUtWeTcYRf4xEcRL8IcHEwh1BZq7bgP42Wu+0aBuaa3eYXNBApCNP39 QmnHlo0iGH2rVeOfcq/wULcCAwEAAaCBqTCBpgYJKoZIhvcNAQkOMYGYMIGVMAkG A1UdEwQCMAAwCwYDVR0PBAQDAgXgMHsGA1UdEQR0MHKCE3NlcnZlcjEuZXhhbXBs ZS5jb22CEG1haWwuZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNvbYITd3d3LnN1 Yi5leGFtcGxlLmNvbYIObXguZXhhbXBsZS5jb22CE3N1cHBvcnQuZXhhbXBsZS5j b20wDQYJKoZIhvcNAQEFBQADggIBAMiFPtDKVsy4HBhVkHSnbbIl41baaGGFjI/O MG8fI7P9jplq5rNZcLxSW2zLzMVuYzCoC+q5roRE5zVVyJlB+5dY0A8e2xKaWVOT AB9WvgepPvXDoGNViMBoX/idj3J2BU3e/cX08QWRPjKigwQWQWvUGsZYitGJv+Yv /LbIDlxr8Jr+1Txcm1EdXcff6Owlh6Nu59bgCMRdZvABmWfU5ULmUDTJnmc3P9St onz07v8ku8/XL7wwOfLJWVSVOk7RONySIJiPfVkgrU3YWiT64JaluDbFEIwnEgJS 04xL6Pl66bADXCaeG3pZ8ypCs41+4bqFvCnOYma0Sk8fv8hSCWvJfMQI+nQslPJu UuGK4C4EEnYvoh/Qs/XEshfrVaNcG0zER3XtsRPAjhZjTPTcRgEjpOI0w3TJAvlN LSQV4mXN6E2bcU+cRYvNSgqITwJ7c6wpsONwApIQwFryLsFSCHaIdSLpAZbEPNEW UPa3uWXk5lWrBBPPkxyPbt8D3zpzahY4ycYEFKdz8MLdgA7pDalI2XpwgmoUybkw AJnsFg7fnFc03R4FsqxCqvbRYj3Bccb8Uhg1zTeXU+7nxjP2yYdT+In16L9SYOsU 4ozEPqnGY9aI11i6C7hBwrUTvHYD6ZSDlylsUXKw/VZXQvS3+C0h6NuRmjBx8jNU RG1EyxL4 -----END CERTIFICATE REQUEST----- ]] -- baseline do local expected = { { type = "DNS", data = "server1.example.com" }, { type = "DNS", data = "mail.example.com" }, { type = "DNS", data = "www.example.com" }, { type = "DNS", data = "www.sub.example.com" }, { type = "DNS", data = "mx.example.com" }, { type = "DNS", data = "support.example.com" }, } checknames((x509_csr.new(data)):getSubjectAlt(), expected) end -- modifying existing altnames do local expected = { { type = "DNS", data = "foo.com" }, { type = "DNS", data = "*.foo.com" }, } local csr = x509_csr.new(data) local gn = x509_altname.new() gn:add("DNS", "foo.com") gn:add("DNS", "*.foo.com") csr:setSubjectAlt(gn) csr:setPublicKey(key) csr:sign(key) -- check modified object checknames(csr:getSubjectAlt(), expected) -- check after a round-trip through PEM checknames(x509_csr.new(tostring(csr)):getSubjectAlt(), expected) end -- adding altnames where none existed do local expected = { name = { { type = "CN", data = "example.com" }, }, altname = { { type = "DNS", data = "foo.com" }, { type = "DNS", data = "*.foo.com" }, }, } local csr = x509_csr.new() local name = x509_name.new() name:add("CN", "example.com") csr:setSubject(name) local gn = x509_altname.new() gn:add("DNS", "foo.com") gn:add("DNS", "*.foo.com") csr:setSubjectAlt(gn) csr:setPublicKey(key) csr:sign(key) checknames(csr:getSubject(), expected.name) checknames(csr:getSubjectAlt(), expected.altname) local csr1 = x509_csr.new(tostring(csr)) checknames(csr1:getSubject(), expected.name) checknames(csr1:getSubjectAlt(), expected.altname) end return OK()