Compare commits

...

9 Commits

Author SHA1 Message Date
Aron Podrigal 1c28eba62f
Merge 23e89a5596 into 3b58ebc5f3 2025-01-21 00:17:28 +00:00
junction1153b 3b58ebc5f3
[mod_sofia] Update Polycom UA to recognize new Poly phones
We observed that the new Poly phones (formerly known as Polycom) were not getting sent a SIP UPDATE in certain circumstances (example: retrieving a parked call, and therefore, Caller ID would not show the parked caller). I renamed Polycom to Poly which will catch all Poly AND Polycom UA's. I also added Acrobits, and Ringotel to extend such functionality to those UA's. There were also other minor compatibility issues with the new Poly phones which have been resolved with tweaking the UA recognition on the code.

Co-authored-by: Joseph <junction1153@gmail.com>
2025-01-21 00:57:25 +03:00
Aron Podrigal 23e89a5596 Remove duplicate declaration of switch_uuid_generate_v7 2025-01-16 08:52:24 -06:00
Aron Podrigal 575e9bfcff Fix UUID generation error handling in switch_utils.c
Ensure that invalid UUID generation scenarios are correctly handled by checking the return status of `switch_uuid_generate_version`. This prevents potential incorrect formatting or uninitialized usage.
2025-01-16 08:52:24 -06:00
Aron Podrigal 323e907011 fixes 4 2025-01-16 08:52:24 -06:00
Aron Podrigal d6b17a0f15 fixes 3 2025-01-16 08:52:24 -06:00
Aron Podrigal 7c16b80e45 fixes 2 2025-01-16 08:52:24 -06:00
Aron Podrigal 338186ee5e fixes 2025-01-16 08:52:23 -06:00
Aron Podrigal fef78d728f Add support for UUID versioning and generation of UUIDv7.
This update introduces support for generating UUIDs with specific versions, including the newly implemented UUIDv7. The `create_uuid` API has been updated to accept optional version parameters. Additionally, a new utility function `switch_getentropy` was added to ensure secure random number generation.
2025-01-16 08:52:23 -06:00
9 changed files with 145 additions and 13 deletions

View File

@ -560,7 +560,12 @@ SWITCH_DECLARE(void) switch_uuid_format(char *buffer, const switch_uuid_t *uuid)
* Generate and return a (new) UUID * Generate and return a (new) UUID
* @param uuid The resulting UUID * @param uuid The resulting UUID
*/ */
SWITCH_DECLARE(void) switch_uuid_get(switch_uuid_t *uuid); #ifndef DEFAULT_UUID_VERSION
#define DEFAULT_UUID_VERSION 4
#endif
SWITCH_DECLARE(switch_status_t) switch_uuid_generate_v4(switch_uuid_t *uuid);
SWITCH_DECLARE(switch_status_t) switch_uuid_generate_version(switch_uuid_t *uuid, int version);
#define switch_uuid_get(uuid) switch_uuid_generate_version(uuid, DEFAULT_UUID_VERSION);
/** /**
* Parse a standard-format string into a UUID * Parse a standard-format string into a UUID

View File

@ -1421,7 +1421,8 @@ SWITCH_DECLARE(void *) switch_calloc(size_t nmemb, size_t size);
SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size); SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size);
#endif #endif
SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len); #define switch_uuid_str(buf, len) switch_uuid_str_version(buf, len, DEFAULT_UUID_VERSION);
SWITCH_DECLARE(char *) switch_uuid_str_version(char *buf, switch_size_t len, int version);
SWITCH_DECLARE(char *) switch_format_number(const char *num); SWITCH_DECLARE(char *) switch_format_number(const char *num);
SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr); SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr);
@ -1518,6 +1519,8 @@ SWITCH_DECLARE(const char *) switch_memory_usage_stream(switch_stream_handle_t *
/ Compliant random number generator. Returns the value between 0 and 0x7fff (RAND_MAX). / Compliant random number generator. Returns the value between 0 and 0x7fff (RAND_MAX).
**/ **/
SWITCH_DECLARE(int) switch_rand(void); SWITCH_DECLARE(int) switch_rand(void);
SWITCH_DECLARE(int) switch_getentropy(void *buffer, switch_size_t length);
SWITCH_DECLARE(switch_status_t) switch_uuid_generate_v7(switch_uuid_t *uuid);
SWITCH_END_EXTERN_C SWITCH_END_EXTERN_C
#endif #endif

View File

@ -3162,11 +3162,16 @@ SWITCH_STANDARD_API(tone_detect_session_function)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
#define UUID_GENERATE_SYNTAX "<create_uuid> [4|7]"
SWITCH_STANDARD_API(uuid_function) SWITCH_STANDARD_API(uuid_function)
{ {
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
int version = DEFAULT_UUID_VERSION;
if (!zstr(cmd)) {
version = atoi(cmd);
}
switch_uuid_str(uuid_str, sizeof(uuid_str)); switch_uuid_str_version(uuid_str, sizeof(uuid_str), version);
stream->write_function(stream, "%s", uuid_str); stream->write_function(stream, "%s", uuid_str);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -7598,7 +7603,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "cond", "Evaluate a conditional", cond_function, "<expr> ? <true val> : <false val>"); SWITCH_ADD_API(commands_api_interface, "cond", "Evaluate a conditional", cond_function, "<expr> ? <true val> : <false val>");
SWITCH_ADD_API(commands_api_interface, "console_complete", "", console_complete_function, "<line>"); SWITCH_ADD_API(commands_api_interface, "console_complete", "", console_complete_function, "<line>");
SWITCH_ADD_API(commands_api_interface, "console_complete_xml", "", console_complete_xml_function, "<line>"); SWITCH_ADD_API(commands_api_interface, "console_complete_xml", "", console_complete_xml_function, "<line>");
SWITCH_ADD_API(commands_api_interface, "create_uuid", "Create a uuid", uuid_function, UUID_SYNTAX); SWITCH_ADD_API(commands_api_interface, "create_uuid", "Create a uuid", uuid_function, UUID_GENERATE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "db_cache", "Manage db cache", db_cache_function, "status"); SWITCH_ADD_API(commands_api_interface, "db_cache", "Manage db cache", db_cache_function, "status");
SWITCH_ADD_API(commands_api_interface, "domain_data", "Find domain data", domain_data_function, "<domain> [var|param|attr] <name>"); SWITCH_ADD_API(commands_api_interface, "domain_data", "Find domain data", domain_data_function, "<domain> [var|param|attr] <name>");
SWITCH_ADD_API(commands_api_interface, "domain_exists", "Check if a domain exists", domain_exists_function, "<domain>"); SWITCH_ADD_API(commands_api_interface, "domain_exists", "Check if a domain exists", domain_exists_function, "<domain>");

View File

@ -254,7 +254,7 @@ char *generate_pai_str(private_object_t *tech_pvt)
callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number)); callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number));
callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name)); callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name));
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) { if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("poly", ua))) {
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host); callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
} }
@ -2075,13 +2075,15 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END()); TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if (update_allowed && ua && (switch_channel_var_true(tech_pvt->channel, "update_ignore_ua") || } else if (update_allowed && ua && (switch_channel_var_true(tech_pvt->channel, "update_ignore_ua") ||
switch_stristr("polycom", ua) || switch_stristr("poly", ua) ||
(switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) || (switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) || (switch_stristr("cisco/spa50", ua) ||
switch_stristr("cisco/spa525", ua)) || switch_stristr("cisco/spa525", ua)) ||
switch_stristr("cisco/spa30", ua) || switch_stristr("cisco/spa30", ua) ||
switch_stristr("Fanvil", ua) || switch_stristr("Fanvil", ua) ||
switch_stristr("Grandstream", ua) || switch_stristr("Grandstream", ua) ||
switch_stristr("Ringotel", ua) ||
switch_stristr("Groundwire", ua) ||
switch_stristr("Yealink", ua) || switch_stristr("Yealink", ua) ||
switch_stristr("Mitel", ua) || switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) { switch_stristr("Panasonic", ua))) {
@ -2152,7 +2154,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SIPTAG_PAYLOAD_STR(message), SIPTAG_PAYLOAD_STR(message),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END()); TAG_END());
} else if (ua && switch_stristr("polycom", ua)) { } else if (ua && switch_stristr("poly", ua)) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number); snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number);
nua_update(tech_pvt->nh, nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout), NUTAG_SESSION_TIMER(tech_pvt->session_timeout),

View File

@ -10476,7 +10476,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
(!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) && (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
profile->server_rport_level >= 2 && sip->sip_user_agent && profile->server_rport_level >= 2 && sip->sip_user_agent &&
sip->sip_user_agent->g_string && sip->sip_user_agent->g_string &&
(!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20))) (!strncasecmp(sip->sip_user_agent->g_string, "Poly", 4) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20)))
) { ) {
if (sip->sip_via) { if (sip->sip_via) {
const char *port = sip->sip_via->v_port; const char *port = sip->sip_via->v_port;

View File

@ -2501,7 +2501,7 @@ static char *gen_pidf(char *user_agent, char *id, char *url, char *open, char *r
{ {
char *ret = NULL; char *ret = NULL;
if (switch_stristr("polycom", user_agent)) { if (switch_stristr("poly", user_agent)) {
*ct = "application/xpidf+xml"; *ct = "application/xpidf+xml";
/* If unknown/none prpid is provided, just show the user as online. */ /* If unknown/none prpid is provided, just show the user as online. */

View File

@ -1661,7 +1661,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
if (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) && if (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
profile->server_rport_level >= 2 && sip->sip_user_agent && profile->server_rport_level >= 2 && sip->sip_user_agent &&
sip->sip_user_agent->g_string && sip->sip_user_agent->g_string &&
( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || ( !strncasecmp(sip->sip_user_agent->g_string, "Poly", 4) ||
!strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
!strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) { !strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) {
if (sip->sip_via) { if (sip->sip_via) {

View File

@ -1149,7 +1149,7 @@ SWITCH_DECLARE(void) switch_uuid_format(char *buffer, const switch_uuid_t *uuid)
#endif #endif
} }
SWITCH_DECLARE(void) switch_uuid_get(switch_uuid_t *uuid) SWITCH_DECLARE(switch_status_t) switch_uuid_generate_v4(switch_uuid_t *uuid)
{ {
switch_mutex_lock(runtime.uuid_mutex); switch_mutex_lock(runtime.uuid_mutex);
#ifndef WIN32 #ifndef WIN32
@ -1158,6 +1158,23 @@ SWITCH_DECLARE(void) switch_uuid_get(switch_uuid_t *uuid)
UuidCreate((UUID *) uuid); UuidCreate((UUID *) uuid);
#endif #endif
switch_mutex_unlock(runtime.uuid_mutex); switch_mutex_unlock(runtime.uuid_mutex);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_uuid_generate_version(switch_uuid_t *uuid, int version)
{
switch(version) {
case 4:
return switch_uuid_generate_v4(uuid);
break;
case 7:
return switch_uuid_generate_v7(uuid);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Unsupported UUID version %d\n", version);
return SWITCH_STATUS_FALSE;
}
} }
SWITCH_DECLARE(switch_status_t) switch_uuid_parse(switch_uuid_t *uuid, const char *uuid_str) SWITCH_DECLARE(switch_status_t) switch_uuid_parse(switch_uuid_t *uuid, const char *uuid_str)

View File

@ -4110,14 +4110,15 @@ SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domai
} }
SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len) SWITCH_DECLARE(char *) switch_uuid_str_version(char *buf, switch_size_t len, int version)
{ {
switch_uuid_t uuid; switch_uuid_t uuid;
if (len < (SWITCH_UUID_FORMATTED_LENGTH + 1)) { if (len < (SWITCH_UUID_FORMATTED_LENGTH + 1)) {
switch_snprintf(buf, len, "INVALID"); switch_snprintf(buf, len, "INVALID");
} else if (switch_uuid_generate_version(&uuid, version) != SWITCH_STATUS_SUCCESS) {
switch_snprintf(buf, len, "INVALID");
} else { } else {
switch_uuid_get(&uuid);
switch_uuid_format(buf, &uuid); switch_uuid_format(buf, &uuid);
} }
@ -4872,6 +4873,105 @@ SWITCH_DECLARE(int) switch_rand(void)
#endif #endif
} }
static int _switch_getentropy(void *buffer, switch_size_t length)
{
#ifdef WIN32
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
NTSTATUS status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptOpenAlgorithmProvider failed with status %d\n", status);
errno = EIO; // Input/Output error
return -1;
}
status = BCryptGenRandom(hAlgorithm, (PUCHAR)buffer, (ULONG)length, 0);
if (!BCRYPT_SUCCESS(status)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptGenRandom failed with status %d\n", status);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
errno = EIO; // Input/Output error
return -1;
}
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return 0;
#elif defined(__unix__) || defined(__APPLE__)
int random_fd = open("/dev/urandom", O_RDONLY);
switch_ssize_t result;
char error_msg[100];
if (random_fd == -1) {
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
error_msg[sizeof(error_msg) - 1] = '\0';
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open failed: %s\n", error_msg);
errno = EIO; // Input/Output error
return -1;
}
result = read(random_fd, buffer, length);
if (result < 0 || (switch_size_t)result != length) {
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
error_msg[sizeof(error_msg) - 1] = '\0';
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read failed: %s\n", error_msg);
close(random_fd);
errno = EIO; // Input/Output error
return -1;
}
close(random_fd);
return 0;
#else
// Fallback: Use rand() for platforms that do not support secure randomness
unsigned char *buf = (unsigned char *)buffer;
for (switch_size_t i = 0; i < length; i++) {
buf[i] = (unsigned char)(rand() & 0xFF); // Generate byte-wise randomness
}
return 0;
#endif
}
SWITCH_DECLARE(int) switch_getentropy(void *buffer, switch_size_t length)
{
if (!buffer || length > 256) { // Enforce same limit as `getentropy`
errno = EIO; // Input/Output error
return -1;
}
return _switch_getentropy(buffer, length);
}
SWITCH_DECLARE(switch_status_t) switch_uuid_generate_v7(switch_uuid_t *uuid) {
/* random bytes */
unsigned char *value = uuid->data;
/* current timestamp in ms */
switch_time_t timestamp = switch_time_now() / 1000;
if (switch_getentropy(value, 16) != 0) {
return -1;
}
// timestamp
value[0] = (timestamp >> 40) & 0xFF;
value[1] = (timestamp >> 32) & 0xFF;
value[2] = (timestamp >> 24) & 0xFF;
value[3] = (timestamp >> 16) & 0xFF;
value[4] = (timestamp >> 8) & 0xFF;
value[5] = timestamp & 0xFF;
// version and variant
value[6] = (value[6] & 0x0F) | 0x70;
value[8] = (value[8] & 0x3F) | 0x80;
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:
* mode:c * mode:c