cfg->host is static configuration, so an over-long path is a config
error: validate it once at startup in config_sanity_check() for both
is_unix listen endpoints and is_unix protocol targets, instead of at
bind()/connect() time. This also fails fast for protocol targets,
where the previous runtime check only dropped each connection instead
of reporting the bad config.
The memset()/bounded strncpy() calls stay in place: they are what make
sun_path termination structurally safe regardless of the input length.
Both start_listen_unix() and connect_unix() copied the configured
path into sun_path without checking its length and without zeroing
the sockaddr first. A path of 107+ bytes fills sun_path completely,
leaving it unterminated; bind()/connect() then read past the array
into uninitialised stack bytes (verified: garbage bytes visible in
the sockaddr passed to bind).
Fail listen startup with a clear message when the path cannot fit -
before unlink()ing whatever file currently sits at that path - and
make connect_unix() return -1 so the connection is dropped cleanly.
Zero both sockaddr structures, check the socket() return value in
connect_unix(), label unix listen endpoints AF_UNIX instead of
AF_INET, and route the "binding" message through print_message() so
it respects verbosity flags like everything else.
- 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.
err_log was fclose()'d before the "Successfully generated all targets"
fprintf(), resulting in a write-after-close that corrupted glibc's
internal stdio buffers and triggered an abort() via SIGABRT on every
systemd-invoked run regardless of whether /etc/sslh/ exists.
Fix by moving the success fprintf() above the fclose() call.