File: //opt/imunify360-webshield/lualib/resty/openssl/x509/name.lua
local ffi = require "ffi"
local C = ffi.C
local ffi_gc = ffi.gc
local ffi_str = ffi.string
require "resty.openssl.include.x509.name"
require "resty.openssl.include.err"
local objects_lib = require "resty.openssl.objects"
local asn1_macro = require "resty.openssl.include.asn1"
-- local MBSTRING_FLAG = 0x1000
local MBSTRING_ASC = 0x1001 -- (MBSTRING_FLAG|1)
local _M = {}
local x509_name_ptr_ct = ffi.typeof("X509_NAME*")
-- starts from 0
local function value_at(ctx, i)
local entry = C.X509_NAME_get_entry(ctx, i)
local obj = C.X509_NAME_ENTRY_get_object(entry)
local ret = objects_lib.obj2table(obj)
local str = C.X509_NAME_ENTRY_get_data(entry)
if str ~= nil then
ret.blob = ffi_str(asn1_macro.ASN1_STRING_get0_data(str))
end
return ret
end
local function iter(tbl)
local i = 0
local n = tonumber(C.X509_NAME_entry_count(tbl.ctx))
return function()
i = i + 1
if i <= n then
local obj = value_at(tbl.ctx, i-1)
return obj.sn or obj.ln or obj.id, obj
end
end
end
local mt = {
__index = _M,
__pairs = iter,
__len = function(tbl) return tonumber(C.X509_NAME_entry_count(tbl.ctx)) end,
}
function _M.new()
local ctx = C.X509_NAME_new()
if ctx == nil then
return nil, "x509.name.new: X509_NAME_new() failed"
end
ffi_gc(ctx, C.X509_NAME_free)
local self = setmetatable({
ctx = ctx,
}, mt)
return self, nil
end
function _M.istype(l)
return l and l.ctx and ffi.istype(x509_name_ptr_ct, l.ctx)
end
function _M.dup(ctx)
if not ffi.istype(x509_name_ptr_ct, ctx) then
return nil, "x509.name.dup: expect a x509.name ctx at #1, got " .. type(ctx)
end
local ctx = C.X509_NAME_dup(ctx)
ffi_gc(ctx, C.X509_NAME_free)
local self = setmetatable({
ctx = ctx,
}, mt)
return self, nil
end
function _M:add(nid, txt)
local asn1 = C.OBJ_txt2obj(nid, 0)
if asn1 == nil then
-- clean up error occurs during OBJ_txt2*
C.ERR_clear_error()
return nil, "x509.name:add: invalid NID text " .. (nid or "nil")
end
local code = C.X509_NAME_add_entry_by_OBJ(self.ctx, asn1, MBSTRING_ASC, txt, #txt, -1, 0)
C.ASN1_OBJECT_free(asn1)
if code ~= 1 then
return nil, "x509.name:add: X509_NAME_add_entry_by_OBJ() failed"
end
return self
end
function _M:find(nid, last_pos)
local asn1 = C.OBJ_txt2obj(nid, 0)
if asn1 == nil then
-- clean up error occurs during OBJ_txt2*
C.ERR_clear_error()
return nil, nil, "x509.name:find: invalid NID text " .. (nid or "nil")
end
-- make 1-index array to 0-index
last_pos = (last_pos or 0) - 1
local pos = C.X509_NAME_get_index_by_OBJ(self.ctx, asn1, last_pos)
if pos == -1 then
return nil
end
C.ASN1_OBJECT_free(asn1)
return value_at(self.ctx, pos), pos+1
end
-- fallback function to iterate if LUAJIT_ENABLE_LUA52COMPAT not enabled
function _M:all()
local ret = {}
local _next = iter(self)
while true do
local k, obj = _next()
if obj then
ret[k] = obj
else
break
end
end
return ret
end
function _M:each()
return iter(self)
end
mt.__tostring = function(self)
local values = {}
local _next = iter(self)
while true do
local k, v = _next()
if k then
table.insert(values, k .. "=" .. v.blob)
else
break
end
end
table.sort(values)
return table.concat(values, "/")
end
_M.tostring = mt.__tostring
return _M