ims_registrar_pcscf: parse security verify header 1964/head
authorAleksandar Yosifov <alexyosifov@gmail.com>
Thu, 23 May 2019 08:05:12 +0000 (11:05 +0300)
committerAleksandar Yosifov <alexyosifov@gmail.com>
Thu, 23 May 2019 08:34:12 +0000 (11:34 +0300)
- 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
src/modules/ims_registrar_pcscf/sec_agree.c
src/modules/ims_registrar_pcscf/sec_agree.h

index 0789a52..fb701e6 100644 (file)
@@ -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");
index 099dbbf..0af3814 100644 (file)
@@ -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 @@ cleanup:
 
 
 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
index 958a79c..e187e3b 100644 (file)
  */
 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