openresty / lua-nginx-module

Embed the Power of Lua into NGINX HTTP servers
https://openresty.org/
11.33k stars 2.04k forks source link

ssl.verify_client uses only first certificate in chain to perform validation #2045

Open mlga opened 2 years ago

mlga commented 2 years ago

Problem

When I define multiple CA certificates:

-----BEGIN CERTIFICATE-----
<CA cert one>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<CA cert two>
-----END CERTIFICATE-----

parse them using ssl.parse_pem_cert, and pass the resulting cert chain to ssl.verify_client, only the first certificate is being used to perform client validation.

When I change the order of certificates, again only the first one is being used. Always only requests with certs signed by first CA are being verified successfully.

Verification error is

Certificate signature failure

Code snippet

init_by_lua_block

(not exact code, some of it is extracted to separate module, loaded by require)

local ssl = require "ngx.ssl"
local ca = {}

local cert_data = [[-----BEGIN CERTIFICATE-----
<CA cert one>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<CA cert two>
-----END CERTIFICATE-----]]

local cert_chain, err = ssl.parse_pem_cert(cert_data)
if err ~= nil then
    ngx.log(ngx.ERR, "Cert chain parsing error. ", err)
end

ca.cert_chain = cert_chain

return ca

ssl_certificate_by_lua_block

local ssl = require "ngx.ssl"
local ca = require "custom.ca"

ssl.verify_client(ca.cert_chain, 1) -- was playing with different depths as well

access_by_lua_file

Here, I just check value of ngx.var.ssl_client_verify and return error / proceed.

Software versions

I'm using openresty docker image.

Software Version
Nginx openresty/1.19.9.1
ngx_lua 0.10.20

Full info:

$ nginx -V
nginx version: openresty/1.19.9.1
built by gcc 10.2.1 20200804 (Red Hat 10.2.1-2) (GCC)
built with OpenSSL 1.1.1k  25 Mar 2021 (running with OpenSSL 1.1.1n  15 Mar 2022)
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt='-O2 -DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/zlib/include -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl111/include' --add-module=../ngx_devel_kit-0.3.1 --add-module=../echo-nginx-module-0.62 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.32 --add-module=../ngx_lua-0.10.20 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../ngx_stream_lua-0.0.10 --with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib -L/usr/local/openresty/zlib/lib -L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl111/lib -Wl,-rpath,/usr/local/openresty/zlib/lib:/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl111/lib' --with-cc='ccache gcc -fdiagnostics-color=always' --with-pcre-jit --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-threads --with-compat --with-stream --with-http_ssl_module

Am I doing something wrong or unexpected? Is there any way to perform client auth against multiple CAs? I can prepare small docker-compose.yml with a demonstration of required.

zhuizhuhaomeng commented 2 years ago

Can you provide a reproducible test case so we can analyze the problem more quickly?