From 7cc9dc90bee591c01bfd1e5b322bf2d2728f34c3 Mon Sep 17 00:00:00 2001 From: Stefan Meinecke Date: Sun, 18 Oct 2026 02:14:06 +0200 Subject: [PATCH] probes: fix msrdp length truncation, teamspeak match, unaligned reads - is_msrdp_protocol() stored the 16-bit TPKT length in a char, so a packet claiming length 263 (0x0107) but carrying only 7 bytes compared 7 == 7 and matched - any sufficiently short packet whose declared length low byte equals its size is accepted as RDP. Keep the declared length in a uint16_t. Verified with a harness: {0x03 0x00 0x01 0x07 ...} no longer matches. - is_teamspeak_protocol() used strncmp(p, "TS3INIT1", len): for the first datagram of a real TS3 client (len > 8) this compares the string literal's terminating NUL against packet byte 8, which is a version field, so it could never match real traffic (and reads past the literal for len > 9). Use a fixed 8-byte memcmp prefix. - is_openvpn_protocol() and is_wireguard_protocol() dereferenced the packet buffer through uint16_t*/uint32_t* casts; the buffer is not aligned, which is UB and traps on strict-alignment targets (ARM). Use memcpy() instead, as already done elsewhere in this file. --- probe.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/probe.c b/probe.c index eeb16b2..3b3327b 100644 --- a/probe.c +++ b/probe.c @@ -156,7 +156,10 @@ static int is_openvpn_protocol (const char*p,ssize_t len, struct sslhcfg_protoco if (len < 2) return PROBE_AGAIN; - packet_len = ntohs(*(uint16_t*)p); + /* p may be unaligned (e.g. on ARM), do not cast to uint16_t* */ + uint16_t wire_len; + memcpy(&wire_len, p, sizeof(wire_len)); + packet_len = ntohs(wire_len); return packet_len == len - 2; } else { if (len < 1) @@ -205,7 +208,9 @@ static int is_wireguard_protocol(const char *p, ssize_t len, struct sslhcfg_prot return PROBE_NEXT; // Handshake Init: p[0] = 0x01, p[1..3] = 0x000000 (reserved) - if (ntohl(*(uint32_t*)p) != 0x01000000) + uint32_t type; + memcpy(&type, p, sizeof(type)); + if (ntohl(type) != 0x01000000) return PROBE_NEXT; return PROBE_MATCH; @@ -407,20 +412,25 @@ static int is_teamspeak_protocol(const char *p, ssize_t len, struct sslhcfg_prot if (len < 8) return PROBE_NEXT; - return !strncmp(p, "TS3INIT1", len); + /* Compare a fixed-length prefix: strncmp(p, "TS3INIT1", len) would read + * len bytes of the 9-byte literal and never match a real packet, whose + * byte 8 is not NUL */ + return !memcmp(p, "TS3INIT1", 8); } static int is_msrdp_protocol(const char *p, ssize_t len, struct sslhcfg_protocols_item* proto) { char version; - char packet_len; + uint16_t packet_len; if (len < 7) return PROBE_NEXT; version=*p; if (version!=0x03) return 0; - packet_len = ntohs(*(uint16_t*)(p+2)); - return packet_len == len; + memcpy(&packet_len, p+2, sizeof(packet_len)); + /* The declared TPKT length must fit the entire received packet; a char + * would truncate e.g. 0x0107 to 7 and accept truncated packets */ + return ntohs(packet_len) == len; } #ifdef ENABLE_REGEX