From 97a46278d0276a639253755ffe30241022ccebb0 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 2 Aug 2026 12:11:50 +0200 Subject: [PATCH] openssl: Check return value of SSL_CTX_set_alpn_protos() Discovered by ESSS. --- ext/openssl/tests/alpn_protocols_invalid.phpt | 55 +++++++++++++++++++ ext/openssl/xp_ssl.c | 8 ++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 ext/openssl/tests/alpn_protocols_invalid.phpt diff --git a/ext/openssl/tests/alpn_protocols_invalid.phpt b/ext/openssl/tests/alpn_protocols_invalid.phpt new file mode 100644 index 000000000000..b440af9ad74b --- /dev/null +++ b/ext/openssl/tests/alpn_protocols_invalid.phpt @@ -0,0 +1,55 @@ +--TEST-- +Setting an invalid TLS ALPN protocol list on a client stream fails +--EXTENSIONS-- +openssl +--SKIPIF-- += 3.0'); +?> +--FILE-- + ['alpn_protocols' => $protocols, 'verify_peer' => false], + 'stream' => $streamOptions, + ]); + $client = stream_socket_client("tcp://$address", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $context); + var_dump(stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)); + fclose($client); +} + +foreach (['', ',', 'h2,', ',h2', 'h2,,http/1.1'] as $protocols) { + try_alpn($protocols, []); +} + +try_alpn('', [ + 'error_mode' => StreamErrorMode::Silent, + 'error_store' => StreamErrorStore::All, +]); +foreach (stream_last_errors() as $error) { + var_dump($error->code, $error->message); +} +?> +--EXPECTF-- +Warning: stream_socket_enable_crypto(): Failed setting TLS ALPN protocols, protocol names must not be empty in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): Failed setting TLS ALPN protocols, protocol names must not be empty in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): Failed setting TLS ALPN protocols, protocol names must not be empty in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): Failed setting TLS ALPN protocols, protocol names must not be empty in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): Failed setting TLS ALPN protocols, protocol names must not be empty in %s on line %d +bool(false) +bool(false) +enum(StreamErrorCode::DecodingFailed) +string(67) "Failed setting TLS ALPN protocols, protocol names must not be empty" diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index a8105a15c43b..130d3717ccc9 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2654,7 +2654,13 @@ static zend_result php_openssl_create_server_ctx(php_stream *stream, return FAILURE; } if (sslsock->is_client) { - SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len); + if (SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len)) { + php_stream_warn(stream, DecodingFailed, "Failed setting TLS ALPN protocols, protocol names must not be empty"); + efree(alpn); + SSL_CTX_free(sslsock->ctx); + sslsock->ctx = NULL; + return FAILURE; + } } else { sslsock->alpn_ctx.data = (unsigned char *) pestrndup((const char*)alpn, alpn_len, php_stream_is_persistent(stream)); sslsock->alpn_ctx.len = alpn_len;