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.
This commit is contained in:
Stefan Meinecke authored and Yves Rutschle committed 2026-10-18 11:44:36 +02:00
1 parent ca5e7fe6f3
commit 7cc9dc90be
1 file changed
+16 -6
+16 -6
View File
@@ -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