From 7015f6a73ab3d67fed5fbfc277ecfb88a74c2a86 Mon Sep 17 00:00:00 2001 From: Dmitry Verenitsin Date: Wed, 26 Aug 2026 18:46:56 +0500 Subject: [PATCH] [mod_sofia] Add enable-chat-api-proto to gate the api chat proto (#3135) The chat layer lets an inbound SIP MESSAGE select which chat proto handles it, and the `api` proto runs the address as a FreeSWITCH API command. The new per-profile `enable-chat-api-proto` param controls that route and is off unless set. A MESSAGE selecting the proto on a profile without it is answered 403 and logged with the source and the requested command. The proto compare is case-insensitive, matching the chat interface registry, which is created with `switch_core_hash_init_nocase()`. The param ships commented out in the four vanilla profiles and the mod_sofia sofia.conf.xml sample. --- conf/vanilla/sip_profiles/external-ipv6.xml | 2 ++ conf/vanilla/sip_profiles/external.xml | 2 ++ conf/vanilla/sip_profiles/internal-ipv6.xml | 2 ++ conf/vanilla/sip_profiles/internal.xml | 3 +++ .../endpoints/mod_sofia/conf/sofia.conf.xml | 4 ++++ src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 6 ++++++ src/mod/endpoints/mod_sofia/sofia_presence.c | 18 ++++++++++++++++++ 8 files changed, 38 insertions(+) diff --git a/conf/vanilla/sip_profiles/external-ipv6.xml b/conf/vanilla/sip_profiles/external-ipv6.xml index 1b9d0c857d..f278cd1d19 100644 --- a/conf/vanilla/sip_profiles/external-ipv6.xml +++ b/conf/vanilla/sip_profiles/external-ipv6.xml @@ -56,6 +56,8 @@ + + + + + diff --git a/conf/vanilla/sip_profiles/internal.xml b/conf/vanilla/sip_profiles/internal.xml index eb07779f43..79fcad741e 100644 --- a/conf/vanilla/sip_profiles/internal.xml +++ b/conf/vanilla/sip_profiles/internal.xml @@ -107,6 +107,9 @@ + + + + + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 3689f82a20..81d0517d78 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -311,6 +311,7 @@ typedef enum { PFLAG_AUTH_REQUIRE_USER, PFLAG_AUTH_CALLS_ACL_ONLY, PFLAG_USE_PORT_FOR_ACL_CHECK, + PFLAG_ENABLE_CHAT_API_PROTO, /* No new flags below this line */ PFLAG_MAX diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0451a4bdea..f5bc04de26 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4917,6 +4917,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_ENABLE_CHAT); } + } else if (!strcasecmp(var, "enable-chat-api-proto")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_ENABLE_CHAT_API_PROTO); + } else { + sofia_clear_pflag(profile, PFLAG_ENABLE_CHAT_API_PROTO); + } } else if (!strcasecmp(var, "fire-bye-response-events")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index d9257285a1..667886bccb 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -4879,6 +4879,24 @@ void sofia_presence_handle_sip_i_message(int status, p = strchr(proto, '+'); *p++ = '\0'; + if (!strcasecmp(proto, "api") && !sofia_test_pflag(profile, PFLAG_ENABLE_CHAT_API_PROTO)) { + /* p is the rest of the To user, still percent-encoded and bounded by the proto buffer. */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Profile [%s] rejected a MESSAGE from %s@%s (%s:%d) addressed to the 'api' chat proto [%s]. " + "Set enable-chat-api-proto=true on the profile to permit it.\n", + profile->name, switch_str_nil(from_user), switch_str_nil(from_host), network_ip, network_port, p); + + nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + + if (full_from) { + su_free(nua_handle_get_home(nh), full_from); + } + + /* Return rather than goto end: the end label answers 200/202, which would be a + second response on this transaction. */ + return; + } + if ((to_addr = strdup(p))) { if ((p = strchr(to_addr, '+'))) { *p = '@';