From 489ae109ca432594cda461c74e3c3049dade98de Mon Sep 17 00:00:00 2001 From: spacewander Date: Fri, 7 Aug 2020 12:23:16 +0800 Subject: [PATCH] feature: shared ngx.ctx among SSL_* phases and the following phases. --- README.markdown | 8 ++++ doc/HttpLuaModule.wiki | 8 ++++ src/ngx_http_lua_ctx.c | 62 ++++++++++++++++++++++---- src/ngx_http_lua_ssl.h | 4 ++ src/ngx_http_lua_ssl_certby.c | 2 + src/ngx_http_lua_ssl_session_fetchby.c | 2 + src/ngx_http_lua_ssl_session_storeby.c | 2 + src/ngx_http_lua_util.h | 1 + 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/README.markdown b/README.markdown index 9395d50cae..93e899f19e 100644 --- a/README.markdown +++ b/README.markdown @@ -3769,6 +3769,14 @@ Then `GET /orig` will give rather than the original `"hello"` value. +Because HTTP request is created after SSL handshake, the `ngx.ctx` created +in [ssl_certificate_by_lua*](#ssl_certificate_by_lua), [ssl_session_store_by_lua*](#ssl_session_store_by_lua) and [ssl_session_fetch_by_lua*](#ssl_session_fetch_by_lua) +is not available in the following phases like [rewrite_by_lua*](#rewrite_by_lua). + +Since `dev`, the `ngx.ctx` created during a SSL handshake +will be inherited by the requests which share the same TCP connection established by the handshake. +Note that overwrite values in `ngx.ctx` in the http request phases (like `rewrite_by_lua*`) will only take affect in the current http request. + Arbitrary data values, including Lua closures and nested tables, can be inserted into this "magic" table. It also allows the registration of custom meta methods. Overriding `ngx.ctx` with a new Lua table is also supported, for example, diff --git a/doc/HttpLuaModule.wiki b/doc/HttpLuaModule.wiki index 65558e9e6f..15cee7112d 100644 --- a/doc/HttpLuaModule.wiki +++ b/doc/HttpLuaModule.wiki @@ -3082,6 +3082,14 @@ Then GET /orig will give rather than the original "hello" value. +Because HTTP request is created after SSL handshake, the ngx.ctx created +in [[#ssl_certificate_by_lua|ssl_certificate_by_lua*]], [[#ssl_session_store_by_lua|ssl_session_store_by_lua*]] and [[#ssl_session_fetch_by_lua|ssl_session_fetch_by_lua*]] +is not available in the following phases like [[#rewrite_by_lua|rewrite_by_lua*]]. + +Since dev, the ngx.ctx created during a SSL handshake +will be inherited by the requests which share the same TCP connection established by the handshake. +Note that overwrite values in ngx.ctx in the http request phases (like `rewrite_by_lua*`) will only take affect in the current http request. + Arbitrary data values, including Lua closures and nested tables, can be inserted into this "magic" table. It also allows the registration of custom meta methods. Overriding ngx.ctx with a new Lua table is also supported, for example, diff --git a/src/ngx_http_lua_ctx.c b/src/ngx_http_lua_ctx.c index 74571378c0..1709aefa78 100644 --- a/src/ngx_http_lua_ctx.c +++ b/src/ngx_http_lua_ctx.c @@ -11,6 +11,7 @@ #include "ngx_http_lua_util.h" +#include "ngx_http_lua_ssl.h" #include "ngx_http_lua_ctx.h" @@ -21,7 +22,7 @@ typedef struct { static ngx_int_t ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, - int ref); + ngx_pool_t *pool, int ref); static void ngx_http_lua_ngx_ctx_cleanup(void *data); @@ -29,6 +30,8 @@ int ngx_http_lua_ngx_set_ctx_helper(lua_State *L, ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx, int index) { + ngx_pool_t *pool; + if (index < 0) { index = lua_gettop(L) + index + 1; } @@ -43,7 +46,8 @@ ngx_http_lua_ngx_set_ctx_helper(lua_State *L, ngx_http_request_t *r, ctx->ctx_ref = luaL_ref(L, -2); lua_pop(L, 1); - if (ngx_http_lua_ngx_ctx_add_cleanup(r, ctx->ctx_ref) != NGX_OK) { + pool = r->pool; + if (ngx_http_lua_ngx_ctx_add_cleanup(r, pool, ctx->ctx_ref) != NGX_OK) { return luaL_error(L, "no memory"); } @@ -66,32 +70,71 @@ ngx_http_lua_ngx_set_ctx_helper(lua_State *L, ngx_http_request_t *r, int -ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r) +ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r, int *in_ssl_phase, + int *ssl_ctx_ref) { - ngx_http_lua_ctx_t *ctx; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_ssl_ctx_t *ssl_ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return NGX_HTTP_LUA_FFI_NO_REQ_CTX; } - return ctx->ctx_ref; + if (ctx->ctx_ref >= 0 || in_ssl_phase == NULL) { + return ctx->ctx_ref; + } + + *in_ssl_phase = ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE); + *ssl_ctx_ref = LUA_NOREF; + + if (r->connection->ssl != NULL) { + ssl_ctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection); + + if (ssl_ctx != NULL) { + *ssl_ctx_ref = ssl_ctx->ctx_ref; + } + } + + return LUA_NOREF; } int ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref) { - ngx_http_lua_ctx_t *ctx; + ngx_pool_t *pool; + ngx_connection_t *c; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_ssl_ctx_t *ssl_ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return NGX_HTTP_LUA_FFI_NO_REQ_CTX; } + if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE)) + { + ssl_ctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection); + if (ssl_ctx == NULL) { + return NGX_ERROR; + } + + ssl_ctx->ctx_ref = ref; + c = ngx_ssl_get_connection(r->connection->ssl->connection); + pool = c->pool; + + } else { + pool = r->pool; + } + ctx->ctx_ref = ref; - if (ngx_http_lua_ngx_ctx_add_cleanup(r, ref) != NGX_OK) { + if (ngx_http_lua_ngx_ctx_add_cleanup(r, pool, ref) != NGX_OK) { return NGX_ERROR; } @@ -100,7 +143,8 @@ ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref) static ngx_int_t -ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, int ref) +ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, ngx_pool_t *pool, + int ref) { lua_State *L; ngx_pool_cleanup_t *cln; @@ -111,7 +155,7 @@ ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, int ref) ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); L = ngx_http_lua_get_lua_vm(r, ctx); - cln = ngx_pool_cleanup_add(r->pool, + cln = ngx_pool_cleanup_add(pool, sizeof(ngx_http_lua_ngx_ctx_cleanup_data_t)); if (cln == NULL) { return NGX_ERROR; diff --git a/src/ngx_http_lua_ssl.h b/src/ngx_http_lua_ssl.h index acb8c4b16c..f50ecc5194 100644 --- a/src/ngx_http_lua_ssl.h +++ b/src/ngx_http_lua_ssl.h @@ -27,6 +27,10 @@ typedef struct { int exit_code; /* exit code for openssl's set_cert_cb callback */ + int ctx_ref; /* reference to anchor + request ctx data in lua + registry */ + unsigned done:1; unsigned aborted:1; diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c index 2e09a03857..c6fc8832f5 100644 --- a/src/ngx_http_lua_ssl_certby.c +++ b/src/ngx_http_lua_ssl_certby.c @@ -257,6 +257,8 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) if (cctx == NULL) { goto failed; /* error */ } + + cctx->ctx_ref = LUA_NOREF; } cctx->exit_code = 1; /* successful by default */ diff --git a/src/ngx_http_lua_ssl_session_fetchby.c b/src/ngx_http_lua_ssl_session_fetchby.c index c54e8eadd8..3ac9272693 100644 --- a/src/ngx_http_lua_ssl_session_fetchby.c +++ b/src/ngx_http_lua_ssl_session_fetchby.c @@ -279,6 +279,8 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, if (cctx == NULL) { goto failed; /* error */ } + + cctx->ctx_ref = LUA_NOREF; } cctx->exit_code = 1; /* successful by default */ diff --git a/src/ngx_http_lua_ssl_session_storeby.c b/src/ngx_http_lua_ssl_session_storeby.c index 1067b3bb2e..10803522a9 100644 --- a/src/ngx_http_lua_ssl_session_storeby.c +++ b/src/ngx_http_lua_ssl_session_storeby.c @@ -241,6 +241,8 @@ ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, if (cctx == NULL) { goto failed; /* error */ } + + cctx->ctx_ref = LUA_NOREF; } #if OPENSSL_VERSION_NUMBER >= 0x1000200fL diff --git a/src/ngx_http_lua_util.h b/src/ngx_http_lua_util.h index 52d804bff0..fa24f4072b 100644 --- a/src/ngx_http_lua_util.h +++ b/src/ngx_http_lua_util.h @@ -15,6 +15,7 @@ #include "ngx_http_lua_common.h" +#include "ngx_http_lua_ssl.h" #include "ngx_http_lua_api.h"