aboutsummaryrefslogtreecommitdiffstats
path: root/server/resty/openssl/x509/name.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/openssl/x509/name.lua')
-rw-r--r--server/resty/openssl/x509/name.lua156
1 files changed, 156 insertions, 0 deletions
diff --git a/server/resty/openssl/x509/name.lua b/server/resty/openssl/x509/name.lua
new file mode 100644
index 0000000..f83fcc1
--- /dev/null
+++ b/server/resty/openssl/x509/name.lua
@@ -0,0 +1,156 @@
+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