Skip to content

Commit

Permalink
Fix segfault in parse_quic_decrypted
Browse files Browse the repository at this point in the history
  • Loading branch information
Waujito committed Jan 6, 2025
1 parent 40e1101 commit 480870a
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 71 deletions.
86 changes: 43 additions & 43 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
arch: [x86_64, x86, aarch64, armhf, armv7]
arch: [x86_64] #, x86, aarch64, armhf, armv7]
branch: [latest-stable]
steps:
- name: Checkout
Expand Down Expand Up @@ -107,18 +107,18 @@ jobs:
include:
- arch: mips64el
tool: mips64el-unknown-linux-musl
- arch: mips64
tool: mips64-unknown-linux-musl
- arch: mipsel
tool: mipsel-unknown-linux-musl
- arch: mipselsf
tool: mipsel-unknown-linux-muslsf
- arch: mips
tool: mips-unknown-linux-musl
- arch: mipssf
tool: mips-unknown-linux-muslsf
- arch: armv7sf
tool: armv7-unknown-linux-musleabi
# - arch: mips64
# tool: mips64-unknown-linux-musl
# - arch: mipsel
# tool: mipsel-unknown-linux-musl
# - arch: mipselsf
# tool: mipsel-unknown-linux-muslsf
# - arch: mips
# tool: mips-unknown-linux-musl
# - arch: mipssf
# tool: mips-unknown-linux-muslsf
# - arch: armv7sf
# tool: armv7-unknown-linux-musleabi
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -169,31 +169,31 @@ jobs:
branch:
- openwrt-23.05
arch:
- aarch64_cortex-a53
- aarch64_cortex-a72
- aarch64_generic
- arm_arm1176jzf-s_vfp
- arm_arm926ej-s
- arm_cortex-a15_neon-vfpv4
- arm_cortex-a5_vfpv4
- arm_cortex-a7
- arm_cortex-a7_neon-vfpv4
- arm_cortex-a7_vfpv4
- arm_cortex-a8_vfpv3
- arm_cortex-a9
- arm_cortex-a9_neon
- arm_cortex-a9_vfpv3-d16
- arm_fa526
- arm_mpcore
- arm_xscale
- mips64_octeonplus
- mips_24kc
- mips_4kec
- mips_mips32
# - aarch64_cortex-a53
# - aarch64_cortex-a72
# - aarch64_generic
# - arm_arm1176jzf-s_vfp
# - arm_arm926ej-s
# - arm_cortex-a15_neon-vfpv4
# - arm_cortex-a5_vfpv4
# - arm_cortex-a7
# - arm_cortex-a7_neon-vfpv4
# - arm_cortex-a7_vfpv4
# - arm_cortex-a8_vfpv3
# - arm_cortex-a9
# - arm_cortex-a9_neon
# - arm_cortex-a9_vfpv3-d16
# - arm_fa526
# - arm_mpcore
# - arm_xscale
# - mips64_octeonplus
# - mips_24kc
# - mips_4kec
# - mips_mips32
- mipsel_24kc
- mipsel_24kc_24kf
- mipsel_74kc
- mipsel_mips32
# - mipsel_24kc_24kf
# - mipsel_74kc
# - mipsel_mips32
- x86_64
container:
image: openwrt/sdk:${{ matrix.arch }}-${{ matrix.branch }}
Expand Down Expand Up @@ -306,12 +306,12 @@ jobs:
strategy:
matrix:
arch:
- aarch64-3.10
- armv7-3.2
- mips-3.4
- mipsel-3.4
- x64-3.2
- x86-2.6
# - aarch64-3.10
# - armv7-3.2
# - mips-3.4
# - mipsel-3.4
# - x64-3.2
# - x86-2.6
- armv7-2.6
container:
image: waujito/entware_builder:${{ matrix.arch }}
Expand Down
48 changes: 31 additions & 17 deletions src/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -371,7 +372,7 @@ struct tls_verdict parse_quic_decrypted(
break;
case QUIC_FRAME_CRYPTO:
fret = quic_parse_crypto(&fr_cr, curptr, curptr_len);
lgtrace_addp("crypto %lu", fr_cr.offset);
lgtrace_addp("crypto %lu %lu %lu", fr_cr.offset, fr_cr.payload_length, fret);
if (fret < 0)
break;
curptr += fret;
Expand All @@ -391,16 +392,10 @@ struct tls_verdict parse_quic_decrypted(
}

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,
Expand Down Expand Up @@ -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(
Expand All @@ -473,21 +470,38 @@ 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);
}

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:
Expand Down
9 changes: 6 additions & 3 deletions src/quic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 34 additions & 8 deletions test/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,48 +141,74 @@ 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(
(const uint8_t *)quic_testing_payload, sizeof(quic_testing_payload) - 1,
&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(
(const uint8_t *)quic_sparse_payload, sizeof(quic_sparse_payload) - 1,
&decrypted_payload, &decrypted_payload_len,
&decrypted_message, &decrypted_message_len
);
TEST_ASSERT_EQUAL(ret, 0);
TEST_ASSERT_EQUAL(0, ret);

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;

tlsv = parse_quic_decrypted(&sconf, decrypted_message, decrypted_message_len);
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
}

Expand Down

0 comments on commit 480870a

Please sign in to comment.