Adding HTTP/3 dissection to Wireshark.

This is a copy of MR #9330 all code and credit to Omer Shapira.
This commit is contained in:
Anders Broman 2023-08-25 14:50:55 +02:00 committed by AndersBroman
parent 963c73b987
commit 80f9a28921
16 changed files with 2376 additions and 206 deletions

View File

@ -1359,6 +1359,9 @@ ws_find_package(ZSTD ENABLE_ZSTD HAVE_ZSTD "1.0.0")
# Enhanced HTTP/2 dissection
ws_find_package(NGHTTP2 ENABLE_NGHTTP2 HAVE_NGHTTP2 "1.11.0")
# Enhanced HTTP/3 dissection
ws_find_package(NGHTTP3 ENABLE_NGHTTP3 HAVE_NGHTTP3 "0.6.0")
# Embedded Lua interpreter
if(FETCH_lua)
# Download and build lua
@ -1921,6 +1924,11 @@ set_package_properties(NGHTTP2 PROPERTIES
URL "https://nghttp2.org"
PURPOSE "Header decompression in HTTP2"
)
set_package_properties(NGHTTP3 PROPERTIES
DESCRIPTION "HTTP/3 C library and tools"
URL "https://nghttp2.org"
PURPOSE "Header decompression in HTTP3"
)
set_package_properties(CARES PROPERTIES
DESCRIPTION "Library for asynchronous DNS requests"
URL "https://c-ares.org/"
@ -2193,6 +2201,10 @@ if(USE_REPOSITORY)
list (APPEND THIRD_PARTY_DLLS "${NGHTTP2_DLL_DIR}/${NGHTTP2_DLL}")
list (APPEND THIRD_PARTY_PDBS "${NGHTTP2_DLL_DIR}/${NGHTTP2_PDB}")
endif(NGHTTP2_FOUND)
if (NGHTTP3_FOUND)
list (APPEND THIRD_PARTY_DLLS "${NGHTTP3_DLL_DIR}/${NGHTTP3_DLL}")
list (APPEND THIRD_PARTY_PDBS "${NGHTTP3_DLL_DIR}/${NGHTTP3_PDB}")
endif(NGHTTP2_FOUND)
if (PCRE2_FOUND)
list (APPEND THIRD_PARTY_DLLS "${PCRE2_DLL_DIR}/${PCRE2_DLL}")
list (APPEND THIRD_PARTY_PDBS "${PCRE2_DLL_DIR}/${PCRE2_PDB}")

View File

@ -107,6 +107,7 @@ option(ENABLE_BROTLI "Build with brotli compression support" ON)
option(ENABLE_SNAPPY "Build with Snappy compression support" ON)
option(ENABLE_ZSTD "Build with Facebook zstd compression support" ON)
option(ENABLE_NGHTTP2 "Build with HTTP/2 header decompression support" ON)
option(ENABLE_NGHTTP3 "Build with HTTP/3 header decompression support" ON)
option(ENABLE_LUA "Build with Lua dissector support" ON)
option(ENABLE_SMI "Build with libsmi snmp support" ON)
option(ENABLE_GNUTLS "Build with RSA decryption support" ON)

View File

@ -103,6 +103,9 @@
/* Define to use nghttp2 */
#cmakedefine HAVE_NGHTTP2 1
/* Define to use nghttp3 */
#cmakedefine HAVE_NGHTTP3 1
/* Define to use the libcap library */
#cmakedefine HAVE_LIBCAP 1

View File

@ -343,6 +343,7 @@ target_link_libraries(epan
${LZ4_LIBRARIES}
${M_LIBRARIES}
${NGHTTP2_LIBRARIES}
${NGHTTP3_LIBRARIES}
${SMI_LIBRARIES}
${SNAPPY_LIBRARIES}
${WIN_PSAPI_LIBRARY}
@ -374,6 +375,7 @@ target_include_directories(epan
${LUA_INCLUDE_DIRS}
${LZ4_INCLUDE_DIRS}
${NGHTTP2_INCLUDE_DIRS}
${NGHTTP3_INCLUDE_DIRS}
${SMI_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
${ZSTD_INCLUDE_DIRS}

View File

@ -2215,6 +2215,7 @@ target_include_directories(dissectors
${LIBXML2_INCLUDE_DIRS}
${LZ4_INCLUDE_DIRS}
${NGHTTP2_INCLUDE_DIRS}
${NGHTTP3_INCLUDE_DIRS}
${SMI_INCLUDE_DIRS}
${SNAPPY_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}

File diff suppressed because it is too large Load Diff

View File

@ -5567,6 +5567,25 @@ proto_reg_handoff_quic(void)
quic_follow_tap = register_tap("quic_follow");
}
gboolean
quic_conn_data_get_conn_client_dcid_initial(struct _packet_info *pinfo, quic_cid_t *dcid)
{
if (pinfo == NULL || dcid == NULL) {
return false;
}
quic_info_data_t * conn = quic_connection_from_conv(pinfo);
if (conn == NULL) {
return false;
}
dcid->len = conn->client_dcid_initial.len;
memset(dcid->cid, 0, QUIC_MAX_CID_LENGTH);
memcpy(dcid->cid, conn->client_dcid_initial.cid, dcid->len);
return true;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*

View File

@ -12,12 +12,14 @@
#include "ws_symbol_export.h"
#include <glibconfig.h>
#include <wsutil/wsgcrypt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Metadata for a STREAM frame.
* https://tools.ietf.org/html/draft-ietf-quic-transport-23#section-19.8
@ -26,6 +28,7 @@ typedef struct _quic_stream_info {
guint64 stream_id; /**< 62-bit Stream ID. */
guint64 stream_offset; /**< 62-bit stream offset. */
guint32 offset; /**< Offset within the stream (different for reassembled data). */
guint32 inorder_offset; /**< Offset of the inorder data. */
struct quic_info_data *quic_info; /**< Opaque data structure to find the QUIC session. */
gboolean from_server;
} quic_stream_info;
@ -97,6 +100,12 @@ WS_DLL_PUBLIC gboolean
quic_get_stream_id_ge(guint streamid, guint sub_stream_id, guint *sub_stream_id_out);
/**
* Retrieves the initial client DCID from the packet info, if available
*/
WS_DLL_PUBLIC gboolean
quic_conn_data_get_conn_client_dcid_initial(struct _packet_info *pinfo, quic_cid_t *dcid);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -8950,7 +8950,7 @@ ssl_is_authoritative_version_message(guint8 content_type, guint8 handshake_type,
*/
void
tls_scan_server_hello(tvbuff_t *tvb, guint32 offset, guint32 offset_end,
guint16 *server_version, gboolean *is_hrr)
guint16 *server_version, gboolean *is_hrr, guint16 *max_supported_version)
{
/* SHA256("HelloRetryRequest") */
static const guint8 tls13_hrr_random_magic[] = {
@ -8985,7 +8985,12 @@ tls_scan_server_hello(tvbuff_t *tvb, guint32 offset, guint32 offset_end,
break; /* not enough data for type, length and data */
}
if (ext_type == SSL_HND_HELLO_EXT_SUPPORTED_VERSIONS && ext_len == 2) {
*server_version = tvb_get_ntohs(tvb, offset + 4);
guint16 higher_version = tvb_get_ntohs(tvb, offset + 4);
if (max_supported_version) {
*max_supported_version = higher_version;
} else {
*server_version = higher_version;
}
return;
}
offset += 4 + ext_len;

View File

@ -824,7 +824,7 @@ ssl_is_valid_handshake_type(guint8 hs_type, gboolean is_dtls);
extern void
tls_scan_server_hello(tvbuff_t *tvb, guint32 offset, guint32 offset_end,
guint16 *server_version, gboolean *is_hrr);
guint16 *server_version, gboolean *is_hrr, guint16 *max_supported_version);
extern void
ssl_try_set_version(SslSession *session, SslDecryptSession *ssl,

View File

@ -2581,6 +2581,7 @@ dissect_tls_handshake(tvbuff_t *tvb, packet_info *pinfo,
if (!PINFO_FD_VISITED(pinfo)) {
// 1. (First pass:) If a previous handshake message needed reasembly.
ssl_debug_printf("%s Handshake %s fragmented", G_STRFUNC, (*hs_reassembly_id_p) ? " is " : " is not ");
if (*hs_reassembly_id_p) {
// Continuation, so a previous fragment *must* exist.
fh = fragment_get(&tls_hs_reassembly_table, pinfo, *hs_reassembly_id_p, NULL);
@ -2788,9 +2789,13 @@ dissect_tls_handshake_full(tvbuff_t *tvb, packet_info *pinfo,
}
if (is_first_msg && msg_type == SSL_HND_SERVER_HELLO && length > 2) {
guint16 server_version;
guint16 server_version, max_supported_version;
tls_scan_server_hello(tvb, offset + 4, offset + 4 + length, &server_version, &is_hrr, &max_supported_version);
if (ssl && ssl->session.version != server_version && ssl->session.version == max_supported_version) {
server_version = max_supported_version;
}
tls_scan_server_hello(tvb, offset + 4, offset + 4 + length, &server_version, &is_hrr);
ssl_try_set_version(session, ssl, SSL_ID_HANDSHAKE, SSL_HND_SERVER_HELLO, FALSE, server_version);
if (is_hrr) {
msg_type_str = "Hello Retry Request";
@ -2864,6 +2869,7 @@ dissect_tls_handshake_full(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_SERVER_HELLO:
ssl_debug_printf("%s SSL_HND_SERVER_HELLO\n", G_STRFUNC);
ssl_dissect_hnd_srv_hello(&dissect_ssl3_hf, tvb, pinfo, ssl_hand_tree,
offset, offset + length, session, ssl, FALSE, is_hrr);
if (ssl) {
@ -4121,15 +4127,26 @@ tls13_get_quic_secret(packet_info *pinfo, gboolean is_from_server, int type, gui
ws_assert_not_reached();
}
ssl_debug_printf("%s Looking for QUIC %s of size %d..%d for client_random of size %d bytes: ",
G_STRFUNC, label, secret_min_len, secret_max_len, ssl->client_random.data_len);
ssl_print_data("Client random", ssl->client_random.data, ssl->client_random.data_len);
ssl_print_data("Server random", ssl->server_random.data, ssl->server_random.data_len);
StringInfo *secret = (StringInfo *)g_hash_table_lookup(key_map, &ssl->client_random);
if (!secret || secret->data_len < secret_min_len || secret->data_len > secret_max_len) {
ssl_debug_printf("%s Cannot find QUIC %s of size %d..%d, found bad size %d!\n",
G_STRFUNC, label, secret_min_len, secret_max_len, secret ? secret->data_len : 0);
if (!secret) {
ssl_debug_printf("%s Can not find QUIC %s of size %d..%d: not found\n",
G_STRFUNC, label, secret_min_len, secret_max_len);
return 0;
}
if (secret->data_len < secret_min_len || secret->data_len > secret_max_len) {
ssl_debug_printf("%s Cannot find QUIC %s: size %d out of bounds %d..%d\n",
G_STRFUNC, label, secret->data_len, secret_min_len, secret_max_len);
return 0;
}
ssl_debug_printf("%s Retrieved QUIC traffic secret.\n", G_STRFUNC);
ssl_print_string("Client Random", &ssl->client_random);
ssl_print_string(label, secret);
memcpy(secret_out, secret->data, secret->data_len);
return secret->data_len;

View File

@ -89,6 +89,10 @@
#include <nghttp2/nghttp2.h>
#endif
#ifdef HAVE_NGHTTP3
#include <nghttp3/nghttp3.h>
#endif
#ifdef HAVE_BROTLI
#include <brotli/decode.h>
#endif
@ -827,6 +831,13 @@ epan_gather_compile_info(feature_list l)
without_feature(l, "nghttp2");
#endif /* HAVE_NGHTTP2 */
/* nghttp3 */
#ifdef HAVE_NGHTTP3
with_feature(l, "nghttp3 %s", NGHTTP3_VERSION);
#else
without_feature(l, "nghttp3");
#endif /* HAVE_NGHTTP3 */
/* brotli */
#ifdef HAVE_BROTLI
with_feature(l, "brotli");

View File

@ -157,7 +157,7 @@ if (BUILD_wireshark)
set(_all_manifest_contents "${_all_manifest_contents}!endif\n")
foreach(_dll ${CARES_DLL} ${PCRE2_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
${ZLIB_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
${SPEEXDSP_DLL}
@ -206,7 +206,7 @@ if (BUILD_logray)
set(_all_manifest_contents "${_all_manifest_contents}!endif\n")
foreach(_dll ${CARES_DLL} ${PCRE2_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
${ZLIB_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
${SPEEXDSP_DLL}

View File

@ -308,6 +308,11 @@ development of Wireshark scripts and plugins.
%else
-DENABLE_NGHTTP2=OFF \
%endif
%if %{with nghttp3}
-DENABLE_NGHTTP3=ON \
%else
-DENABLE_NGHTTP3=OFF \
%endif
%if %{with sdjournal}
-DBUILD_sdjournal=ON \
%else

View File

@ -128,7 +128,7 @@ file(APPEND "${_all_manifest_wix}" " <?endif?>\n")
SET(unique_component "")
foreach(_dll ${CARES_DLL} ${PCRE2_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
${ZLIB_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
${SPEEXDSP_DLL}
@ -162,7 +162,7 @@ file(APPEND "${_all_manifest_wix}" " <?endif?>\n")
SET(unique_file "")
foreach(_dll ${CARES_DLL} ${PCRE2_DLL} ${GCRYPT_DLLS}
${GNUTLS_DLLS} ${KERBEROS_DLLS} ${LIBSSH_DLLS} ${LUA_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${LZ4_DLL} ${NGHTTP2_DLL} ${NGHTTP3_DLL} ${SBC_DLL} ${SMI_DLL} ${SNAPPY_DLL}
${SPANDSP_DLL} ${BCG729_DLL} ${LIBXML2_DLLS} ${WINSPARKLE_DLL}
${ZLIB_DLL} ${BROTLI_DLLS} ${ZSTD_DLL} ${ILBC_DLL} ${OPUS_DLL}
${SPEEXDSP_DLL}

View File

@ -177,6 +177,7 @@ LIBSSH_VERSION=0.9.6
# mmdbresolve
MAXMINDDB_VERSION=1.4.3
NGHTTP2_VERSION=1.46.0
NGHTTP3_VERSION=0.6.0
SPANDSP_VERSION=0.0.6
SPEEXDSP_VERSION=1.2.0
if [ "$SPANDSP_VERSION" ]; then
@ -2038,6 +2039,42 @@ uninstall_nghttp2() {
fi
}
install_nghttp3() {
if [ "$NGHTTP3_VERSION" -a ! -f nghttp3-$NGHTTP3_VERSION-done ] ; then
echo "Downloading, building, and installing nghttp3:"
[ -f nghttp3-$NGHTTP3_VERSION.tar.xz ] || curl -L -O https://github.com/ngtcp2/nghttp3/releases/download/v$NGHTTP3_VERSION/nghttp3-$NGHTTP3_VERSION.tar.xz || exit 1
$no_build && echo "Skipping installation" && return
xzcat nghttp3-$NGHTTP3_VERSION.tar.xz | tar xf - || exit 1
cd nghttp3-$NGHTTP3_VERSION
CFLAGS="$CFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" CXXFLAGS="$CXXFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" LDFLAGS="$LDFLAGS $VERSION_MIN_FLAGS $SDKFLAGS" ./configure --enable-lib-only || exit 1
make $MAKE_BUILD_OPTS || exit 1
$DO_MAKE_INSTALL || exit 1
cd ..
touch nghttp3-$NGHTTP3_VERSION-done
fi
}
uninstall_nghttp3() {
if [ ! -z "$installed_nghttp3_version" ] ; then
echo "Uninstalling nghttp3:"
cd nghttp3-$installed_nghttp3_version
$DO_MAKE_UNINSTALL || exit 1
make distclean || exit 1
cd ..
rm nghttp3-$installed_nghttp3_version-done
if [ "$#" -eq 1 -a "$1" = "-r" ] ; then
#
# Get rid of the previously downloaded and unpacked version.
#
rm -rf nghttp3-$installed_nghttp3_version
rm -rf nghttp3-$installed_nghttp3_version.tar.xz
fi
installed_nghttp3_version=""
fi
}
install_libtiff() {
if [ "$LIBTIFF_VERSION" -a ! -f tiff-$LIBTIFF_VERSION-done ] ; then
echo "Downloading, building, and installing libtiff:"
@ -2574,6 +2611,17 @@ install_all() {
uninstall_nghttp2 -r
fi
if [ ! -z "$installed_nghttp3_version" -a \
"$installed_nghttp3_version" != "$NGHTTP3_VERSION" ] ; then
echo "Installed nghttp3 version is $installed_nghttp3_version"
if [ -z "$NGHTTP3_VERSION" ] ; then
echo "nghttp3 is not requested"
else
echo "Requested nghttp3 version is $NGHTTP3_VERSION"
fi
uninstall_nghttp3 -r
fi
if [ ! -z "$installed_libssh_version" -a \
"$installed_libssh_version" != "$LIBSSH_VERSION" ] ; then
echo "Installed libssh version is $installed_libssh_version"
@ -3074,6 +3122,8 @@ install_all() {
install_nghttp2
install_nghttp3
install_libtiff
install_spandsp
@ -3127,6 +3177,8 @@ uninstall_all() {
uninstall_nghttp2
uninstall_nghttp3
uninstall_libssh
uninstall_c_ares
@ -3342,6 +3394,7 @@ then
installed_cares_version=`ls c-ares-*-done 2>/dev/null | sed 's/c-ares-\(.*\)-done/\1/'`
installed_libssh_version=`ls libssh-*-done 2>/dev/null | sed 's/libssh-\(.*\)-done/\1/'`
installed_nghttp2_version=`ls nghttp2-*-done 2>/dev/null | sed 's/nghttp2-\(.*\)-done/\1/'`
installed_nghttp3_version=`ls nghttp3-*-done 2>/dev/null | sed 's/nghttp3-\(.*\)-done/\1/'`
installed_libtiff_version=`ls tiff-*-done 2>/dev/null | sed 's/tiff-\(.*\)-done/\1/'`
installed_spandsp_version=`ls spandsp-*-done 2>/dev/null | sed 's/spandsp-\(.*\)-done/\1/'`
installed_speexdsp_version=`ls speexdsp-*-done 2>/dev/null | sed 's/speexdsp-\(.*\)-done/\1/'`