From 6845772a5345d60d48b702b624f673d979451004 Mon Sep 17 00:00:00 2001 From: Aleksandar Yosifov Date: Thu, 23 May 2019 11:05:12 +0300 Subject: [PATCH] ims_registrar_pcscf: parse security verify header - Parse 'security verify' header from REGISTER request message and save updated parameters into the database. - Added debug messages in save_pendign and save for easy debugging. --- src/modules/ims_registrar_pcscf/save.c | 24 +++++++- src/modules/ims_registrar_pcscf/sec_agree.c | 66 ++++++++++++++++----- src/modules/ims_registrar_pcscf/sec_agree.h | 8 +++ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/modules/ims_registrar_pcscf/save.c b/src/modules/ims_registrar_pcscf/save.c index 0789a52bfba..fb701e6af68 100644 --- a/src/modules/ims_registrar_pcscf/save.c +++ b/src/modules/ims_registrar_pcscf/save.c @@ -291,7 +291,8 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) { LM_DBG("not doing pending reg on de-registration\n"); return 1; } - LM_DBG("Save Pending"); + + LM_DBG("Save pending contact with AOR [%.*s], proto %d, port %d\n", c->uri.len, c->uri.s, proto, port); LM_DBG("contact requesting to expire in %d seconds\n", expires-local_time_now); /*populate CI with bare minimum*/ @@ -339,6 +340,21 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) { LM_ERR("Will save pending contact without security parameters\n"); } + // Parse security-verify parameters + security_t* sec_verify_params = NULL; + if((sec_verify_params = cscf_get_security_verify(_m)) == NULL){ + LM_ERR("Will save pending contact without security-verify parameters\n"); + }else{ + if(sec_params){ + // for REGISTER request try to set spi pc and spi ps from security-verify header + sec_params->data.ipsec->spi_ps = sec_verify_params->data.ipsec->spi_us; + sec_params->data.ipsec->spi_pc = sec_verify_params->data.ipsec->spi_uc; + + LM_DBG("Will save pending contact with security-verify parameters, spc_ps %u, spi_pc %u\n", + sec_params->data.ipsec->spi_ps, sec_params->data.ipsec->spi_pc); + } + } + ul.lock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(_d, &ci, &pcontact) != 0) { //need to insert new contact LM_DBG("Adding pending pcontact: <%.*s>\n", c->uri.len, c->uri.s); @@ -428,6 +444,12 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags) { cscf_get_p_associated_uri(_m, &public_ids, &num_public_ids, 1); service_routes = cscf_get_service_route(_m, &num_service_routes, 1); + { + struct via_body* vb = cscf_get_ue_via(_m); + LM_DBG("Save contact with AOR(uri) [%.*s], proto %d, port %d\n", + cb->contacts->uri.len, cb->contacts->uri.s, vb->proto, vb->port?vb->port:5060); + } + //update contacts if (!update_contacts(req, _m, _d, cb->star, expires_hdr, public_ids, num_public_ids, service_routes, num_service_routes, 0)) { LM_ERR("failed to update pcontact\n"); diff --git a/src/modules/ims_registrar_pcscf/sec_agree.c b/src/modules/ims_registrar_pcscf/sec_agree.c index 099dbbfff30..0af38148223 100644 --- a/src/modules/ims_registrar_pcscf/sec_agree.c +++ b/src/modules/ims_registrar_pcscf/sec_agree.c @@ -46,6 +46,18 @@ static uint32_t parse_digits(str value) return ret; } +static void trim_whitespaces(str* string) { + // skip leading whitespace + while(string->len && (string->s[0]==' ' || string->s[0]=='\t' || string->s[0]=='<')){ + string->s = string->s + 1; + string->len --; + } + + // skip trailing whitespace + while(string->len && (string->s[string->len-1]==' ' || string->s[string->len-1]=='\t')){ + string->len--; + } +} #define SEC_COPY_STR_PARAM(DST, SRC)\ DST.s = shm_malloc(SRC.len);\ @@ -58,6 +70,8 @@ static uint32_t parse_digits(str value) static int process_sec_agree_param(str name, str value, ipsec_t *ret) { + trim_whitespaces(&name); + trim_whitespaces(&value); if(strncasecmp(name.s, "alg", name.len) == 0) { SEC_COPY_STR_PARAM(ret->r_alg, value); @@ -100,18 +114,9 @@ static security_t* parse_sec_agree(struct hdr_field* h) security_t* params = NULL; str body = h->body; - // skip leading whitespace - while(body.len && (body.s[0]==' ' || body.s[0]=='\t' || body.s[0]=='<')){ - body.s = body.s + 1; - body.len --; - } + trim_whitespaces(&body); - // skip trailing whitespace - while(body.len && (body.s[body.len-1]==' ' || body.s[body.len-1]=='\t')){ - body.len--; - } - - // skip header name - noone seems to need it + // find mechanism name end for(i = 0; body.s[i] != ';' && i < body.len; i++); mechanism_name.s = body.s; @@ -227,12 +232,11 @@ static security_t* parse_sec_agree(struct hdr_field* h) static str s_security_client={"Security-Client",15}; -static str s_security_server={"Security-Server",15}; +//static str s_security_server={"Security-Server",15}; static str s_security_verify={"Security-Verify",15}; /** * Looks for the Security-Client header * @param msg - the sip message - * @param hr - ptr to return the found hdr_field * @param params - ptr to struct sec_agree_params, where parsed values will be saved * @returns 0 on success, error code on failure */ @@ -249,9 +253,7 @@ security_t* cscf_get_security(struct sip_msg *msg) h = msg->headers; while(h) { - if ((h->name.len == s_security_client.len && strncasecmp(h->name.s, s_security_client.s, s_security_client.len)==0) || - (h->name.len == s_security_server.len && strncasecmp(h->name.s, s_security_server.s, s_security_server.len)==0) || - (h->name.len == s_security_verify.len && strncasecmp(h->name.s, s_security_verify.s, s_security_verify.len)==0) ) + if (h->name.len == s_security_client.len && strncasecmp(h->name.s, s_security_client.s, s_security_client.len)==0) { return parse_sec_agree(h); } @@ -263,3 +265,35 @@ security_t* cscf_get_security(struct sip_msg *msg) return NULL; } + +/** + * Looks for the Security-Verify header + * @param msg - the sip message + * @param params - ptr to struct sec_agree_params, where parsed values will be saved + * @returns 0 on success, error code on failure + */ +security_t* cscf_get_security_verify(struct sip_msg *msg) +{ + struct hdr_field *h = NULL; + + if (!msg) return NULL; + + if (parse_headers(msg, HDR_EOH_F, 0)<0) { + return NULL; + } + + h = msg->headers; + while(h) + { + if (h->name.len == s_security_verify.len && strncasecmp(h->name.s, s_security_verify.s, s_security_verify.len)==0) + { + return parse_sec_agree(h); + } + + h = h->next; + } + + LM_INFO("No security-verify parameters found\n"); + + return NULL; +} \ No newline at end of file diff --git a/src/modules/ims_registrar_pcscf/sec_agree.h b/src/modules/ims_registrar_pcscf/sec_agree.h index 958a79ca3b7..e187e3b8d99 100644 --- a/src/modules/ims_registrar_pcscf/sec_agree.h +++ b/src/modules/ims_registrar_pcscf/sec_agree.h @@ -32,4 +32,12 @@ */ security_t* cscf_get_security(struct sip_msg *msg); +/** + * Looks for the Security-Verify header + * @param msg - the sip message + * @param params - ptr to struct sec_agree_params, where parsed values will be saved + * @returns 0 on success, error code on failure + */ +security_t* cscf_get_security_verify(struct sip_msg *msg); + #endif // SEC_AGREE_H