From e2fd3c3e85762b4d3e2f7706bfc32deafef46497 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Fri, 12 Jun 2020 10:55:16 +0200 Subject: [PATCH] siputils: functions to encode/decode contact address in a uri param --- src/modules/siputils/contact_ops.c | 249 +++++++++++++++++++++++++++++ src/modules/siputils/contact_ops.h | 4 + src/modules/siputils/siputils.c | 67 ++++++++ 3 files changed, 320 insertions(+) diff --git a/src/modules/siputils/contact_ops.c b/src/modules/siputils/contact_ops.c index 427bf3bb131..be3ec21497c 100644 --- a/src/modules/siputils/contact_ops.c +++ b/src/modules/siputils/contact_ops.c @@ -33,9 +33,11 @@ #include "utils.h" #include "../../core/mem/mem.h" #include "../../core/data_lump.h" +#include "../../core/basex.h" #include "../../core/parser/hf.h" #include "../../core/parser/parse_uri.h" #include "../../core/parser/contact/parse_contact.h" +#include "../../core/dset.h" #include "../../core/ut.h" #include @@ -628,3 +630,250 @@ int decode_uri(str uri, char separator, str *result) return 0; } + +int ki_contact_param_encode(sip_msg_t *msg, str *nparam, str *saddr) +{ + contact_body_t *cb; + contact_t *c; + str nuri; + char bval[MAX_URI_SIZE]; + str pval; + + if((msg->contact == NULL) + && ((parse_headers(msg, HDR_CONTACT_F, 0) == -1) + || (msg->contact == NULL))) { + LM_DBG("no Contact header present\n"); + return 1; + } + + cb = (contact_body_t *)msg->contact->parsed; + c = cb->contacts; + /* we visit each contact */ + while(c != NULL) { + if(c->uri.len>4) { + pval.len = base64url_enc(c->uri.s, c->uri.len, bval, MAX_URI_SIZE-1); + if (pval.len < 0) { + LM_ERR("failed to encode contact uri [%.*s]\n", + c->uri.len, c->uri.s); + return -1; + } + if (pval.len>1 && bval[pval.len-1] == '=') { + pval.len--; + if (pval.len>1 && bval[pval.len-1] == '=') { + pval.len--; + } + } + bval[pval.len] = '\0'; + pval.s = bval; + nuri.s = (char*)pkg_malloc(MAX_URI_SIZE * sizeof(char)); + if(nuri.s==NULL) { + PKG_MEM_ERROR; + return -1; + } + nuri.len = snprintf(nuri.s, MAX_URI_SIZE-1, "sip:%.*s;%.*s=%.*s", + saddr->len, saddr->s, nparam->len, nparam->s, + pval.len, pval.s); + if(nuri.len<=0 || nuri.len>=MAX_URI_SIZE) { + LM_ERR("failed to build the new contact for [%.*s] uri (%d)\n", + c->uri.len, c->uri.s, nuri.len); + pkg_free(nuri.s); + return -2; + } + if(patch(msg, c->uri.s, c->uri.len, nuri.s, nuri.len) < 0) { + LM_ERR("failed to update contact uri [%.*s]\n", + c->uri.len, c->uri.s); + pkg_free(nuri.s); + return -3; + } + } + c = c->next; + } + + return 1; +} + +int ki_contact_param_decode(sip_msg_t *msg, str *nparam) +{ + contact_body_t *cb; + contact_t *c; + param_t* pit; + char boval[MAX_URI_SIZE]; + char bnval[MAX_URI_SIZE]; + str oval; + str nval; + int i; + + if((msg->contact == NULL) + && ((parse_headers(msg, HDR_CONTACT_F, 0) == -1) + || (msg->contact == NULL))) { + LM_DBG("no Contact header present\n"); + return 1; + } + + if(msg->contact->parsed == NULL) { + if(parse_contact(msg->contact) < 0 || msg->contact->parsed == NULL) { + LM_ERR("contact parsing failed\n"); + return -1; + } + } + + cb = (contact_body_t *)msg->contact->parsed; + c = cb->contacts; + while(c != NULL) { + pit = c->params; + while(pit!=NULL) { + if(pit->name.len==nparam->len + && strncasecmp(pit->name.s, nparam->s, nparam->len)==0) { + break; + } + pit=pit->next; + } + if(pit!=NULL && pit->body.len>0) { + oval = pit->body; + if(oval.len % 4) { + if(oval.len + 4 >= MAX_URI_SIZE-1) { + LM_ERR("not enough space to insert padding [%.*s]\n", + c->uri.len, c->uri.s); + return -1; + } + memcpy(boval, oval.s, oval.len); + for(i=0; i < (4 - (oval.len % 4)); i++) { + boval[oval.len + i] = '='; + } + oval.s = boval; + oval.len += (4 - (oval.len % 4)); + /* move to next buffer */ + } + nval.len = base64url_dec(oval.s, oval.len, bnval, MAX_URI_SIZE-1); + if (nval.len <= 0) { + LM_ERR("failed to decode contact uri [%.*s]\n", + c->uri.len, c->uri.s); + return -1; + } + nval.s = (char*)pkg_malloc((nval.len+1)*sizeof(char)); + if(nval.s==NULL) { + PKG_MEM_ERROR; + return -1; + } + memcpy(nval.s, bnval, nval.len); + nval.s[nval.len] = '\0'; + + LM_DBG("new uri [%.*s]\n", nval.len, nval.s); + if(patch(msg, c->uri.s, c->uri.len, nval.s, nval.len) < 0) { + LM_ERR("failed to update contact uri [%.*s]\n", + c->uri.len, c->uri.s); + pkg_free(nval.s); + return -2; + } + } + + c = c->next; + } + + return 1; +} + +/** + * + */ +int ki_contact_param_decode_ruri(sip_msg_t *msg, str *nparam) +{ + str uri; + sip_uri_t puri; + str sparams; + param_t* params = NULL; + param_hooks_t phooks; + param_t *pit=NULL; + char boval[MAX_URI_SIZE]; + char bnval[MAX_URI_SIZE]; + str oval; + str nval; + int i; + + if((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) { + uri = msg->first_line.u.request.uri; + if(uri.s == NULL) { + LM_ERR("r-uri not found\n"); + return -1; + } + } else { + uri = msg->new_uri; + } + + if (parse_uri (uri.s, uri.len, &puri) < 0) { + LM_ERR("failed to parse r-uri [%.*s]\n", uri.len, uri.s); + return -1; + } + if(puri.sip_params.len>0) { + sparams = puri.sip_params; + } else if(puri.params.len>0) { + sparams = puri.params; + } else { + LM_DBG("no uri params [%.*s]\n", uri.len, uri.s); + return 1; + } + + if (parse_params2(&sparams, CLASS_ANY, &phooks, ¶ms, ';')<0) { + LM_ERR("failed to parse uri params [%.*s]\n", uri.len, uri.s); + return -1; + } + + pit = params; + while(pit!=NULL) { + if(pit->name.len==nparam->len + && strncasecmp(pit->name.s, nparam->s, nparam->len)==0) { + break; + } + pit=pit->next; + } + if(pit==NULL || pit->body.len<=0) { + free_params(params); + LM_DBG("no uri param value [%.*s]\n", uri.len, uri.s); + return 1; + } + + oval = pit->body; + if(oval.len % 4) { + if(oval.len + 4 >= MAX_URI_SIZE-1) { + LM_ERR("not enough space to insert padding [%.*s]\n", + uri.len, uri.s); + free_params(params); + return -1; + } + memcpy(boval, oval.s, oval.len); + for(i=0; i < (4 - (oval.len % 4)); i++) { + boval[oval.len + i] = '='; + } + oval.s = boval; + oval.len += (4 - (oval.len % 4)); + /* move to next buffer */ + } + nval.len = base64url_dec(oval.s, oval.len, bnval, MAX_URI_SIZE-1); + if (nval.len <= 0) { + free_params(params); + LM_ERR("failed to decode uri [%.*s]\n", uri.len, uri.s); + return -1; + } + nval.s = (char*)pkg_malloc((nval.len+1)*sizeof(char)); + if(nval.s==NULL) { + free_params(params); + PKG_MEM_ERROR; + return -1; + } + memcpy(nval.s, bnval, nval.len); + nval.s[nval.len] = '\0'; + + LM_DBG("new uri [%.*s]\n", nval.len, nval.s); + + if((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) { + msg->new_uri = nval; + } else { + pkg_free(msg->new_uri.s); + msg->new_uri = nval; + } + ruri_mark_new(); /* re-use uri for serial forking */ + + free_params(params); + + return 1; +} diff --git a/src/modules/siputils/contact_ops.h b/src/modules/siputils/contact_ops.h index bacf42c1715..4bf6038be98 100644 --- a/src/modules/siputils/contact_ops.h +++ b/src/modules/siputils/contact_ops.h @@ -72,4 +72,8 @@ int encode_uri(str uri, char *encoding_prefix, char *public_ip, char separator, str *result); int decode_uri(str uri, char separator, str *result); +int ki_contact_param_encode(sip_msg_t *msg, str *nparam, str *saddr); +int ki_contact_param_decode(sip_msg_t *msg, str *nparam); +int ki_contact_param_decode_ruri(sip_msg_t *msg, str *nparam); + #endif diff --git a/src/modules/siputils/siputils.c b/src/modules/siputils/siputils.c index c2da159088e..45ea6356c1b 100644 --- a/src/modules/siputils/siputils.c +++ b/src/modules/siputils/siputils.c @@ -108,6 +108,10 @@ sl_api_t opt_slb; static int mod_init(void); static void mod_destroy(void); +static int w_contact_param_encode(sip_msg_t *msg, char *pnparam, char *psaddr); +static int w_contact_param_decode(sip_msg_t *msg, char *pnparam, char *p2); +static int w_contact_param_decode_ruri(sip_msg_t *msg, char *pnparam, char *p2); + /* Fixup functions to be defined later */ static int fixup_set_uri(void** param, int param_no); static int fixup_free_set_uri(void** param, int param_no); @@ -186,6 +190,12 @@ static cmd_export_t cmds[]={ 0, ANY_ROUTE}, {"sip_p_charging_vector", (cmd_function)sip_handle_pcv, 1, fixup_spve_null, fixup_free_spve_null, ANY_ROUTE}, + {"contact_param_encode", (cmd_function)w_contact_param_encode, 2, + fixup_spve_spve, fixup_free_spve_spve, REQUEST_ROUTE|ONREPLY_ROUTE}, + {"contact_param_decode", (cmd_function)w_contact_param_decode, 1, + fixup_spve_null, fixup_free_spve_null, REQUEST_ROUTE|ONREPLY_ROUTE}, + {"contact_param_decode_ruri", (cmd_function)w_contact_param_decode_ruri, 1, + fixup_spve_null, fixup_free_spve_null, REQUEST_ROUTE}, {"bind_siputils", (cmd_function)bind_siputils, 1, 0, 0, 0}, @@ -460,6 +470,47 @@ static int fixup_option(void** param, int param_no) { return 0; } +static int w_contact_param_encode(sip_msg_t *msg, char *pnparam, char *psaddr) +{ + str nparam = STR_NULL; + str saddr = STR_NULL; + + if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) { + LM_ERR("failed to get p1\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t*)psaddr, &saddr)<0) { + LM_ERR("failed to get p1\n"); + return -1; + } + return ki_contact_param_encode(msg, &nparam, &saddr); +} + +static int w_contact_param_decode(sip_msg_t *msg, char *pnparam, char *p2) +{ + str nparam = STR_NULL; + + if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) { + LM_ERR("failed to get p1\n"); + return -1; + } + + return ki_contact_param_decode(msg, &nparam); +} + +static int w_contact_param_decode_ruri(sip_msg_t *msg, char *pnparam, char *p3) +{ + str nparam = STR_NULL; + + if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) { + LM_ERR("failed to get p1\n"); + return -1; + } + + return ki_contact_param_decode_ruri(msg, &nparam); +} + /* * Check if pseudo variable contains a valid uri */ @@ -561,6 +612,22 @@ static sr_kemi_t sr_kemi_siputils_exports[] = { { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } }, + { str_init("siputils"), str_init("contact_param_encode"), + SR_KEMIP_INT, ki_contact_param_encode, + { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, + { str_init("siputils"), str_init("contact_param_decode"), + SR_KEMIP_INT, ki_contact_param_decode, + { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, + { str_init("siputils"), str_init("contact_param_decode_ruri"), + SR_KEMIP_INT, ki_contact_param_decode_ruri, + { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, + { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } } };