Skip to content

Commit d3dbc0c

Browse files
spacewanderthibaultcha
authored andcommitted
bugfix: skipped 'ssl_session_store_by_lua*' and 'ssl_session_fetch_by_lua*' when using TLS 1.3.
Previously, we used the OpenSSL 1.1.1 ClientHello callback to do ssl session fetching non-blockingly. However, this way cannot handle an edge case: the ssl session resumption via session ticket might fail, and the client fallbacks to session ID resumption. The ClientHello callback is run too early to know if the client will fallback to use session ID resumption. Therefore, we have to take back the OpenSSL sess_set_get_cb_yield patch and upgrade it to adapt OpenSSL 1.1.1, which was done in our openresty/openresty repository. Now, this means that for the time being, we must skip `ssl_session_(fetch|store)_by_lua*` for TLS 1.3. It is possible to support PSK with session ID in TLS 1.3., but we need to modify a number of functions to pass the result up, which will make the patch too complex to maintain. Since PSK with session ticket is supported, supporting PSK with session ID is not so profitable. If someone needs this feature, they can contribute it themselves. Thanks Yongjian Xu and crasyangel for their help. Signed-off-by: Thibault Charbonnier <thibaultcha@me.com>
1 parent 2014dd8 commit d3dbc0c

File tree

4 files changed

+226
-0
lines changed

4 files changed

+226
-0
lines changed

src/ngx_http_lua_ssl_session_fetchby.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn,
181181
#endif
182182
u_char *id, int len, int *copy)
183183
{
184+
#if defined(NGX_SSL_TLSv1_3) && defined(TLS1_3_VERSION)
185+
int tls_version;
186+
#endif
184187
lua_State *L;
185188
ngx_int_t rc;
186189
ngx_connection_t *c, *fc = NULL;
@@ -198,6 +201,18 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn,
198201

199202
c = ngx_ssl_get_connection(ssl_conn);
200203

204+
#if defined(NGX_SSL_TLSv1_3) && defined(TLS1_3_VERSION)
205+
tls_version = SSL_version(ssl_conn);
206+
207+
if (tls_version >= TLS1_3_VERSION) {
208+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
209+
"ssl_session_fetch_by_lua*: skipped since "
210+
"TLS version >= 1.3 (%xd)", tls_version);
211+
212+
return 0;
213+
}
214+
#endif
215+
201216
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
202217
"ssl session fetch: connection reusable: %ud", c->reusable);
203218

src/ngx_http_lua_ssl_session_storeby.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ int
176176
ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn,
177177
ngx_ssl_session_t *sess)
178178
{
179+
#if defined(NGX_SSL_TLSv1_3) && defined(TLS1_3_VERSION)
180+
int tls_version;
181+
#endif
179182
const u_char *sess_id;
180183
unsigned int sess_id_len;
181184
lua_State *L;
@@ -189,6 +192,18 @@ ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn,
189192

190193
c = ngx_ssl_get_connection(ssl_conn);
191194

195+
#if defined(NGX_SSL_TLSv1_3) && defined(TLS1_3_VERSION)
196+
tls_version = SSL_version(ssl_conn);
197+
198+
if (tls_version >= TLS1_3_VERSION) {
199+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
200+
"ssl_session_store_by_lua*: skipped since "
201+
"TLS version >= 1.3 (%xd)", tls_version);
202+
203+
return 0;
204+
}
205+
#endif
206+
192207
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
193208
"ssl session store: connection reusable: %ud", c->reusable);
194209

t/142-ssl-session-store.t

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,3 +901,65 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running!
901901
--- no_error_log
902902
[error]
903903
[alert]
904+
905+
906+
907+
=== TEST 13: ssl_session_store_by_lua* is skipped when using TLSv1.3
908+
--- skip_openssl: 6: < 1.1.1
909+
--- http_config
910+
ssl_session_store_by_lua_block { ngx.log(ngx.ERR, "ssl_session_store_by_lua* is running!") }
911+
server {
912+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
913+
server_name test.com;
914+
ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
915+
ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key;
916+
ssl_session_tickets off;
917+
ssl_protocols TLSv1.3;
918+
server_tokens off;
919+
}
920+
--- config
921+
server_tokens off;
922+
lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
923+
lua_ssl_protocols TLSv1.3;
924+
925+
location /t {
926+
content_by_lua_block {
927+
do
928+
local sock = ngx.socket.tcp()
929+
930+
sock:settimeout(5000)
931+
932+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
933+
if not ok then
934+
ngx.say("failed to connect: ", err)
935+
return
936+
end
937+
938+
ngx.say("connected: ", ok)
939+
940+
local sess, err = sock:sslhandshake(nil, "test.com", true)
941+
if not sess then
942+
ngx.say("failed to do SSL handshake: ", err)
943+
return
944+
end
945+
946+
ngx.say("ssl handshake: ", type(sess))
947+
948+
local ok, err = sock:close()
949+
ngx.say("close: ", ok, " ", err)
950+
end -- do
951+
-- collectgarbage()
952+
}
953+
}
954+
--- request
955+
GET /t
956+
--- response_body
957+
connected: 1
958+
ssl handshake: userdata
959+
close: 1 nil
960+
--- error_log eval
961+
qr/ssl_session_store_by_lua\*: skipped since TLS version >= 1\.3 \(\d+\)/
962+
--- no_error_log
963+
[error]
964+
[alert]
965+
[emerg]

t/143-ssl-session-fetch.t

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,3 +1219,137 @@ GET /t
12191219
[error]
12201220
[alert]
12211221
[emerg]
1222+
1223+
1224+
1225+
=== TEST 15: ssl_session_fetch_by_lua* is skipped when session ticket is provided
1226+
--- http_config
1227+
ssl_session_fetch_by_lua_block { ngx.log(ngx.ERR, "ssl_session_fetch_by_lua* is running!") }
1228+
server {
1229+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
1230+
server_name test.com;
1231+
ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
1232+
ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key;
1233+
server_tokens off;
1234+
}
1235+
--- config
1236+
server_tokens off;
1237+
lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
1238+
1239+
location /t {
1240+
content_by_lua_block {
1241+
do
1242+
local sock = ngx.socket.tcp()
1243+
1244+
sock:settimeout(5000)
1245+
1246+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
1247+
if not ok then
1248+
ngx.say("failed to connect: ", err)
1249+
return
1250+
end
1251+
1252+
ngx.say("connected: ", ok)
1253+
1254+
local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true)
1255+
if not sess then
1256+
ngx.say("failed to do SSL handshake: ", err)
1257+
return
1258+
end
1259+
1260+
ngx.say("ssl handshake: ", type(sess))
1261+
1262+
package.loaded.session = sess
1263+
1264+
local ok, err = sock:close()
1265+
ngx.say("close: ", ok, " ", err)
1266+
end -- do
1267+
-- collectgarbage()
1268+
}
1269+
}
1270+
--- request
1271+
GET /t
1272+
--- response_body
1273+
connected: 1
1274+
ssl handshake: userdata
1275+
close: 1 nil
1276+
--- no_error_log
1277+
[warn]
1278+
[error]
1279+
[alert]
1280+
[emerg]
1281+
1282+
1283+
1284+
=== TEST 16: ssl_session_fetch_by_lua* always runs when using SSLv3 (SSLv3 does not support session tickets)
1285+
--- http_config
1286+
ssl_session_fetch_by_lua_block { print("ssl_session_fetch_by_lua* is running!") }
1287+
server {
1288+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
1289+
server_name test.com;
1290+
ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
1291+
ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key;
1292+
ssl_protocols SSLv3;
1293+
server_tokens off;
1294+
}
1295+
--- config
1296+
server_tokens off;
1297+
lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt;
1298+
lua_ssl_protocols SSLv3;
1299+
1300+
location /t {
1301+
content_by_lua_block {
1302+
do
1303+
local sock = ngx.socket.tcp()
1304+
1305+
sock:settimeout(5000)
1306+
1307+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
1308+
if not ok then
1309+
ngx.say("failed to connect: ", err)
1310+
return
1311+
end
1312+
1313+
ngx.say("connected: ", ok)
1314+
1315+
local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true)
1316+
if not sess then
1317+
ngx.say("failed to do SSL handshake: ", err)
1318+
return
1319+
end
1320+
1321+
ngx.say("ssl handshake: ", type(sess))
1322+
1323+
package.loaded.session = sess
1324+
1325+
local ok, err = sock:close()
1326+
ngx.say("close: ", ok, " ", err)
1327+
end -- do
1328+
-- collectgarbage()
1329+
}
1330+
}
1331+
--- request
1332+
GET /t
1333+
--- response_body
1334+
connected: 1
1335+
ssl handshake: userdata
1336+
close: 1 nil
1337+
--- grep_error_log eval: qr/ssl_session_fetch_by_lua_block:.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/
1338+
--- grep_error_log_out eval
1339+
[
1340+
qr/\A(?:reusable connection: [01]\n)+\z/s,
1341+
qr/^reusable connection: 1
1342+
ssl session fetch: connection reusable: 1
1343+
reusable connection: 0
1344+
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
1345+
/m,
1346+
qr/^reusable connection: 1
1347+
ssl session fetch: connection reusable: 1
1348+
reusable connection: 0
1349+
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
1350+
/m,
1351+
]
1352+
--- no_error_log
1353+
[error]
1354+
[alert]
1355+
[emerg]

0 commit comments

Comments
 (0)