diff --git a/src/quic.c b/src/quic.c index b8ec9dc..8d0f024 100644 --- a/src/quic.c +++ b/src/quic.c @@ -109,11 +109,11 @@ int quic_parse_data(const uint8_t *raw_payload, uint32_t raw_payload_len, int64_t qversion = quic_get_version(nqch); if (qversion < 0) { - lgtrace_addp("quic version undefined %ld", -qversion); + lgtrace_addp("quic version undefined %u", (uint32_t)(-qversion)); return -EPROTO; } - lgtrace_addp("quic version valid %ld", qversion); + lgtrace_addp("quic version valid %u", (uint32_t)qversion); if (left_len < 2) goto invalid_packet; struct quic_cids nqci = {0}; @@ -336,9 +336,10 @@ int gen_fake_udp(struct udp_fake_type type, return 0; } -struct tls_verdict parse_quic_decrypted( +int parse_quic_decrypted( const struct section_config_t *section, - const uint8_t *decrypted_message, uint32_t decrypted_message_len + const uint8_t *decrypted_message, uint32_t decrypted_message_len, + uint8_t **crypto_message_buf, uint32_t *crypto_message_buf_len ) { const uint8_t *curptr = decrypted_message; ssize_t curptr_len = decrypted_message_len; @@ -350,7 +351,7 @@ struct tls_verdict parse_quic_decrypted( uint8_t *crypto_message = calloc(AVAILABLE_MTU, 1); if (crypto_message == NULL) { lgerror(-ENOMEM, "No memory"); - return tlsv; + return -ENOMEM; } int crypto_message_len = AVAILABLE_MTU; @@ -371,7 +372,7 @@ pl_incr: break; case QUIC_FRAME_CRYPTO: fret = quic_parse_crypto(&fr_cr, curptr, curptr_len); - lgtrace_addp("crypto %lu", fr_cr.offset); + lgtrace_addp("crypto %d %d %d", (int)fr_cr.offset, (int)fr_cr.payload_length, (int)fret); if (fret < 0) break; curptr += fret; @@ -391,16 +392,10 @@ pl_incr: } out: - if (section->sni_detection == SNI_DETECTION_BRUTE) { - ret = bruteforce_analyze_sni_str(section, crypto_message, crypto_message_len, &tlsv); - } else { - ret = analyze_tls_message( - section, crypto_message, crypto_message_len, &tlsv - ); - } + *crypto_message_buf = crypto_message; + *crypto_message_buf_len = crypto_message_len; - free(crypto_message); - return tlsv; + return 0; } int detect_udp_filtered(const struct section_config_t *section, @@ -461,6 +456,8 @@ int detect_udp_filtered(const struct section_config_t *section, uint32_t decrypted_payload_len; const uint8_t *decrypted_message; uint32_t decrypted_message_len; + uint8_t *crypto_message; + uint32_t crypto_message_len; struct tls_verdict tlsv; ret = quic_parse_initial_message( @@ -473,9 +470,24 @@ int detect_udp_filtered(const struct section_config_t *section, goto match_port; } - tlsv = parse_quic_decrypted(section, - decrypted_message, decrypted_message_len + ret = parse_quic_decrypted(section, + decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len ); + free(decrypted_payload); + decrypted_payload = NULL; + + if (ret < 0) { + goto match_port; + } + + if (section->sni_detection == SNI_DETECTION_BRUTE) { + ret = bruteforce_analyze_sni_str(section, crypto_message, crypto_message_len, &tlsv); + } else { + ret = analyze_tls_message( + section, crypto_message, crypto_message_len, &tlsv + ); + } if (tlsv.sni_len != 0) { lgtrace_addp("QUIC SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr); @@ -483,11 +495,13 @@ int detect_udp_filtered(const struct section_config_t *section, if (tlsv.target_sni) { lgdebugmsg("QUIC target SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr); - free(decrypted_payload); + free(crypto_message); + crypto_message = NULL; goto approve; } - free(decrypted_payload); + free(crypto_message); + crypto_message = NULL; } match_port: diff --git a/src/quic.h b/src/quic.h index 88380e2..5fa3de6 100644 --- a/src/quic.h +++ b/src/quic.h @@ -221,11 +221,14 @@ int quic_parse_initial_message( ); /** - * Like analyze_tls_data for QUIC + * CRYPTO frames may be randomly spried in the message. + * This function _allocates_ crypto_message_buf and fills it with CRYPTO frames + * according to offset and payload_length */ -struct tls_verdict parse_quic_decrypted( +int parse_quic_decrypted( const struct section_config_t *section, - const uint8_t *decrypted_message, uint32_t decrypted_message_len + const uint8_t *decrypted_message, uint32_t decrypted_message_len, + uint8_t **crypto_message_buf, uint32_t *crypto_message_buf_len ); // Like fail_packet for TCP diff --git a/test/quic.c b/test/quic.c index 2363e32..81b0db4 100644 --- a/test/quic.c +++ b/test/quic.c @@ -141,11 +141,15 @@ TEST(QuicTest, Test_varlength_parser) TEST(QuicTest, Test_parse_quic_decrypted) { +#undef free + int ret; uint8_t *decrypted_payload; uint32_t decrypted_payload_len; const uint8_t *decrypted_message; uint32_t decrypted_message_len; + uint8_t *crypto_message; + uint32_t crypto_message_len; struct tls_verdict tlsv = {0}; ret = quic_parse_initial_message( @@ -153,22 +157,35 @@ TEST(QuicTest, Test_parse_quic_decrypted) &decrypted_payload, &decrypted_payload_len, &decrypted_message, &decrypted_message_len ); - TEST_ASSERT_EQUAL(ret, 0); + TEST_ASSERT_EQUAL(0, ret); - tlsv = parse_quic_decrypted(&sconf, decrypted_message, decrypted_message_len); - TEST_ASSERT_EQUAL_STRING_LEN("example.com", tlsv.sni_ptr, 11); -#undef free + ret = parse_quic_decrypted( + &sconf, decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len); + TEST_ASSERT_EQUAL(0, ret); free(decrypted_payload); + decrypted_payload = NULL; + + ret = analyze_tls_message( + &sconf, crypto_message, crypto_message_len, &tlsv + ); + TEST_ASSERT_EQUAL_STRING_LEN("example.com", tlsv.sni_ptr, 11); + free(crypto_message); + #define free unity_free } TEST(QuicTest, Test_parse_quic_decrypted_on_sparse) { +#undef free + int ret; uint8_t *decrypted_payload; uint32_t decrypted_payload_len; const uint8_t *decrypted_message; uint32_t decrypted_message_len; + uint8_t *crypto_message; + uint32_t crypto_message_len; struct tls_verdict tlsv = {0}; ret = quic_parse_initial_message( @@ -176,13 +193,22 @@ TEST(QuicTest, Test_parse_quic_decrypted_on_sparse) &decrypted_payload, &decrypted_payload_len, &decrypted_message, &decrypted_message_len ); - TEST_ASSERT_EQUAL(ret, 0); + TEST_ASSERT_EQUAL(0, ret); - tlsv = parse_quic_decrypted(&sconf, decrypted_message, decrypted_message_len); + ret = parse_quic_decrypted( + &sconf, decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len); + TEST_ASSERT_EQUAL(0, ret); + free(decrypted_payload); + decrypted_payload = NULL; + + ret = analyze_tls_message( + &sconf, crypto_message, crypto_message_len, &tlsv + ); TEST_ASSERT_EQUAL(19, tlsv.sni_len); TEST_ASSERT_EQUAL_STRING_LEN("ipm.adblockplus.dev", tlsv.sni_ptr, 19); -#undef free - free(decrypted_payload); + free(crypto_message); + #define free unity_free }