From 229eb2057e2f8fa54d44a66a13d83464a71f16a5 Mon Sep 17 00:00:00 2001 From: Alexey Vasilyev Date: Thu, 24 Jun 2021 10:27:56 +0200 Subject: [PATCH] [uac_registrant] Match reply Contact with binding_URI by parameter. Added new integer module parameter 'match_contact' to choose, what parts of URI from Contact header should match binding_URI when OpenSIPS chooses expiration time for registration. --- modules/uac_registrant/registrant.c | 5 +- parser/parse_uri.c | 86 +++++++++++++++++++++++++++++ parser/parse_uri.h | 18 ++++++ 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/modules/uac_registrant/registrant.c b/modules/uac_registrant/registrant.c index a44df4a2a96..1ecc7e89ef7 100644 --- a/modules/uac_registrant/registrant.c +++ b/modules/uac_registrant/registrant.c @@ -110,6 +110,7 @@ uac_auth_api_t uac_auth_api; unsigned int default_expires = 3600; unsigned int timer_interval = 100; +unsigned int match_contact = URI_MATCH_ALL; reg_table_t reg_htable = NULL; unsigned int reg_hsize = 1; @@ -139,6 +140,7 @@ static param_export_t params[]= { {"hash_size", INT_PARAM, ®_hsize}, {"default_expires", INT_PARAM, &default_expires}, {"timer_interval", INT_PARAM, &timer_interval}, + {"match_contact", INT_PARAM, &match_contact}, {"enable_clustering", INT_PARAM, &enable_clustering}, {"db_url", STR_PARAM, &db_url.s}, {"table_name", STR_PARAM, ®_table_name.s}, @@ -481,8 +483,7 @@ int run_reg_tm_cback(void *e_data, void *data, void *r_data) contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ - if (contact->uri.len==rec->contact_uri.len && - strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ + if (compare_uris_parts(&contact->uri, &rec->contact_uri, (enum uri_match_flags)match_contact) == 0) { if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" diff --git a/parser/parse_uri.c b/parser/parse_uri.c index 364d91c1f27..90a9023357b 100644 --- a/parser/parse_uri.c +++ b/parser/parse_uri.c @@ -1846,3 +1846,89 @@ int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a, compare_uri_val(headers,strncasecmp); return 0; } + +/* Compare 2 SIP URIs by parts according to opts + * + * Return value : 0 if URIs match + * 1 if URIs don't match + * -1 if errors have occurred + */ +int compare_uris_parts(str *raw_uri_a, str *raw_uri_b, enum uri_match_flags opts) +{ + #define UNESCAPED_BUF_LEN 1024 + char unescaped_a[UNESCAPED_BUF_LEN], unescaped_b[UNESCAPED_BUF_LEN]; + + str unescaped_userA={unescaped_a, UNESCAPED_BUF_LEN}; + str unescaped_userB={unescaped_b, UNESCAPED_BUF_LEN}; + + struct sip_uri first; + struct sip_uri second; + + if ( (!raw_uri_a) || (!raw_uri_b) ) + { + LM_ERR("Provide either a raw form of a SIP URI\n"); + return -1; + } + + /* maybe we're lucky and straight-forward comparison succeeds */ + if ((opts & URI_MATCH_ALL) && (raw_uri_a->len == raw_uri_b->len)) + if (strncasecmp(raw_uri_a->s,raw_uri_b->s,raw_uri_a->len) == 0) + { + LM_DBG("straight-forward URI match\n"); + return 0; + } + + if (parse_uri(raw_uri_a->s,raw_uri_a->len,&first) < 0) + { + LM_ERR("Failed to parse first URI\n"); + return -1; + } + + if (parse_uri(raw_uri_b->s,raw_uri_b->len,&second) < 0) + { + LM_ERR("Failed to parse second URI\n"); + return -1; + } + + if (opts & URI_MATCH_TYPE) + if (first.type != second.type) + { + LM_DBG("Different uri types\n"); + return 1; + } + + if (unescape_user(&first.user, &unescaped_userA) < 0 || + unescape_user(&second.user, &unescaped_userB) < 0) { + LM_ERR("Failed to unescape user!\n"); + return -1; + } + + first.user = unescaped_userA; + second.user = unescaped_userB; + + if (opts & URI_MATCH_USER) + compare_uri_val(user,strncmp); + if (opts & URI_MATCH_PASSWD) + compare_uri_val(passwd,strncmp); + if (opts & URI_MATCH_HOST) + compare_uri_val(host,strncasecmp); + if (opts & URI_MATCH_PORT) + compare_uri_val(port,strncmp); + + if (opts & URI_MATCH_TRANSPORT) + compare_uri_val(transport_val,strncasecmp); + if (opts & URI_MATCH_TTL) + compare_uri_val(ttl_val,strncasecmp); + if (opts & URI_MATCH_USERPARAM) + compare_uri_val(user_param_val,strncasecmp); + if (opts & URI_MATCH_MADDR) + compare_uri_val(maddr_val,strncasecmp); + if (opts & URI_MATCH_METHOD) + compare_uri_val(method_val,strncasecmp); + if (opts & URI_MATCH_LR) + compare_uri_val(lr_val,strncasecmp); + if (opts & URI_MATCH_R2) + compare_uri_val(r2_val,strncasecmp); + + return 0; +} diff --git a/parser/parse_uri.h b/parser/parse_uri.h index f9c700e57d2..d89f3d63ff6 100644 --- a/parser/parse_uri.h +++ b/parser/parse_uri.h @@ -42,6 +42,23 @@ #define URN_NENA_SERVICE_STR ":nena:service:" #define URN_NENA_SERVICE_STR_LEN (sizeof(URN_NENA_SERVICE_STR) - 1) +enum uri_match_flags { + URI_MATCH_TYPE = (1<<0), + URI_MATCH_USER = (1<<1), + URI_MATCH_PASSWD = (1<<2), + URI_MATCH_HOST = (1<<3), + URI_MATCH_PORT = (1<<4), + URI_MATCH_TRANSPORT = (1<<5), + URI_MATCH_TTL = (1<<6), + URI_MATCH_USERPARAM = (1<<7), + URI_MATCH_MADDR = (1<<8), + URI_MATCH_METHOD = (1<<9), + URI_MATCH_LR = (1<<10), + URI_MATCH_R2 = (1<<11), + URI_MATCH_ALL = (URI_MATCH_TYPE | URI_MATCH_USER | URI_MATCH_PASSWD | URI_MATCH_HOST | URI_MATCH_PORT | URI_MATCH_TRANSPORT | + URI_MATCH_TTL | URI_MATCH_USERPARAM | URI_MATCH_MADDR | URI_MATCH_METHOD | URI_MATCH_LR | URI_MATCH_R2), +}; + /* buf= pointer to beginning of uri (sip:x@foo.bar:5060;a=b?h=i) * len= len of uri * returns: fills uri & returns <0 on error or 0 if ok @@ -69,6 +86,7 @@ int parse_sip_msg_uri(struct sip_msg* msg); int parse_orig_ruri(struct sip_msg* msg); int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a, str *raw_uri_b,struct sip_uri *parsed_uri_b); +int compare_uris_parts(str *raw_uri_a, str *raw_uri_b, enum uri_match_flags opts); static inline int get_uri_param_val(const struct sip_uri *uri, const str *param, str *val); static inline int get_uri_param_idx(const str *param,