]> git.ipfire.org Git - thirdparty/freeswitch.git/log
thirdparty/freeswitch.git
10 hours agoversion bump master
Andrey Volk [Sun, 9 Aug 2026 18:01:57 +0000 (21:01 +0300)] 
version bump

12 hours agoswigall (#3117)
Andrey Volk [Sun, 9 Aug 2026 16:13:24 +0000 (19:13 +0300)] 
swigall (#3117)

31 hours ago[mod_silk] Bound decode loop to the codec's frame limit (#3116)
Dmitry Verenitsin [Sat, 8 Aug 2026 21:05:39 +0000 (02:05 +0500)] 
[mod_silk] Bound decode loop to the codec's frame limit (#3116)

`switch_silk_decode()` ran its `do`/`while` decode loop while the SDK
kept reporting more internal frames, advancing the output pointer each
pass with no cap. The destination is a fixed-size PCM buffer, so a
stream reporting more internal frames than a conformant packet can
carry let the accumulated write run past its end.

Stop after `MAX_INPUT_FRAMES` internal frames, the most a conformant
SILK packet can hold, so the accumulated PCM stays within the
destination regardless of the bitstream.

Declare the per-pass sample count inside the loop so it resets to zero
each iteration, and advance the output pointer and length only when it
is positive. A pass that writes no samples, including a tolerated FEC
payload error that leaves the count untouched, then contributes nothing
instead of advancing on a stale count from an earlier pass or on a
negative value.

31 hours ago[core] Validate IPv6 XOR-MAPPED-ADDRESS length in STUN parser (#3115)
Dmitry Verenitsin [Sat, 8 Aug 2026 20:39:40 +0000 (01:39 +0500)] 
[core] Validate IPv6 XOR-MAPPED-ADDRESS length in STUN parser (#3115)

`switch_stun_packet_attribute_get_xor_mapped_address()` read and
XOR-rewrote a 16-byte IPv6 address whenever the `family` byte was 2,
without checking the attribute value was that long. Reject `family == 2`
values shorter than `sizeof(switch_stun_ipv6_t)` and clear the output
address and port. Adds a regression test.

32 hours ago[mod_xml_rpc] Fix OOB write and read-loop hang in WebSocket parser (#3114)
Dmitry Verenitsin [Sat, 8 Aug 2026 20:17:57 +0000 (01:17 +0500)] 
[mod_xml_rpc] Fix OOB write and read-loop hang in WebSocket parser (#3114)

`ws_read_frame()` had two defects in the framing path:

- After header parsing, the remaining payload count
  `need = plen - (datalen - header)` could go negative when the
  initial read buffered more bytes than the frame's declared
  length, even with an in-range `plen`. A negative `need` passed
  the signed size guard and reached `ws_raw_read()` as a `size_t`
  near its maximum, driving a `memcpy` past `wsh->buffer`. Reject
  `need < 0` with a protocol-error close before the read loop.

- The loop filling the frame header called `ws_raw_read()` without
  checking its result, so a connection that stopped delivering
  header bytes left the loop with no terminating condition,
  spinning or hanging the handler thread. Close on a non-advancing
  read, matching the payload read loop.

32 hours ago[mod_rtmp] Harden H.264 video read path bounds and length parsing (#3113)
Dmitry Verenitsin [Sat, 8 Aug 2026 19:55:35 +0000 (00:55 +0500)] 
[mod_rtmp] Harden H.264 video read path bounds and length parsing (#3113)

`rtmp_rtmp2rtpH264` read the two leading bytes that select the parse
branch (`data[0]` and `data[1]`) before any length check, so a video
body shorter than 2 bytes read past the buffer. Reject `len < 2` at
entry, before either classifier byte is dereferenced.

In the NAL-unit branch, move the `pdata = data + 5` assignment below
its `len < 5` check so the pointer is never formed past the end of a
short buffer.

Read the 2-byte big-endian SPS and PPS length prefixes byte-wise
(`(pdata[0] << 8) | pdata[1]`) instead of `ntohs(*(uint16_t *)pdata)`.
`pdata` walks a byte buffer at wire-controlled offsets, so the cast was
an unaligned 16-bit load and a strict-aliasing violation; the byte-wise
read is alignment- and endianness-independent and matches the idiom
already used in the NAL-unit branch.

In `rtmp_read_video_frame`, a buffered record is `len + 6` bytes (2-byte
length prefix, 4-byte timestamp, `len`-byte body), but the guard only
required `inuse >= len` before consuming the whole record. Require
`inuse >= len + 6` so the invariant holds locally instead of relying on
the writer emitting each record atomically.

32 hours ago[core] Harden STUN attribute parsing bounds and USERNAME copy (#3112)
Dmitry Verenitsin [Sat, 8 Aug 2026 19:33:58 +0000 (00:33 +0500)] 
[core] Harden STUN attribute parsing bounds and USERNAME copy (#3112)

Bounds and termination fixes across the STUN attribute receive path
in `handle_ice` and `switch_stun_lookup`:

- `switch_stun_packet_next_attribute` and its `_hbo` variant now
  confirm the 4-byte attribute header is fully within `end` before
  dereferencing `type`/`length`, and include the header when checking
  that the value fits, so a truncated or overrunning attribute is not
  read past the buffer.
- Compute `end_buf` as the 20-byte STUN header plus the attribute
  section (`SWITCH_STUN_PACKET_MIN_LEN + header.length`) so the walk
  covers every attribute, including trailing ones.
- Make `switch_stun_packet_next_attribute` the sole loop terminator
  and drop the redundant `xlen` guard; its seed differed between the
  two functions and could skip a trailing attribute in
  `switch_stun_lookup`.
- `switch_stun_packet_attribute_get_username` reserves a byte for the
  terminator and always NUL-terminates, since callers use the result
  as a C string.

33 hours ago[core] Harden switch_b64_encode output bound (#3111)
Dmitry Verenitsin [Sat, 8 Aug 2026 19:05:20 +0000 (00:05 +0500)] 
[core] Harden switch_b64_encode output bound (#3111)

switch_b64_encode wrote each base64 character before checking the
output bound, and computed that bound as `bytes >= (int)olen - 1`.
Both are unsafe:

- Writing before the check meant a buffer with no room for a data
  byte still received one: `olen == 1` wrote a character at index 0
  and the NUL at index 1, and `olen == 0` (where `(int)olen - 1` is
  -1) wrote two bytes, both past the end.
- Casting the unsigned `olen` to `int` truncated it above INT_MAX,
  producing a wrong bound for very large buffers.

Reject `olen == 0`, make the output index `bytes` a `size_t`, and test
`bytes + 1 >= olen` before each write, so the bound never casts or
underflows and always leaves the last byte for the terminator. Apply
the same `bytes + 1 < olen` guard to the trailing partial-group
character and the `=` padding, so no write can pass the end.

Remove the dead line-wrap counter `y`: it only gated a commented-out
newline emit, so it counted and reset with no effect on the output.

Add unit tests covering the output-bound edges for every write site.

33 hours ago[core] Harden switch_b64_decode output bound and input handling (#3110)
Dmitry Verenitsin [Sat, 8 Aug 2026 18:40:30 +0000 (23:40 +0500)] 
[core] Harden switch_b64_decode output bound and input handling (#3110)

switch_b64_decode bounded its writes with `ol >= olen - 1`, where
`olen` is unsigned. An `olen` of 0 made `olen - 1` wrap to `SIZE_MAX`,
so the bound never fired and the loop wrote the entire decoded input
plus a trailing NUL past the destination. Reject `olen == 0` and test
`ol + 1 >= olen` before each write, so the comparison never subtracts
from an unsigned and always leaves room for the terminator.

The alphabet lookup table `l64` was a `char` indexed by a `char`,
which is unsafe whichever way `char` is signed:

- Where `char` is signed, an input byte >= 0x80 became a negative
  index and read before the table.
- Where `char` is unsigned, the `-1` "not in alphabet" sentinel was
  stored as 255, so the skip test never matched and non-alphabet
  bytes were folded in as data.

Make `l64` a `signed char` and index it with `(unsigned char)`, so the
sentinel survives and the index stays in range on every platform.

Change the bit accumulator `b` from `int` to `unsigned int` to avoid
signed-overflow undefined behavior on long input; decoded output is
unchanged.

Add unit tests: an encode/decode round-trip across the padding cases,
the output-bound edges (`olen` of 0, 1, and a truncating buffer), and
a non-alphabet byte (including one >= 0x80) that must be skipped.

34 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 18:16:07 +0000 (23:16 +0500)] 
Merge commit from fork

Two invoke handlers read an AMF argument's value without first
checking its type, so a wrong-typed argument reads the wrong union
member:

- `rtmp_i_connect()` passed the first invoke argument straight into
  `amf0_object_get()`, which walks the value as a node list. Treat
  the command object as a field source only when it is an AMF object
  or ECMA array, otherwise leave the lookups empty.
- `rtmp_i_receiveaudio()` and `rtmp_i_receivevideo()` read the flag
  argument with `amf0_boolean_get_value()`, which returns the raw
  union byte. Use `amf0_get_boolean()`, which yields `SWITCH_FALSE`
  unless the argument is an AMF boolean.

34 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 18:10:24 +0000 (23:10 +0500)] 
Merge commit from fork

In `udptl_rx_packet()`, decoded values from the error-recovery data were
used without checking them against their destination buffers:

- The FEC entry count is read as a single byte and drives both the
  decode loop and the stored `fec_entries` later walked by the
  reconstruction loop, allowing writes past the `fec[]`/`fec_len[]`
  arrays, which hold only `LOCAL_FAX_MAX_FEC_PACKETS` entries. Reject a
  larger count. `fec_entries` was also stored before the elements were
  decoded, so a mid-loop reject left the slot advertising a count whose
  `fec_len[]`/`fec[]` were stale or out of range; since `s->rx[]`
  persists across packets, a later reconstruction pass could copy such a
  stale length past the fixed `s->rx[].buf`. Commit the count only after
  every element is decoded and bound-checked.
- Each redundancy secondary element length was copied into the fixed
  `LOCAL_FAX_MAX_DATAGRAM`-sized `s->rx[].buf` without a size check,
  unlike the primary packet. Reject an overlength element at decode
  time.

34 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 18:05:01 +0000 (23:05 +0500)] 
Merge commit from fork

`http_directory_auth()` builds the expected "user@domain:password"
token into `z[256]` and base64-encodes it to compare against the
client's Authorization header. Encode with `switch_b64_encode`, which
stops at its output-length argument and always NUL-terminates, and
size `t` from `sizeof(z)`: base64 emits 4 output bytes per 3 input
bytes (final partial group rounded up) plus a NUL, so
`4 * ((sizeof(z) + 2) / 3) + 1` holds the encoding of any `z`. The
encode is confined to `t`, matching the `switch_b64_decode` already
used for the inbound header.

Also in the same function:
- Drop the now-unused `#include <xmlrpc-c/base64_int.h>`, an xmlrpc-c
  internal header that only declared the removed encoder.
- Compare 4 bytes, not 3, when stripping a leading `www.` from the
  virtual-host `Host:` name. A 3-byte compare also matches hosts like
  `www2.example.com` and then strips 4 bytes, yielding `.example.com`
  and a failed directory lookup; for a bare `www` it advanced one
  byte past the terminating NUL.

34 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 18:02:15 +0000 (23:02 +0500)] 
Merge commit from fork

* Merge commit from fork

* [core] Fix XML escape encoder overrun and unsigned-char UTF-8 gate

`switch_xml_ampencode()` had two independent defects in its UTF-8
numeric-escape path.

Buffer overrun: the encoder grows its destination once per source byte,
but the realloc margin reserved only the 10 data characters of the
widest escape `"&#x%X;"` (a 21-bit code point rendered as 6 hex digits),
not the terminating NUL that `sprintf` also writes. At the margin
boundary that NUL landed one byte past the allocation. Reserve 11 bytes
in the guard (10 data chars plus the NUL) and emit the escape with
`snprintf` bounded to the remaining space, so the write stays in bounds
even if the margin is ever miscounted. The other escape sinks are all
within the widened margin and are unchanged.

Char signedness: the lead-byte test `(*s >> 8) & 0x01` reads bit 8 of a
plain `char`, which exists only after sign extension. Where `char` is
signed the high bit sign-extends and the test passes; where `char` is
unsigned it is always zero, so the numeric-escape path never ran and
multi-byte UTF-8 was emitted raw, making serialized XML differ by
architecture. Test bit 7 directly with `(*s & 0x80)`, correct regardless
of `char` signedness. This also makes the overrun fix effective on
unsigned-`char` builds, where the escape path now runs.

Add unit test `test_utf_8_wide_codepoint`, which serializes U+10FFFF and
long runs of it across buffer reallocations, sweeping an ASCII prefix so
an escape is emitted at the minimum-headroom offset, and asserts the
full serialized length.

34 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 17:31:33 +0000 (22:31 +0500)] 
Merge commit from fork

`sofia_dialog_probe_callback()` filled its fixed 512-byte
`remote_display_buf` with unbounded `strcpy`. On the default path the
source is the stored To-header user part, which `sip_dialogs.sip_to_user`
holds verbatim from the wire with no truncation, so a dialog row
addressed to a user part longer than 511 bytes overflowed the buffer
when a `dialog`-package SUBSCRIBE ran the probe.

Copy with `snprintf()` bounded by `sizeof(remote_display_buf)` on every
path that writes it. The four proto branches write short fixed strings
and could not overflow; they are converted for consistency. User parts
under 512 bytes are copied unchanged.

34 hours ago[mod_rtmp] Guard FU-A and short frames in rtmp_rtp2rtmpH264 (#3109)
Dmitry Verenitsin [Sat, 8 Aug 2026 17:28:34 +0000 (22:28 +0500)] 
[mod_rtmp] Guard FU-A and short frames in rtmp_rtp2rtmpH264 (#3109)

The FU-A (type 28) handler read the 2-byte FU header and copied
`datalen - 2` bytes into `fua_buf` without confirming the frame held
those header bytes. On a 1-byte frame `datalen - 2` wraps to a huge
unsigned length passed to `switch_buffer_write`, and `q[1]` is read
past the payload. Reject FU-A frames shorter than 2 bytes.

Also guard the function entry: bail when `datalen < 1` before reading
`payload[0]` for the NAL type, so a zero-length frame does not read
past the payload.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 17:06:17 +0000 (22:06 +0500)] 
Merge commit from fork

`get_display_name_from_contact()` copied the SIP Contact display-name
into the caller's fixed 512-byte `remote_display_buf` with an unbounded
`strcpy`, so a stored dialog row with an over-long Contact could
overflow the stack buffer when a `dialog`-package SUBSCRIBE runs the
probe.

Thread the destination size into the helper and copy with
`switch_copy_string()`. Guard the helper against a zero
`dst_size` and a `NULL` or empty input, and always null-terminate the
destination.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 17:04:15 +0000 (22:04 +0500)] 
Merge commit from fork

In rtmp_rtp2rtmpH264 the STAP-A (type 24) aggregation loop read a
2-byte NALU length prefix at the end of the payload without ensuring
both bytes were in bounds, and copied each NALU without checking its
declared size against the remaining aggregation payload. Stop the loop
one byte earlier so the length prefix is always present, and skip any
NALU whose size exceeds the bytes left.

When building the AVC sequence header, validate the SPS and PPS sizes
before writing: require at least the 4 SPS profile bytes copied into
the header, and confirm the fixed framing plus both payloads fit `buf`
before emitting. Oversized SPS/PPS are logged and skipped instead of
overrunning the stack buffer.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 17:01:20 +0000 (22:01 +0500)] 
Merge commit from fork

`rtmp_rtmp2rtpH264()` parses two kinds of inbound H.264 RTMP video messages: an
AVC configuration record (`0x17/0x00`) that captures SPS/PPS, and NAL-unit
messages (`0x17`/`0x27` with `0x01`). Both paths trusted wire-supplied sizes and
counts without checking them against the bytes actually present, leading to
out-of-bounds reads.

NAL-unit walk:

- The length-prefix walk advanced the cursor and decremented the unsigned
  remaining-byte counter by the wire NAL size with no check that the size fit.
  A NAL size larger than the remaining payload underflowed the counter to near
  `UINT32_MAX`, kept the loop running, and read the next size prefix from a
  cursor already past the end of the buffer. The initializer
  `pdata_len = len - 5` underflowed the same way for a message shorter than the
  5-byte AVC header.
- Reject `len < 5`, change the loop guard to `pdata_len > lenSize` so each
  size-prefix read stays in bounds, and reject any NAL whose declared size
  exceeds the bytes remaining after its prefix.

AVC configuration record:

- The fixed header fields (`configurationVersion`, `lengthSizeMinusOne`,
  `numOfSequenceParameterSets`) plus each 2-byte SPS/PPS length prefix and the
  PPS count byte were read with no minimum-length check. The existing per-entry
  checks bounded only the SPS/PPS body copies and ran after the length reads.
- Reject `len < 11` before the fixed header, and add a remaining-bytes check
  before each `ntohs` length read and before the PPS count byte.

Both changes are correctness-only: well-formed records and NAL streams hit none
of the new guards. Malformed or truncated input is rejected with the existing
"corrupted data" diagnostic.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 16:55:22 +0000 (21:55 +0500)] 
Merge commit from fork

`rtmp_handle_control()` formats the control-message body into a fixed
200-byte stack buffer with an unbounded `sprintf` loop whose iteration
count is the wire message length. A body of ~70 bytes or more runs the
write off the end of `buf`, corrupting the stack frame; the length is
taken straight from the chunk header and reaches this path before any
login, so a remote peer can trigger it.

Bound the loop with `snprintf` against the remaining space and stop when
the buffer is full. This also caps the iteration count, so the loop can
no longer read `state->buf` past what was reassembled. The hex dump is
debug-only output, so capping it changes nothing operational.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 16:54:01 +0000 (21:54 +0500)] 
Merge commit from fork

In `msrp_parse_buffer()`, the `range_star` arm of `MSRP_ST_WAIT_BODY`
computed the body length by subtracting the delimiter length and trailing
framing from the received segment length. `payload_bytes` is a
`switch_size_t`, so a short segment wrapped it to near `SIZE_MAX`, which
`switch_msrp_msg_set_payload()` uses to size its allocation and as the
`memcpy` length. This affects both `len - dlen - 5`, whose scan pointer
also addressed memory before `buf`, and `delim_pos - buf - 2`, covered
only by a `switch_assert()` on received data.

Require room for the trailing end-line and the CRLF closing the body
before either is computed; a short segment is incomplete, so the parser
waits for more bytes.

35 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 16:47:47 +0000 (21:47 +0500)] 
Merge commit from fork

`switch_core_media_add_crypto()` parses the SDP `a=crypto` keysalt and
decodes it into a fixed-size key buffer. Enforce the buffer contract at
the call site:

- Reject a zero-length, negative, or over-long keysalt (the length
  check now has both a lower bound and an upper bound against the copy
  buffer).
- Copy the keysalt token into a NUL-terminated buffer and decode from
  that, so `switch_b64_decode` stops at the token instead of reading on
  into the following key material (it consumes input to the NUL and
  skips non-base64 bytes).
- Pass the destination buffer size as the decode bound rather than the
  parsed token length.
- Require the decoded length to cover the crypto suite's key+salt so the
  subsequent copy cannot read past the decoded bytes.

Add `test_add_crypto_keysalt_bounds`, a table-driven test covering the
accepted and rejected keysalt shapes across suites (AES-128/192/256),
including RFC 4568 lifetime/MKI and multi-key lines.

35 hours ago[unit-tests] Bind the DTLS certificate test on the configured RTP port (#3108)
Dmitry Verenitsin [Sat, 8 Aug 2026 16:46:34 +0000 (21:46 +0500)] 
[unit-tests] Bind the DTLS certificate test on the configured RTP port (#3108)

36 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:29:25 +0000 (20:29 +0500)] 
Merge commit from fork

The RTCP NACK feedback handler used the packet's header length field as the
loop bound instead of the byte count the caller already validated. An
oversized length ran the loop past the fixed-size RTCP buffer, an
out-of-bounds access.

Clamp the entry count to the feedback words that fit in the received packet.

Add an end-to-end test feeding an oversized-length NACK through the RTCP
reader.

36 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:27:47 +0000 (20:27 +0500)] 
Merge commit from fork

The 127-length extended payload field was decoded with `ntohl()`, a
32-bit byte swap, dropping the upper word of the 64-bit length. Combined
with the signed `issize_t plen`, a high low-word truncated to a negative
length that slipped past the signed size guard and became `SIZE_MAX` in
the read loop, driving an out-of-bounds write past `wsh->buffer`.

Decode the full 64-bit length in network byte order and reject any value
that cannot fit the buffer with an unsigned comparison before narrowing
to `issize_t`, so a truncated or oversized length can no longer yield a
negative `plen` or pass the guard.

`ws_write_frame()` had the symmetric defect: it encoded the 64-bit length
field with a 32-bit `htonl()`, mis-framing any payload large enough to
use the 8-byte (127) length field. Emit the full 8 bytes there too.

Factor the byte assembly into `ws_get_be64()` / `ws_put_be64()` helpers.

36 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:25:29 +0000 (20:25 +0500)] 
Merge commit from fork

The nightmare-transfer path built its `switch_ivr_originate()` dial string by
interpolating the raw `Refer-To` URI params/headers into a
`{sip_invite_params=...}` brace block with `switch_core_sprintf()`.
`switch_ivr_originate()` splits a brace block on commas into separate channel
variables, so a comma in the remote-supplied URI params/headers was treated as a
variable separator and could set additional channel variables on the originated
leg.

Set `sip_invite_params` on the originate `ovars` event
(`nightmare_xfer_helper->vars`) instead. Values in that event are applied to the
peer channel verbatim and are never parsed for separators, so a comma stays
inside the single variable value. The composed value is unchanged
(`url_params?url_headers` when headers are present, `url_params` otherwise) and
`sofia_glue` reads `sip_invite_params` on the outbound leg as before, so a
well-formed REFER yields an identical outbound INVITE.

Drop the now-redundant `exten_with_params` helper field;
`nightmare_xfer_thread_run()` and the log use the plain
`nightmare_xfer_helper->exten` dial target directly.

36 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:22:30 +0000 (20:22 +0500)] 
Merge commit from fork

Bound the XOR unmasking loop to `wsh->rplen` (payload only) instead of
`wsh->datalen`, which also covers the header and caused up to a 14-byte
OOB write past the frame payload in `wsh->buffer` using the
client-supplied mask key.

Tighten the size guard from `>` to `>=` to reserve 1 byte for the
trailing NUL written after the payload; a frame filling `buflen` exactly
otherwise NUL-wrote 1 byte past `wsh->buffer`.

Only reachable when `enable-websocket` is set in `mod_xml_rpc.conf.xml`
(off by default).

37 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:18:50 +0000 (20:18 +0500)] 
Merge commit from fork

The positive-offset branch of `${variable:offset}` expansion advanced
`sub_val` past the cloned heap buffer without bounds-checking `offset`
against `strlen(sub_val)`. Subsequent `strlen()` and `strcat()` then
read adjacent heap memory into the output buffer.

37 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 15:14:08 +0000 (20:14 +0500)] 
Merge commit from fork

* [Core, mod_commands] Interface allowlist (#3086)

* [core] Add interface allowlist to gate module app/api registration

Adds an optional, presence-activated allowlist in switch.conf.xml that
controls which modules may register application / api / json_api /
chat-application interfaces. With no <interface-allowlist> configured
nothing is enforced; when at least one <allow> entry is present, only
listed interfaces register at load time and all others are refused (the
module still loads and switch_loadable_module_process still returns
SUCCESS -- the blocked interface is simply never exposed).

Entries match at three levels of precision:
  mod_commands            - whole module
  mod_commands.system     - any interface named "system"
  mod_commands.system.api - a specific type (app|api|json_api|chat_app)

Enforcement lives in switch_loadable_module_process() so every module, at
boot and at runtime `load`, is subject to the same policy. This gives
operators a way to disable the "system"/"spawn" shell-exec API commands
(and equivalents) system-wide.

Also adds the `interface_allowlist_dump [modules] [plain]` API, which
walks the loaded modules and prints their interfaces in the allowlist key
format so the current state can be captured and pruned offline into config.

* [mod_commands] Add tests for the interface allowlist

New test_interface_allowlist boots the core with an active
<interface-allowlist> (conf_interface_allowlist/) that permits only a
couple of mod_commands interfaces, then loads mod_commands and verifies:

- listed commands register and run (status, version) while unlisted and
  shell-exec commands are refused (system, spawn, uptime) -- refusal
  surfaces as switch_api_execute returning FALSE / command-not-found,
  with the command function never invoked;
- a "module.name.type" entry gates by type: the API "status" loads while
  the JSON API of the same name stays blocked;
- interface_allowlist_dump prints the config format in its xml, modules
  and plain variants, and reflects module capabilities (system appears in
  the dump even though it was blocked from registering).

* [config] Fix interior -- in interface-allowlist comment breaking XML parse

The explanatory comment used -- as em-dash pairs. The XML parser treats
-- inside a comment as the comment close, causing an "unclosed <!--"
error that prevents the whole freeswitch.xml from parsing (boot and
reloadxml both fail). Replace the -- pairs with ordinary punctuation.

* update .gitignore

* [core] Warn when interface-allowlist section is present but parses no entries

Co-authored-by: Chris Rienzo <chris@signalwire.com>
* Merge commit from fork

Add `switch_stun_packet_verify_integrity()`, an HMAC-SHA1
MESSAGE-INTEGRITY verifier that is const and non-mutating: it runs
over a private copy of the pristine network-order packet, so the
caller's buffer and byte order stay untouched, and walks attributes
with its own unsigned bounded helper `stun_wire_attr_bounds()`
instead of the host-order iterator macros. A trailing
MESSAGE-INTEGRITY-SHA256 or FINGERPRINT after MESSAGE-INTEGRITY is
tolerated; any other trailing attribute is rejected.

Gate it in `handle_ice()` behind `ice->verify_integrity`: verify
before any ICE state is touched, keyed by message type (local
`ice->pass` for a request, remote `ice->rpass` for a response or
error response), and drop on failure. Keepalive indications carry no
MESSAGE-INTEGRITY and are ignored.

`ice->verify_integrity` is read from the `ice_verify_message_integrity`
channel variable in `switch_rtp_activate_ice()` and defaults off, so
receive-path behavior is unchanged unless it is enabled. Adds unit
tests in `tests/unit/switch_stun.c`.

* Merge commit from fork

* [core] Verify DTLS client cert against SDP fingerprint (server role)

Add opt-in verification of the client certificate when FreeSWITCH is
the DTLS server, mirroring the binding the client role already performs
on the server certificate: match the peer certificate against the SDP
`a=fingerprint` in `dtls_state_setup()`.

Selected per call by the `rtp_dtls_client_cert_verify_mode` channel
variable (`dtls_client_cert_verify_t`). An unset variable keeps the
default `DTLS_CLIENT_CERT_VERIFY_NONE`, so existing behavior is
unchanged:

- `none`: the server does not request a client certificate.
- `fingerprint`: request it (`SSL_VERIFY_PEER` + `dtls_accept_any_cert`)
  and require its fingerprint to match the SDP value; a self-signed
  certificate is accepted at the TLS layer and the match provides
  authenticity.
- `full`: additionally let OpenSSL enforce the certificate chain.

An unrecognized mode string falls back to `fingerprint` (fail closed)
with a warning.

The mode is set per `SSL` object in `switch_rtp_add_dtls()`. Verification
fails (`DS_FAIL`, no SRTP keys derived) when the client presents no
certificate, its fingerprint does not match, or the peer advertised no
usable `a=fingerprint`: `get_evp_by_name()` returns `NULL` for a missing
or empty hash type and `switch_core_cert_extract_fingerprint()` rejects a
`NULL` algorithm rather than passing it to `X509_digest()`.

`conf/vanilla/vars.xml` documents the knob as a disabled example. Tests
in `tests/unit/switch_rtp.c` cover matching, mismatched, absent-cert,
absent-fingerprint, `none`, and unrecognized-mode cases.

---------

Co-authored-by: Andrey Volk <andywolk@gmail.com>
Co-authored-by: Chris Rienzo <chris@signalwire.com>
37 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 14:48:05 +0000 (19:48 +0500)] 
Merge commit from fork

`read_packet()` passed a peer-supplied `Content-Length` straight to
`switch_zmalloc(body, clen + 1)`. Huge values drove `calloc` failure
and `switch_zmalloc` `abort()`-ed the daemon.

- Cap `Content-Length` at 16 MiB; reject negatives.
- Destroy the partially-built `*event` at the new rejection site and
at the existing body-recv failure path so callers don't leak it.
- Add `test_mod_event_socket` covering `INT_MAX`, above-cap,
negative, `atoi`-overflow, zero, and valid-non-zero-body cases.

38 hours agoMerge commit from fork
Jakub Karolczyk [Sat, 8 Aug 2026 14:10:31 +0000 (15:10 +0100)] 
Merge commit from fork

* [core] Add protection for RTP inject DoS

* [core] Wipe malicious packet out

* [core] Introduce rtp_auto_adjustment_wait_for_advertised_ms chanvar to keep the auto-adjustment window opened for X ms or until packet from the source IP advertised in the SDP is received

* [core] Perform auto adjustment logic before bytes can be zeroed by flush

* [core] Add DDoS protection for auto-adjustment window with configurable threshold of packets per ptime from non-advertised source to be rejected. Should be carefully used in bursty environments. Disabled by default.

* [core] Track auto-adjust packets-per-ptime per source IP; wipe and yield CPU on rate-reject of flooding sources

* [core] Harden RTP per-source rate-reject: O(1) LRU eviction, dynamic age window, timer-independent ptime, size guards

38 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 14:07:32 +0000 (19:07 +0500)] 
Merge commit from fork

38 hours agoMerge commit from fork
Dmitry Verenitsin [Sat, 8 Aug 2026 14:03:47 +0000 (19:03 +0500)] 
Merge commit from fork

Add `switch_stun_packet_verify_integrity()`, an HMAC-SHA1
MESSAGE-INTEGRITY verifier that is const and non-mutating: it runs
over a private copy of the pristine network-order packet, so the
caller's buffer and byte order stay untouched, and walks attributes
with its own unsigned bounded helper `stun_wire_attr_bounds()`
instead of the host-order iterator macros. A trailing
MESSAGE-INTEGRITY-SHA256 or FINGERPRINT after MESSAGE-INTEGRITY is
tolerated; any other trailing attribute is rejected.

Gate it in `handle_ice()` behind `ice->verify_integrity`: verify
before any ICE state is touched, keyed by message type (local
`ice->pass` for a request, remote `ice->rpass` for a response or
error response), and drop on failure. Keepalive indications carry no
MESSAGE-INTEGRITY and are ignored.

`ice->verify_integrity` is read from the `ice_verify_message_integrity`
channel variable in `switch_rtp_activate_ice()` and defaults off, so
receive-path behavior is unchanged unless it is enabled. Adds unit
tests in `tests/unit/switch_stun.c`.

4 days ago[Core, mod_commands] Interface allowlist (#3086)
Andrey Volk [Wed, 5 Aug 2026 15:44:33 +0000 (18:44 +0300)] 
[Core, mod_commands] Interface allowlist (#3086)

* [core] Add interface allowlist to gate module app/api registration

Adds an optional, presence-activated allowlist in switch.conf.xml that
controls which modules may register application / api / json_api /
chat-application interfaces. With no <interface-allowlist> configured
nothing is enforced; when at least one <allow> entry is present, only
listed interfaces register at load time and all others are refused (the
module still loads and switch_loadable_module_process still returns
SUCCESS -- the blocked interface is simply never exposed).

Entries match at three levels of precision:
  mod_commands            - whole module
  mod_commands.system     - any interface named "system"
  mod_commands.system.api - a specific type (app|api|json_api|chat_app)

Enforcement lives in switch_loadable_module_process() so every module, at
boot and at runtime `load`, is subject to the same policy. This gives
operators a way to disable the "system"/"spawn" shell-exec API commands
(and equivalents) system-wide.

Also adds the `interface_allowlist_dump [modules] [plain]` API, which
walks the loaded modules and prints their interfaces in the allowlist key
format so the current state can be captured and pruned offline into config.

* [mod_commands] Add tests for the interface allowlist

New test_interface_allowlist boots the core with an active
<interface-allowlist> (conf_interface_allowlist/) that permits only a
couple of mod_commands interfaces, then loads mod_commands and verifies:

- listed commands register and run (status, version) while unlisted and
  shell-exec commands are refused (system, spawn, uptime) -- refusal
  surfaces as switch_api_execute returning FALSE / command-not-found,
  with the command function never invoked;
- a "module.name.type" entry gates by type: the API "status" loads while
  the JSON API of the same name stays blocked;
- interface_allowlist_dump prints the config format in its xml, modules
  and plain variants, and reflects module capabilities (system appears in
  the dump even though it was blocked from registering).

* [config] Fix interior -- in interface-allowlist comment breaking XML parse

The explanatory comment used -- as em-dash pairs. The XML parser treats
-- inside a comment as the comment close, causing an "unclosed <!--"
error that prevents the whole freeswitch.xml from parsing (boot and
reloadxml both fail). Replace the -- pairs with ordinary punctuation.

* update .gitignore

* [core] Warn when interface-allowlist section is present but parses no entries

Co-authored-by: Chris Rienzo <chris@signalwire.com>
5 days agoBump sofia-sip library requirement to version 1.13.18 (#3093)
Andrey Volk [Tue, 4 Aug 2026 12:50:24 +0000 (15:50 +0300)] 
Bump sofia-sip library requirement to version 1.13.18 (#3093)

7 days ago[SpanDSP] Update to v3.1.1 and fix build on Windows. (#3090)
Andrey Volk [Sun, 2 Aug 2026 17:33:59 +0000 (20:33 +0300)] 
[SpanDSP] Update to v3.1.1 and fix build on Windows. (#3090)

3 weeks ago[mod_lua] Fix build on MacOS (#3087)
Andrey Volk [Fri, 17 Jul 2026 20:41:38 +0000 (23:41 +0300)] 
[mod_lua] Fix build on MacOS (#3087)

3 weeks ago[Build-System] Update gawk to 3.1.8 on Windows. (#3085)
Andrey Volk [Thu, 16 Jul 2026 17:47:25 +0000 (20:47 +0300)] 
[Build-System] Update gawk to 3.1.8 on Windows. (#3085)

3 weeks ago[Build-System] Update SQLite to 3.53.3 on Windows. (#3084)
Andrey Volk [Thu, 16 Jul 2026 17:21:00 +0000 (20:21 +0300)] 
[Build-System] Update SQLite to 3.53.3 on Windows. (#3084)

3 weeks ago[Build-System] Wix: Show progress when signing modules on Windows.
Andrey Volk [Tue, 14 Jul 2026 14:19:05 +0000 (17:19 +0300)] 
[Build-System] Wix: Show progress when signing modules on Windows.

4 weeks ago[libvpx] Windows: Use NASM instead of Yasm
Andrey Volk [Fri, 10 Jul 2026 18:05:00 +0000 (21:05 +0300)] 
[libvpx] Windows: Use NASM instead of Yasm

4 weeks agoMerge pull request #3073 from signalwire/vpx1120
Andrey Volk [Fri, 10 Jul 2026 17:13:24 +0000 (20:13 +0300)] 
Merge pull request #3073 from signalwire/vpx1120

[libvpx] Update to v1.12.0

4 weeks ago[Core] Introduce switch_image.c 3073/head
Andrey Volk [Wed, 10 Aug 2022 22:13:05 +0000 (01:13 +0300)] 
[Core] Introduce switch_image.c

4 weeks ago[libvpx] add yield to vpx
Andrey Volk [Wed, 10 Aug 2022 22:21:04 +0000 (01:21 +0300)] 
[libvpx] add yield to vpx

4 weeks ago[libvpx] Fix threading.
Andrey Volk [Wed, 10 Aug 2022 22:19:09 +0000 (01:19 +0300)] 
[libvpx] Fix threading.

4 weeks ago[libvpx] Fix dead nested assignments
Andrey Volk [Wed, 10 Aug 2022 22:24:03 +0000 (01:24 +0300)] 
[libvpx] Fix dead nested assignments

4 weeks ago[libvpx] scan-build: avoid dereference of null pointer
Andrey Volk [Wed, 12 Jan 2022 17:07:20 +0000 (20:07 +0300)] 
[libvpx] scan-build: avoid dereference of null pointer

4 weeks ago[libvpx] scan-build: prevent division by zero in vpx_int_pro_row_c()
Andrey Volk [Wed, 5 Jan 2022 15:35:06 +0000 (18:35 +0300)] 
[libvpx] scan-build: prevent division by zero in vpx_int_pro_row_c()

4 weeks ago[libvpx] scan-build: Assigned value is garbage or undefined
Andrey Volk [Fri, 23 Apr 2021 11:46:06 +0000 (14:46 +0300)] 
[libvpx] scan-build: Assigned value is garbage or undefined

4 weeks ago[libvpx] scan-build: fix false-positive dereference of null pointer
Andrey Volk [Fri, 23 Apr 2021 12:00:21 +0000 (15:00 +0300)] 
[libvpx] scan-build: fix false-positive dereference of null pointer

4 weeks ago[libvpx] scan-build: Fix "Result of operation is garbage or undefined" in vp9/encoder...
Andrey Volk [Fri, 21 Feb 2020 17:10:05 +0000 (21:10 +0400)] 
[libvpx] scan-build: Fix "Result of operation is garbage or undefined" in vp9/encoder/vp9_rd.c

4 weeks ago[libvpx] scan-build: Fix "Assigned value is garbage or undefined" in vpx_post_proc_do...
Andrey Volk [Thu, 20 Feb 2020 19:10:02 +0000 (23:10 +0400)] 
[libvpx] scan-build: Fix "Assigned value is garbage or undefined" in vpx_post_proc_down_and_across_mb_row_c()

4 weeks ago[libvpx] scan-build: Division by zero - measure_square_diff_partial()
Dragos Oancea [Thu, 20 Feb 2020 10:09:21 +0000 (10:09 +0000)] 
[libvpx] scan-build: Division by zero - measure_square_diff_partial()

4 weeks ago[libvpx] scan-build: Fix "Dereference of null pointer" in vp8_peek_si_internal
Andrey Volk [Sun, 16 Feb 2020 10:31:13 +0000 (14:31 +0400)] 
[libvpx] scan-build: Fix "Dereference of null pointer" in vp8_peek_si_internal

4 weeks ago[libvpx] Fix pthread configure checks: "Null pointer passed as an argument to a ...
Andrey Volk [Wed, 12 Feb 2020 17:44:29 +0000 (21:44 +0400)] 
[libvpx] Fix pthread configure checks: "Null pointer passed as an argument to a 'nonnull' parameter"

4 weeks ago[libvpx] Update to v1.12.0
Andrey Volk [Wed, 10 Aug 2022 20:10:49 +0000 (23:10 +0300)] 
[libvpx] Update to v1.12.0

4 weeks ago[GHA] Fix macos workflow
Andrey Volk [Fri, 10 Jul 2026 16:38:13 +0000 (19:38 +0300)] 
[GHA] Fix macos workflow

5 weeks ago[mod_v8_skel] Use libnode instead of libv8 on Windows. vpx
Andrey Volk [Sat, 4 Jul 2026 10:23:34 +0000 (13:23 +0300)] 
[mod_v8_skel] Use libnode instead of libv8 on Windows.

5 weeks ago[Build-System] Windows: Download 7z, icsharpcode/SharpZipLib from GitHub instead...
Andrey Volk [Fri, 3 Jul 2026 19:45:13 +0000 (22:45 +0300)] 
[Build-System] Windows: Download 7z, icsharpcode/SharpZipLib from GitHub instead of files.freeswitch.org during the build.

5 weeks ago[mod_av] Use pre-compiled FFmpeg 7.1.5 binary on Windows
Andrey Volk [Fri, 3 Jul 2026 18:57:07 +0000 (21:57 +0300)] 
[mod_av] Use pre-compiled FFmpeg 7.1.5 binary on Windows

5 weeks ago[Build-system] Migrate music/sounds from files.freeswitch.org to https://github.com...
Andrey Volk [Tue, 30 Jun 2026 20:33:14 +0000 (23:33 +0300)] 
[Build-system] Migrate music/sounds from files.freeswitch.org to https://github.com/freeswitch/freeswitch-sounds/releases (#3062)

6 weeks ago[mod_codec2] Use pre-compiled libcodec2 package on Windows. (#3058)
Andrey Volk [Tue, 23 Jun 2026 20:25:55 +0000 (23:25 +0300)] 
[mod_codec2] Use pre-compiled libcodec2 package on Windows. (#3058)

8 weeks ago[mod_sofia] Fix broken sip: prefix check in deflect handler (#3057)
Andrey Volk [Fri, 12 Jun 2026 16:31:01 +0000 (19:31 +0300)] 
[mod_sofia] Fix broken sip: prefix check in deflect handler (#3057)

8 weeks ago[mod_amqp] prevent segfault on double connection close
Ahron Greenberg (agree) [Fri, 12 Jun 2026 14:53:40 +0000 (10:53 -0400)] 
[mod_amqp] prevent segfault on double connection close

When a command response publish failed, `mod_amqp_command_response` closed
the connection and cleared conn_active. The command thread teardown then
called mod_amqp_connection_close(NULL), causing a segfault.

Also fix amqp_error_string2() calls to pass status codes without erroneous negation.

8 weeks ago[Core] switch_sockaddr_info_get() will not resolve if the hostname is an IP address...
Andrey Volk [Fri, 12 Jun 2026 13:13:47 +0000 (16:13 +0300)] 
[Core] switch_sockaddr_info_get() will not resolve if the hostname is an IP address. Add new switch_is_ip_address() API. Add a unit-test. (#3055)

8 weeks ago[mod_v8] Use pre-compiled libnode 20.19.2 binary instead of custom v8-6.1 lib on...
Andrey Volk [Thu, 11 Jun 2026 00:00:34 +0000 (03:00 +0300)] 
[mod_v8] Use pre-compiled libnode 20.19.2 binary instead of custom v8-6.1 lib on Windows. (#3053)

8 weeks ago[mod_v8] Use upstream libnode-dev instead of custom libv8-6.1-dev on Linux. Enable...
Andrey Volk [Wed, 10 Jun 2026 22:38:53 +0000 (01:38 +0300)] 
[mod_v8] Use upstream libnode-dev instead of custom libv8-6.1-dev on Linux. Enable for ARM64 and armhf. (#3052)

2 months ago[mod_lua] Move SWIG wrapper patches into ".i" typemaps, drop hack.diff (#3043)
Dmitry Verenitsin [Wed, 27 May 2026 22:34:53 +0000 (03:34 +0500)] 
[mod_lua] Move SWIG wrapper patches into ".i" typemaps, drop hack.diff (#3043)

A swig 4.1 regeneration dropped several hand-patched wrapper edits.
Express them (and the rest) as SWIG typemaps in `freeswitch.i` so they
survive reswig. `make reswig` now produces the final wrapper directly;
`hack.diff` and its `patch` step are removed.

Restored regressions:
- `setLUA(L)` on returned `Session`: a hangup hook or input callback on
a script-created `freeswitch.Session()` no longer crashes the process
- binary-safe `Stream::read` (`lua_pushlstring`)

Also moved to typemaps:
- `Dbh`/`JSON` self-pointer guards (`%typemap(check)`), now covering
every wrapper including four the hand-patch missed
- type-table isolation (`#define SWIG_TYPE_TABLE mod_lua`)

2 months ago[GHA] Add source tarball generation workflow (#3019)
Serhii Ivanov [Wed, 27 May 2026 09:01:12 +0000 (11:01 +0200)] 
[GHA] Add source tarball generation workflow (#3019)

* [GHA] Add source tarball generation workflow

* [GHA] Add manual dispatch with ref input and artifact upload to tarball workflow

2 months agoversion bump
Andrey Volk [Tue, 26 May 2026 23:06:10 +0000 (02:06 +0300)] 
version bump

2 months agoswigall (#3039)
Andrey Volk [Tue, 26 May 2026 20:37:13 +0000 (23:37 +0300)] 
swigall (#3039)

2 months ago[libesl] Fix build of tests (#3038)
Dmitry Verenitsin [Tue, 26 May 2026 20:11:19 +0000 (01:11 +0500)] 
[libesl] Fix build of tests (#3038)

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:28:23 +0000 (00:28 +0500)] 
Merge commit from fork

* [libesl] Validate `Content-Length` in `esl_recv_event`.

`atol()` accepted negative values, allowing a remote ESL peer to cause
a one-byte heap underwrite (`Content-Length: -1`) or NULL-pointer
dereference (`Content-Length: -2`, since `esl_assert` compiles out
under `NDEBUG`). Reject negative and oversized values, and check
`malloc` failure instead of relying on `assert`.

Cap at `ESL_MAX_CONTENT_LENGTH` (16 MiB).

* [libesl] Add test_recv_event.

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:27:05 +0000 (00:27 +0500)] 
Merge commit from fork

Lower `CJSON_NESTING_LIMIT` from upstream default 1000 to 64 via
`SWITCH_AM_CFLAGS` / `SWITCH_AM_CXXFLAGS`. The mutually recursive
`parse_value`/`parse_array`/`parse_object` chain in cJSON consumes
~2 stack frames per nesting level, which can overflow worker
threads running on `SWITCH_THREAD_STACKSIZE` (240 KB).

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:26:29 +0000 (00:26 +0500)] 
Merge commit from fork

In `check_auth()` the userauth branch committed request `userVariables`,
`JPFLAG_RESUME_CALL`, identity fields, `<user><params>`/`<variables>`,
`dialplan`, and `context` to `jsock` *before* the password compare. On
mismatch only `jsock->uid` was reverted; the rest persisted on the
socket and leaked into outbound/inbound INVITE setup and `jsapi`/event
publishes.

Restructure so the gate runs first: pre-scan `<user><params>` into
locals, compare, and on mismatch return FALSE with no `jsock` writes.
Identity/vars commits and `<user><params>`/`<variables>` persistence
move past the gate. Blind-reg short-circuit and
`req_params`/`x_user` ownership preserved on every exit; success-path
writes are bit-for-bit equivalent.

Side cleanups:
- "Login sucessful" → "Login successful" typo;
- success log WARNING → NOTICE;
- the spurious WARNING "Login sucessful" no longer fires on bad-password
attempts that located the user in the directory;

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:24:48 +0000 (00:24 +0500)] 
Merge commit from fork

`process_jrpc()` called `set_session_id()` before `check_auth()`, so an
unauthenticated client could insert its jsock into `jsock_hash` under a
foreign `sessid` and have `attach_jsock()` evict the prior owner
(`verto.punt` + `detach_calls()` + `drop=1`) with no identity check.

Move the bind past the auth gate; `JPFLAG_INIT` now means "jsock is
bound", not "first frame seen". Additionally, `attach_jsock()` refuses
the bind when prior and new jsock are authed under different `uid`s,
replying `CODE_AUTH_FAILED` "Session in use". Same-uid reconnect and
no-auth profile binds are unchanged.

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:23:35 +0000 (00:23 +0500)] 
Merge commit from fork

Unchecked `atoi()` on declared payload size let a client
request up to `INT_MAX`, forcing the server to write ~20 GB
per request via the download phase. Short `#` frames also
triggered OOB reads on `s[1..3]`.

- Gate `#` branch on `JPFLAG_AUTHED`.
- Cap declared size at 10 MiB (`VERTO_SPEED_TEST_MAX_SIZE`).
- Replace `atoi()` with bounded `strtol()`.
- Require `bytes >= 4` before indexing `s[1..3]`.

2 months agoMerge commit from fork
Dmitry Verenitsin [Tue, 26 May 2026 19:02:42 +0000 (00:02 +0500)] 
Merge commit from fork

Cap `Content-Length` at `HTTP_POST_MAX_BODY` (10 MiB) and size the
allocation to the actual body length (`content_length + 1` for
the trailing NUL).

Also fix `WS_BLOCK` units — `kws_raw_read` takes ms, set to 10000.

2 months ago[GHA] Update ffmpeg and libpq in macos.yml
MarioG-X [Tue, 26 May 2026 16:29:55 +0000 (09:29 -0700)] 
[GHA] Update ffmpeg and libpq in macos.yml

ffmpeg@5 changed to ffmpeg@7
Note: tested ffmpeg@8 but it causes missing ft2build.h in truetype include library.

libpq@16 changed to libpq@18

Co-authored-by: Andrey Volk <andywolk@gmail.com>
2 months ago[core] Use switch_stun_ipv6_t for STUN IPv6 write paths. (#3037)
Dmitry Verenitsin [Tue, 26 May 2026 15:11:11 +0000 (20:11 +0500)] 
[core] Use switch_stun_ipv6_t for STUN IPv6 write paths. (#3037)

Route IPv6 writes in `switch_stun_packet_attribute_add_binded_address`
and `switch_stun_packet_attribute_add_xor_binded_address` through
`switch_stun_ipv6_t` (16-byte `address[]`) instead of `switch_stun_ip_t`
(4-byte `uint32_t address`).

Add IPv4/IPv6 unit tests for both encoders.

Co-authored-by: Andrey Volk <andywolk@gmail.com>
2 months ago[mod_sofia] Add SIP 603+ detection and passthrough control. Add unit-tests. (#3035)
Dmitry Verenitsin [Tue, 26 May 2026 14:33:23 +0000 (19:33 +0500)] 
[mod_sofia] Add SIP 603+ detection and passthrough control. Add unit-tests. (#3035)

Implement SIP 603+ (ATIS-1000099) support for FCC analytics-based call blocking compliance.

Detection:
- Detect incoming 603+ responses by checking "Network Blocked" phrase
and "v=analytics1;" in the `Reason` header text
- Set `sip_603plus_reason` channel variable on both legs for CDR visibility

Passthrough control:
- `sip_603plus_passthrough=true`: forward 603+ phrase and Reason header
- `sip_603plus_passthrough=false`: strip `Reason` header, send clean `603 Decline`
- Not set: existing behavior preserved
- Works independently of `disable_q850_reason` for selective forwarding

2 months ago[mod_sofia] capture SIP reason header on INVITE failure (#3036)
Dmitry Verenitsin [Tue, 26 May 2026 13:42:52 +0000 (18:42 +0500)] 
[mod_sofia] capture SIP reason header on INVITE failure (#3036)

Co-authored-by: Chris Rienzo <chris@signalwire.com>
2 months ago[mod_sofia] Reload certificates on the fly without disconnects using reloadcert API...
Andrey Volk [Mon, 25 May 2026 22:12:37 +0000 (01:12 +0300)] 
[mod_sofia] Reload certificates on the fly without disconnects using reloadcert API. (#3034)

2 months ago[mod_commands, mod_verto] Add new reloadcert API and let mod_verto reload certificate...
Andrey Volk [Mon, 25 May 2026 21:25:56 +0000 (00:25 +0300)] 
[mod_commands, mod_verto] Add new reloadcert API and let mod_verto reload certificates on the fly without disconnects. (#3033)

2 months ago[core] Fix segments count check in clean_uri(). Add unit-test. (#3032)
Dmitry Verenitsin [Mon, 25 May 2026 21:16:40 +0000 (02:16 +0500)] 
[core] Fix segments count check in clean_uri(). Add unit-test. (#3032)

2 months ago[mod_sofia] Fix use-after-free in dispatch event thread. (#3031)
Dmitry Verenitsin [Mon, 25 May 2026 21:15:19 +0000 (02:15 +0500)] 
[mod_sofia] Fix use-after-free in dispatch event thread. (#3031)

`sofia_process_dispatch_event_in_thread` allocated `td` from a memory pool,
then `sofia_msg_thread_run_once` destroyed that same pool after processing
the event — leaving `td` dangling when the thread pool worker accessed it.

Allocate `td` with `switch_zmalloc` (`td->alloc = 1`) so the worker frees it
safely after the function returns. Remove the now-unused `pool` field from
`sofia_dispatch_event_t`.

2 months ago[core] Fix use-after-free in session thread pool worker. (#3030)
Dmitry Verenitsin [Mon, 25 May 2026 21:13:29 +0000 (02:13 +0500)] 
[core] Fix use-after-free in session thread pool worker. (#3030)

`switch_core_session_thread_pool_launch()` allocated the thread data (`td`)
from the session pool. However, `switch_core_session_thread()` destroys
the session pool before returning, leaving td as a dangling pointer.
The worker then accesses `td->running` and `td->pool` — a use-after-free
that crashes under memory pressure when the freed pool is reused.

Allocate `td` with `switch_zmalloc()` and set `td->alloc = 1` so the worker frees it
after the task completes. This ensures `td` outlives the session pool
destruction.

2 months ago[mod_erlang_event] Fix correctness, OTP compatibility, and memory issues
Dmitry Verenitsin [Mon, 25 May 2026 21:12:08 +0000 (02:12 +0500)] 
[mod_erlang_event] Fix correctness, OTP compatibility, and memory issues

Changes:
- Snapshot `erl_errno` after `ei_xreceive_msg_tmo()` — outbound `ei_*` calls in the same loop iteration clobber the thread-local errno before the listener checks it, causing wrong exit decisions and misleading logs.
- Fix `switch_size_t ` cast of `int` in `ei_link`* — `(switch_size_t *)&index` reads/writes 8 bytes through a 4-byte `int` on LP64. Use a real `switch_size_t` local.
- Dispatch `ERL_NEWER_REFERENCE_EXT` — newer OTP encodes refs with this tag; spawn replies from modern nodes were silently dropped to the default branch.
- Handle `ERL_EXIT2` — processes killed via `erlang:exit/2` arrive with this tag, not `ERL_EXIT`. Without it, sessions stayed attached to dead Erlang pids.
- Modernize `-spec` syntax in `freeswitch.erl` — old `-spec(F/N :: (...))` form was removed in OTP 21+; module no longer compiled.
- Fix multiple memory issues:
  - `ei_hash_ref()`: replace unbounded `sprintf` with `snprintf` + shared `EI_HASH_REF_LEN`.
  - `handle_msg_sendevent` / `handle_msg_sendmsg`: free the heap `value` on `ei_decode_string` failure; remove dead `if (!fail)` branches.
  - `listener_main_loop`: free `buf`/`rbuf` on the two `handle_msg` early-exit paths.
  - `erlang_sendmsg_function` app: move `ei_x_new_with_version` past arg validation and add `ei_x_free` at the end.

2 months ago[Core, modules] Fix various dead assignments.
Andrey Volk [Mon, 25 May 2026 20:56:13 +0000 (23:56 +0300)] 
[Core, modules] Fix various dead assignments.

2 months ago[mod_sofia] Fix handling of sip-options-respond-503-on-busy profile parameter
Gustavo Almeida [Mon, 25 May 2026 18:15:13 +0000 (19:15 +0100)] 
[mod_sofia] Fix handling of sip-options-respond-503-on-busy profile parameter

2 months ago[mod_commands] Fix reloadacl description
Niall Dooley [Mon, 25 May 2026 18:11:10 +0000 (20:11 +0200)] 
[mod_commands] Fix reloadacl description

2 months ago[Build-System] Update libks requirements to 2.0.11 (#3025)
Andrey Volk [Wed, 20 May 2026 20:18:38 +0000 (23:18 +0300)] 
[Build-System] Update libks requirements to 2.0.11 (#3025)

3 months agoversion bump bump
Andrey Volk [Thu, 7 May 2026 23:26:52 +0000 (02:26 +0300)] 
version bump

3 months ago[GHA] Use release libs for `trixie` releases (#3016)
Serhii Ivanov [Thu, 7 May 2026 21:53:07 +0000 (23:53 +0200)] 
[GHA] Use release libs for `trixie` releases (#3016)

3 months agoswigall (#3015)
Andrey Volk [Thu, 7 May 2026 18:52:56 +0000 (21:52 +0300)] 
swigall (#3015)

3 months agoMerge commit from fork
Andrey Volk [Thu, 7 May 2026 17:20:52 +0000 (20:20 +0300)] 
Merge commit from fork

3 months agoMerge commit from fork
Andrey Volk [Thu, 7 May 2026 17:18:11 +0000 (20:18 +0300)] 
Merge commit from fork

3 months agoMerge commit from fork
Andrey Volk [Thu, 7 May 2026 17:14:34 +0000 (20:14 +0300)] 
Merge commit from fork

Co-authored-by: Jakub Karolczyk <jakub.karolczyk@signalwire.com>
3 months ago[GHA] Treat v1.11 as a release branch (#2873)
Serhii Ivanov [Thu, 7 May 2026 15:19:08 +0000 (17:19 +0200)] 
[GHA] Treat v1.11 as a release branch (#2873)

* [GHA] Add `v1.11` branch target
* [GHA] Treat `v1.11` as a release branch

---------

Co-authored-by: Andrey Volk <andywolk@gmail.com>
4 months ago[Core] Fix DTLS Peer Certificate verification 1691/head
praveen-kd-23 [Thu, 2 Apr 2026 15:03:28 +0000 (20:33 +0530)] 
[Core] Fix DTLS Peer Certificate verification

5 months ago[mod_cdr_mongodb] Remove from tree (#2992)
Andrey Volk [Thu, 5 Mar 2026 22:26:20 +0000 (01:26 +0300)] 
[mod_cdr_mongodb] Remove from tree (#2992)