Skip to content

Commit 0110e9f

Browse files
committed
feature: support custom trusted CA store for cosocket TLS handshake.
Adds the cosocket-level plumbing for a new tcpsock:settrustedstore(store) method, allowing Lua code to supply a per-handshake X509_STORE that overrides lua_ssl_trusted_certificate for the upcoming sslhandshake(). This is needed for use cases where the set of trusted CAs is determined at request time (e.g. per-tenant mTLS upstreams). * a new X509_STORE *ssl_trusted_store field on ngx_http_lua_socket_tcp_upstream_t, used as a one-shot slot consumed by the handshake; * the FFI entry point ngx_http_lua_ffi_socket_tcp_settrustedstore() that validates the cosocket state and stores the pointer on the upstream; * SSL_set1_verify_cert_store() invocation inside ngx_http_lua_ffi_socket_tcp_sslhandshake() when a store has been set, with the slot cleared after use so it cannot leak across handshakes. The matching tcpsock:settrustedstore() Lua wrapper will land in lua-resty-core in a separate change. Signed-off-by: Walker Zhao <walker.zhao@konghq.com>
1 parent cf9f7aa commit 0110e9f

4 files changed

Lines changed: 428 additions & 1 deletion

File tree

README.markdown

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4060,6 +4060,7 @@ Nginx API for Lua
40604060
* [tcpsock:connect](#tcpsockconnect)
40614061
* [tcpsock:getfd](#getfd)
40624062
* [tcpsock:setclientcert](#tcpsocksetclientcert)
4063+
* [tcpsock:settrustedstore](#tcpsocksettrustedstore)
40634064
* [tcpsock:sslhandshake](#tcpsocksslhandshake)
40644065
* [tcpsock:send](#tcpsocksend)
40654066
* [tcpsock:receive](#tcpsockreceive)
@@ -8126,6 +8127,7 @@ Creates and returns a TCP or stream-oriented unix domain socket object (also kno
81268127
* [bind](#tcpsockbind)
81278128
* [connect](#tcpsockconnect)
81288129
* [setclientcert](#tcpsocksetclientcert)
8130+
* [settrustedstore](#tcpsocksettrustedstore)
81298131
* [sslhandshake](#tcpsocksslhandshake)
81308132
* [send](#tcpsocksend)
81318133
* [receive](#tcpsockreceive)
@@ -8365,6 +8367,36 @@ This method was first introduced in the `v0.10.22` release.
83658367

83668368
[Back to TOC](#nginx-api-for-lua)
83678369

8370+
tcpsock:settrustedstore
8371+
-----------------------
8372+
8373+
**syntax:** *ok, err = tcpsock:settrustedstore(x509_store)*
8374+
8375+
**context:** *rewrite_by_lua&#42;, access_by_lua&#42;, content_by_lua&#42;, ngx.timer.&#42;*
8376+
8377+
Set an X509 trusted certificate store on the TCP socket object. The store will be used by the
8378+
[tcpsock:sslhandshake](#tcpsocksslhandshake) method to verify the remote server's certificate, in
8379+
place of the CAs configured by the [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate)
8380+
directive. This is useful when the set of trusted CAs is determined at request time, for example
8381+
when talking to per-tenant upstreams whose CAs are not known at configuration time.
8382+
8383+
* `x509_store` specifies an `X509_STORE *` cdata object that will be used during the SSL/TLS
8384+
handshake. Such an object can be built using the
8385+
[resty.openssl.x509.store](https://github.com/fffonion/lua-resty-openssl) library or directly via
8386+
raw OpenSSL FFI bindings.
8387+
8388+
If `x509_store` is `nil`, this method will clear any previously set trusted store on the cosocket
8389+
object.
8390+
8391+
The TCP connection must already be established before calling this method.
8392+
8393+
The trusted store only takes effect when the next [tcpsock:sslhandshake](#tcpsocksslhandshake)
8394+
call is made with `ssl_verify` set to `true`; with verification off, the store is ignored. The
8395+
store is consumed once per handshake and is not retained across handshakes, so callers wishing to
8396+
apply it to a subsequent handshake on the same cosocket must call this method again.
8397+
8398+
[Back to TOC](#nginx-api-for-lua)
8399+
83688400
tcpsock:sslhandshake
83698401
--------------------
83708402

@@ -8394,7 +8426,10 @@ the remote.
83948426
The optional `ssl_verify` argument takes a Lua boolean value to
83958427
control whether to perform SSL verification. When set to `true`, the server
83968428
certificate will be verified according to the CA certificates specified by
8397-
the [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate) directive.
8429+
the [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate) directive,
8430+
or, if [tcpsock:settrustedstore](#tcpsocksettrustedstore) has been called on
8431+
this cosocket, by the X509 store supplied there (which takes precedence for
8432+
this handshake).
83988433
You may also need to adjust the [lua_ssl_verify_depth](#lua_ssl_verify_depth)
83998434
directive to control how deep we should follow along the certificate chain.
84008435
Also, when the `ssl_verify` argument is true and the

src/ngx_http_lua_socket_tcp.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,16 @@ ngx_http_lua_ffi_socket_tcp_sslhandshake(ngx_http_request_t *r,
19391939

19401940
u->ssl_verify = verify;
19411941

1942+
if (u->ssl_trusted_store) {
1943+
if (SSL_set1_verify_cert_store(ssl_conn, u->ssl_trusted_store) == 0) {
1944+
ERR_clear_error();
1945+
*errmsg = "SSL_set1_verify_cert_store() failed";
1946+
return NGX_ERROR;
1947+
}
1948+
1949+
u->ssl_trusted_store = NULL;
1950+
}
1951+
19421952
if (ocsp_status_req) {
19431953
#ifdef NGX_HTTP_LUA_USE_OCSP
19441954
SSL_set_tlsext_status_type(c->ssl->connection,
@@ -2255,6 +2265,35 @@ ngx_http_lua_ffi_socket_tcp_get_ssl_ctx(ngx_http_request_t *r,
22552265
}
22562266

22572267

2268+
int
2269+
ngx_http_lua_ffi_socket_tcp_settrustedstore(ngx_http_request_t *r,
2270+
ngx_http_lua_socket_tcp_upstream_t *u, void *store, const char **errmsg)
2271+
{
2272+
if (u == NULL
2273+
|| u->peer.connection == NULL
2274+
|| u->read_closed
2275+
|| u->write_closed)
2276+
{
2277+
*errmsg = "closed";
2278+
return NGX_ERROR;
2279+
}
2280+
2281+
if (u->request != r) {
2282+
*errmsg = "bad request";
2283+
return NGX_ERROR;
2284+
}
2285+
2286+
if (store == NULL) {
2287+
*errmsg = "no trusted store";
2288+
return NGX_ERROR;
2289+
}
2290+
2291+
u->ssl_trusted_store = store;
2292+
2293+
return NGX_OK;
2294+
}
2295+
2296+
22582297
#endif /* NGX_HTTP_SSL */
22592298

22602299

src/ngx_http_lua_socket_tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct ngx_http_lua_socket_tcp_upstream_s {
135135
ngx_ssl_session_t *ssl_session_ret;
136136
const char *error_ret;
137137
int openssl_error_code_ret;
138+
X509_STORE *ssl_trusted_store;
138139
#endif
139140

140141
ngx_chain_t *busy_bufs;

0 commit comments

Comments
 (0)