Commit Graph
36145 Commits
Author SHA1 Message Date
Dmitry Verenitsin d557ca6d29 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.
2026-08-08 18:27:47 +03:00
Dmitry Verenitsin fbac12b451 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.
2026-08-08 18:25:29 +03:00
Dmitry Verenitsin fb9f37b9c7 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).
2026-08-08 18:22:30 +03:00
Dmitry Verenitsin 30cdb387ae 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.
2026-08-08 18:18:50 +03:00
ea74c0acb8 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>
2026-08-08 18:14:08 +03:00
Dmitry Verenitsin a097e12421 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.
2026-08-08 17:48:05 +03:00
Jakub Karolczyk a38cd80733 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
2026-08-08 17:10:31 +03:00
Dmitry Verenitsin 587474a158 Merge commit from fork 2026-08-08 17:07:32 +03:00
Dmitry Verenitsin 68ec688eb6 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`.
2026-08-08 17:03:47 +03:00
Andrey VolkandChris Rienzo c1bb5c6ab3 [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>
2026-08-05 18:44:33 +03:00
Andrey Volk a75491a318 Bump sofia-sip library requirement to version 1.13.18 (#3093) 2026-08-04 15:50:24 +03:00
Andrey Volk 1d77a57750 [SpanDSP] Update to v3.1.1 and fix build on Windows. (#3090) 2026-08-02 20:33:59 +03:00
Andrey Volk 0a54a48f37 [mod_lua] Fix build on MacOS (#3087) 2026-07-17 23:41:38 +03:00
Andrey Volk 95fad5ce1c [Build-System] Update gawk to 3.1.8 on Windows. (#3085) 2026-07-16 20:47:25 +03:00
Andrey Volk 2cae9b9aa2 [Build-System] Update SQLite to 3.53.3 on Windows. (#3084) 2026-07-16 20:21:00 +03:00
Andrey Volk 8020f5f2e7 [Build-System] Wix: Show progress when signing modules on Windows. 2026-07-14 17:19:05 +03:00
Andrey Volk d5f9409e9d [libvpx] Windows: Use NASM instead of Yasm 2026-07-10 21:05:00 +03:00
Andrey Volk 40ccfdb051 Merge pull request #3073 from signalwire/vpx1120
[libvpx] Update to v1.12.0
2026-07-10 20:13:24 +03:00
Andrey Volk 4939e86013 [Core] Introduce switch_image.c 2026-07-10 19:38:46 +03:00
Andrey Volk e5cacd7644 [libvpx] add yield to vpx 2026-07-10 19:38:46 +03:00
Andrey Volk 97ceaf43b2 [libvpx] Fix threading. 2026-07-10 19:38:46 +03:00
Andrey Volk 5136b60544 [libvpx] Fix dead nested assignments 2026-07-10 19:38:46 +03:00
Andrey Volk eb124e409b [libvpx] scan-build: avoid dereference of null pointer 2026-07-10 19:38:46 +03:00
Andrey Volk b41f55b33a [libvpx] scan-build: prevent division by zero in vpx_int_pro_row_c() 2026-07-10 19:38:46 +03:00
Andrey Volk d0af9bf4a3 [libvpx] scan-build: Assigned value is garbage or undefined 2026-07-10 19:38:46 +03:00
Andrey Volk 9ffb37a352 [libvpx] scan-build: fix false-positive dereference of null pointer 2026-07-10 19:38:46 +03:00
Andrey Volk 2f4160e024 [libvpx] scan-build: Fix "Result of operation is garbage or undefined" in vp9/encoder/vp9_rd.c 2026-07-10 19:38:46 +03:00
Andrey Volk 6c510d60bc [libvpx] scan-build: Fix "Assigned value is garbage or undefined" in vpx_post_proc_down_and_across_mb_row_c() 2026-07-10 19:38:46 +03:00
Dragos Oancea c27534c89a [libvpx] scan-build: Division by zero - measure_square_diff_partial() 2026-07-10 19:38:46 +03:00
Andrey Volk f4c9499198 [libvpx] scan-build: Fix "Dereference of null pointer" in vp8_peek_si_internal 2026-07-10 19:38:46 +03:00
Andrey Volk 51742eed1e [libvpx] Fix pthread configure checks: "Null pointer passed as an argument to a 'nonnull' parameter" 2026-07-10 19:38:46 +03:00
Andrey Volk b5046d2a76 [libvpx] Update to v1.12.0 2026-07-10 19:38:46 +03:00
Andrey Volk 287a71dc66 [GHA] Fix macos workflow 2026-07-10 19:38:13 +03:00
Andrey Volk 2d85032cef [mod_v8_skel] Use libnode instead of libv8 on Windows. 2026-07-04 13:23:34 +03:00
Andrey Volk 0615f8f3fa [Build-System] Windows: Download 7z, icsharpcode/SharpZipLib from GitHub instead of files.freeswitch.org during the build. 2026-07-03 22:45:13 +03:00
Andrey Volk 2096190199 [mod_av] Use pre-compiled FFmpeg 7.1.5 binary on Windows 2026-07-03 21:57:07 +03:00
Andrey Volk 225a5e197e [Build-system] Migrate music/sounds from files.freeswitch.org to https://github.com/freeswitch/freeswitch-sounds/releases (#3062) 2026-06-30 23:33:14 +03:00
Andrey Volk b9c41705b7 [mod_codec2] Use pre-compiled libcodec2 package on Windows. (#3058) 2026-06-23 23:25:55 +03:00
Andrey Volk 390444bc42 [mod_sofia] Fix broken sip: prefix check in deflect handler (#3057) 2026-06-12 19:31:01 +03:00
Ahron Greenberg (agree) 174b16a3d1 [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.
2026-06-12 17:53:40 +03:00
Andrey Volk be554e4a08 [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) 2026-06-12 16:13:47 +03:00
Andrey Volk 2e9b721d43 [mod_v8] Use pre-compiled libnode 20.19.2 binary instead of custom v8-6.1 lib on Windows. (#3053) 2026-06-11 03:00:34 +03:00
Andrey Volk f31b902a0a [mod_v8] Use upstream libnode-dev instead of custom libv8-6.1-dev on Linux. Enable for ARM64 and armhf. (#3052) 2026-06-11 01:38:53 +03:00
Dmitry Verenitsin 153c3a5139 [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`)
2026-05-28 01:34:53 +03:00
Serhii Ivanov 077393376a [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
2026-05-27 12:01:12 +03:00
Andrey Volk ac60d2f6ec version bump 2026-05-27 02:06:10 +03:00
Andrey Volk 0f25e294bc swigall (#3039) 2026-05-26 23:37:13 +03:00
Dmitry Verenitsin dc5c802627 [libesl] Fix build of tests (#3038) 2026-05-26 23:11:19 +03:00
Dmitry Verenitsin 22de26cc7c 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.
2026-05-26 22:28:23 +03:00
Dmitry Verenitsin 02ac36bb11 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).
2026-05-26 22:27:05 +03:00