1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
local ffi = require "ffi"
local C = ffi.C
local ffi_gc = ffi.gc
local ffi_cast = ffi.cast
require "resty.openssl.include.x509"
require "resty.openssl.include.x509v3"
require "resty.openssl.include.err"
local altname_lib = require "resty.openssl.x509.altname"
local stack_lib = require "resty.openssl.stack"
local _M = {}
local authority_info_access_ptr_ct = ffi.typeof("AUTHORITY_INFO_ACCESS*")
local STACK = "ACCESS_DESCRIPTION"
local new = stack_lib.new_of(STACK)
local add = stack_lib.add_of(STACK)
local dup = stack_lib.dup_of(STACK)
local aia_decode = function(ctx)
local nid = C.OBJ_obj2nid(ctx.method)
local gn = altname_lib.gn_decode(ctx.location)
return { nid, unpack(gn) }
end
local mt = stack_lib.mt_of(STACK, aia_decode, _M)
local mt__pairs = mt.__pairs
mt.__pairs = function(tbl)
local f = mt__pairs(tbl)
return function()
local _, e = f()
if not e then return end
return unpack(e)
end
end
function _M.new()
local ctx = new()
if ctx == nil then
return nil, "OPENSSL_sk_new_null() failed"
end
local cast = ffi_cast("AUTHORITY_INFO_ACCESS*", ctx)
local self = setmetatable({
ctx = ctx,
cast = cast,
_is_shallow_copy = false,
}, mt)
return self, nil
end
function _M.istype(l)
return l and l.cast and ffi.istype(authority_info_access_ptr_ct, l.cast)
end
function _M.dup(ctx)
if ctx == nil or not ffi.istype(authority_info_access_ptr_ct, ctx) then
return nil, "expect a AUTHORITY_INFO_ACCESS* ctx at #1"
end
local dup_ctx = dup(ctx)
return setmetatable({
ctx = dup_ctx,
cast = ffi_cast("AUTHORITY_INFO_ACCESS*", dup_ctx),
-- don't let lua gc the original stack to keep its elements
_dupped_from = ctx,
_is_shallow_copy = true,
_elem_refs = {},
_elem_refs_idx = 1,
}, mt), nil
end
function _M:add(nid, typ, value)
-- the stack element stays with stack
-- we shouldn't add gc handler if it's already been
-- pushed to stack. instead, rely on the gc handler
-- of the stack to release all memories
local ad = C.ACCESS_DESCRIPTION_new()
if ad == nil then
return nil, "ACCESS_DESCRIPTION_new() failed"
end
-- C.ASN1_OBJECT_free(ad.method)
local asn1 = C.OBJ_txt2obj(nid, 0)
if asn1 == nil then
C.ACCESS_DESCRIPTION_free(ad)
-- clean up error occurs during OBJ_txt2*
C.ERR_clear_error()
return nil, "invalid NID text " .. (nid or "nil")
end
ad.method = asn1
local err = altname_lib.gn_set(ad.location, typ, value)
if err then
C.ACCESS_DESCRIPTION_free(ad)
return nil, err
end
local _, err = add(self.ctx, ad)
if err then
C.ACCESS_DESCRIPTION_free(ad)
return nil, err
end
-- if the stack is duplicated, the gc handler is not pop_free
-- handle the gc by ourselves
if self._is_shallow_copy then
ffi_gc(ad, C.ACCESS_DESCRIPTION_free)
self._elem_refs[self._elem_refs_idx] = ad
self._elem_refs_idx = self._elem_refs_idx + 1
end
return self
end
_M.all = function(stack)
local ret = {}
local _next = mt.__ipairs(stack)
while true do
local i, e = _next()
if i then
ret[i] = e
else
break
end
end
return ret
end
_M.each = mt.__ipairs
_M.index = mt.__index
_M.count = mt.__len
return _M
|