Skip to content

HTTP/3: reject an unknown ALPN instead of aborting - #13631

Draft
brbzull0 wants to merge 1 commit into
apache:masterfrom
brbzull0:h3-reject-unknown-alpn
Draft

HTTP/3: reject an unknown ALPN instead of aborting#13631
brbzull0 wants to merge 1 commit into
apache:masterfrom
brbzull0:h3-reject-unknown-alpn

Conversation

@brbzull0

@brbzull0 brbzull0 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Http3SessionAccept::accept() dispatched on the negotiated ALPN with an
if/else-if chain ending in:

} else {
  ink_abort("Negotiated App Name is unknown");
}

An absent or empty ALPN lands in that final arm, so a QUIC handshake that
completes without an ALPN extension aborts the process rather than closing the
connection. 08d1896d6a64 ("Reject TLS if client offers alpn with no match",
#7981) removed the earlier alpn.empty() arm that used to catch this case
before it reached the abort.

That the empty state is expected elsewhere in the same path is visible in both
_start_application() implementations, which already have null-ALPN fallbacks.

Change

  • Http3SessionAccept.h / .cc: add an AppType enum and a static
    select_app_type(std::string_view) helper, and turn the dispatch into a
    switch. The UNKNOWN arm logs and returns false;
    Http3SessionAccept::mainEvent() already converts a false return into
    netvc->do_io_close(), so no new teardown path is introduced.
  • QUICNetVConnection.cc: negotiated_application_name() declared
    const uint8_t *name; uninitialised and passed it to
    quiche_conn_application_proto(), which leaves it untouched when no protocol
    was negotiated -- so the std::string_view was constructed over an
    indeterminate pointer. Initialise to nullptr and return an empty
    string_view in that case. This also makes alpn.data() non-null for the
    %.*s in the new log line.

Extracting select_app_type() keeps the tag-to-application mapping in one place
and makes it directly unit-testable, though no unit test is added here (see
below).

Test

Honest summary: no existing test fails without this change, and a targeted new
test is not portable.

An unrecognised tag such as banana never reaches accept() -- the TLS layer
answers no_application_protocol first, which is what
tests/gold_tests/tls/tls_bad_alpn.test.py already covers over TCP. The empty
ALPN case only completes a handshake on a backend that does not enforce
RFC 9001 s8.1, so a gold test for it would pass or skip inconsistently across
BoringSSL, QUICTLS and the OpenSSL QUIC-TLS-callbacks shim. Rather than add a
backend-dependent test, this is submitted as hardening.

What was run, 9/9 pass: h3_active_timeout, h3_flow_control, h3_go_client,
h3_proxy_verifier, h3_python_client, h3_sni_check, h3_stream_lifetime,
quic_no_activity_timeout, tls_bad_alpn. Three of those assert on the exact
start HTTP/3 app (ALPN=h3) debug line, so they confirm the switch conversion
did not disturb the happy path.

Built on both QUIC backends. Under ENABLE_QUICHE=ON,
src/iocore/net/QUICNetVConnection.cc compiles clean -- that file is only built
under elseif(TS_HAS_QUICHE) in src/iocore/net/CMakeLists.txt, so the
OpenSSL-QUIC build does not cover it. The quiche configuration was
compile-verified only; the autests above ran against the OpenSSL-QUIC build.

Http3SessionAccept::accept() ended its ALPN dispatch with
ink_abort("Negotiated App Name is unknown"), and an absent or empty ALPN
falls into that branch, so a completed QUIC handshake carrying no ALPN
extension took down traffic_server. 08d1896 removed the earlier
alpn.empty() arm that used to catch it.

Move the dispatch into a switch over a new select_app_type() helper and
return false for the unknown case, which mainEvent() already turns into
do_io_close(). Also initialise the out-pointer in
QUICNetVConnection::negotiated_application_name(), which quiche leaves
untouched when no protocol was negotiated.
@brbzull0 brbzull0 added the quiche libquiche related. label Sep 3, 2026
@brbzull0 brbzull0 self-assigned this Sep 3, 2026
@brbzull0 brbzull0 added this to the 11.0.0 milestone Sep 3, 2026
@brbzull0

brbzull0 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

[approve ci autest 2]

@brbzull0

brbzull0 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

[approve ci fedora]

@brbzull0

brbzull0 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

[approve ci freebsd]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

quiche libquiche related.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant