mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-08-19 09:40:21 +00:00
* [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>
FreeSWITCH unit tests should be kept as shallow unit tests and micro benchmarks testing functionality exposed through libfreeswitch. Requirements for a new unit tests: 1. Tests must use switch_test.h framework