aboutsummaryrefslogtreecommitdiffstats
path: root/server/resty/openssl/x509/store.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/openssl/x509/store.lua')
-rw-r--r--server/resty/openssl/x509/store.lua227
1 files changed, 227 insertions, 0 deletions
diff --git a/server/resty/openssl/x509/store.lua b/server/resty/openssl/x509/store.lua
new file mode 100644
index 0000000..1722e4c
--- /dev/null
+++ b/server/resty/openssl/x509/store.lua
@@ -0,0 +1,227 @@
+local ffi = require "ffi"
+local C = ffi.C
+local ffi_gc = ffi.gc
+local ffi_str = ffi.string
+local bor = bit.bor
+
+local x509_vfy_macro = require "resty.openssl.include.x509_vfy"
+local x509_lib = require "resty.openssl.x509"
+local chain_lib = require "resty.openssl.x509.chain"
+local crl_lib = require "resty.openssl.x509.crl"
+local ctx_lib = require "resty.openssl.ctx"
+local format_error = require("resty.openssl.err").format_all_error
+local format_all_error = require("resty.openssl.err").format_error
+local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
+
+local _M = {}
+local mt = { __index = _M }
+
+_M.verify_flags = x509_vfy_macro.verify_flags
+
+local x509_store_ptr_ct = ffi.typeof('X509_STORE*')
+
+function _M.new()
+ local ctx = C.X509_STORE_new()
+ if ctx == nil then
+ return nil, "x509.store.new: X509_STORE_new() failed"
+ end
+ ffi_gc(ctx, C.X509_STORE_free)
+
+ local self = setmetatable({
+ ctx = ctx,
+ _elem_refs = {},
+ _elem_refs_idx = 1,
+ }, mt)
+
+ return self, nil
+end
+
+function _M.istype(l)
+ return l and l.ctx and ffi.istype(x509_store_ptr_ct, l.ctx)
+end
+
+function _M:use_default(properties)
+ if x509_vfy_macro.X509_STORE_set_default_paths(self.ctx, ctx_lib.get_libctx(), properties) ~= 1 then
+ return false, format_all_error("x509.store:use_default")
+ end
+ return true
+end
+
+function _M:add(item)
+ local dup
+ local err
+ if x509_lib.istype(item) then
+ dup = C.X509_dup(item.ctx)
+ if dup == nil then
+ return false, "x509.store:add: X509_dup() failed"
+ end
+ -- ref counter of dup is increased by 1
+ if C.X509_STORE_add_cert(self.ctx, dup) ~= 1 then
+ err = format_all_error("x509.store:add: X509_STORE_add_cert")
+ end
+ -- decrease the dup ctx ref count immediately to make leak test happy
+ C.X509_free(dup)
+ elseif crl_lib.istype(item) then
+ dup = C.X509_CRL_dup(item.ctx)
+ if dup == nil then
+ return false, "x509.store:add: X509_CRL_dup() failed"
+ end
+ -- ref counter of dup is increased by 1
+ if C.X509_STORE_add_crl(self.ctx, dup) ~= 1 then
+ err = format_all_error("x509.store:add: X509_STORE_add_crl")
+ end
+
+ -- define X509_V_FLAG_CRL_CHECK 0x4
+ -- enables CRL checking for the certificate chain leaf certificate.
+ -- An error occurs if a suitable CRL cannot be found.
+ -- Note: this does not check for certificates in the chain.
+ if C.X509_STORE_set_flags(self.ctx, 0x4) ~= 1 then
+ return false, format_error("x509.store:add: X509_STORE_set_flags")
+ end
+ -- decrease the dup ctx ref count immediately to make leak test happy
+ C.X509_CRL_free(dup)
+ else
+ return false, "x509.store:add: expect an x509 or crl instance at #1"
+ end
+
+ if err then
+ return false, err
+ end
+
+ -- X509_STORE doesn't have stack gc handler, we need to gc by ourselves
+ self._elem_refs[self._elem_refs_idx] = dup
+ self._elem_refs_idx = self._elem_refs_idx + 1
+
+ return true
+end
+
+function _M:load_file(path, properties)
+ if type(path) ~= "string" then
+ return false, "x509.store:load_file: expect a string at #1"
+ else
+ if x509_vfy_macro.X509_STORE_load_locations(self.ctx, path, nil,
+ ctx_lib.get_libctx(), properties) ~= 1 then
+ return false, format_all_error("x509.store:load_file")
+ end
+ end
+
+ return true
+end
+
+function _M:load_directory(path, properties)
+ if type(path) ~= "string" then
+ return false, "x509.store:load_directory expect a string at #1"
+ else
+ if x509_vfy_macro.X509_STORE_load_locations(self.ctx, nil, path,
+ ctx_lib.get_libctx(), properties) ~= 1 then
+ return false, format_all_error("x509.store:load_directory")
+ end
+ end
+
+ return true
+end
+
+function _M:set_depth(depth)
+ depth = depth and tonumber(depth)
+ if not depth then
+ return nil, "x509.store:set_depth: expect a number at #1"
+ end
+
+ if C.X509_STORE_set_depth(self.ctx, depth) ~= 1 then
+ return false, format_error("x509.store:set_depth")
+ end
+
+ return true
+end
+
+function _M:set_purpose(purpose)
+ if type(purpose) ~= "string" then
+ return nil, "x509.store:set_purpose: expect a string at #1"
+ end
+
+ local pchar = ffi.new("char[?]", #purpose, purpose)
+ local idx = C.X509_PURPOSE_get_by_sname(pchar)
+ idx = tonumber(idx)
+
+ if idx == -1 then
+ return false, "invalid purpose \"" .. purpose .. "\""
+ end
+
+ local purp = C.X509_PURPOSE_get0(idx)
+ local i = C.X509_PURPOSE_get_id(purp)
+
+ if C.X509_STORE_set_purpose(self.ctx, i) ~= 1 then
+ return false, format_error("x509.store:set_purpose: X509_STORE_set_purpose")
+ end
+
+ return true
+end
+
+function _M:set_flags(...)
+ local flag = 0
+ for _, f in ipairs({...}) do
+ flag = bor(flag, f)
+ end
+
+ if C.X509_STORE_set_flags(self.ctx, flag) ~= 1 then
+ return false, format_error("x509.store:set_flags: X509_STORE_set_flags")
+ end
+
+ return true
+end
+
+function _M:verify(x509, chain, return_chain, properties, verify_method)
+ if not x509_lib.istype(x509) then
+ return nil, "x509.store:verify: expect a x509 instance at #1"
+ elseif chain and not chain_lib.istype(chain) then
+ return nil, "x509.store:verify: expect a x509.chain instance at #1"
+ end
+
+ local ctx
+ if OPENSSL_3X then
+ ctx = C.X509_STORE_CTX_new_ex(ctx_lib.get_libctx(), properties)
+ else
+ ctx = C.X509_STORE_CTX_new()
+ end
+ if ctx == nil then
+ return nil, "x509.store:verify: X509_STORE_CTX_new() failed"
+ end
+
+ ffi_gc(ctx, C.X509_STORE_CTX_free)
+
+ local chain_dup_ctx
+ if chain then
+ local chain_dup, err = chain_lib.dup(chain.ctx)
+ if err then
+ return nil, err
+ end
+ chain_dup_ctx = chain_dup.ctx
+ end
+
+ if C.X509_STORE_CTX_init(ctx, self.ctx, x509.ctx, chain_dup_ctx) ~= 1 then
+ return nil, format_error("x509.store:verify: X509_STORE_CTX_init")
+ end
+
+ if verify_method and C.X509_STORE_CTX_set_default(ctx, verify_method) ~= 1 then
+ return nil, "x509.store:verify: invalid verify_method \"" .. verify_method .. "\""
+ end
+
+ local code = C.X509_verify_cert(ctx)
+ if code == 1 then -- verified
+ if not return_chain then
+ return true, nil
+ end
+ local ret_chain_ctx = x509_vfy_macro.X509_STORE_CTX_get0_chain(ctx)
+ return chain_lib.dup(ret_chain_ctx)
+ elseif code == 0 then -- unverified
+ local vfy_code = C.X509_STORE_CTX_get_error(ctx)
+
+ return nil, ffi_str(C.X509_verify_cert_error_string(vfy_code))
+ end
+
+ -- error
+ return nil, format_error("x509.store:verify: X509_verify_cert", code)
+
+end
+
+return _M